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:
commit
c00ed46d58
|
@ -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) +
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue