I fix here two issues that are related to the firmware

loading flow. A user reported that he couldn't load the
 driver because the rfkill line was pulled up while we
 were running the calibrations. This was happening while
 booting the system: systemd was restoring the "disable
 wifi settings" and that raised an RFKILL interrupt during
 the calibration. Our driver didn't handle that properly
 and this is now fixed.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJUV9s6AAoJEC0Llv5uNjIBd+0P+gIWPyBhONNgFPWpo1v+cRVo
 p8aGIPc3ZMroZFcSO6gLukkXuM4xmZz1ldyZmw6Pnfeakqu2mhix15a+uh8z1s8r
 KJWRVT379ZZ5yWQVzeEtEnT8ZYAkzta5DayCRGhBngCeM5zRlYtQLHXDrCaYj7Ag
 95IzrNdOWS7IS3L+mNeB0mm1OUgMfAEVkpHu5OQdFH3i64NADU4toq1FslNbret7
 ERp0kFBXDIHyPNc+/oynDpJwRWMTImVwe6S4eua9BGVEtRp1gjRs2eSh19XGwGst
 ZUg16YyMVg/tjpiopsHKHc1+p99MRdeL/A4lb9toqMjLiziMhOjZZY6vqLLnYFju
 XTP2fnVJQPWFDiJih9AmEuQIIdy52R6OwlU9CCxx5SVXVNaz6gkgzI3NYXupEq1E
 tgTJw1NrxlLdevLaeG+jywoW0ll3HkTA6heiNmYwLQL+G+rCTWoSy2Ht+QphM5GG
 VWBEsyVF/w/4+xvKzUEKd/0n5oU1sJdx75gnoSDQK7WIyyWRC2jibqZ9vNaXSo35
 a1WIlErC8hj10wfaSF62TG0cnCxxPj6RkZlPyqwMEKwBzfWf4qqaMs+295rHs0dn
 YKvy1N/deJ6bZIL1JpL0yYJd3S2Kc02ZvahyYx7kDfGJfJkIOA7GtYU2SEZqFCNH
 jc9vQfxZY4w9Cyo7ksTi
 =3v6b
 -----END PGP SIGNATURE-----

Merge tag 'iwlwifi-for-john-2014-11-03' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

Emmanuel Grumbach <egrumbach@gmail.com> says:

"I fix here two issues that are related to the firmware
loading flow. A user reported that he couldn't load the
driver because the rfkill line was pulled up while we
were running the calibrations. This was happening while
booting the system: systemd was restoring the "disable
wifi settings" and that raised an RFKILL interrupt during
the calibration. Our driver didn't handle that properly
and this is now fixed."

Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
John W. Linville 2014-11-04 15:46:15 -05:00
commit c00ed46d58
5 changed files with 24 additions and 4 deletions

View file

@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held(&mvm->mutex);
if (WARN_ON_ONCE(mvm->init_ucode_complete))
if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto out;
}
mvm->calibrating = true;
/* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
MVM_UCODE_CALIB_TIMEOUT);
if (!ret)
mvm->init_ucode_complete = true;
if (ret && iwl_mvm_is_radio_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
ret = 1;
}
goto out;
error:
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out:
mvm->calibrating = false;
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
/* we want to debug INIT and we have no NVM - fake */
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +

View file

@ -788,6 +788,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->scan_status = IWL_MVM_SCAN_NONE;
mvm->ps_disabled = false;
mvm->calibrating = false;
/* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw);

View file

@ -548,6 +548,7 @@ struct iwl_mvm {
enum iwl_ucode_type cur_ucode;
bool ucode_loaded;
bool init_ucode_complete;
bool calibrating;
u32 error_event_table;
u32 log_event_table;
u32 umac_error_event_table;

View file

@ -424,6 +424,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
}
mvm->sf_state = SF_UNINIT;
mvm->low_latency_agg_frame_limit = 6;
mvm->cur_ucode = IWL_UCODE_INIT;
mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex);
@ -752,6 +753,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
bool calibrating = ACCESS_ONCE(mvm->calibrating);
if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@ -760,7 +762,15 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
return state && mvm->cur_ucode != IWL_UCODE_INIT;
/* iwl_run_init_mvm_ucode is waiting for results, abort it */
if (calibrating)
iwl_abort_notification_waits(&mvm->notif_wait);
/*
* Stop the device if we run OPERATIONAL firmware or if we are in the
* middle of the calibrations.
*/
return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
}
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)

View file

@ -915,7 +915,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
* restart. So don't process again if the device is
* already dead.
*/
if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
iwl_pcie_tx_stop(trans);
iwl_pcie_rx_stop(trans);
@ -945,7 +946,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
/* clear all status bits */
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status);
clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
clear_bit(STATUS_TPOWER_PMI, &trans->status);
clear_bit(STATUS_RFKILL, &trans->status);