aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c33
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h8
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
639int 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));
719done: 688done:
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));
2837done: 2837done:
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);
102int iwlagn_send_tx_power(struct iwl_priv *priv); 102int iwlagn_send_tx_power(struct iwl_priv *priv);
103void iwlagn_temperature(struct iwl_priv *priv); 103void iwlagn_temperature(struct iwl_priv *priv);
104u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv); 104u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv);
105int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv);
106int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); 105int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
107void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); 106void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control);
108int iwlagn_send_beacon_cmd(struct iwl_priv *priv); 107int 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
1451static 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
257static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
258{
259 return trans->ops->wait_tx_queue_empty(trans);
260}
261
254static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans, 262static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
255 struct dentry *dir) 263 struct dentry *dir)
256{ 264{