iwlwifi: unify SW rf-kill flow
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Fri, 13 Jun 2008 07:44:55 +0000 (15:44 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Sat, 14 Jun 2008 16:18:11 +0000 (12:18 -0400)
This patch unifies SW rf-kill flow between 4965 and 5000. It enables SW
RF-kill for 5000. This patch also solves a bug in iwl4965_mac_config:
bad mutex locking balance.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-rfkill.c
drivers/net/wireless/iwlwifi/iwl-rfkill.h
drivers/net/wireless/iwlwifi/iwl4965-base.c

index 9662fae0f739d1f5d0e2c15c3f13b024c5512918..df345cb6fd7de4fa4b5adc99e53c3c7225dcf77a 100644 (file)
@@ -3388,7 +3388,6 @@ static struct iwl_lib_ops iwl4965_lib = {
                .check_version = iwl4965_eeprom_check_version,
                .query_addr = iwlcore_eeprom_query_addr,
        },
-       .radio_kill_sw = iwl4965_radio_kill_sw,
        .set_power = iwl4965_set_power,
        .send_tx_power  = iwl4965_send_tx_power,
        .update_chain_flags = iwl4965_update_chain_flags,
index fa17cd9838cb6d73cdc29b6acbd21378eaf73f4c..eb74a40a62ebdb2835eb468c26bb1557b5fa9fed 100644 (file)
@@ -1319,3 +1319,90 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
                        cmd.critical_temperature_R);
 }
 EXPORT_SYMBOL(iwl_rf_kill_ct_config);
+
+/*
+ * CARD_STATE_CMD
+ *
+ * Use: Sets the device's internal card state to enable, disable, or halt
+ *
+ * When in the 'enable' state the card operates as normal.
+ * When in the 'disable' state, the card enters into a low power mode.
+ * When in the 'halt' state, the card is shut down and must be fully
+ * restarted to come back on.
+ */
+static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+{
+       struct iwl_host_cmd cmd = {
+               .id = REPLY_CARD_STATE_CMD,
+               .len = sizeof(u32),
+               .data = &flags,
+               .meta.flags = meta_flag,
+       };
+
+       return iwl_send_cmd(priv, &cmd);
+}
+
+void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv)
+{
+       unsigned long flags;
+
+       if (test_bit(STATUS_RF_KILL_SW, &priv->status))
+               return;
+
+       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO OFF\n");
+
+       iwl_scan_cancel(priv);
+       /* FIXME: This is a workaround for AP */
+       if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
+               spin_lock_irqsave(&priv->lock, flags);
+               iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+                           CSR_UCODE_SW_BIT_RFKILL);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               /* call the host command only if no hw rf-kill set */
+               if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
+                   iwl_is_ready(priv))
+                       iwl_send_card_state(priv,
+                               CARD_STATE_CMD_DISABLE, 0);
+               set_bit(STATUS_RF_KILL_SW, &priv->status);
+                       /* make sure mac80211 stop sending Tx frame */
+               if (priv->mac80211_registered)
+                       ieee80211_stop_queues(priv->hw);
+       }
+}
+EXPORT_SYMBOL(iwl_radio_kill_sw_disable_radio);
+
+int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
+{
+       unsigned long flags;
+
+       if (!test_bit(STATUS_RF_KILL_SW, &priv->status))
+               return 0;
+
+       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO ON\n");
+
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+       clear_bit(STATUS_RF_KILL_SW, &priv->status);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       /* wake up ucode */
+       msleep(10);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_read32(priv, CSR_UCODE_DRV_GP1);
+       if (!iwl_grab_nic_access(priv))
+               iwl_release_nic_access(priv);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+               IWL_DEBUG_RF_KILL("Can not turn radio back on - "
+                                 "disabled by HW switch\n");
+               return 0;
+       }
+
+       if (priv->is_open)
+               queue_work(priv->workqueue, &priv->restart);
+       return 1;
+}
+EXPORT_SYMBOL(iwl_radio_kill_sw_enable_radio);
index 66266655317150c53a4111c059ce840d0b56d475..2838093b44595930013b987c5934e4e7a1160627 100644 (file)
@@ -128,8 +128,6 @@ struct iwl_lib_ops {
        int (*is_valid_rtc_data_addr)(u32 addr);
        /* 1st ucode load */
        int (*load_ucode)(struct iwl_priv *priv);
-       /* rfkill */
-       int (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio);
         /* power management */
        struct {
                int (*init)(struct iwl_priv *priv);
@@ -243,6 +241,13 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
  ****************************************************/
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
 
+/*****************************************************
+ * RF -Kill - here and not in iwl-rfkill.h to be available when
+ * RF-kill subsystem is not compiled.
+ ****************************************************/
+void iwl_radio_kill_sw_disable_radio(struct iwl_priv *priv);
+int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv);
+
 /*******************************************************************************
  * Rate
  ******************************************************************************/
@@ -359,10 +364,10 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
        return iwl_is_ready(priv);
 }
 
+extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
 extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags);
 extern int iwl_verify_ucode(struct iwl_priv *priv);
-extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
-int iwl_send_lq_cmd(struct iwl_priv *priv,
+extern int iwl_send_lq_cmd(struct iwl_priv *priv,
                    struct iwl_link_quality_cmd *lq, u8 flags);
 
 static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
index c508b11b6fc860ce42142979c217495266083cc6..81ff4c2c6a5abb30aa7b031c981774c1c16e59d1 100644 (file)
@@ -653,7 +653,6 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
 
 struct iwl_priv;
 
-extern int iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio);
 /*
  * Forward declare iwl-4965.c functions for iwl-base.c
  */
index 59c8a716bd96562c1f53851e289ce536968ede0b..5f098747cf95cfc99a1e1bf877b08ffef0340d18 100644 (file)
@@ -55,13 +55,13 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
 
        switch (state) {
        case RFKILL_STATE_ON:
-               priv->cfg->ops->lib->radio_kill_sw(priv, 0);
+               iwl_radio_kill_sw_enable_radio(priv);
                /* if HW rf-kill is set dont allow ON state */
                if (iwl_is_rfkill(priv))
                        err = -EBUSY;
                break;
        case RFKILL_STATE_OFF:
-               priv->cfg->ops->lib->radio_kill_sw(priv, 1);
+               iwl_radio_kill_sw_disable_radio(priv);
                if (!iwl_is_rfkill(priv))
                        err = -EBUSY;
                break;
index a7f04b8554036d55ae749be38060fe3a55f8545b..b3c04dba45cfc639b1074a03d3a4a97deb058a11 100644 (file)
@@ -33,7 +33,6 @@ struct iwl_priv;
 #include <linux/rfkill.h>
 #include <linux/input.h>
 
-
 #ifdef CONFIG_IWLWIFI_RFKILL
 struct iwl_rfkill_mngr {
        struct rfkill *rfkill;
index a9da17ce0e1d46357fa6669418c2fc5f7c5f3c5e..f5911687671b1a28b3cdc0dc350b25aaee514914 100644 (file)
@@ -379,28 +379,6 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv)
                                sizeof(struct iwl4965_bt_cmd), &bt_cmd);
 }
 
-/*
- * CARD_STATE_CMD
- *
- * Use: Sets the device's internal card state to enable, disable, or halt
- *
- * When in the 'enable' state the card operates as normal.
- * When in the 'disable' state, the card enters into a low power mode.
- * When in the 'halt' state, the card is shut down and must be fully
- * restarted to come back on.
- */
-static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
-{
-       struct iwl_host_cmd cmd = {
-               .id = REPLY_CARD_STATE_CMD,
-               .len = sizeof(u32),
-               .data = &flags,
-               .meta.flags = meta_flag,
-       };
-
-       return iwl_send_cmd(priv, &cmd);
-}
-
 static void iwl_clear_free_frames(struct iwl_priv *priv)
 {
        struct list_head *element;
@@ -916,65 +894,6 @@ static void iwl4965_set_rate(struct iwl_priv *priv)
                   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 }
 
-int iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
-{
-       unsigned long flags;
-
-       if (!!disable_radio == test_bit(STATUS_RF_KILL_SW, &priv->status))
-               return 0;
-
-       IWL_DEBUG_RF_KILL("Manual SW RF KILL set to: RADIO %s\n",
-                         disable_radio ? "OFF" : "ON");
-
-       if (disable_radio) {
-               iwl_scan_cancel(priv);
-               /* FIXME: This is a workaround for AP */
-               if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-                                   CSR_UCODE_SW_BIT_RFKILL);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       /* call the host command only if no hw rf-kill set */
-                       if (!test_bit(STATUS_RF_KILL_HW, &priv->status) &&
-                           iwl_is_ready(priv))
-                               iwl4965_send_card_state(priv,
-                                                       CARD_STATE_CMD_DISABLE,
-                                                       0);
-                       set_bit(STATUS_RF_KILL_SW, &priv->status);
-
-                       /* make sure mac80211 stop sending Tx frame */
-                       if (priv->mac80211_registered)
-                               ieee80211_stop_queues(priv->hw);
-               }
-               return 0;
-       }
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-       clear_bit(STATUS_RF_KILL_SW, &priv->status);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       /* wake up ucode */
-       msleep(10);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_read32(priv, CSR_UCODE_DRV_GP1);
-       if (!iwl_grab_nic_access(priv))
-               iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-               IWL_DEBUG_RF_KILL("Can not turn radio back on - "
-                                 "disabled by HW switch\n");
-               return 0;
-       }
-
-       if (priv->is_open)
-               queue_work(priv->workqueue, &priv->restart);
-       return 1;
-}
-
 #define IWL_PACKET_RETRY_TIME HZ
 
 int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
@@ -2982,13 +2901,14 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
 
        priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
 
-
-       if (priv->cfg->ops->lib->radio_kill_sw &&
-           priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled)) {
+       if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
                IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
-               mutex_unlock(&priv->mutex);
+               goto out;
        }
 
+       if (!conf->radio_enabled)
+               iwl_radio_kill_sw_disable_radio(priv);
+
        if (!iwl_is_ready(priv)) {
                IWL_DEBUG_MAC80211("leave - not ready\n");
                ret = -EIO;