aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2011-07-08 11:46:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-07-11 15:02:00 -0400
commit1359ca4f305a1680ea6a1347a43bea76c352097c (patch)
treebcd25bd2b13668ea5ed95c15a6bb5593bcac5362 /drivers
parentafaf6b5742f85bab46232faae97fdd1493061173 (diff)
iwlagn: add an API to free the TX context
Tx free functions move to the transport layer. Unify the functions that deal with tx queues and cmd queue. Since the CMD queue is not fully allocated, but uses the q->n_bd / q->window trick, the release flow of TX queue and CMD queue was different. iwlagn_txq_free_tfd receives now the index of the TFD to be freed, which allows to unify the release flow for all the queues. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c83
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c108
8 files changed, 95 insertions, 148 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index a87e95728b1d..c90c78a081dd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -852,31 +852,6 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
852} 852}
853 853
854/** 854/**
855 * iwlagn_hw_txq_ctx_free - Free TXQ Context
856 *
857 * Destroy all TX DMA queues and structures
858 */
859void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv)
860{
861 int txq_id;
862
863 /* Tx queues */
864 if (priv->txq) {
865 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
866 if (txq_id == priv->cmd_queue)
867 iwl_cmd_queue_free(priv);
868 else
869 iwl_tx_queue_free(priv, txq_id);
870 }
871 iwlagn_free_dma_ptr(priv, &priv->kw);
872
873 iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
874
875 /* free tx queue structure */
876 iwl_free_txq_mem(priv);
877}
878
879/**
880 * iwlagn_txq_ctx_stop - Stop all Tx DMA channels 855 * iwlagn_txq_ctx_stop - Stop all Tx DMA channels
881 */ 856 */
882void iwlagn_txq_ctx_stop(struct iwl_priv *priv) 857void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
@@ -906,10 +881,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
906 881
907 /* Unmap DMA from host system and free skb's */ 882 /* Unmap DMA from host system and free skb's */
908 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) 883 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
909 if (txq_id == priv->cmd_queue) 884 iwl_tx_queue_unmap(priv, txq_id);
910 iwl_cmd_queue_unmap(priv);
911 else
912 iwl_tx_queue_unmap(priv, txq_id);
913} 885}
914 886
915/* 887/*
@@ -1170,7 +1142,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
1170 1142
1171 iwlagn_txq_inval_byte_cnt_tbl(priv, txq); 1143 iwlagn_txq_inval_byte_cnt_tbl(priv, txq);
1172 1144
1173 iwlagn_txq_free_tfd(priv, txq); 1145 iwlagn_txq_free_tfd(priv, txq, txq->q.read_ptr);
1174 } 1146 }
1175 return nfreed; 1147 return nfreed;
1176} 1148}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 7e6c463abbdf..4d5b7cc33946 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3710,7 +3710,7 @@ void __devexit iwl_remove(struct iwl_priv * priv)
3710 iwl_dealloc_ucode(priv); 3710 iwl_dealloc_ucode(priv);
3711 3711
3712 priv->trans.ops->rx_free(priv); 3712 priv->trans.ops->rx_free(priv);
3713 iwlagn_hw_txq_ctx_free(priv); 3713 priv->trans.ops->tx_free(priv);
3714 3714
3715 iwl_eeprom_free(priv); 3715 iwl_eeprom_free(priv);
3716 3716
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 4351151e2a91..fabab0ff5577 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -198,7 +198,8 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
198void iwl_setup_rx_handlers(struct iwl_priv *priv); 198void iwl_setup_rx_handlers(struct iwl_priv *priv);
199 199
200/* tx */ 200/* tx */
201void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); 201void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
202 int index);
202int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, 203int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv,
203 struct iwl_tx_queue *txq, 204 struct iwl_tx_queue *txq,
204 dma_addr_t addr, u16 len, u8 reset); 205 dma_addr_t addr, u16 len, u8 reset);
@@ -217,7 +218,6 @@ int iwlagn_txq_check_empty(struct iwl_priv *priv,
217void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, 218void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
218 struct iwl_rx_mem_buffer *rxb); 219 struct iwl_rx_mem_buffer *rxb);
219int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); 220int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
220void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv);
221void iwlagn_txq_ctx_stop(struct iwl_priv *priv); 221void iwlagn_txq_ctx_stop(struct iwl_priv *priv);
222 222
223static inline u32 iwl_tx_status_to_mac80211(u32 status) 223static inline u32 iwl_tx_status_to_mac80211(u32 status)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index f91e306c2498..9bf46864f0d1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1370,12 +1370,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
1370 1370
1371} 1371}
1372 1372
1373void iwl_free_txq_mem(struct iwl_priv *priv)
1374{
1375 kfree(priv->txq);
1376 priv->txq = NULL;
1377}
1378
1379#ifdef CONFIG_IWLWIFI_DEBUGFS 1373#ifdef CONFIG_IWLWIFI_DEBUGFS
1380 1374
1381#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) 1375#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 6c21de9f5b60..7d8be6b26acd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -328,8 +328,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
328int iwl_mac_change_interface(struct ieee80211_hw *hw, 328int iwl_mac_change_interface(struct ieee80211_hw *hw,
329 struct ieee80211_vif *vif, 329 struct ieee80211_vif *vif,
330 enum nl80211_iftype newtype, bool newp2p); 330 enum nl80211_iftype newtype, bool newp2p);
331void iwl_free_txq_mem(struct iwl_priv *priv);
332
333#ifdef CONFIG_IWLWIFI_DEBUGFS 331#ifdef CONFIG_IWLWIFI_DEBUGFS
334int iwl_alloc_traffic_mem(struct iwl_priv *priv); 332int iwl_alloc_traffic_mem(struct iwl_priv *priv);
335void iwl_free_traffic_mem(struct iwl_priv *priv); 333void iwl_free_traffic_mem(struct iwl_priv *priv);
@@ -371,8 +369,6 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
371/***************************************************** 369/*****************************************************
372* RX 370* RX
373******************************************************/ 371******************************************************/
374void iwl_cmd_queue_free(struct iwl_priv *priv);
375void iwl_cmd_queue_unmap(struct iwl_priv *priv);
376void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, 372void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
377 struct iwl_rx_queue *q); 373 struct iwl_rx_queue *q);
378int iwl_rx_queue_space(const struct iwl_rx_queue *q); 374int iwl_rx_queue_space(const struct iwl_rx_queue *q);
@@ -386,7 +382,6 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
386* TX 382* TX
387******************************************************/ 383******************************************************/
388void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); 384void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
389void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
390int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, 385int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
391 int count, int slots_num, u32 id); 386 int count, int slots_num, u32 id);
392void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); 387void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index e429e32f748e..a29fdd43a9f3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1233,11 +1233,14 @@ struct iwl_trans;
1233 * @rx_init: inits the rx memory, allocate it if needed 1233 * @rx_init: inits the rx memory, allocate it if needed
1234 * @rx_free: frees the rx memory 1234 * @rx_free: frees the rx memory
1235 * @tx_init:inits the tx memory, allocate if needed 1235 * @tx_init:inits the tx memory, allocate if needed
1236 * @tx_free: frees the tx memory
1236 */ 1237 */
1237struct iwl_trans_ops { 1238struct iwl_trans_ops {
1238 int (*rx_init)(struct iwl_priv *priv); 1239 int (*rx_init)(struct iwl_priv *priv);
1239 void (*rx_free)(struct iwl_priv *priv); 1240 void (*rx_free)(struct iwl_priv *priv);
1241
1240 int (*tx_init)(struct iwl_priv *priv); 1242 int (*tx_init)(struct iwl_priv *priv);
1243 void (*tx_free)(struct iwl_priv *priv);
1241}; 1244};
1242 1245
1243struct iwl_trans { 1246struct iwl_trans {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 7b7b97d8c2e1..38b43e41d561 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -203,6 +203,16 @@ static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
203 return 0; 203 return 0;
204} 204}
205 205
206static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
207 struct iwl_dma_ptr *ptr)
208{
209 if (unlikely(!ptr->addr))
210 return;
211
212 dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma);
213 memset(ptr, 0, sizeof(*ptr));
214}
215
206static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq, 216static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
207 int slots_num, u32 txq_id) 217 int slots_num, u32 txq_id)
208{ 218{
@@ -212,6 +222,8 @@ static int iwl_trans_txq_alloc(struct iwl_priv *priv, struct iwl_tx_queue *txq,
212 if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds)) 222 if (WARN_ON(txq->meta || txq->cmd || txq->txb || txq->tfds))
213 return -EINVAL; 223 return -EINVAL;
214 224
225 txq->q.n_window = slots_num;
226
215 txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num, 227 txq->meta = kzalloc(sizeof(txq->meta[0]) * slots_num,
216 GFP_KERNEL); 228 GFP_KERNEL);
217 txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num, 229 txq->cmd = kzalloc(sizeof(txq->cmd[0]) * slots_num,
@@ -307,6 +319,72 @@ static int iwl_trans_txq_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
307} 319}
308 320
309/** 321/**
322 * iwl_tx_queue_free - Deallocate DMA queue.
323 * @txq: Transmit queue to deallocate.
324 *
325 * Empty queue by removing and destroying all BD's.
326 * Free all buffers.
327 * 0-fill, but do not free "txq" descriptor structure.
328 */
329static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
330{
331 struct iwl_tx_queue *txq = &priv->txq[txq_id];
332 struct device *dev = priv->bus.dev;
333 int i;
334 if (WARN_ON(!txq))
335 return;
336
337 iwl_tx_queue_unmap(priv, txq_id);
338
339 /* De-alloc array of command/tx buffers */
340 for (i = 0; i < txq->q.n_window; i++)
341 kfree(txq->cmd[i]);
342
343 /* De-alloc circular buffer of TFDs */
344 if (txq->q.n_bd) {
345 dma_free_coherent(dev, priv->hw_params.tfd_size *
346 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
347 memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
348 }
349
350 /* De-alloc array of per-TFD driver data */
351 kfree(txq->txb);
352 txq->txb = NULL;
353
354 /* deallocate arrays */
355 kfree(txq->cmd);
356 kfree(txq->meta);
357 txq->cmd = NULL;
358 txq->meta = NULL;
359
360 /* 0-fill queue descriptor structure */
361 memset(txq, 0, sizeof(*txq));
362}
363
364/**
365 * iwl_trans_tx_free - Free TXQ Context
366 *
367 * Destroy all TX DMA queues and structures
368 */
369static void iwl_trans_tx_free(struct iwl_priv *priv)
370{
371 int txq_id;
372
373 /* Tx queues */
374 if (priv->txq) {
375 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
376 iwl_tx_queue_free(priv, txq_id);
377 }
378
379 kfree(priv->txq);
380 priv->txq = NULL;
381
382 iwlagn_free_dma_ptr(priv, &priv->kw);
383
384 iwlagn_free_dma_ptr(priv, &priv->scd_bc_tbls);
385}
386
387/**
310 * iwl_trans_tx_alloc - allocate TX context 388 * iwl_trans_tx_alloc - allocate TX context
311 * Allocate all Tx DMA structures and initialize them 389 * Allocate all Tx DMA structures and initialize them
312 * 390 *
@@ -362,7 +440,7 @@ static int iwl_trans_tx_alloc(struct iwl_priv *priv)
362 return 0; 440 return 0;
363 441
364error: 442error:
365 iwlagn_hw_txq_ctx_free(priv); 443 priv->trans.ops->tx_free(priv);
366 444
367 return ret; 445 return ret;
368} 446}
@@ -406,7 +484,7 @@ static int iwl_trans_tx_init(struct iwl_priv *priv)
406error: 484error:
407 /*Upon error, free only if we allocated something */ 485 /*Upon error, free only if we allocated something */
408 if (alloc) 486 if (alloc)
409 iwlagn_hw_txq_ctx_free(priv); 487 priv->trans.ops->tx_free(priv);
410 return ret; 488 return ret;
411} 489}
412 490
@@ -415,6 +493,7 @@ static const struct iwl_trans_ops trans_ops = {
415 .rx_free = iwl_trans_rx_free, 493 .rx_free = iwl_trans_rx_free,
416 494
417 .tx_init = iwl_trans_tx_init, 495 .tx_init = iwl_trans_tx_init,
496 .tx_free = iwl_trans_tx_free,
418}; 497};
419 498
420void iwl_trans_register(struct iwl_trans *trans) 499void iwl_trans_register(struct iwl_trans *trans)
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index dc8f63f81cfa..36b643a385be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -157,14 +157,15 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
157 * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] 157 * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
158 * @priv - driver private data 158 * @priv - driver private data
159 * @txq - tx queue 159 * @txq - tx queue
160 * @index - the index of the TFD to be freed
160 * 161 *
161 * Does NOT advance any TFD circular buffer read/write indexes 162 * Does NOT advance any TFD circular buffer read/write indexes
162 * Does NOT free the TFD itself (which is within circular buffer) 163 * Does NOT free the TFD itself (which is within circular buffer)
163 */ 164 */
164void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) 165void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq,
166 int index)
165{ 167{
166 struct iwl_tfd *tfd_tmp = txq->tfds; 168 struct iwl_tfd *tfd_tmp = txq->tfds;
167 int index = txq->q.read_ptr;
168 169
169 iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index], 170 iwlagn_unmap_tfd(priv, &txq->meta[index], &tfd_tmp[index],
170 DMA_TO_DEVICE); 171 DMA_TO_DEVICE);
@@ -173,12 +174,12 @@ void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
173 if (txq->txb) { 174 if (txq->txb) {
174 struct sk_buff *skb; 175 struct sk_buff *skb;
175 176
176 skb = txq->txb[txq->q.read_ptr].skb; 177 skb = txq->txb[index].skb;
177 178
178 /* can be called from irqs-disabled context */ 179 /* can be called from irqs-disabled context */
179 if (skb) { 180 if (skb) {
180 dev_kfree_skb_any(skb); 181 dev_kfree_skb_any(skb);
181 txq->txb[txq->q.read_ptr].skb = NULL; 182 txq->txb[index].skb = NULL;
182 } 183 }
183 } 184 }
184} 185}
@@ -232,108 +233,11 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
232 return; 233 return;
233 234
234 while (q->write_ptr != q->read_ptr) { 235 while (q->write_ptr != q->read_ptr) {
235 iwlagn_txq_free_tfd(priv, txq); 236 iwlagn_txq_free_tfd(priv, txq, get_cmd_index(q, q->read_ptr));
236 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); 237 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
237 } 238 }
238} 239}
239 240
240/**
241 * iwl_tx_queue_free - Deallocate DMA queue.
242 * @txq: Transmit queue to deallocate.
243 *
244 * Empty queue by removing and destroying all BD's.
245 * Free all buffers.
246 * 0-fill, but do not free "txq" descriptor structure.
247 */
248void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
249{
250 struct iwl_tx_queue *txq = &priv->txq[txq_id];
251 struct device *dev = priv->bus.dev;
252 int i;
253
254 iwl_tx_queue_unmap(priv, txq_id);
255
256 /* De-alloc array of command/tx buffers */
257 for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
258 kfree(txq->cmd[i]);
259
260 /* De-alloc circular buffer of TFDs */
261 if (txq->q.n_bd)
262 dma_free_coherent(dev, priv->hw_params.tfd_size *
263 txq->q.n_bd, txq->tfds, txq->q.dma_addr);
264
265 /* De-alloc array of per-TFD driver data */
266 kfree(txq->txb);
267 txq->txb = NULL;
268
269 /* deallocate arrays */
270 kfree(txq->cmd);
271 kfree(txq->meta);
272 txq->cmd = NULL;
273 txq->meta = NULL;
274
275 /* 0-fill queue descriptor structure */
276 memset(txq, 0, sizeof(*txq));
277}
278
279/**
280 * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
281 */
282void iwl_cmd_queue_unmap(struct iwl_priv *priv)
283{
284 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
285 struct iwl_queue *q = &txq->q;
286 int i;
287
288 if (q->n_bd == 0)
289 return;
290
291 while (q->read_ptr != q->write_ptr) {
292 i = get_cmd_index(q, q->read_ptr);
293
294 iwlagn_unmap_tfd(priv, &txq->meta[i], &txq->tfds[i],
295 DMA_BIDIRECTIONAL);
296 txq->meta[i].flags = 0;
297
298 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
299 }
300}
301
302/**
303 * iwl_cmd_queue_free - Deallocate DMA queue.
304 * @txq: Transmit queue to deallocate.
305 *
306 * Empty queue by removing and destroying all BD's.
307 * Free all buffers.
308 * 0-fill, but do not free "txq" descriptor structure.
309 */
310void iwl_cmd_queue_free(struct iwl_priv *priv)
311{
312 struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
313 struct device *dev = priv->bus.dev;
314 int i;
315
316 iwl_cmd_queue_unmap(priv);
317
318 /* De-alloc array of command/tx buffers */
319 for (i = 0; i < TFD_CMD_SLOTS; i++)
320 kfree(txq->cmd[i]);
321
322 /* De-alloc circular buffer of TFDs */
323 if (txq->q.n_bd)
324 dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
325 txq->tfds, txq->q.dma_addr);
326
327 /* deallocate arrays */
328 kfree(txq->cmd);
329 kfree(txq->meta);
330 txq->cmd = NULL;
331 txq->meta = NULL;
332
333 /* 0-fill queue descriptor structure */
334 memset(txq, 0, sizeof(*txq));
335}
336
337/*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** 241/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
338 * DMA services 242 * DMA services
339 * 243 *