From: Greg Kroah-Hartman Date: Wed, 19 Nov 2014 17:29:07 +0000 (-0800) Subject: 3.17-stable patches X-Git-Tag: v3.10.61~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e257524a4314570257be83bc4275ed255cf0a31f;p=thirdparty%2Fkernel%2Fstable-queue.git 3.17-stable patches added patches: iwlwifi-fix-rfkill-while-calibrating.patch --- diff --git a/queue-3.17/iwlwifi-fix-rfkill-while-calibrating.patch b/queue-3.17/iwlwifi-fix-rfkill-while-calibrating.patch new file mode 100644 index 00000000000..bfe2c518fb8 --- /dev/null +++ b/queue-3.17/iwlwifi-fix-rfkill-while-calibrating.patch @@ -0,0 +1,140 @@ +From 31b8b343e019e0a0c57ca9c13520a87f9cab884b Mon Sep 17 00:00:00 2001 +From: Emmanuel Grumbach +Date: Sun, 2 Nov 2014 15:48:09 +0200 +Subject: iwlwifi: fix RFkill while calibrating + +From: Emmanuel Grumbach + +commit 31b8b343e019e0a0c57ca9c13520a87f9cab884b upstream. + +If the RFkill interrupt fires while we calibrate, it would +make the firmware fail and the driver wasn't able to recover. +Change the flow so that the driver will kill the firmware +in that case. + +Since we have now two flows that are calling +trans_stop_device (the RFkill interrupt and the +op_mode_mvm_start function) - we need to better sync this. +Use the STATUS_DEVICE_ENABLED in the pcie transport in an +atomic way to achieve this. + +This fixes: https://bugzilla.kernel.org/show_bug.cgi?id=86231 + +Reviewed-by: Johannes Berg +Reviewed-by: Luciano Coelho +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/iwlwifi/mvm/fw.c | 10 +++++++++- + drivers/net/wireless/iwlwifi/mvm/mac80211.c | 1 + + drivers/net/wireless/iwlwifi/mvm/mvm.h | 1 + + drivers/net/wireless/iwlwifi/mvm/ops.c | 11 ++++++++++- + drivers/net/wireless/iwlwifi/pcie/trans.c | 4 ++-- + 5 files changed, 23 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/iwlwifi/mvm/fw.c +@@ -282,7 +282,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mv + + 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, +@@ -332,6 +332,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mv + 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) +@@ -356,11 +358,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mv + 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) + +--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c ++++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c +@@ -778,6 +778,7 @@ static void iwl_mvm_restart_cleanup(stru + iwl_trans_stop_device(mvm->trans); + + mvm->scan_status = IWL_MVM_SCAN_NONE; ++ mvm->calibrating = false; + + /* just in case one was running */ + ieee80211_remain_on_channel_expired(mvm->hw); +--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h ++++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h +@@ -541,6 +541,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; +--- a/drivers/net/wireless/iwlwifi/mvm/ops.c ++++ b/drivers/net/wireless/iwlwifi/mvm/ops.c +@@ -745,6 +745,7 @@ void iwl_mvm_set_hw_ctkill_state(struct + 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); +@@ -753,7 +754,15 @@ static bool iwl_mvm_set_hw_rfkill_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) +--- a/drivers/net/wireless/iwlwifi/pcie/trans.c ++++ b/drivers/net/wireless/iwlwifi/pcie/trans.c +@@ -913,7 +913,8 @@ static void iwl_trans_pcie_stop_device(s + * 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); + +@@ -943,7 +944,6 @@ static void iwl_trans_pcie_stop_device(s + /* 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); + diff --git a/queue-3.17/series b/queue-3.17/series index 07417cd7287..e8868958a0d 100644 --- a/queue-3.17/series +++ b/queue-3.17/series @@ -138,3 +138,4 @@ net-sctp-fix-panic-on-duplicate-asconf-chunks.patch net-sctp-fix-skb_over_panic-when-receiving-malformed-asconf-chunks.patch asus-nb-wmi-add-wapf4-quirk-for-the-x550vb.patch keys-reinstate-eperm-for-a-key-type-name-beginning-with-a.patch +iwlwifi-fix-rfkill-while-calibrating.patch