iwl3945: fix deep sleep when removing the driver.
authorAbbas, Mohamed <mohamed.abbas@intel.com>
Wed, 21 Jan 2009 05:33:55 +0000 (21:33 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 29 Jan 2009 21:01:06 +0000 (16:01 -0500)
A warning message "MAC is in deep sleep" sometimes happen when user removes
the driver.  This warning is related to card not being ready. In __iwl3945_down
function some of the going down steps are in wrong order, to fix this this patch
do the following:
1- make sure we are calling iwl3945_apm_reset and iwl3945_apm_stop
   in the right order.

2- make sure we set CSR_GP_CNTRL_REG_FLAG_INIT_DONE in apm_reset before
   poll on CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY.

3- set correct polling counter.

This fixes bug
http://www.intellinuxwireless.org/bugzilla/show_bug.cgi?id=1834

Signed-off-by: mohamed abbas <mohamed.abbas@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-3945.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl3945-base.c

index fe907f353368a7e08e847c037aca06e8f1a9253b..4aeb101fc45b8d638eacadff83eafc9bc30d8891 100644 (file)
@@ -1338,6 +1338,9 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
        spin_lock_irqsave(&priv->lock, flags);
 
        iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       udelay(10);
+
+       iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 
        iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
                         CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
@@ -1347,11 +1350,6 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
                iwl_write_prph(priv, APMG_CLK_CTRL_REG,
                                         APMG_CLK_VAL_BSM_CLK_RQT);
 
-               udelay(10);
-
-               iwl_set_bit(priv, CSR_GP_CNTRL,
-                           CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
                iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
                iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
                                        0xFFFFFFFF);
index bc3f3daef6ed7849190a490b1765044af50930b0..7341a2da84310c9ffdd4697c0836552089d497d7 100644 (file)
@@ -165,7 +165,7 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
        ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
                           CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
                           (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
-                           CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+                           CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
        if (ret < 0) {
                IWL_ERR(priv, "MAC is in deep sleep!\n");
                return -EIO;
index 78271936801a69c56b220bf1d549bff730ed2b0f..d520bfe2db990a24a7364c48747990f5cfa045de 100644 (file)
@@ -4941,6 +4941,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
                        test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                STATUS_EXIT_PENDING;
 
+       priv->cfg->ops->lib->apm_ops.reset(priv);
        spin_lock_irqsave(&priv->lock, flags);
        iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        spin_unlock_irqrestore(&priv->lock, flags);
@@ -4958,7 +4959,11 @@ static void __iwl3945_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       priv->cfg->ops->lib->apm_ops.reset(priv);
+       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+               priv->cfg->ops->lib->apm_ops.stop(priv);
+       else
+               priv->cfg->ops->lib->apm_ops.reset(priv);
+
  exit:
        memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));