aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c71
3 files changed, 59 insertions, 26 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 266490d8a39..a709d05c586 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -947,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv)
947 */ 947 */
948void iwlagn_txq_ctx_stop(struct iwl_priv *priv) 948void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
949{ 949{
950 int ch; 950 int ch, txq_id;
951 unsigned long flags; 951 unsigned long flags;
952 952
953 /* Turn off all Tx DMA fifos */ 953 /* Turn off all Tx DMA fifos */
@@ -966,6 +966,16 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
966 iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); 966 iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
967 } 967 }
968 spin_unlock_irqrestore(&priv->lock, flags); 968 spin_unlock_irqrestore(&priv->lock, flags);
969
970 if (!priv->txq)
971 return;
972
973 /* Unmap DMA from host system and free skb's */
974 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
975 if (txq_id == priv->cmd_queue)
976 iwl_cmd_queue_unmap(priv);
977 else
978 iwl_tx_queue_unmap(priv, txq_id);
969} 979}
970 980
971/* 981/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 909b42d5d9c..ce368d8d402 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -510,6 +510,7 @@ void iwl_rx_reply_error(struct iwl_priv *priv,
510* RX 510* RX
511******************************************************/ 511******************************************************/
512void iwl_cmd_queue_free(struct iwl_priv *priv); 512void iwl_cmd_queue_free(struct iwl_priv *priv);
513void iwl_cmd_queue_unmap(struct iwl_priv *priv);
513int iwl_rx_queue_alloc(struct iwl_priv *priv); 514int iwl_rx_queue_alloc(struct iwl_priv *priv);
514void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, 515void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
515 struct iwl_rx_queue *q); 516 struct iwl_rx_queue *q);
@@ -534,6 +535,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
534void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, 535void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
535 int slots_num, u32 txq_id); 536 int slots_num, u32 txq_id);
536void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); 537void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
538void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
537void iwl_setup_watchdog(struct iwl_priv *priv); 539void iwl_setup_watchdog(struct iwl_priv *priv);
538/***************************************************** 540/*****************************************************
539 * TX power 541 * TX power
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 7e607d39da1..277c9175dcf 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -86,6 +86,23 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
86} 86}
87 87
88/** 88/**
89 * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's
90 */
91void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
92{
93 struct iwl_tx_queue *txq = &priv->txq[txq_id];
94 struct iwl_queue *q = &txq->q;
95
96 if (q->n_bd == 0)
97 return;
98
99 while (q->write_ptr != q->read_ptr) {
100 priv->cfg->ops->lib->txq_free_tfd(priv, txq);
101 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
102 }
103}
104
105/**
89 * iwl_tx_queue_free - Deallocate DMA queue. 106 * iwl_tx_queue_free - Deallocate DMA queue.
90 * @txq: Transmit queue to deallocate. 107 * @txq: Transmit queue to deallocate.
91 * 108 *
@@ -96,17 +113,10 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
96void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) 113void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
97{ 114{
98 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 115 struct iwl_tx_queue *txq = &priv->txq[txq_id];
99 struct iwl_queue *q = &txq->q;
100 struct device *dev = &priv->pci_dev->dev; 116 struct device *dev = &priv->pci_dev->dev;
101 int i; 117 int i;
102 118
103 if (q->n_bd == 0) 119 iwl_tx_queue_unmap(priv, txq_id);
104 return;
105
106 /* first, empty all BD's */
107 for (; q->write_ptr != q->read_ptr;
108 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
109 priv->cfg->ops->lib->txq_free_tfd(priv, txq);
110 120
111 /* De-alloc array of command/tx buffers */ 121 /* De-alloc array of command/tx buffers */
112 for (i = 0; i < TFD_TX_CMD_SLOTS; i++) 122 for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -132,39 +142,33 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
132} 142}
133 143
134/** 144/**
135 * iwl_cmd_queue_free - Deallocate DMA queue. 145 * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
136 * @txq: Transmit queue to deallocate.
137 *
138 * Empty queue by removing and destroying all BD's.
139 * Free all buffers.
140 * 0-fill, but do not free "txq" descriptor structure.
141 */ 146 */
142void iwl_cmd_queue_free(struct iwl_priv *priv) 147void iwl_cmd_queue_unmap(struct iwl_priv *priv)
143{ 148{
144 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; 149 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
145 struct iwl_queue *q = &txq->q; 150 struct iwl_queue *q = &txq->q;
146 struct device *dev = &priv->pci_dev->dev;
147 int i; 151 int i;
148 bool huge = false; 152 bool huge = false;
149 153
150 if (q->n_bd == 0) 154 if (q->n_bd == 0)
151 return; 155 return;
152 156
153 for (; q->read_ptr != q->write_ptr; 157 while (q->read_ptr != q->write_ptr) {
154 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
155 /* we have no way to tell if it is a huge cmd ATM */ 158 /* we have no way to tell if it is a huge cmd ATM */
156 i = get_cmd_index(q, q->read_ptr, 0); 159 i = get_cmd_index(q, q->read_ptr, 0);
157 160
158 if (txq->meta[i].flags & CMD_SIZE_HUGE) { 161 if (txq->meta[i].flags & CMD_SIZE_HUGE)
159 huge = true; 162 huge = true;
160 continue; 163 else
161 } 164 pci_unmap_single(priv->pci_dev,
165 dma_unmap_addr(&txq->meta[i], mapping),
166 dma_unmap_len(&txq->meta[i], len),
167 PCI_DMA_BIDIRECTIONAL);
162 168
163 pci_unmap_single(priv->pci_dev, 169 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
164 dma_unmap_addr(&txq->meta[i], mapping),
165 dma_unmap_len(&txq->meta[i], len),
166 PCI_DMA_BIDIRECTIONAL);
167 } 170 }
171
168 if (huge) { 172 if (huge) {
169 i = q->n_window; 173 i = q->n_window;
170 pci_unmap_single(priv->pci_dev, 174 pci_unmap_single(priv->pci_dev,
@@ -172,6 +176,23 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
172 dma_unmap_len(&txq->meta[i], len), 176 dma_unmap_len(&txq->meta[i], len),
173 PCI_DMA_BIDIRECTIONAL); 177 PCI_DMA_BIDIRECTIONAL);
174 } 178 }
179}
180
181/**
182 * iwl_cmd_queue_free - Deallocate DMA queue.
183 * @txq: Transmit queue to deallocate.
184 *
185 * Empty queue by removing and destroying all BD's.
186 * Free all buffers.
187 * 0-fill, but do not free "txq" descriptor structure.
188 */
189void iwl_cmd_queue_free(struct iwl_priv *priv)
190{
191 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
192 struct device *dev = &priv->pci_dev->dev;
193 int i;
194
195 iwl_cmd_queue_unmap(priv);
175 196
176 /* De-alloc array of command/tx buffers */ 197 /* De-alloc array of command/tx buffers */
177 for (i = 0; i <= TFD_CMD_SLOTS; i++) 198 for (i = 0; i <= TFD_CMD_SLOTS; i++)