aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-05 14:24:35 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-06 15:16:12 -0500
commit2dd4f9f731f593a52a3fdca20bb32a78d917baf7 (patch)
tree85da9965d4384031e466690de2ad8828491e6085 /drivers/net
parentce9e80af4f2c5dffb0df470538573d473c91d540 (diff)
iwlwifi: clean up (wowlan) suspend flow
In the WoWLAN suspend flow, instead of accessing registers directly, ask the transport to do the required setup at the end of suspend. If the transport doesn't implement this, don't tell the stack we support WoWLAN. When the device suspends w/o WoWLAN, mac80211 will have stopped it already, which has already called iwl_apm_stop() via stop_hw(). Thus, it isn't necessary to call it again in pcie_suspend and we can simply do nothing there. This unifies the regular and WoWLAN suspend. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-mac80211.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h11
3 files changed, 26 insertions, 22 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
index 8b26f3217823..8c7ca7318c00 100644
--- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c
+++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c
@@ -196,6 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
196 WIPHY_FLAG_IBSS_RSN; 196 WIPHY_FLAG_IBSS_RSN;
197 197
198 if (nic(priv)->fw.ucode_wowlan.code.len && 198 if (nic(priv)->fw.ucode_wowlan.code.len &&
199 trans(priv)->ops->wowlan_suspend &&
199 device_can_wakeup(trans(priv)->dev)) { 200 device_can_wakeup(trans(priv)->dev)) {
200 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | 201 hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
201 WIPHY_WOWLAN_DISCONNECT | 202 WIPHY_WOWLAN_DISCONNECT |
@@ -412,9 +413,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
412 413
413 device_set_wakeup_enable(trans(priv)->dev, true); 414 device_set_wakeup_enable(trans(priv)->dev, true);
414 415
415 /* Now let the ucode operate on its own */ 416 iwl_trans_wowlan_suspend(trans(priv));
416 iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET,
417 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
418 417
419 goto out; 418 goto out;
420 419
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
index f47426a5ef4d..bb8f2fdf1281 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
@@ -1303,6 +1303,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
1303 iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); 1303 iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
1304} 1304}
1305 1305
1306static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
1307{
1308 /* let the ucode operate on its own */
1309 iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
1310 CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
1311
1312 iwl_disable_interrupts(trans);
1313 iwl_clear_bit(trans, CSR_GP_CNTRL,
1314 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1315}
1316
1306static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, 1317static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
1307 struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx, 1318 struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
1308 u8 sta_id, u8 tid) 1319 u8 sta_id, u8 tid)
@@ -1641,25 +1652,6 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans)
1641#ifdef CONFIG_PM_SLEEP 1652#ifdef CONFIG_PM_SLEEP
1642static int iwl_trans_pcie_suspend(struct iwl_trans *trans) 1653static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
1643{ 1654{
1644 /*
1645 * This function is called when system goes into suspend state
1646 * mac80211 will call iwlagn_mac_stop() from the mac80211 suspend
1647 * function first but since iwlagn_mac_stop() has no knowledge of
1648 * who the caller is,
1649 * it will not call apm_ops.stop() to stop the DMA operation.
1650 * Calling apm_ops.stop here to make sure we stop the DMA.
1651 *
1652 * But of course ... if we have configured WoWLAN then we did other
1653 * things already :-)
1654 */
1655 if (!trans->shrd->wowlan) {
1656 iwl_apm_stop(trans);
1657 } else {
1658 iwl_disable_interrupts(trans);
1659 iwl_clear_bit(trans, CSR_GP_CNTRL,
1660 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
1661 }
1662
1663 return 0; 1655 return 0;
1664} 1656}
1665 1657
@@ -2227,6 +2219,8 @@ const struct iwl_trans_ops trans_ops_pcie = {
2227 .start_fw = iwl_trans_pcie_start_fw, 2219 .start_fw = iwl_trans_pcie_start_fw,
2228 .stop_device = iwl_trans_pcie_stop_device, 2220 .stop_device = iwl_trans_pcie_stop_device,
2229 2221
2222 .wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
2223
2230 .wake_any_queue = iwl_trans_pcie_wake_any_queue, 2224 .wake_any_queue = iwl_trans_pcie_wake_any_queue,
2231 2225
2232 .send_cmd = iwl_trans_pcie_send_cmd, 2226 .send_cmd = iwl_trans_pcie_send_cmd,
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index e2f21cfc2cd4..83f04c9d77e5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -210,6 +210,9 @@ struct iwl_host_cmd {
210 * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_* 210 * @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
211 * @stop_device:stops the whole device (embedded CPU put to reset) 211 * @stop_device:stops the whole device (embedded CPU put to reset)
212 * May sleep 212 * May sleep
213 * @wowlan_suspend: put the device into the correct mode for WoWLAN during
214 * suspend. This is optional, if not implemented WoWLAN will not be
215 * supported. This callback may sleep.
213 * @send_cmd:send a host command 216 * @send_cmd:send a host command
214 * May sleep only if CMD_SYNC is set 217 * May sleep only if CMD_SYNC is set
215 * @tx: send an skb 218 * @tx: send an skb
@@ -247,6 +250,8 @@ struct iwl_trans_ops {
247 void (*fw_alive)(struct iwl_trans *trans); 250 void (*fw_alive)(struct iwl_trans *trans);
248 void (*stop_device)(struct iwl_trans *trans); 251 void (*stop_device)(struct iwl_trans *trans);
249 252
253 void (*wowlan_suspend)(struct iwl_trans *trans);
254
250 void (*wake_any_queue)(struct iwl_trans *trans, 255 void (*wake_any_queue)(struct iwl_trans *trans,
251 enum iwl_rxon_context_id ctx, 256 enum iwl_rxon_context_id ctx,
252 const char *msg); 257 const char *msg);
@@ -396,6 +401,12 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans)
396 trans->state = IWL_TRANS_NO_FW; 401 trans->state = IWL_TRANS_NO_FW;
397} 402}
398 403
404static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
405{
406 might_sleep();
407 trans->ops->wowlan_suspend(trans);
408}
409
399static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, 410static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
400 enum iwl_rxon_context_id ctx, 411 enum iwl_rxon_context_id ctx,
401 const char *msg) 412 const char *msg)