Commit 45967089 authored by Michal Kazior's avatar Michal Kazior Committed by Kalle Valo

ath10k: reduce htt tx/rx spinlock overhead

It is inefficient to grab irqsave spinlocks for
skb lists for each queue/dequeue action.

Using rx_ring.lock and tx_lock allows to use less
heavy bh spinlock functions and moving locking
upwards allows to toggle spinlocks less often.
Signed-off-by: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 6c5151a9
...@@ -274,7 +274,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) ...@@ -274,7 +274,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
int idx; int idx;
struct sk_buff *msdu; struct sk_buff *msdu;
spin_lock_bh(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
if (ath10k_htt_rx_ring_elems(htt) == 0) if (ath10k_htt_rx_ring_elems(htt) == 0)
ath10k_warn("htt rx ring is empty!\n"); ath10k_warn("htt rx ring is empty!\n");
...@@ -287,7 +287,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) ...@@ -287,7 +287,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
htt->rx_ring.sw_rd_idx.msdu_payld = idx; htt->rx_ring.sw_rd_idx.msdu_payld = idx;
htt->rx_ring.fill_cnt--; htt->rx_ring.fill_cnt--;
spin_unlock_bh(&htt->rx_ring.lock);
return msdu; return msdu;
} }
...@@ -311,6 +310,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -311,6 +310,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
struct sk_buff *msdu; struct sk_buff *msdu;
struct htt_rx_desc *rx_desc; struct htt_rx_desc *rx_desc;
lockdep_assert_held(&htt->rx_ring.lock);
if (ath10k_htt_rx_ring_elems(htt) == 0) if (ath10k_htt_rx_ring_elems(htt) == 0)
ath10k_warn("htt rx ring is empty!\n"); ath10k_warn("htt rx ring is empty!\n");
...@@ -918,6 +919,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -918,6 +919,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
u8 *fw_desc; u8 *fw_desc;
int i, j; int i, j;
lockdep_assert_held(&htt->rx_ring.lock);
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes);
...@@ -1055,8 +1058,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1055,8 +1058,11 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
msdu_head = NULL; msdu_head = NULL;
msdu_tail = NULL; msdu_tail = NULL;
spin_lock_bh(&htt->rx_ring.lock);
msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
&msdu_head, &msdu_tail); &msdu_head, &msdu_tail);
spin_unlock_bh(&htt->rx_ring.lock);
ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
...@@ -1158,6 +1164,8 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, ...@@ -1158,6 +1164,8 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
__le16 msdu_id; __le16 msdu_id;
int i; int i;
lockdep_assert_held(&htt->tx_lock);
switch (status) { switch (status) {
case HTT_DATA_TX_STATUS_NO_ACK: case HTT_DATA_TX_STATUS_NO_ACK:
tx_done.no_ack = true; tx_done.no_ack = true;
...@@ -1204,7 +1212,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1204,7 +1212,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break; break;
} }
case HTT_T2H_MSG_TYPE_RX_IND: case HTT_T2H_MSG_TYPE_RX_IND:
skb_queue_tail(&htt->rx_compl_q, skb); spin_lock_bh(&htt->rx_ring.lock);
__skb_queue_tail(&htt->rx_compl_q, skb);
spin_unlock_bh(&htt->rx_ring.lock);
tasklet_schedule(&htt->txrx_compl_task); tasklet_schedule(&htt->txrx_compl_task);
return; return;
case HTT_T2H_MSG_TYPE_PEER_MAP: { case HTT_T2H_MSG_TYPE_PEER_MAP: {
...@@ -1298,14 +1308,18 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr) ...@@ -1298,14 +1308,18 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
struct htt_resp *resp; struct htt_resp *resp;
struct sk_buff *skb; struct sk_buff *skb;
while ((skb = skb_dequeue(&htt->tx_compl_q))) { spin_lock_bh(&htt->tx_lock);
while ((skb = __skb_dequeue(&htt->tx_compl_q))) {
ath10k_htt_rx_frm_tx_compl(htt->ar, skb); ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} }
spin_unlock_bh(&htt->tx_lock);
while ((skb = skb_dequeue(&htt->rx_compl_q))) { spin_lock_bh(&htt->rx_ring.lock);
while ((skb = __skb_dequeue(&htt->rx_compl_q))) {
resp = (struct htt_resp *)skb->data; resp = (struct htt_resp *)skb->data;
ath10k_htt_rx_handler(htt, &resp->rx_ind); ath10k_htt_rx_handler(htt, &resp->rx_ind);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
} }
spin_unlock_bh(&htt->rx_ring.lock);
} }
...@@ -125,9 +125,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) ...@@ -125,9 +125,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
struct htt_tx_done tx_done = {0}; struct htt_tx_done tx_done = {0};
int msdu_id; int msdu_id;
/* No locks needed. Called after communication with the device has spin_lock_bh(&htt->tx_lock);
* been stopped. */
for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) {
if (!test_bit(msdu_id, htt->used_msdu_ids)) if (!test_bit(msdu_id, htt->used_msdu_ids))
continue; continue;
...@@ -140,6 +138,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt) ...@@ -140,6 +138,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
ath10k_txrx_tx_unref(htt, &tx_done); ath10k_txrx_tx_unref(htt, &tx_done);
} }
spin_unlock_bh(&htt->tx_lock);
} }
void ath10k_htt_tx_detach(struct ath10k_htt *htt) void ath10k_htt_tx_detach(struct ath10k_htt *htt)
......
...@@ -52,6 +52,8 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -52,6 +52,8 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu; struct sk_buff *msdu;
lockdep_assert_held(&htt->tx_lock);
ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n",
tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack);
...@@ -91,13 +93,11 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -91,13 +93,11 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
/* we do not own the msdu anymore */ /* we do not own the msdu anymore */
exit: exit:
spin_lock_bh(&htt->tx_lock);
htt->pending_tx[tx_done->msdu_id] = NULL; htt->pending_tx[tx_done->msdu_id] = NULL;
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
__ath10k_htt_tx_dec_pending(htt); __ath10k_htt_tx_dec_pending(htt);
if (htt->num_pending_tx == 0) if (htt->num_pending_tx == 0)
wake_up(&htt->empty_tx_wq); wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
} }
static const u8 rx_legacy_rate_idx[] = { static const u8 rx_legacy_rate_idx[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment