int ath10k_htt_tx_alloc(struct ath10k_htt *htt) { struct ath10k *ar = htt->ar; int ret, size; ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", htt->max_num_pending_tx); spin_lock_init(&htt->tx_lock); idr_init(&htt->pending_tx); size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size, &htt->txbuf.paddr, GFP_KERNEL); if (!htt->txbuf.vaddr) { ath10k_err(ar, "failed to alloc tx buffer\n"); ret = -ENOMEM; goto free_idr_pending_tx; } ret = ath10k_htt_tx_alloc_cont_frag_desc(htt); if (ret) { ath10k_err(ar, "failed to alloc cont frag desc: %d\n", ret); goto free_txbuf; } ret = ath10k_htt_tx_alloc_txq(htt); if (ret) { ath10k_err(ar, "failed to alloc txq: %d\n", ret); goto free_frag_desc; } size = roundup_pow_of_two(htt->max_num_pending_tx); ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL); if (ret) { ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret); goto free_txq; } return 0; free_txq: ath10k_htt_tx_free_txq(htt); free_frag_desc: ath10k_htt_tx_free_cont_frag_desc(htt); free_txbuf: size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); free_idr_pending_tx: idr_destroy(&htt->pending_tx); return ret; }
void ath10k_htt_tx_free(struct ath10k_htt *htt) { int size; idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); idr_destroy(&htt->pending_tx); if (htt->txbuf.vaddr) { size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); } ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_cont_frag_desc(htt); }
void ath10k_htt_tx_free(struct ath10k_htt *htt) { int size; tasklet_kill(&htt->txrx_compl_task); idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); idr_destroy(&htt->pending_tx); if (htt->txbuf.vaddr) { size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); dma_free_coherent(htt->ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr); } ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_cont_frag_desc(htt); WARN_ON(!kfifo_is_empty(&htt->txdone_fifo)); kfifo_free(&htt->txdone_fifo); }