diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7d8b4e2d5094..725f62fce7a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -56,6 +56,26 @@ static const u16 default_tid_to_tx_fifo[] = { | |||
56 | IWL_TX_FIFO_AC3 | 56 | IWL_TX_FIFO_AC3 |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, | ||
60 | struct iwl_dma_ptr *ptr, size_t size) | ||
61 | { | ||
62 | ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma); | ||
63 | if (!ptr->addr) | ||
64 | return -ENOMEM; | ||
65 | ptr->size = size; | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static inline void iwl_free_dma_ptr(struct iwl_priv *priv, | ||
70 | struct iwl_dma_ptr *ptr) | ||
71 | { | ||
72 | if (unlikely(!ptr->addr)) | ||
73 | return; | ||
74 | |||
75 | pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma); | ||
76 | memset(ptr, 0, sizeof(*ptr)); | ||
77 | } | ||
78 | |||
59 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 79 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) |
60 | { | 80 | { |
61 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | 81 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; |
@@ -517,8 +537,9 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) | |||
517 | else | 537 | else |
518 | iwl_tx_queue_free(priv, txq_id); | 538 | iwl_tx_queue_free(priv, txq_id); |
519 | 539 | ||
520 | /* Keep-warm buffer */ | 540 | iwl_free_dma_ptr(priv, &priv->kw); |
521 | iwl_kw_free(priv); | 541 | |
542 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
522 | } | 543 | } |
523 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 544 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); |
524 | 545 | ||
@@ -535,13 +556,17 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
535 | int txq_id, slots_num; | 556 | int txq_id, slots_num; |
536 | unsigned long flags; | 557 | unsigned long flags; |
537 | 558 | ||
538 | iwl_kw_free(priv); | ||
539 | |||
540 | /* Free all tx/cmd queues and keep-warm buffer */ | 559 | /* Free all tx/cmd queues and keep-warm buffer */ |
541 | iwl_hw_txq_ctx_free(priv); | 560 | iwl_hw_txq_ctx_free(priv); |
542 | 561 | ||
562 | ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, | ||
563 | priv->hw_params.scd_bc_tbls_size); | ||
564 | if (ret) { | ||
565 | IWL_ERROR("Scheduler BC Table allocation failed\n"); | ||
566 | goto error_bc_tbls; | ||
567 | } | ||
543 | /* Alloc keep-warm buffer */ | 568 | /* Alloc keep-warm buffer */ |
544 | ret = iwl_kw_alloc(priv); | 569 | ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); |
545 | if (ret) { | 570 | if (ret) { |
546 | IWL_ERROR("Keep Warm allocation failed\n"); | 571 | IWL_ERROR("Keep Warm allocation failed\n"); |
547 | goto error_kw; | 572 | goto error_kw; |
@@ -556,16 +581,13 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
556 | /* Turn off all Tx DMA fifos */ | 581 | /* Turn off all Tx DMA fifos */ |
557 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | 582 | priv->cfg->ops->lib->txq_set_sched(priv, 0); |
558 | 583 | ||
584 | /* Tell NIC where to find the "keep warm" buffer */ | ||
585 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
586 | |||
559 | iwl_release_nic_access(priv); | 587 | iwl_release_nic_access(priv); |
560 | spin_unlock_irqrestore(&priv->lock, flags); | 588 | spin_unlock_irqrestore(&priv->lock, flags); |
561 | 589 | ||
562 | 590 | ||
563 | /* Tell nic where to find the keep-warm buffer */ | ||
564 | ret = iwl_kw_init(priv); | ||
565 | if (ret) { | ||
566 | IWL_ERROR("kw_init failed\n"); | ||
567 | goto error_reset; | ||
568 | } | ||
569 | 591 | ||
570 | /* Alloc and init all Tx queues, including the command queue (#4) */ | 592 | /* Alloc and init all Tx queues, including the command queue (#4) */ |
571 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | 593 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { |
@@ -584,8 +606,10 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) | |||
584 | error: | 606 | error: |
585 | iwl_hw_txq_ctx_free(priv); | 607 | iwl_hw_txq_ctx_free(priv); |
586 | error_reset: | 608 | error_reset: |
587 | iwl_kw_free(priv); | 609 | iwl_free_dma_ptr(priv, &priv->kw); |
588 | error_kw: | 610 | error_kw: |
611 | iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); | ||
612 | error_bc_tbls: | ||
589 | return ret; | 613 | return ret; |
590 | } | 614 | } |
591 | 615 | ||