iwlwifi: merge and better support of suspend/resume for iwlagn and iwl3945
Wey-Yi Guy [Thu, 26 Mar 2009 17:14:08 +0000 (10:14 -0700)]
With mac80211's help to call stop() and start() in mac80211
suspend/resume function, both iwlagn and iwl3945 no longer calling
stop() and start(); remove un-necessary STATUS_IN_SUSPEND bit from both
header files and functions,

Move apm_ops.stop() function into pci_suspend() to ensure
DMA is stopped before go into suspend mode.

iwl3945 has the similar suspend/resume function as iwlagn, so move both
functions to iwlcore to be shared by both drivers.

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@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.h
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl3945-base.c

index ab7aaf6..29bc0d2 100644 (file)
@@ -162,7 +162,6 @@ struct iwl3945_frame {
 #define STATUS_TEMPERATURE     8
 #define STATUS_GEO_CONFIGURED  9
 #define STATUS_EXIT_PENDING    10
-#define STATUS_IN_SUSPEND      11
 #define STATUS_STATISTICS      12
 #define STATUS_SCANNING                13
 #define STATUS_SCAN_ABORTING   14
index 3889158..2cb073e 100644 (file)
@@ -1654,7 +1654,7 @@ static void __iwl_down(struct iwl_priv *priv)
                ieee80211_stop_queues(priv->hw);
 
        /* If we have not previously called iwl_init() then
-        * clear all bits but the RF Kill and SUSPEND bits and return */
+        * clear all bits but the RF Kill bits and return */
        if (!iwl_is_init(priv)) {
                priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                        STATUS_RF_KILL_HW |
@@ -1662,23 +1662,19 @@ static void __iwl_down(struct iwl_priv *priv)
                                        STATUS_RF_KILL_SW |
                               test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
-                              test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND |
                               test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                        STATUS_EXIT_PENDING;
                goto exit;
        }
 
-       /* ...otherwise clear out all the status bits but the RF Kill and
-        * SUSPEND bits and continue taking the NIC down. */
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bits and continue taking the NIC down. */
        priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                STATUS_RF_KILL_HW |
                        test_bit(STATUS_RF_KILL_SW, &priv->status) <<
                                STATUS_RF_KILL_SW |
                        test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                STATUS_GEO_CONFIGURED |
-                       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                               STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
                                STATUS_FW_ERROR |
                       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -1703,7 +1699,7 @@ static void __iwl_down(struct iwl_priv *priv)
        udelay(5);
 
        /* FIXME: apm_ops.suspend(priv) */
-       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+       if (exit_pending)
                priv->cfg->ops->lib->apm_ops.stop(priv);
        else
                priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -2064,9 +2060,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
 
        IWL_DEBUG_INFO(priv, "Start UP work done.\n");
 
-       if (test_bit(STATUS_IN_SUSPEND, &priv->status))
-               return 0;
-
        /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
         * mac80211 will not be run successfully. */
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -3566,45 +3559,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-       if (priv->is_open) {
-               set_bit(STATUS_IN_SUSPEND, &priv->status);
-               iwl_mac_stop(priv->hw);
-               priv->is_open = 1;
-       }
-
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       return 0;
-}
-
-static int iwl_pci_resume(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-       pci_restore_state(pdev);
-       iwl_enable_interrupts(priv);
-
-       if (priv->is_open)
-               iwl_mac_start(priv->hw);
-
-       clear_bit(STATUS_IN_SUSPEND, &priv->status);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
index c54fb93..2e44d6e 100644 (file)
@@ -2112,3 +2112,43 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_rx_reply_error);
 
+#ifdef CONFIG_PM
+
+int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+       /*
+        * This function is called when system goes into suspend state
+        * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
+        * first but since iwl_mac_stop() has no knowledge of who the caller is,
+        * it will not call apm_ops.stop() to stop the DMA operation.
+        * Calling apm_ops.stop here to make sure we stop the DMA.
+        */
+       priv->cfg->ops->lib->apm_ops.stop(priv);
+
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+
+       return 0;
+}
+EXPORT_SYMBOL(iwl_pci_suspend);
+
+int iwl_pci_resume(struct pci_dev *pdev)
+{
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
+       int ret;
+
+       pci_set_power_state(pdev, PCI_D0);
+       ret = pci_enable_device(pdev);
+       if (ret)
+               return ret;
+       pci_restore_state(pdev);
+       iwl_enable_interrupts(priv);
+
+       return 0;
+}
+EXPORT_SYMBOL(iwl_pci_resume);
+
+#endif /* CONFIG_PM */
index a8eac8c..5d49045 100644 (file)
@@ -432,6 +432,10 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
        pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
        return pci_lnk_ctl;
 }
