diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 33 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.c | 32 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-trans.h | 8 |
5 files changed, 42 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 359bd906056..7c036b9c2b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -634,37 +634,6 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
634 | vif->bss_conf.bssid); | 634 | vif->bss_conf.bssid); |
635 | } | 635 | } |
636 | 636 | ||
637 | #define IWL_FLUSH_WAIT_MS 2000 | ||
638 | |||
639 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv) | ||
640 | { | ||
641 | struct iwl_tx_queue *txq; | ||
642 | struct iwl_queue *q; | ||
643 | int cnt; | ||
644 | unsigned long now = jiffies; | ||
645 | int ret = 0; | ||
646 | |||
647 | /* waiting for all the tx frames complete might take a while */ | ||
648 | for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { | ||
649 | if (cnt == priv->shrd->cmd_queue) | ||
650 | continue; | ||
651 | txq = &priv->txq[cnt]; | ||
652 | q = &txq->q; | ||
653 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
654 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
655 | msleep(1); | ||
656 | |||
657 | if (q->read_ptr != q->write_ptr) { | ||
658 | IWL_ERR(priv, "fail to flush all tx fifo queues\n"); | ||
659 | ret = -ETIMEDOUT; | ||
660 | break; | ||
661 | } | ||
662 | } | ||
663 | return ret; | ||
664 | } | ||
665 | |||
666 | #define IWL_TX_QUEUE_MSK 0xfffff | ||
667 | |||
668 | /** | 637 | /** |
669 | * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode | 638 | * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode |
670 | * | 639 | * |
@@ -715,7 +684,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control) | |||
715 | goto done; | 684 | goto done; |
716 | } | 685 | } |
717 | IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); | 686 | IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n"); |
718 | iwlagn_wait_tx_queue_empty(priv); | 687 | iwl_trans_wait_tx_queue_empty(trans(priv)); |
719 | done: | 688 | done: |
720 | ieee80211_wake_queues(priv->hw); | 689 | ieee80211_wake_queues(priv->hw); |
721 | mutex_unlock(&priv->shrd->mutex); | 690 | mutex_unlock(&priv->shrd->mutex); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 724c50a069d..5d0888a7fbc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2833,7 +2833,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop) | |||
2833 | } | 2833 | } |
2834 | } | 2834 | } |
2835 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); | 2835 | IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); |
2836 | iwlagn_wait_tx_queue_empty(priv); | 2836 | iwl_trans_wait_tx_queue_empty(trans(priv)); |
2837 | done: | 2837 | done: |
2838 | mutex_unlock(&priv->shrd->mutex); | 2838 | mutex_unlock(&priv->shrd->mutex); |
2839 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2839 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2b94a10561d..a7b4948e43d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -102,7 +102,6 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
102 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 102 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
103 | void iwlagn_temperature(struct iwl_priv *priv); | 103 | void iwlagn_temperature(struct iwl_priv *priv); |
104 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); | 104 | u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); |
105 | int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); | ||
106 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 105 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
107 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); | 106 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); |
108 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 107 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 9b0ecd4b1e1..7b868c7b523 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c | |||
@@ -1446,6 +1446,35 @@ static struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd) | |||
1446 | return iwl_trans; | 1446 | return iwl_trans; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | #define IWL_FLUSH_WAIT_MS 2000 | ||
1450 | |||
1451 | static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans) | ||
1452 | { | ||
1453 | struct iwl_tx_queue *txq; | ||
1454 | struct iwl_queue *q; | ||
1455 | int cnt; | ||
1456 | unsigned long now = jiffies; | ||
1457 | int ret = 0; | ||
1458 | |||
1459 | /* waiting for all the tx frames complete might take a while */ | ||
1460 | for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) { | ||
1461 | if (cnt == trans->shrd->cmd_queue) | ||
1462 | continue; | ||
1463 | txq = &priv(trans)->txq[cnt]; | ||
1464 | q = &txq->q; | ||
1465 | while (q->read_ptr != q->write_ptr && !time_after(jiffies, | ||
1466 | now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) | ||
1467 | msleep(1); | ||
1468 | |||
1469 | if (q->read_ptr != q->write_ptr) { | ||
1470 | IWL_ERR(trans, "fail to flush all tx fifo queues\n"); | ||
1471 | ret = -ETIMEDOUT; | ||
1472 | break; | ||
1473 | } | ||
1474 | } | ||
1475 | return ret; | ||
1476 | } | ||
1477 | |||
1449 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1478 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
1450 | /* create and remove of files */ | 1479 | /* create and remove of files */ |
1451 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ | 1480 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
@@ -2024,6 +2053,9 @@ const struct iwl_trans_ops trans_ops_pcie = { | |||
2024 | .free = iwl_trans_pcie_free, | 2053 | .free = iwl_trans_pcie_free, |
2025 | 2054 | ||
2026 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, | 2055 | .dbgfs_register = iwl_trans_pcie_dbgfs_register, |
2056 | |||
2057 | .wait_tx_queue_empty = iwl_trans_pcie_wait_tx_queue_empty, | ||
2058 | |||
2027 | .suspend = iwl_trans_pcie_suspend, | 2059 | .suspend = iwl_trans_pcie_suspend, |
2028 | .resume = iwl_trans_pcie_resume, | 2060 | .resume = iwl_trans_pcie_resume, |
2029 | }; | 2061 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index c92c9fed8fe..45d6dff47eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -101,6 +101,7 @@ struct iwl_device_cmd; | |||
101 | * @kick_nic: remove the RESET from the embedded CPU and let it run | 101 | * @kick_nic: remove the RESET from the embedded CPU and let it run |
102 | * @free: release all the ressource for the transport layer itself such as | 102 | * @free: release all the ressource for the transport layer itself such as |
103 | * irq, tasklet etc... | 103 | * irq, tasklet etc... |
104 | * @wait_tx_queue_empty: wait until all tx queues are empty | ||
104 | * @dbgfs_register: add the dbgfs files under this directory. Files will be | 105 | * @dbgfs_register: add the dbgfs files under this directory. Files will be |
105 | * automatically deleted. | 106 | * automatically deleted. |
106 | * @suspend: stop the device unless WoWLAN is configured | 107 | * @suspend: stop the device unless WoWLAN is configured |
@@ -142,6 +143,8 @@ struct iwl_trans_ops { | |||
142 | void (*free)(struct iwl_trans *trans); | 143 | void (*free)(struct iwl_trans *trans); |
143 | 144 | ||
144 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); | 145 | int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir); |
146 | int (*wait_tx_queue_empty)(struct iwl_trans *trans); | ||
147 | |||
145 | int (*suspend)(struct iwl_trans *trans); | 148 | int (*suspend)(struct iwl_trans *trans); |
146 | int (*resume)(struct iwl_trans *trans); | 149 | int (*resume)(struct iwl_trans *trans); |
147 | }; | 150 | }; |
@@ -251,6 +254,11 @@ static inline void iwl_trans_free(struct iwl_trans *trans) | |||
251 | trans->ops->free(trans); | 254 | trans->ops->free(trans); |
252 | } | 255 | } |
253 | 256 | ||
257 | static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans) | ||
258 | { | ||
259 | return trans->ops->wait_tx_queue_empty(trans); | ||
260 | } | ||
261 | |||
254 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, | 262 | static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, |
255 | struct dentry *dir) | 263 | struct dentry *dir) |
256 | { | 264 | { |