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 fe907f3..4aeb101 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 bc3f3da..7341a2d 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 7827193..d520bfe 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));