iwlwifi: turn off device when not used.
Ben Cahill [Fri, 9 Oct 2009 20:20:20 +0000 (13:20 -0700)]
In some cases (e.g. when mac80211 calls iwl_mac_stop() for suspend or user
no longer wants device active), device has not been going into low power state
via __iwl_down().  apm_ops.reset() does not put device into low power state;
instead it resets the device, then puts it into a powered-up state ready to be
re-loaded with uCode and re-started.  This has needlessly warmed up user's
laptops and drained batteries.

With current architecture in which mac80211 controls device up/down (including
resetting device after firmware errors), there is no need for apm_ops.reset()
any more; apm_ops.reset() is basically a combination of apm_ops.stop() and
apm_ops.init().

Instead, __iwl_down() now unconditionally places the device into a low-power
state via apm_ops.stop(). Device may be re-started via __iwl_up() calling
apm_ops.init() as soon as it may be needed (e.g. quickly for firmware errors),
but in the meantime, device will stop wasting energy.

Note that, even in this low power state, if driver re-enables interrupts,
the device retains the ability to sense the hardware RF-KILL switch, and
(except for 3945) interrupt the host when it changes.

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/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl3945-base.c

index 8d7bc38..0878b34 100644 (file)
@@ -1899,11 +1899,9 @@ static void __iwl_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       /* FIXME: apm_ops.suspend(priv) */
-       if (exit_pending)
-               priv->cfg->ops->lib->apm_ops.stop(priv);
-       else
-               priv->cfg->ops->lib->apm_ops.reset(priv);
+       /* Stop the device, and put it in low power state */
+       priv->cfg->ops->lib->apm_ops.stop(priv);
+
  exit:
        memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
 
index c347d66..adf4ebe 100644 (file)
@@ -2576,10 +2576,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       if (exit_pending)
-               priv->cfg->ops->lib->apm_ops.stop(priv);
-       else
-               priv->cfg->ops->lib->apm_ops.reset(priv);
+       /* Stop the device, and put it in low power state */
+       priv->cfg->ops->lib->apm_ops.stop(priv);
 
  exit:
        memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));