aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-tx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c48
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
59static 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
69static 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
59static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) 79static 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}
523EXPORT_SYMBOL(iwl_hw_txq_ctx_free); 544EXPORT_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