Commit c00ed46d authored by John W. Linville's avatar John W. Linville

Merge tag 'iwlwifi-for-john-2014-11-03' of...

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: default avatarJohn W. Linville <linville@tuxdriver.com>
parents 75a916e1 31b8b343
...@@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -284,7 +284,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
lockdep_assert_held(&mvm->mutex); 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; return 0;
iwl_init_notification_wait(&mvm->notif_wait, iwl_init_notification_wait(&mvm->notif_wait,
...@@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -334,6 +334,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
goto out; goto out;
} }
mvm->calibrating = true;
/* Send TX valid antennas before triggering calibrations */ /* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret) if (ret)
...@@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) ...@@ -358,11 +360,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
MVM_UCODE_CALIB_TIMEOUT); MVM_UCODE_CALIB_TIMEOUT);
if (!ret) if (!ret)
mvm->init_ucode_complete = true; 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; goto out;
error: error:
iwl_remove_notification(&mvm->notif_wait, &calib_wait); iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out: out:
mvm->calibrating = false;
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) { if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
/* we want to debug INIT and we have no NVM - fake */ /* we want to debug INIT and we have no NVM - fake */
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
......
...@@ -788,6 +788,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) ...@@ -788,6 +788,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
mvm->ps_disabled = false; mvm->ps_disabled = false;
mvm->calibrating = false;
/* just in case one was running */ /* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw); ieee80211_remain_on_channel_expired(mvm->hw);
......
...@@ -548,6 +548,7 @@ struct iwl_mvm { ...@@ -548,6 +548,7 @@ struct iwl_mvm {
enum iwl_ucode_type cur_ucode; enum iwl_ucode_type cur_ucode;
bool ucode_loaded; bool ucode_loaded;
bool init_ucode_complete; bool init_ucode_complete;
bool calibrating;
u32 error_event_table; u32 error_event_table;
u32 log_event_table; u32 log_event_table;
u32 umac_error_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, ...@@ -424,6 +424,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
} }
mvm->sf_state = SF_UNINIT; mvm->sf_state = SF_UNINIT;
mvm->low_latency_agg_frame_limit = 6; mvm->low_latency_agg_frame_limit = 6;
mvm->cur_ucode = IWL_UCODE_INIT;
mutex_init(&mvm->mutex); mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex); mutex_init(&mvm->d0i3_suspend_mutex);
...@@ -752,6 +753,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) ...@@ -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) 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); struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
bool calibrating = ACCESS_ONCE(mvm->calibrating);
if (state) if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); 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) ...@@ -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)); 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) 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) ...@@ -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 * restart. So don't process again if the device is
* already dead. * 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_tx_stop(trans);
iwl_pcie_rx_stop(trans); iwl_pcie_rx_stop(trans);
...@@ -945,7 +946,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -945,7 +946,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
/* clear all status bits */ /* clear all status bits */
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &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_TPOWER_PMI, &trans->status);
clear_bit(STATUS_RFKILL, &trans->status); clear_bit(STATUS_RFKILL, &trans->status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment