aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-02-27 11:50:05 -0500
committerKalle Valo <kvalo@qca.qualcomm.com>2014-02-28 04:59:55 -0500
commit45967089d2685d2327c9710fe796d499d90ae844 (patch)
tree7600c8c437adc82454701f7a0991f4cfefbdea79
parent6c5151a9ffa9f796f2d707617cecb6b6b241dff8 (diff)
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: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c24
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c4
3 files changed, 23 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index b7150de984e7..8e708dfb63e3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -274,7 +274,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
274 int idx; 274 int idx;
275 struct sk_buff *msdu; 275 struct sk_buff *msdu;
276 276
277 spin_lock_bh(&htt->rx_ring.lock); 277 lockdep_assert_held(&htt->rx_ring.lock);
278 278
279 if (ath10k_htt_rx_ring_elems(htt) == 0) 279 if (ath10k_htt_rx_ring_elems(htt) == 0)
280 ath10k_warn("htt rx ring is empty!\n"); 280 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 htt->rx_ring.sw_rd_idx.msdu_payld = idx; 287 htt->rx_ring.sw_rd_idx.msdu_payld = idx;
288 htt->rx_ring.fill_cnt--; 288 htt->rx_ring.fill_cnt--;
289 289
290 spin_unlock_bh(&htt->rx_ring.lock);
291 return msdu; 290 return msdu;
292} 291}
293 292
@@ -311,6 +310,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
311 struct sk_buff *msdu; 310 struct sk_buff *msdu;
312 struct htt_rx_desc *rx_desc; 311 struct htt_rx_desc *rx_desc;
313 312
313 lockdep_assert_held(&htt->rx_ring.lock);
314
314 if (ath10k_htt_rx_ring_elems(htt) == 0) 315 if (ath10k_htt_rx_ring_elems(htt) == 0)
315 ath10k_warn("htt rx ring is empty!\n"); 316 ath10k_warn("htt rx ring is empty!\n");
316 317
@@ -918,6 +919,8 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
918 u8 *fw_desc; 919 u8 *fw_desc;
919 int i, j; 920 int i, j;
920 921
922 lockdep_assert_held(&htt->rx_ring.lock);
923
921 memset(&info, 0, sizeof(info)); 924 memset(&info, 0, sizeof(info));
922 925
923 fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes); 926 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 1058
1056 msdu_head = NULL; 1059 msdu_head = NULL;
1057 msdu_tail = NULL; 1060 msdu_tail = NULL;
1061
1062 spin_lock_bh(&htt->rx_ring.lock);
1058 msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len, 1063 msdu_chaining = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
1059 &msdu_head, &msdu_tail); 1064 &msdu_head, &msdu_tail);
1065 spin_unlock_bh(&htt->rx_ring.lock);
1060 1066
1061 ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); 1067 ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
1062 1068
@@ -1158,6 +1164,8 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
1158 __le16 msdu_id; 1164 __le16 msdu_id;
1159 int i; 1165 int i;
1160 1166
1167 lockdep_assert_held(&htt->tx_lock);
1168
1161 switch (status) { 1169 switch (status) {
1162 case HTT_DATA_TX_STATUS_NO_ACK: 1170 case HTT_DATA_TX_STATUS_NO_ACK:
1163 tx_done.no_ack = true; 1171 tx_done.no_ack = true;
@@ -1204,7 +1212,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
1204 break; 1212 break;
1205 } 1213 }
1206 case HTT_T2H_MSG_TYPE_RX_IND: 1214 case HTT_T2H_MSG_TYPE_RX_IND:
1207 skb_queue_tail(&htt->rx_compl_q, skb); 1215 spin_lock_bh(&htt->rx_ring.lock);
1216 __skb_queue_tail(&htt->rx_compl_q, skb);
1217 spin_unlock_bh(&htt->rx_ring.lock);
1208 tasklet_schedule(&htt->txrx_compl_task); 1218 tasklet_schedule(&htt->txrx_compl_task);
1209 return; 1219 return;
1210 case HTT_T2H_MSG_TYPE_PEER_MAP: { 1220 case HTT_T2H_MSG_TYPE_PEER_MAP: {
@@ -1298,14 +1308,18 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
1298 struct htt_resp *resp; 1308 struct htt_resp *resp;
1299 struct sk_buff *skb; 1309 struct sk_buff *skb;
1300 1310
1301 while ((skb = skb_dequeue(&htt->tx_compl_q))) { 1311 spin_lock_bh(&htt->tx_lock);
1312 while ((skb = __skb_dequeue(&htt->tx_compl_q))) {
1302 ath10k_htt_rx_frm_tx_compl(htt->ar, skb); 1313 ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
1303 dev_kfree_skb_any(skb); 1314 dev_kfree_skb_any(skb);
1304 } 1315 }
1316 spin_unlock_bh(&htt->tx_lock);
1305 1317
1306 while ((skb = skb_dequeue(&htt->rx_compl_q))) { 1318 spin_lock_bh(&htt->rx_ring.lock);
1319 while ((skb = __skb_dequeue(&htt->rx_compl_q))) {
1307 resp = (struct htt_resp *)skb->data; 1320 resp = (struct htt_resp *)skb->data;
1308 ath10k_htt_rx_handler(htt, &resp->rx_ind); 1321 ath10k_htt_rx_handler(htt, &resp->rx_ind);
1309 dev_kfree_skb_any(skb); 1322 dev_kfree_skb_any(skb);
1310 } 1323 }
1324 spin_unlock_bh(&htt->rx_ring.lock);
1311} 1325}
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 20b7a446a9f8..7a3e2e40dd5c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -125,9 +125,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
125 struct htt_tx_done tx_done = {0}; 125 struct htt_tx_done tx_done = {0};
126 int msdu_id; 126 int msdu_id;
127 127
128 /* No locks needed. Called after communication with the device has 128 spin_lock_bh(&htt->tx_lock);
129 * been stopped. */
130
131 for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) { 129 for (msdu_id = 0; msdu_id < htt->max_num_pending_tx; msdu_id++) {
132 if (!test_bit(msdu_id, htt->used_msdu_ids)) 130 if (!test_bit(msdu_id, htt->used_msdu_ids))
133 continue; 131 continue;
@@ -140,6 +138,7 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
140 138
141 ath10k_txrx_tx_unref(htt, &tx_done); 139 ath10k_txrx_tx_unref(htt, &tx_done);
142 } 140 }
141 spin_unlock_bh(&htt->tx_lock);
143} 142}
144 143
145void ath10k_htt_tx_detach(struct ath10k_htt *htt) 144void ath10k_htt_tx_detach(struct ath10k_htt *htt)
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 2993ca772c56..0541dd939ce9 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -52,6 +52,8 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
52 struct ath10k_skb_cb *skb_cb; 52 struct ath10k_skb_cb *skb_cb;
53 struct sk_buff *msdu; 53 struct sk_buff *msdu;
54 54
55 lockdep_assert_held(&htt->tx_lock);
56
55 ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", 57 ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n",
56 tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); 58 tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack);
57 59
@@ -91,13 +93,11 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
91 /* we do not own the msdu anymore */ 93 /* we do not own the msdu anymore */
92 94
93exit: 95exit:
94 spin_lock_bh(&htt->tx_lock);
95 htt->pending_tx[tx_done->msdu_id] = NULL; 96 htt->pending_tx[tx_done->msdu_id] = NULL;
96 ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); 97 ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
97 __ath10k_htt_tx_dec_pending(htt); 98 __ath10k_htt_tx_dec_pending(htt);
98 if (htt->num_pending_tx == 0) 99 if (htt->num_pending_tx == 0)
99 wake_up(&htt->empty_tx_wq); 100 wake_up(&htt->empty_tx_wq);
100 spin_unlock_bh(&htt->tx_lock);
101} 101}
102 102
103static const u8 rx_legacy_rate_idx[] = { 103static const u8 rx_legacy_rate_idx[] = {