+#ifdef CONFIG_PM
+int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
+int iwl_pci_resume(struct pci_dev *pdev);
+#endif /* CONFIG_PM */
 
 /*****************************************************
 *  Error Handling Debugging
@@ -458,7 +462,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
 #define STATUS_TEMPERATURE     8
 #define STATUS_GEO_CONFIGURED  9
 #define STATUS_EXIT_PENDING    10
-#define STATUS_IN_SUSPEND      11
 #define STATUS_STATISTICS      12
 #define STATUS_SCANNING                13
 #define STATUS_SCAN_ABORTING   14
index 64eb585..af1d121 100644 (file)
@@ -456,8 +456,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
                test_bit(STATUS_GEO_CONFIGURED, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
                test_bit(STATUS_EXIT_PENDING, &priv->status));
-       pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n",
-               test_bit(STATUS_IN_SUSPEND, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
                test_bit(STATUS_STATISTICS, &priv->status));
        pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
index da61ecd..afb838b 100644 (file)
@@ -2996,7 +2996,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
                ieee80211_stop_queues(priv->hw);
 
        /* If we have not previously called iwl3945_init() then
-        * clear all bits but the RF Kill and SUSPEND bits and return */
+        * clear all bits but the RF Kill bits and return */
        if (!iwl_is_init(priv)) {
                priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                        STATUS_RF_KILL_HW |
@@ -3004,23 +3004,19 @@ static void __iwl3945_down(struct iwl_priv *priv)
                                        STATUS_RF_KILL_SW |
                               test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                        STATUS_GEO_CONFIGURED |
-                              test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                                       STATUS_IN_SUSPEND |
                                test_bit(STATUS_EXIT_PENDING, &priv->status) <<
                                        STATUS_EXIT_PENDING;
                goto exit;
        }
 
-       /* ...otherwise clear out all the status bits but the RF Kill and
-        * SUSPEND bits and continue taking the NIC down. */
+       /* ...otherwise clear out all the status bits but the RF Kill
+        * bits and continue taking the NIC down. */
        priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
                                STATUS_RF_KILL_HW |
                        test_bit(STATUS_RF_KILL_SW, &priv->status) <<
                                STATUS_RF_KILL_SW |
                        test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
                                STATUS_GEO_CONFIGURED |
-                       test_bit(STATUS_IN_SUSPEND, &priv->status) <<
-                               STATUS_IN_SUSPEND |
                        test_bit(STATUS_FW_ERROR, &priv->status) <<
                                STATUS_FW_ERROR |
                        test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -3044,7 +3040,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
 
        udelay(5);
 
-       if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status))
+       if (exit_pending)
                priv->cfg->ops->lib->apm_ops.stop(priv);
        else
                priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -3097,10 +3093,8 @@ static int __iwl3945_up(struct iwl_priv *priv)
                clear_bit(STATUS_RF_KILL_HW, &priv->status);
        else {
                set_bit(STATUS_RF_KILL_HW, &priv->status);
-               if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
-                       IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-                       return -ENODEV;
-               }
+               IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+               return -ENODEV;
        }
 
        iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
@@ -3592,9 +3586,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
 
        IWL_DEBUG_INFO(priv, "Start UP work.\n");
 
-       if (test_bit(STATUS_IN_SUSPEND, &priv->status))
-               return 0;
-
        /* Wait for START_ALIVE from ucode. Otherwise callbacks from
         * mac80211 will not be run successfully. */
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -5233,43 +5224,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
        ieee80211_free_hw(priv->hw);
 }
 
-#ifdef CONFIG_PM
-
-static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
-       if (priv->is_open) {
-               set_bit(STATUS_IN_SUSPEND, &priv->status);
-               iwl3945_mac_stop(priv->hw);
-               priv->is_open = 1;
-       }
-       pci_save_state(pdev);
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, PCI_D3hot);
-
-       return 0;
-}
-
-static int iwl3945_pci_resume(struct pci_dev *pdev)
-{
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-       int ret;
-
-       pci_set_power_state(pdev, PCI_D0);
-       ret = pci_enable_device(pdev);
-       if (ret)
-               return ret;
-       pci_restore_state(pdev);
-
-       if (priv->is_open)
-               iwl3945_mac_start(priv->hw);
-
-       clear_bit(STATUS_IN_SUSPEND, &priv->status);
-       return 0;
-}
-
-#endif /* CONFIG_PM */
 
 /*****************************************************************************
  *
@@ -5283,8 +5237,8 @@ static struct pci_driver iwl3945_driver = {
        .probe = iwl3945_pci_probe,
        .remove = __devexit_p(iwl3945_pci_remove),
 #ifdef CONFIG_PM
-       .suspend = iwl3945_pci_suspend,
-       .resume = iwl3945_pci_resume,
+       .suspend = iwl_pci_suspend,
+       .resume = iwl_pci_resume,
 #endif
 };