aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c59
3 files changed, 60 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 112149e9b31e..894bcb8b8b37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -307,10 +307,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
307 307
308 spin_unlock_irqrestore(&priv->lock, flags); 308 spin_unlock_irqrestore(&priv->lock, flags);
309 309
310 /* Allocate and init all Tx and Command queues */ 310 /* Allocate or reset and init all Tx and Command queues */
311 ret = iwl_txq_ctx_reset(priv); 311 if (!priv->txq) {
312 if (ret) 312 ret = iwl_txq_ctx_alloc(priv);
313 return ret; 313 if (ret)
314 return ret;
315 } else
316 iwl_txq_ctx_reset(priv);
314 317
315 set_bit(STATUS_INIT, &priv->status); 318 set_bit(STATUS_INIT, &priv->status);
316 319
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4ef7739f9e8e..732590f5fe30 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
442/***************************************************** 442/*****************************************************
443* TX 443* TX
444******************************************************/ 444******************************************************/
445int iwl_txq_ctx_reset(struct iwl_priv *priv); 445int iwl_txq_ctx_alloc(struct iwl_priv *priv);
446void iwl_txq_ctx_reset(struct iwl_priv *priv);
446void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); 447void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
447int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, 448int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
448 struct iwl_tx_queue *txq, 449 struct iwl_tx_queue *txq,
@@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
456void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); 457void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
457int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, 458int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
458 int slots_num, u32 txq_id); 459 int slots_num, u32 txq_id);
460void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
461 int slots_num, u32 txq_id);
459void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); 462void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
460int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); 463int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
461int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); 464int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 6aa309032f4e..343d81ad2653 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -433,6 +433,26 @@ out_free_arrays:
433} 433}
434EXPORT_SYMBOL(iwl_tx_queue_init); 434EXPORT_SYMBOL(iwl_tx_queue_init);
435 435
436void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
437 int slots_num, u32 txq_id)
438{
439 int actual_slots = slots_num;
440
441 if (txq_id == IWL_CMD_QUEUE_NUM)
442 actual_slots++;
443
444 memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
445
446 txq->need_update = 0;
447
448 /* Initialize queue's high/low-water marks, and head/tail indexes */
449 iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
450
451 /* Tell device where to find queue */
452 priv->cfg->ops->lib->txq_init(priv, txq);
453}
454EXPORT_SYMBOL(iwl_tx_queue_reset);
455
436/** 456/**
437 * iwl_hw_txq_ctx_free - Free TXQ Context 457 * iwl_hw_txq_ctx_free - Free TXQ Context
438 * 458 *
@@ -444,8 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
444 464
445 /* Tx queues */ 465 /* Tx queues */
446 if (priv->txq) { 466 if (priv->txq) {
447 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; 467 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
448 txq_id++)
449 if (txq_id == IWL_CMD_QUEUE_NUM) 468 if (txq_id == IWL_CMD_QUEUE_NUM)
450 iwl_cmd_queue_free(priv); 469 iwl_cmd_queue_free(priv);
451 else 470 else
@@ -461,15 +480,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
461EXPORT_SYMBOL(iwl_hw_txq_ctx_free); 480EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
462 481
463/** 482/**
464 * iwl_txq_ctx_reset - Reset TX queue context 483 * iwl_txq_ctx_alloc - allocate TX queue context
465 * Destroys all DMA structures and initialize them again 484 * Allocate all Tx DMA structures and initialize them
466 * 485 *
467 * @param priv 486 * @param priv
468 * @return error code 487 * @return error code
469 */ 488 */
470int iwl_txq_ctx_reset(struct iwl_priv *priv) 489int iwl_txq_ctx_alloc(struct iwl_priv *priv)
471{ 490{
472 int ret = 0; 491 int ret;
473 int txq_id, slots_num; 492 int txq_id, slots_num;
474 unsigned long flags; 493 unsigned long flags;
475 494
@@ -527,8 +546,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
527 return ret; 546 return ret;
528} 547}
529 548
549void iwl_txq_ctx_reset(struct iwl_priv *priv)
550{
551 int txq_id, slots_num;
552 unsigned long flags;
553
554 spin_lock_irqsave(&priv->lock, flags);
555
556 /* Turn off all Tx DMA fifos */
557 priv->cfg->ops->lib->txq_set_sched(priv, 0);
558
559 /* Tell NIC where to find the "keep warm" buffer */
560 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
561
562 spin_unlock_irqrestore(&priv->lock, flags);
563
564 /* Alloc and init all Tx queues, including the command queue (#4) */
565 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
566 slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
567 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
568 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
569 }
570}
571
530/** 572/**
531 * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory 573 * iwl_txq_ctx_stop - Stop all Tx DMA channels
532 */ 574 */
533void iwl_txq_ctx_stop(struct iwl_priv *priv) 575void iwl_txq_ctx_stop(struct iwl_priv *priv)
534{ 576{
@@ -548,9 +590,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
548 1000); 590 1000);
549 } 591 }
550 spin_unlock_irqrestore(&priv->lock, flags); 592 spin_unlock_irqrestore(&priv->lock, flags);
551
552 /* Deallocate memory for all Tx queues */
553 iwl_hw_txq_ctx_free(priv);
554} 593}
555EXPORT_SYMBOL(iwl_txq_ctx_stop); 594EXPORT_SYMBOL(iwl_txq_ctx_stop);
556 595