aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2009-03-26 13:14:08 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:54:27 -0400
commit6da3a13e4fcab0ff58592087d28bd283caf23d88 (patch)
tree1b67e34373d8b17ae66a66526cc72dfd6ad067b1 /drivers/net/wireless
parent4f5cab969bdbec1ab0c5b690282372b4978123ac (diff)
iwlwifi: merge and better support of suspend/resume for iwlagn and iwl3945
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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c62
6 files changed, 56 insertions, 108 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index ab7aaf6872c7..29bc0d2656bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -162,7 +162,6 @@ struct iwl3945_frame {
162#define STATUS_TEMPERATURE 8 162#define STATUS_TEMPERATURE 8
163#define STATUS_GEO_CONFIGURED 9 163#define STATUS_GEO_CONFIGURED 9
164#define STATUS_EXIT_PENDING 10 164#define STATUS_EXIT_PENDING 10
165#define STATUS_IN_SUSPEND 11
166#define STATUS_STATISTICS 12 165#define STATUS_STATISTICS 12
167#define STATUS_SCANNING 13 166#define STATUS_SCANNING 13
168#define STATUS_SCAN_ABORTING 14 167#define STATUS_SCAN_ABORTING 14
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 3889158b359c..2cb073efb95d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1654,7 +1654,7 @@ static void __iwl_down(struct iwl_priv *priv)
1654 ieee80211_stop_queues(priv->hw); 1654 ieee80211_stop_queues(priv->hw);
1655 1655
1656 /* If we have not previously called iwl_init() then 1656 /* If we have not previously called iwl_init() then
1657 * clear all bits but the RF Kill and SUSPEND bits and return */ 1657 * clear all bits but the RF Kill bits and return */
1658 if (!iwl_is_init(priv)) { 1658 if (!iwl_is_init(priv)) {
1659 priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << 1659 priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
1660 STATUS_RF_KILL_HW | 1660 STATUS_RF_KILL_HW |
@@ -1662,23 +1662,19 @@ static void __iwl_down(struct iwl_priv *priv)
1662 STATUS_RF_KILL_SW | 1662 STATUS_RF_KILL_SW |
1663 test_bit(STATUS_GEO_CONFIGURED, &priv->status) << 1663 test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
1664 STATUS_GEO_CONFIGURED | 1664 STATUS_GEO_CONFIGURED |
1665 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
1666 STATUS_IN_SUSPEND |
1667 test_bit(STATUS_EXIT_PENDING, &priv->status) << 1665 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
1668 STATUS_EXIT_PENDING; 1666 STATUS_EXIT_PENDING;
1669 goto exit; 1667 goto exit;
1670 } 1668 }
1671 1669
1672 /* ...otherwise clear out all the status bits but the RF Kill and 1670 /* ...otherwise clear out all the status bits but the RF Kill
1673 * SUSPEND bits and continue taking the NIC down. */ 1671 * bits and continue taking the NIC down. */
1674 priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << 1672 priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
1675 STATUS_RF_KILL_HW | 1673 STATUS_RF_KILL_HW |
1676 test_bit(STATUS_RF_KILL_SW, &priv->status) << 1674 test_bit(STATUS_RF_KILL_SW, &priv->status) <<
1677 STATUS_RF_KILL_SW | 1675 STATUS_RF_KILL_SW |
1678 test_bit(STATUS_GEO_CONFIGURED, &priv->status) << 1676 test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
1679 STATUS_GEO_CONFIGURED | 1677 STATUS_GEO_CONFIGURED |
1680 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
1681 STATUS_IN_SUSPEND |
1682 test_bit(STATUS_FW_ERROR, &priv->status) << 1678 test_bit(STATUS_FW_ERROR, &priv->status) <<
1683 STATUS_FW_ERROR | 1679 STATUS_FW_ERROR |
1684 test_bit(STATUS_EXIT_PENDING, &priv->status) << 1680 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -1703,7 +1699,7 @@ static void __iwl_down(struct iwl_priv *priv)
1703 udelay(5); 1699 udelay(5);
1704 1700
1705 /* FIXME: apm_ops.suspend(priv) */ 1701 /* FIXME: apm_ops.suspend(priv) */
1706 if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) 1702 if (exit_pending)
1707 priv->cfg->ops->lib->apm_ops.stop(priv); 1703 priv->cfg->ops->lib->apm_ops.stop(priv);
1708 else 1704 else
1709 priv->cfg->ops->lib->apm_ops.reset(priv); 1705 priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -2064,9 +2060,6 @@ static int iwl_mac_start(struct ieee80211_hw *hw)
2064 2060
2065 IWL_DEBUG_INFO(priv, "Start UP work done.\n"); 2061 IWL_DEBUG_INFO(priv, "Start UP work done.\n");
2066 2062
2067 if (test_bit(STATUS_IN_SUSPEND, &priv->status))
2068 return 0;
2069
2070 /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from 2063 /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
2071 * mac80211 will not be run successfully. */ 2064 * mac80211 will not be run successfully. */
2072 ret = wait_event_interruptible_timeout(priv->wait_command_queue, 2065 ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -3566,45 +3559,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3566 ieee80211_free_hw(priv->hw); 3559 ieee80211_free_hw(priv->hw);
3567} 3560}
3568 3561
3569#ifdef CONFIG_PM
3570
3571static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
3572{
3573 struct iwl_priv *priv = pci_get_drvdata(pdev);
3574
3575 if (priv->is_open) {
3576 set_bit(STATUS_IN_SUSPEND, &priv->status);
3577 iwl_mac_stop(priv->hw);
3578 priv->is_open = 1;
3579 }
3580
3581 pci_save_state(pdev);
3582 pci_disable_device(pdev);
3583 pci_set_power_state(pdev, PCI_D3hot);
3584
3585 return 0;
3586}
3587
3588static int iwl_pci_resume(struct pci_dev *pdev)
3589{
3590 struct iwl_priv *priv = pci_get_drvdata(pdev);
3591 int ret;
3592
3593 pci_set_power_state(pdev, PCI_D0);
3594 ret = pci_enable_device(pdev);
3595 if (ret)
3596 return ret;
3597 pci_restore_state(pdev);
3598 iwl_enable_interrupts(priv);
3599
3600 if (priv->is_open)
3601 iwl_mac_start(priv->hw);
3602
3603 clear_bit(STATUS_IN_SUSPEND, &priv->status);
3604 return 0;
3605}
3606
3607#endif /* CONFIG_PM */
3608 3562
3609/***************************************************************************** 3563/*****************************************************************************
3610 * 3564 *
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index c54fb93e9d72..2e44d6e19e2b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2112,3 +2112,43 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
2112} 2112}
2113EXPORT_SYMBOL(iwl_rx_reply_error); 2113EXPORT_SYMBOL(iwl_rx_reply_error);
2114 2114
2115#ifdef CONFIG_PM
2116
2117int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
2118{
2119 struct iwl_priv *priv = pci_get_drvdata(pdev);
2120
2121 /*
2122 * This function is called when system goes into suspend state
2123 * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
2124 * first but since iwl_mac_stop() has no knowledge of who the caller is,
2125 * it will not call apm_ops.stop() to stop the DMA operation.
2126 * Calling apm_ops.stop here to make sure we stop the DMA.
2127 */
2128 priv->cfg->ops->lib->apm_ops.stop(priv);
2129
2130 pci_save_state(pdev);
2131 pci_disable_device(pdev);
2132 pci_set_power_state(pdev, PCI_D3hot);
2133
2134 return 0;
2135}
2136EXPORT_SYMBOL(iwl_pci_suspend);
2137
2138int iwl_pci_resume(struct pci_dev *pdev)
2139{
2140 struct iwl_priv *priv = pci_get_drvdata(pdev);
2141 int ret;
2142
2143 pci_set_power_state(pdev, PCI_D0);
2144 ret = pci_enable_device(pdev);
2145 if (ret)
2146 return ret;
2147 pci_restore_state(pdev);
2148 iwl_enable_interrupts(priv);
2149
2150 return 0;
2151}
2152EXPORT_SYMBOL(iwl_pci_resume);
2153
2154#endif /* CONFIG_PM */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index a8eac8c3c1fa..5d4904584686 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -432,6 +432,10 @@ static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
432 pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); 432 pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
433 return pci_lnk_ctl; 433 return pci_lnk_ctl;
434} 434}
435#ifdef CONFIG_PM
436int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
437int iwl_pci_resume(struct pci_dev *pdev);
438#endif /* CONFIG_PM */
435 439
436/***************************************************** 440/*****************************************************
437* Error Handling Debugging 441* Error Handling Debugging
@@ -458,7 +462,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
458#define STATUS_TEMPERATURE 8 462#define STATUS_TEMPERATURE 8
459#define STATUS_GEO_CONFIGURED 9 463#define STATUS_GEO_CONFIGURED 9
460#define STATUS_EXIT_PENDING 10 464#define STATUS_EXIT_PENDING 10
461#define STATUS_IN_SUSPEND 11
462#define STATUS_STATISTICS 12 465#define STATUS_STATISTICS 12
463#define STATUS_SCANNING 13 466#define STATUS_SCANNING 13
464#define STATUS_SCAN_ABORTING 14 467#define STATUS_SCAN_ABORTING 14
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 64eb585f1578..af1d1214b184 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -456,8 +456,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
456 test_bit(STATUS_GEO_CONFIGURED, &priv->status)); 456 test_bit(STATUS_GEO_CONFIGURED, &priv->status));
457 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", 457 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
458 test_bit(STATUS_EXIT_PENDING, &priv->status)); 458 test_bit(STATUS_EXIT_PENDING, &priv->status));
459 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_IN_SUSPEND:\t %d\n",
460 test_bit(STATUS_IN_SUSPEND, &priv->status));
461 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", 459 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
462 test_bit(STATUS_STATISTICS, &priv->status)); 460 test_bit(STATUS_STATISTICS, &priv->status));
463 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", 461 pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index da61ecd62882..afb838b39a6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2996,7 +2996,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
2996 ieee80211_stop_queues(priv->hw); 2996 ieee80211_stop_queues(priv->hw);
2997 2997
2998 /* If we have not previously called iwl3945_init() then 2998 /* If we have not previously called iwl3945_init() then
2999 * clear all bits but the RF Kill and SUSPEND bits and return */ 2999 * clear all bits but the RF Kill bits and return */
3000 if (!iwl_is_init(priv)) { 3000 if (!iwl_is_init(priv)) {
3001 priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << 3001 priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
3002 STATUS_RF_KILL_HW | 3002 STATUS_RF_KILL_HW |
@@ -3004,23 +3004,19 @@ static void __iwl3945_down(struct iwl_priv *priv)
3004 STATUS_RF_KILL_SW | 3004 STATUS_RF_KILL_SW |
3005 test_bit(STATUS_GEO_CONFIGURED, &priv->status) << 3005 test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
3006 STATUS_GEO_CONFIGURED | 3006 STATUS_GEO_CONFIGURED |
3007 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
3008 STATUS_IN_SUSPEND |
3009 test_bit(STATUS_EXIT_PENDING, &priv->status) << 3007 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
3010 STATUS_EXIT_PENDING; 3008 STATUS_EXIT_PENDING;
3011 goto exit; 3009 goto exit;
3012 } 3010 }
3013 3011
3014 /* ...otherwise clear out all the status bits but the RF Kill and 3012 /* ...otherwise clear out all the status bits but the RF Kill
3015 * SUSPEND bits and continue taking the NIC down. */ 3013 * bits and continue taking the NIC down. */
3016 priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << 3014 priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
3017 STATUS_RF_KILL_HW | 3015 STATUS_RF_KILL_HW |
3018 test_bit(STATUS_RF_KILL_SW, &priv->status) << 3016 test_bit(STATUS_RF_KILL_SW, &priv->status) <<
3019 STATUS_RF_KILL_SW | 3017 STATUS_RF_KILL_SW |
3020 test_bit(STATUS_GEO_CONFIGURED, &priv->status) << 3018 test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
3021 STATUS_GEO_CONFIGURED | 3019 STATUS_GEO_CONFIGURED |
3022 test_bit(STATUS_IN_SUSPEND, &priv->status) <<
3023 STATUS_IN_SUSPEND |
3024 test_bit(STATUS_FW_ERROR, &priv->status) << 3020 test_bit(STATUS_FW_ERROR, &priv->status) <<
3025 STATUS_FW_ERROR | 3021 STATUS_FW_ERROR |
3026 test_bit(STATUS_EXIT_PENDING, &priv->status) << 3022 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
@@ -3044,7 +3040,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
3044 3040
3045 udelay(5); 3041 udelay(5);
3046 3042
3047 if (exit_pending || test_bit(STATUS_IN_SUSPEND, &priv->status)) 3043 if (exit_pending)
3048 priv->cfg->ops->lib->apm_ops.stop(priv); 3044 priv->cfg->ops->lib->apm_ops.stop(priv);
3049 else 3045 else
3050 priv->cfg->ops->lib->apm_ops.reset(priv); 3046 priv->cfg->ops->lib->apm_ops.reset(priv);
@@ -3097,10 +3093,8 @@ static int __iwl3945_up(struct iwl_priv *priv)
3097 clear_bit(STATUS_RF_KILL_HW, &priv->status); 3093 clear_bit(STATUS_RF_KILL_HW, &priv->status);
3098 else { 3094 else {
3099 set_bit(STATUS_RF_KILL_HW, &priv->status); 3095 set_bit(STATUS_RF_KILL_HW, &priv->status);
3100 if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { 3096 IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
3101 IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); 3097 return -ENODEV;
3102 return -ENODEV;
3103 }
3104 } 3098 }
3105 3099
3106 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 3100 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
@@ -3592,9 +3586,6 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
3592 3586
3593 IWL_DEBUG_INFO(priv, "Start UP work.\n"); 3587 IWL_DEBUG_INFO(priv, "Start UP work.\n");
3594 3588
3595 if (test_bit(STATUS_IN_SUSPEND, &priv->status))
3596 return 0;
3597
3598 /* Wait for START_ALIVE from ucode. Otherwise callbacks from 3589 /* Wait for START_ALIVE from ucode. Otherwise callbacks from
3599 * mac80211 will not be run successfully. */ 3590 * mac80211 will not be run successfully. */
3600 ret = wait_event_interruptible_timeout(priv->wait_command_queue, 3591 ret = wait_event_interruptible_timeout(priv->wait_command_queue,
@@ -5233,43 +5224,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
5233 ieee80211_free_hw(priv->hw); 5224 ieee80211_free_hw(priv->hw);
5234} 5225}
5235 5226
5236#ifdef CONFIG_PM
5237
5238static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
5239{
5240 struct iwl_priv *priv = pci_get_drvdata(pdev);
5241
5242 if (priv->is_open) {
5243 set_bit(STATUS_IN_SUSPEND, &priv->status);
5244 iwl3945_mac_stop(priv->hw);
5245 priv->is_open = 1;
5246 }
5247 pci_save_state(pdev);
5248 pci_disable_device(pdev);
5249 pci_set_power_state(pdev, PCI_D3hot);
5250
5251 return 0;
5252}
5253
5254static int iwl3945_pci_resume(struct pci_dev *pdev)
5255{
5256 struct iwl_priv *priv = pci_get_drvdata(pdev);
5257 int ret;
5258
5259 pci_set_power_state(pdev, PCI_D0);
5260 ret = pci_enable_device(pdev);
5261 if (ret)
5262 return ret;
5263 pci_restore_state(pdev);
5264
5265 if (priv->is_open)
5266 iwl3945_mac_start(priv->hw);
5267
5268 clear_bit(STATUS_IN_SUSPEND, &priv->status);
5269 return 0;
5270}
5271
5272#endif /* CONFIG_PM */
5273 5227
5274/***************************************************************************** 5228/*****************************************************************************
5275 * 5229 *
@@ -5283,8 +5237,8 @@ static struct pci_driver iwl3945_driver = {
5283 .probe = iwl3945_pci_probe, 5237 .probe = iwl3945_pci_probe,
5284 .remove = __devexit_p(iwl3945_pci_remove), 5238 .remove = __devexit_p(iwl3945_pci_remove),
5285#ifdef CONFIG_PM 5239#ifdef CONFIG_PM
5286 .suspend = iwl3945_pci_suspend, 5240 .suspend = iwl_pci_suspend,
5287 .resume = iwl3945_pci_resume, 5241 .resume = iwl_pci_resume,
5288#endif 5242#endif
5289}; 5243};
5290 5244