From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Sun, 22 Dec 2013 13:13:01 +0000 (+0200)
Subject: iwlwifi: pcie: don't update the op_mode if rfkill hasn't changed
X-Git-Tag: firefly_0821_release~176^2~4570^2~3^2^2~5^2~32
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=3dc3374fcebe30fefebf1fdce660d33b3e2bd0f9;p=firefly-linux-kernel-4.4.55.git

iwlwifi: pcie: don't update the op_mode if rfkill hasn't changed

This is useless and introduces a dependency between rfkill
and stop_device - the op_mode can't call stop_device from
the rfkill notification since it would lead to an endless
recursion.
Next patches will need to do so.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
---

diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index d9ccb4edc602..bc584efcebab 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -607,7 +607,9 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
 static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 {
 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-	bool hw_rfkill;
+	bool hw_rfkill, was_hw_rfkill;
+
+	was_hw_rfkill = iwl_is_rfkill_set(trans);
 
 	/* tell the device to stop sending interrupts */
 	spin_lock(&trans_pcie->irq_lock);
@@ -669,13 +671,20 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 	 * all the interrupts were disabled, in this case we couldn't
 	 * receive the RF kill interrupt and update the state in the
 	 * op_mode.
+	 * Don't call the op_mode if the rkfill state hasn't changed.
+	 * This allows the op_mode to call stop_device from the rfkill
+	 * notification without endless recursion. Under very rare
+	 * circumstances, we might have a small recursion if the rfkill
+	 * state changed exactly now while we were called from stop_device.
+	 * This is very unlikely but can happen and is supported.
 	 */
 	hw_rfkill = iwl_is_rfkill_set(trans);
 	if (hw_rfkill)
 		set_bit(STATUS_RFKILL, &trans->status);
 	else
 		clear_bit(STATUS_RFKILL, &trans->status);
-	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+	if (hw_rfkill != was_hw_rfkill)
+		iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 }
 
 static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)