iwl3945: streamline iwl3945_rfkill_poll()
authorBen Cahill <ben.m.cahill@intel.com>
Fri, 9 Oct 2009 20:20:26 +0000 (13:20 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 27 Oct 2009 20:47:59 +0000 (16:47 -0400)
iwl3945_rfkill_poll() has been silently calling wiphy_rfkill_set_hw_state()
every 2 seconds, regardless of whether hardware RF KILL switch changed state.

Call wiphy_rfkill_set_hw_state() only when RFKILL switch changes.
Add IWL_DEBUG_RF_KILL log message and documentation.

Signed-off-by: Ben Cahill <ben.m.cahill@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl3945-base.c

index ab4c4bae76009c18d499e4e6af3b4c90123b4577..2406b73e90934b8a8cadad057167f907e99b74f1 100644 (file)
@@ -2717,19 +2717,34 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
        mutex_unlock(&priv->mutex);
 }
 
        mutex_unlock(&priv->mutex);
 }
 
+/*
+ * 3945 cannot interrupt driver when hardware rf kill switch toggles;
+ * driver must poll CSR_GP_CNTRL_REG register for change.  This register
+ * *is* readable even when device has been SW_RESET into low power mode
+ * (e.g. during RF KILL).
+ */
 static void iwl3945_rfkill_poll(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, rfkill_poll.work);
 static void iwl3945_rfkill_poll(struct work_struct *data)
 {
        struct iwl_priv *priv =
            container_of(data, struct iwl_priv, rfkill_poll.work);
+       bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
+       bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
+                       & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
 
 
-       if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
-               clear_bit(STATUS_RF_KILL_HW, &priv->status);
-       else
-               set_bit(STATUS_RF_KILL_HW, &priv->status);
+       if (new_rfkill != old_rfkill) {
+               if (new_rfkill)
+                       set_bit(STATUS_RF_KILL_HW, &priv->status);
+               else
+                       clear_bit(STATUS_RF_KILL_HW, &priv->status);
 
 
-       wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-                       test_bit(STATUS_RF_KILL_HW, &priv->status));
+               wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill);
+
+               IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+                               new_rfkill ? "disable radio" : "enable radio");
+       }
 
 
+       /* Keep this running, even if radio now enabled.  This will be
+        * cancelled in mac_start() if system decides to start again */
        queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
                           round_jiffies_relative(2 * HZ));
 
        queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
                           round_jiffies_relative(2 * HZ));