diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 59 |
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 | ******************************************************/ |
445 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
446 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
447 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int 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, | |||
456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int 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); |
460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
461 | int slots_num, u32 txq_id); | ||
459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
460 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
461 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int 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 | } |
434 | EXPORT_SYMBOL(iwl_tx_queue_init); | 434 | EXPORT_SYMBOL(iwl_tx_queue_init); |
435 | 435 | ||
436 | void 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 | } | ||
454 | EXPORT_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) | |||
461 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 480 | EXPORT_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 | */ |
470 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 489 | int 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 | ||
549 | void 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 | */ |
533 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 575 | void 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 | } |
555 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 594 | EXPORT_SYMBOL(iwl_txq_ctx_stop); |
556 | 595 | ||