iwlwifi: return whether to stop from rfkill method
authorJohannes Berg <johannes.berg@intel.com>
Tue, 25 Feb 2014 19:50:53 +0000 (20:50 +0100)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 9 Mar 2014 17:16:46 +0000 (19:16 +0200)
When indicating RF-kill toggle to the higher layer, that
may in turn call back to the transport (for MVM at least)
to turn off the device quickly. Instead of that, allow it
to return whether or not the device should be turned off,
this gets rid of the call indirection and will help make
the API more consistent when we go back to non-threaded
interrupts again for PCIe.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/iwl-op-mode.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/pcie/drv.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c

index ba1b1ea54252c8d1ce9018263c42ef88fca9d50f..4a5cacce143eff8b359023a95b97ae5c11bc6ac7 100644 (file)
@@ -2035,7 +2035,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
        ieee80211_free_txskb(priv->hw, skb);
 }
 
-static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
+static bool iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
 {
        struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
 
@@ -2045,6 +2045,8 @@ static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
        wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
+
+       return false;
 }
 
 static const struct iwl_op_mode_ops iwl_dvm_ops = {
index 5d78207040b0c09718a7a73228b1a375644ac962..ea29504ac61704c39c24a117dec0a5d92aa58376 100644 (file)
@@ -119,7 +119,8 @@ struct iwl_cfg;
  * @queue_not_full: notifies that a HW queue is not full any more.
  *     Must be atomic and called with BH disabled.
  * @hw_rf_kill:notifies of a change in the HW rf kill switch. True means that
- *     the radio is killed. May sleep.
+ *     the radio is killed. Return %true if the device should be stopped by
+ *     the transport immediately after the call. May sleep.
  * @free_skb: allows the transport layer to free skbs that haven't been
  *     reclaimed by the op_mode. This can happen when the driver is freed and
  *     there are Tx packets pending in the transport layer.
@@ -144,7 +145,7 @@ struct iwl_op_mode_ops {
                  struct iwl_device_cmd *cmd);
        void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
        void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
-       void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
+       bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
        void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
        void (*nic_error)(struct iwl_op_mode *op_mode);
        void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
@@ -195,11 +196,11 @@ static inline void iwl_op_mode_queue_not_full(struct iwl_op_mode *op_mode,
        op_mode->ops->queue_not_full(op_mode, queue);
 }
 
-static inline void iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode,
-                                         bool state)
+static inline bool __must_check
+iwl_op_mode_hw_rf_kill(struct iwl_op_mode *op_mode, bool state)
 {
        might_sleep();
-       op_mode->ops->hw_rf_kill(op_mode, state);
+       return op_mode->ops->hw_rf_kill(op_mode, state);
 }
 
 static inline void iwl_op_mode_free_skb(struct iwl_op_mode *op_mode,
index ae347fb16a5d74d1b7e7b1409e65875e98efd47d..05f6355720637f4993be79fd64f5d41e240a9112 100644 (file)
@@ -690,7 +690,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state)
        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
 }
 
-static void 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);
 
@@ -699,9 +699,9 @@ static void iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
        else
                clear_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
 
-       if (state && mvm->cur_ucode != IWL_UCODE_INIT)
-               iwl_trans_stop_device(mvm->trans);
        wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
+
+       return state && mvm->cur_ucode != IWL_UCODE_INIT;
 }
 
 static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
index 22b6b7ee5fd2f8e0074fa3dc8a10d44eeea152fb..e530055019ce3974deeba57eb29e3837c2226694 100644 (file)
@@ -561,7 +561,7 @@ static int iwl_pci_resume(struct device *device)
        iwl_enable_rfkill_int(trans);
 
        hw_rfkill = iwl_is_rfkill_set(trans);
-       iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
 
        return 0;
 }
index 3120bc5bb12d76331f387c23a2bb479384ed818f..9091513ea7388ce11f2294fbb609b3581073e2a0 100644 (file)
@@ -488,4 +488,6 @@ static inline void __iwl_trans_pcie_set_bit(struct iwl_trans *trans,
        __iwl_trans_pcie_set_bits_mask(trans, reg, mask, mask);
 }
 
+void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state);
+
 #endif /* __iwl_trans_int_pcie_h__ */
index cf49f6ce0ff813ec9d4ab5a0d36cba582bea22ba..fdfa3969cac986c1824bd65c41512a9ac4ba7b39 100644 (file)
@@ -994,7 +994,7 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id)
 
                isr_stats->rfkill++;
 
-               iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+               iwl_trans_pcie_rf_kill(trans, hw_rfkill);
                if (hw_rfkill) {
                        set_bit(STATUS_RFKILL, &trans->status);
                        if (test_and_clear_bit(STATUS_SYNC_HCMD_ACTIVE,
index 32a5a9a20811977206f3076ff5dcf697d335d458..dcfd6d866d095081d7001795c4ec802c3044926f 100644 (file)
@@ -770,7 +770,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
                set_bit(STATUS_RFKILL, &trans->status);
        else
                clear_bit(STATUS_RFKILL, &trans->status);
-       iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
        if (hw_rfkill && !run_in_rfkill)
                return -ERFKILL;
 
@@ -885,7 +885,13 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
        else
                clear_bit(STATUS_RFKILL, &trans->status);
        if (hw_rfkill != was_hw_rfkill)
-               iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+               iwl_trans_pcie_rf_kill(trans, hw_rfkill);
+}
+
+void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
+{
+       if (iwl_op_mode_hw_rf_kill(trans->op_mode, state))
+               iwl_trans_pcie_stop_device(trans);
 }
 
 static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)
@@ -994,7 +1000,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
                set_bit(STATUS_RFKILL, &trans->status);
        else
                clear_bit(STATUS_RFKILL, &trans->status);
-       iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+       iwl_trans_pcie_rf_kill(trans, hw_rfkill);
 
        return 0;
 }