|
@@ -350,21 +350,15 @@ static int ath10k_htt_tx_alloc_txdone_fifo(struct ath10k_htt *htt)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
|
|
|
|
|
|
+static int ath10k_htt_tx_alloc_buf(struct ath10k_htt *htt)
|
|
{
|
|
{
|
|
struct ath10k *ar = htt->ar;
|
|
struct ath10k *ar = htt->ar;
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
- 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);
|
|
|
|
-
|
|
|
|
ret = ath10k_htt_tx_alloc_cont_txbuf(htt);
|
|
ret = ath10k_htt_tx_alloc_cont_txbuf(htt);
|
|
if (ret) {
|
|
if (ret) {
|
|
ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret);
|
|
ath10k_err(ar, "failed to alloc cont tx buffer: %d\n", ret);
|
|
- goto free_idr_pending_tx;
|
|
|
|
|
|
+ return ret;
|
|
}
|
|
}
|
|
|
|
|
|
ret = ath10k_htt_tx_alloc_cont_frag_desc(htt);
|
|
ret = ath10k_htt_tx_alloc_cont_frag_desc(htt);
|
|
@@ -396,6 +390,31 @@ free_frag_desc:
|
|
free_txbuf:
|
|
free_txbuf:
|
|
ath10k_htt_tx_free_cont_txbuf(htt);
|
|
ath10k_htt_tx_free_cont_txbuf(htt);
|
|
|
|
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int ath10k_htt_tx_start(struct ath10k_htt *htt)
|
|
|
|
+{
|
|
|
|
+ struct ath10k *ar = htt->ar;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ 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);
|
|
|
|
+
|
|
|
|
+ if (htt->tx_mem_allocated)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ ret = ath10k_htt_tx_alloc_buf(htt);
|
|
|
|
+ if (ret)
|
|
|
|
+ goto free_idr_pending_tx;
|
|
|
|
+
|
|
|
|
+ htt->tx_mem_allocated = true;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
free_idr_pending_tx:
|
|
free_idr_pending_tx:
|
|
idr_destroy(&htt->pending_tx);
|
|
idr_destroy(&htt->pending_tx);
|
|
|
|
|
|
@@ -418,15 +437,28 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void ath10k_htt_tx_free(struct ath10k_htt *htt)
|
|
|
|
|
|
+void ath10k_htt_tx_destroy(struct ath10k_htt *htt)
|
|
{
|
|
{
|
|
- idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
|
|
|
|
- idr_destroy(&htt->pending_tx);
|
|
|
|
|
|
+ if (!htt->tx_mem_allocated)
|
|
|
|
+ return;
|
|
|
|
|
|
ath10k_htt_tx_free_cont_txbuf(htt);
|
|
ath10k_htt_tx_free_cont_txbuf(htt);
|
|
ath10k_htt_tx_free_txq(htt);
|
|
ath10k_htt_tx_free_txq(htt);
|
|
ath10k_htt_tx_free_cont_frag_desc(htt);
|
|
ath10k_htt_tx_free_cont_frag_desc(htt);
|
|
ath10k_htt_tx_free_txdone_fifo(htt);
|
|
ath10k_htt_tx_free_txdone_fifo(htt);
|
|
|
|
+ htt->tx_mem_allocated = false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ath10k_htt_tx_stop(struct ath10k_htt *htt)
|
|
|
|
+{
|
|
|
|
+ idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
|
|
|
|
+ idr_destroy(&htt->pending_tx);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ath10k_htt_tx_free(struct ath10k_htt *htt)
|
|
|
|
+{
|
|
|
|
+ ath10k_htt_tx_stop(htt);
|
|
|
|
+ ath10k_htt_tx_destroy(htt);
|
|
}
|
|
}
|
|
|
|
|
|
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
|
|
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
|