1 | // SPDX-License-Identifier: BSD-3-Clause-Clear |
2 | /* |
3 | * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. |
4 | * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. |
5 | */ |
6 | |
7 | #include "core.h" |
8 | #include "dp_tx.h" |
9 | #include "debug.h" |
10 | #include "hw.h" |
11 | |
12 | static enum hal_tcl_encap_type |
13 | ath12k_dp_tx_get_encap_type(struct ath12k_vif *arvif, struct sk_buff *skb) |
14 | { |
15 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
16 | struct ath12k_base *ab = arvif->ar->ab; |
17 | |
18 | if (test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) |
19 | return HAL_TCL_ENCAP_TYPE_RAW; |
20 | |
21 | if (tx_info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) |
22 | return HAL_TCL_ENCAP_TYPE_ETHERNET; |
23 | |
24 | return HAL_TCL_ENCAP_TYPE_NATIVE_WIFI; |
25 | } |
26 | |
27 | static void ath12k_dp_tx_encap_nwifi(struct sk_buff *skb) |
28 | { |
29 | struct ieee80211_hdr *hdr = (void *)skb->data; |
30 | u8 *qos_ctl; |
31 | |
32 | if (!ieee80211_is_data_qos(fc: hdr->frame_control)) |
33 | return; |
34 | |
35 | qos_ctl = ieee80211_get_qos_ctl(hdr); |
36 | memmove(skb->data + IEEE80211_QOS_CTL_LEN, |
37 | skb->data, (void *)qos_ctl - (void *)skb->data); |
38 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
39 | |
40 | hdr = (void *)skb->data; |
41 | hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
42 | } |
43 | |
44 | static u8 ath12k_dp_tx_get_tid(struct sk_buff *skb) |
45 | { |
46 | struct ieee80211_hdr *hdr = (void *)skb->data; |
47 | struct ath12k_skb_cb *cb = ATH12K_SKB_CB(skb); |
48 | |
49 | if (cb->flags & ATH12K_SKB_HW_80211_ENCAP) |
50 | return skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
51 | else if (!ieee80211_is_data_qos(fc: hdr->frame_control)) |
52 | return HAL_DESC_REO_NON_QOS_TID; |
53 | else |
54 | return skb->priority & IEEE80211_QOS_CTL_TID_MASK; |
55 | } |
56 | |
57 | enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher) |
58 | { |
59 | switch (cipher) { |
60 | case WLAN_CIPHER_SUITE_WEP40: |
61 | return HAL_ENCRYPT_TYPE_WEP_40; |
62 | case WLAN_CIPHER_SUITE_WEP104: |
63 | return HAL_ENCRYPT_TYPE_WEP_104; |
64 | case WLAN_CIPHER_SUITE_TKIP: |
65 | return HAL_ENCRYPT_TYPE_TKIP_MIC; |
66 | case WLAN_CIPHER_SUITE_CCMP: |
67 | return HAL_ENCRYPT_TYPE_CCMP_128; |
68 | case WLAN_CIPHER_SUITE_CCMP_256: |
69 | return HAL_ENCRYPT_TYPE_CCMP_256; |
70 | case WLAN_CIPHER_SUITE_GCMP: |
71 | return HAL_ENCRYPT_TYPE_GCMP_128; |
72 | case WLAN_CIPHER_SUITE_GCMP_256: |
73 | return HAL_ENCRYPT_TYPE_AES_GCMP_256; |
74 | default: |
75 | return HAL_ENCRYPT_TYPE_OPEN; |
76 | } |
77 | } |
78 | |
79 | static void ath12k_dp_tx_release_txbuf(struct ath12k_dp *dp, |
80 | struct ath12k_tx_desc_info *tx_desc, |
81 | u8 pool_id) |
82 | { |
83 | spin_lock_bh(lock: &dp->tx_desc_lock[pool_id]); |
84 | list_move_tail(list: &tx_desc->list, head: &dp->tx_desc_free_list[pool_id]); |
85 | spin_unlock_bh(lock: &dp->tx_desc_lock[pool_id]); |
86 | } |
87 | |
88 | static struct ath12k_tx_desc_info *ath12k_dp_tx_assign_buffer(struct ath12k_dp *dp, |
89 | u8 pool_id) |
90 | { |
91 | struct ath12k_tx_desc_info *desc; |
92 | |
93 | spin_lock_bh(lock: &dp->tx_desc_lock[pool_id]); |
94 | desc = list_first_entry_or_null(&dp->tx_desc_free_list[pool_id], |
95 | struct ath12k_tx_desc_info, |
96 | list); |
97 | if (!desc) { |
98 | spin_unlock_bh(lock: &dp->tx_desc_lock[pool_id]); |
99 | ath12k_warn(ab: dp->ab, fmt: "failed to allocate data Tx buffer\n" ); |
100 | return NULL; |
101 | } |
102 | |
103 | list_move_tail(list: &desc->list, head: &dp->tx_desc_used_list[pool_id]); |
104 | spin_unlock_bh(lock: &dp->tx_desc_lock[pool_id]); |
105 | |
106 | return desc; |
107 | } |
108 | |
109 | static void ath12k_hal_tx_cmd_ext_desc_setup(struct ath12k_base *ab, |
110 | struct hal_tx_msdu_ext_desc *tcl_ext_cmd, |
111 | struct hal_tx_info *ti) |
112 | { |
113 | tcl_ext_cmd->info0 = le32_encode_bits(v: ti->paddr, |
114 | HAL_TX_MSDU_EXT_INFO0_BUF_PTR_LO); |
115 | tcl_ext_cmd->info1 = le32_encode_bits(v: 0x0, |
116 | HAL_TX_MSDU_EXT_INFO1_BUF_PTR_HI) | |
117 | le32_encode_bits(v: ti->data_len, |
118 | HAL_TX_MSDU_EXT_INFO1_BUF_LEN); |
119 | |
120 | tcl_ext_cmd->info1 = le32_encode_bits(v: 1, HAL_TX_MSDU_EXT_INFO1_EXTN_OVERRIDE) | |
121 | le32_encode_bits(v: ti->encap_type, |
122 | HAL_TX_MSDU_EXT_INFO1_ENCAP_TYPE) | |
123 | le32_encode_bits(v: ti->encrypt_type, |
124 | HAL_TX_MSDU_EXT_INFO1_ENCRYPT_TYPE); |
125 | } |
126 | |
127 | int ath12k_dp_tx(struct ath12k *ar, struct ath12k_vif *arvif, |
128 | struct sk_buff *skb) |
129 | { |
130 | struct ath12k_base *ab = ar->ab; |
131 | struct ath12k_dp *dp = &ab->dp; |
132 | struct hal_tx_info ti = {0}; |
133 | struct ath12k_tx_desc_info *tx_desc; |
134 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
135 | struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); |
136 | struct hal_tcl_data_cmd *hal_tcl_desc; |
137 | struct hal_tx_msdu_ext_desc *msg; |
138 | struct sk_buff *skb_ext_desc; |
139 | struct hal_srng *tcl_ring; |
140 | struct ieee80211_hdr *hdr = (void *)skb->data; |
141 | struct dp_tx_ring *tx_ring; |
142 | u8 pool_id; |
143 | u8 hal_ring_id; |
144 | int ret; |
145 | u8 ring_selector, ring_map = 0; |
146 | bool tcl_ring_retry; |
147 | bool msdu_ext_desc = false; |
148 | |
149 | if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) |
150 | return -ESHUTDOWN; |
151 | |
152 | if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) && |
153 | !ieee80211_is_data(fc: hdr->frame_control)) |
154 | return -EOPNOTSUPP; |
155 | |
156 | pool_id = skb_get_queue_mapping(skb) & (ATH12K_HW_MAX_QUEUES - 1); |
157 | |
158 | /* Let the default ring selection be based on current processor |
159 | * number, where one of the 3 tcl rings are selected based on |
160 | * the smp_processor_id(). In case that ring |
161 | * is full/busy, we resort to other available rings. |
162 | * If all rings are full, we drop the packet. |
163 | * TODO: Add throttling logic when all rings are full |
164 | */ |
165 | ring_selector = ab->hw_params->hw_ops->get_ring_selector(skb); |
166 | |
167 | tcl_ring_sel: |
168 | tcl_ring_retry = false; |
169 | ti.ring_id = ring_selector % ab->hw_params->max_tx_ring; |
170 | |
171 | ring_map |= BIT(ti.ring_id); |
172 | ti.rbm_id = ab->hw_params->hal_ops->tcl_to_wbm_rbm_map[ti.ring_id].rbm_id; |
173 | |
174 | tx_ring = &dp->tx_ring[ti.ring_id]; |
175 | |
176 | tx_desc = ath12k_dp_tx_assign_buffer(dp, pool_id); |
177 | if (!tx_desc) |
178 | return -ENOMEM; |
179 | |
180 | ti.bank_id = arvif->bank_id; |
181 | ti.meta_data_flags = arvif->tcl_metadata; |
182 | |
183 | if (arvif->tx_encap_type == HAL_TCL_ENCAP_TYPE_RAW && |
184 | test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags)) { |
185 | if (skb_cb->flags & ATH12K_SKB_CIPHER_SET) { |
186 | ti.encrypt_type = |
187 | ath12k_dp_tx_get_encrypt_type(cipher: skb_cb->cipher); |
188 | |
189 | if (ieee80211_has_protected(fc: hdr->frame_control)) |
190 | skb_put(skb, IEEE80211_CCMP_MIC_LEN); |
191 | } else { |
192 | ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN; |
193 | } |
194 | |
195 | msdu_ext_desc = true; |
196 | } |
197 | |
198 | ti.encap_type = ath12k_dp_tx_get_encap_type(arvif, skb); |
199 | ti.addr_search_flags = arvif->hal_addr_search_flags; |
200 | ti.search_type = arvif->search_type; |
201 | ti.type = HAL_TCL_DESC_TYPE_BUFFER; |
202 | ti.pkt_offset = 0; |
203 | ti.lmac_id = ar->lmac_id; |
204 | ti.vdev_id = arvif->vdev_id; |
205 | ti.bss_ast_hash = arvif->ast_hash; |
206 | ti.bss_ast_idx = arvif->ast_idx; |
207 | ti.dscp_tid_tbl_idx = 0; |
208 | |
209 | if (skb->ip_summed == CHECKSUM_PARTIAL && |
210 | ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) { |
211 | ti.flags0 |= u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO2_IP4_CKSUM_EN) | |
212 | u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO2_UDP4_CKSUM_EN) | |
213 | u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO2_UDP6_CKSUM_EN) | |
214 | u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO2_TCP4_CKSUM_EN) | |
215 | u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO2_TCP6_CKSUM_EN); |
216 | } |
217 | |
218 | ti.flags1 |= u32_encode_bits(v: 1, HAL_TCL_DATA_CMD_INFO3_TID_OVERWRITE); |
219 | |
220 | ti.tid = ath12k_dp_tx_get_tid(skb); |
221 | |
222 | switch (ti.encap_type) { |
223 | case HAL_TCL_ENCAP_TYPE_NATIVE_WIFI: |
224 | ath12k_dp_tx_encap_nwifi(skb); |
225 | break; |
226 | case HAL_TCL_ENCAP_TYPE_RAW: |
227 | if (!test_bit(ATH12K_FLAG_RAW_MODE, &ab->dev_flags)) { |
228 | ret = -EINVAL; |
229 | goto fail_remove_tx_buf; |
230 | } |
231 | break; |
232 | case HAL_TCL_ENCAP_TYPE_ETHERNET: |
233 | /* no need to encap */ |
234 | break; |
235 | case HAL_TCL_ENCAP_TYPE_802_3: |
236 | default: |
237 | /* TODO: Take care of other encap modes as well */ |
238 | ret = -EINVAL; |
239 | atomic_inc(v: &ab->soc_stats.tx_err.misc_fail); |
240 | goto fail_remove_tx_buf; |
241 | } |
242 | |
243 | ti.paddr = dma_map_single(ab->dev, skb->data, skb->len, DMA_TO_DEVICE); |
244 | if (dma_mapping_error(dev: ab->dev, dma_addr: ti.paddr)) { |
245 | atomic_inc(v: &ab->soc_stats.tx_err.misc_fail); |
246 | ath12k_warn(ab, fmt: "failed to DMA map data Tx buffer\n" ); |
247 | ret = -ENOMEM; |
248 | goto fail_remove_tx_buf; |
249 | } |
250 | |
251 | tx_desc->skb = skb; |
252 | tx_desc->mac_id = ar->pdev_idx; |
253 | ti.desc_id = tx_desc->desc_id; |
254 | ti.data_len = skb->len; |
255 | skb_cb->paddr = ti.paddr; |
256 | skb_cb->vif = arvif->vif; |
257 | skb_cb->ar = ar; |
258 | |
259 | if (msdu_ext_desc) { |
260 | skb_ext_desc = dev_alloc_skb(length: sizeof(struct hal_tx_msdu_ext_desc)); |
261 | if (!skb_ext_desc) { |
262 | ret = -ENOMEM; |
263 | goto fail_unmap_dma; |
264 | } |
265 | |
266 | skb_put(skb: skb_ext_desc, len: sizeof(struct hal_tx_msdu_ext_desc)); |
267 | memset(skb_ext_desc->data, 0, skb_ext_desc->len); |
268 | |
269 | msg = (struct hal_tx_msdu_ext_desc *)skb_ext_desc->data; |
270 | ath12k_hal_tx_cmd_ext_desc_setup(ab, tcl_ext_cmd: msg, ti: &ti); |
271 | |
272 | ti.paddr = dma_map_single(ab->dev, skb_ext_desc->data, |
273 | skb_ext_desc->len, DMA_TO_DEVICE); |
274 | ret = dma_mapping_error(dev: ab->dev, dma_addr: ti.paddr); |
275 | if (ret) { |
276 | kfree_skb(skb: skb_ext_desc); |
277 | goto fail_unmap_dma; |
278 | } |
279 | |
280 | ti.data_len = skb_ext_desc->len; |
281 | ti.type = HAL_TCL_DESC_TYPE_EXT_DESC; |
282 | |
283 | skb_cb->paddr_ext_desc = ti.paddr; |
284 | } |
285 | |
286 | hal_ring_id = tx_ring->tcl_data_ring.ring_id; |
287 | tcl_ring = &ab->hal.srng_list[hal_ring_id]; |
288 | |
289 | spin_lock_bh(lock: &tcl_ring->lock); |
290 | |
291 | ath12k_hal_srng_access_begin(ab, srng: tcl_ring); |
292 | |
293 | hal_tcl_desc = ath12k_hal_srng_src_get_next_entry(ab, srng: tcl_ring); |
294 | if (!hal_tcl_desc) { |
295 | /* NOTE: It is highly unlikely we'll be running out of tcl_ring |
296 | * desc because the desc is directly enqueued onto hw queue. |
297 | */ |
298 | ath12k_hal_srng_access_end(ab, srng: tcl_ring); |
299 | ab->soc_stats.tx_err.desc_na[ti.ring_id]++; |
300 | spin_unlock_bh(lock: &tcl_ring->lock); |
301 | ret = -ENOMEM; |
302 | |
303 | /* Checking for available tcl descriptors in another ring in |
304 | * case of failure due to full tcl ring now, is better than |
305 | * checking this ring earlier for each pkt tx. |
306 | * Restart ring selection if some rings are not checked yet. |
307 | */ |
308 | if (ring_map != (BIT(ab->hw_params->max_tx_ring) - 1) && |
309 | ab->hw_params->tcl_ring_retry) { |
310 | tcl_ring_retry = true; |
311 | ring_selector++; |
312 | } |
313 | |
314 | goto fail_unmap_dma; |
315 | } |
316 | |
317 | ath12k_hal_tx_cmd_desc_setup(ab, tcl_cmd: hal_tcl_desc, ti: &ti); |
318 | |
319 | ath12k_hal_srng_access_end(ab, srng: tcl_ring); |
320 | |
321 | spin_unlock_bh(lock: &tcl_ring->lock); |
322 | |
323 | ath12k_dbg_dump(ab, mask: ATH12K_DBG_DP_TX, NULL, prefix: "dp tx msdu: " , |
324 | buf: skb->data, len: skb->len); |
325 | |
326 | atomic_inc(v: &ar->dp.num_tx_pending); |
327 | |
328 | return 0; |
329 | |
330 | fail_unmap_dma: |
331 | dma_unmap_single(ab->dev, ti.paddr, ti.data_len, DMA_TO_DEVICE); |
332 | |
333 | if (skb_cb->paddr_ext_desc) |
334 | dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, |
335 | sizeof(struct hal_tx_msdu_ext_desc), |
336 | DMA_TO_DEVICE); |
337 | |
338 | fail_remove_tx_buf: |
339 | ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id); |
340 | if (tcl_ring_retry) |
341 | goto tcl_ring_sel; |
342 | |
343 | return ret; |
344 | } |
345 | |
346 | static void ath12k_dp_tx_free_txbuf(struct ath12k_base *ab, |
347 | struct sk_buff *msdu, u8 mac_id, |
348 | struct dp_tx_ring *tx_ring) |
349 | { |
350 | struct ath12k *ar; |
351 | struct ath12k_skb_cb *skb_cb; |
352 | u8 pdev_id = ath12k_hw_mac_id_to_pdev_id(hw: ab->hw_params, mac_id); |
353 | |
354 | skb_cb = ATH12K_SKB_CB(skb: msdu); |
355 | |
356 | dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
357 | if (skb_cb->paddr_ext_desc) |
358 | dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, |
359 | sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); |
360 | |
361 | dev_kfree_skb_any(skb: msdu); |
362 | |
363 | ar = ab->pdevs[pdev_id].ar; |
364 | if (atomic_dec_and_test(v: &ar->dp.num_tx_pending)) |
365 | wake_up(&ar->dp.tx_empty_waitq); |
366 | } |
367 | |
368 | static void |
369 | ath12k_dp_tx_htt_tx_complete_buf(struct ath12k_base *ab, |
370 | struct sk_buff *msdu, |
371 | struct dp_tx_ring *tx_ring, |
372 | struct ath12k_dp_htt_wbm_tx_status *ts) |
373 | { |
374 | struct ieee80211_tx_info *info; |
375 | struct ath12k_skb_cb *skb_cb; |
376 | struct ath12k *ar; |
377 | |
378 | skb_cb = ATH12K_SKB_CB(skb: msdu); |
379 | info = IEEE80211_SKB_CB(skb: msdu); |
380 | |
381 | ar = skb_cb->ar; |
382 | |
383 | if (atomic_dec_and_test(v: &ar->dp.num_tx_pending)) |
384 | wake_up(&ar->dp.tx_empty_waitq); |
385 | |
386 | dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
387 | if (skb_cb->paddr_ext_desc) |
388 | dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, |
389 | sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); |
390 | |
391 | memset(&info->status, 0, sizeof(info->status)); |
392 | |
393 | if (ts->acked) { |
394 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
395 | info->flags |= IEEE80211_TX_STAT_ACK; |
396 | info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + |
397 | ts->ack_rssi; |
398 | info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; |
399 | } else { |
400 | info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
401 | } |
402 | } |
403 | |
404 | ieee80211_tx_status_skb(hw: ath12k_ar_to_hw(ar), skb: msdu); |
405 | } |
406 | |
407 | static void |
408 | ath12k_dp_tx_process_htt_tx_complete(struct ath12k_base *ab, |
409 | void *desc, u8 mac_id, |
410 | struct sk_buff *msdu, |
411 | struct dp_tx_ring *tx_ring) |
412 | { |
413 | struct htt_tx_wbm_completion *status_desc; |
414 | struct ath12k_dp_htt_wbm_tx_status ts = {0}; |
415 | enum hal_wbm_htt_tx_comp_status wbm_status; |
416 | |
417 | status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET; |
418 | |
419 | wbm_status = le32_get_bits(v: status_desc->info0, |
420 | HTT_TX_WBM_COMP_INFO0_STATUS); |
421 | |
422 | switch (wbm_status) { |
423 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: |
424 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: |
425 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: |
426 | ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); |
427 | ts.ack_rssi = le32_get_bits(v: status_desc->info2, |
428 | HTT_TX_WBM_COMP_INFO2_ACK_RSSI); |
429 | ath12k_dp_tx_htt_tx_complete_buf(ab, msdu, tx_ring, ts: &ts); |
430 | break; |
431 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: |
432 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: |
433 | ath12k_dp_tx_free_txbuf(ab, msdu, mac_id, tx_ring); |
434 | break; |
435 | case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY: |
436 | /* This event is to be handled only when the driver decides to |
437 | * use WDS offload functionality. |
438 | */ |
439 | break; |
440 | default: |
441 | ath12k_warn(ab, fmt: "Unknown htt tx status %d\n" , wbm_status); |
442 | break; |
443 | } |
444 | } |
445 | |
446 | static void ath12k_dp_tx_complete_msdu(struct ath12k *ar, |
447 | struct sk_buff *msdu, |
448 | struct hal_tx_status *ts) |
449 | { |
450 | struct ath12k_base *ab = ar->ab; |
451 | struct ieee80211_tx_info *info; |
452 | struct ath12k_skb_cb *skb_cb; |
453 | |
454 | if (WARN_ON_ONCE(ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM)) { |
455 | /* Must not happen */ |
456 | return; |
457 | } |
458 | |
459 | skb_cb = ATH12K_SKB_CB(skb: msdu); |
460 | |
461 | dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); |
462 | if (skb_cb->paddr_ext_desc) |
463 | dma_unmap_single(ab->dev, skb_cb->paddr_ext_desc, |
464 | sizeof(struct hal_tx_msdu_ext_desc), DMA_TO_DEVICE); |
465 | |
466 | rcu_read_lock(); |
467 | |
468 | if (!rcu_dereference(ab->pdevs_active[ar->pdev_idx])) { |
469 | dev_kfree_skb_any(skb: msdu); |
470 | goto exit; |
471 | } |
472 | |
473 | if (!skb_cb->vif) { |
474 | dev_kfree_skb_any(skb: msdu); |
475 | goto exit; |
476 | } |
477 | |
478 | info = IEEE80211_SKB_CB(skb: msdu); |
479 | memset(&info->status, 0, sizeof(info->status)); |
480 | |
481 | /* skip tx rate update from ieee80211_status*/ |
482 | info->status.rates[0].idx = -1; |
483 | |
484 | if (ts->status == HAL_WBM_TQM_REL_REASON_FRAME_ACKED && |
485 | !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
486 | info->flags |= IEEE80211_TX_STAT_ACK; |
487 | info->status.ack_signal = ATH12K_DEFAULT_NOISE_FLOOR + |
488 | ts->ack_rssi; |
489 | info->status.flags = IEEE80211_TX_STATUS_ACK_SIGNAL_VALID; |
490 | } |
491 | |
492 | if (ts->status == HAL_WBM_TQM_REL_REASON_CMD_REMOVE_TX && |
493 | (info->flags & IEEE80211_TX_CTL_NO_ACK)) |
494 | info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; |
495 | |
496 | /* NOTE: Tx rate status reporting. Tx completion status does not have |
497 | * necessary information (for example nss) to build the tx rate. |
498 | * Might end up reporting it out-of-band from HTT stats. |
499 | */ |
500 | |
501 | ieee80211_tx_status_skb(hw: ath12k_ar_to_hw(ar), skb: msdu); |
502 | |
503 | exit: |
504 | rcu_read_unlock(); |
505 | } |
506 | |
507 | static void ath12k_dp_tx_status_parse(struct ath12k_base *ab, |
508 | struct hal_wbm_completion_ring_tx *desc, |
509 | struct hal_tx_status *ts) |
510 | { |
511 | ts->buf_rel_source = |
512 | le32_get_bits(v: desc->info0, HAL_WBM_COMPL_TX_INFO0_REL_SRC_MODULE); |
513 | if (ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_FW && |
514 | ts->buf_rel_source != HAL_WBM_REL_SRC_MODULE_TQM) |
515 | return; |
516 | |
517 | if (ts->buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) |
518 | return; |
519 | |
520 | ts->status = le32_get_bits(v: desc->info0, |
521 | HAL_WBM_COMPL_TX_INFO0_TQM_RELEASE_REASON); |
522 | |
523 | ts->ppdu_id = le32_get_bits(v: desc->info1, |
524 | HAL_WBM_COMPL_TX_INFO1_TQM_STATUS_NUMBER); |
525 | if (le32_to_cpu(desc->rate_stats.info0) & HAL_TX_RATE_STATS_INFO0_VALID) |
526 | ts->rate_stats = le32_to_cpu(desc->rate_stats.info0); |
527 | else |
528 | ts->rate_stats = 0; |
529 | } |
530 | |
531 | void ath12k_dp_tx_completion_handler(struct ath12k_base *ab, int ring_id) |
532 | { |
533 | struct ath12k *ar; |
534 | struct ath12k_dp *dp = &ab->dp; |
535 | int hal_ring_id = dp->tx_ring[ring_id].tcl_comp_ring.ring_id; |
536 | struct hal_srng *status_ring = &ab->hal.srng_list[hal_ring_id]; |
537 | struct ath12k_tx_desc_info *tx_desc = NULL; |
538 | struct sk_buff *msdu; |
539 | struct hal_tx_status ts = { 0 }; |
540 | struct dp_tx_ring *tx_ring = &dp->tx_ring[ring_id]; |
541 | struct hal_wbm_release_ring *desc; |
542 | u8 mac_id, pdev_id; |
543 | u64 desc_va; |
544 | |
545 | spin_lock_bh(lock: &status_ring->lock); |
546 | |
547 | ath12k_hal_srng_access_begin(ab, srng: status_ring); |
548 | |
549 | while (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) != tx_ring->tx_status_tail) { |
550 | desc = ath12k_hal_srng_dst_get_next_entry(ab, srng: status_ring); |
551 | if (!desc) |
552 | break; |
553 | |
554 | memcpy(&tx_ring->tx_status[tx_ring->tx_status_head], |
555 | desc, sizeof(*desc)); |
556 | tx_ring->tx_status_head = |
557 | ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head); |
558 | } |
559 | |
560 | if (ath12k_hal_srng_dst_peek(ab, srng: status_ring) && |
561 | (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_head) == tx_ring->tx_status_tail)) { |
562 | /* TODO: Process pending tx_status messages when kfifo_is_full() */ |
563 | ath12k_warn(ab, fmt: "Unable to process some of the tx_status ring desc because status_fifo is full\n" ); |
564 | } |
565 | |
566 | ath12k_hal_srng_access_end(ab, srng: status_ring); |
567 | |
568 | spin_unlock_bh(lock: &status_ring->lock); |
569 | |
570 | while (ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_tail) != tx_ring->tx_status_head) { |
571 | struct hal_wbm_completion_ring_tx *tx_status; |
572 | u32 desc_id; |
573 | |
574 | tx_ring->tx_status_tail = |
575 | ATH12K_TX_COMPL_NEXT(tx_ring->tx_status_tail); |
576 | tx_status = &tx_ring->tx_status[tx_ring->tx_status_tail]; |
577 | ath12k_dp_tx_status_parse(ab, desc: tx_status, ts: &ts); |
578 | |
579 | if (le32_get_bits(v: tx_status->info0, HAL_WBM_COMPL_TX_INFO0_CC_DONE)) { |
580 | /* HW done cookie conversion */ |
581 | desc_va = ((u64)le32_to_cpu(tx_status->buf_va_hi) << 32 | |
582 | le32_to_cpu(tx_status->buf_va_lo)); |
583 | tx_desc = (struct ath12k_tx_desc_info *)((unsigned long)desc_va); |
584 | } else { |
585 | /* SW does cookie conversion to VA */ |
586 | desc_id = le32_get_bits(v: tx_status->buf_va_hi, |
587 | BUFFER_ADDR_INFO1_SW_COOKIE); |
588 | |
589 | tx_desc = ath12k_dp_get_tx_desc(ab, desc_id); |
590 | } |
591 | if (!tx_desc) { |
592 | ath12k_warn(ab, fmt: "unable to retrieve tx_desc!" ); |
593 | continue; |
594 | } |
595 | |
596 | msdu = tx_desc->skb; |
597 | mac_id = tx_desc->mac_id; |
598 | |
599 | /* Release descriptor as soon as extracting necessary info |
600 | * to reduce contention |
601 | */ |
602 | ath12k_dp_tx_release_txbuf(dp, tx_desc, pool_id: tx_desc->pool_id); |
603 | if (ts.buf_rel_source == HAL_WBM_REL_SRC_MODULE_FW) { |
604 | ath12k_dp_tx_process_htt_tx_complete(ab, |
605 | desc: (void *)tx_status, |
606 | mac_id, msdu, |
607 | tx_ring); |
608 | continue; |
609 | } |
610 | |
611 | pdev_id = ath12k_hw_mac_id_to_pdev_id(hw: ab->hw_params, mac_id); |
612 | ar = ab->pdevs[pdev_id].ar; |
613 | |
614 | if (atomic_dec_and_test(v: &ar->dp.num_tx_pending)) |
615 | wake_up(&ar->dp.tx_empty_waitq); |
616 | |
617 | ath12k_dp_tx_complete_msdu(ar, msdu, ts: &ts); |
618 | } |
619 | } |
620 | |
621 | static int |
622 | ath12k_dp_tx_get_ring_id_type(struct ath12k_base *ab, |
623 | int mac_id, u32 ring_id, |
624 | enum hal_ring_type ring_type, |
625 | enum htt_srng_ring_type *htt_ring_type, |
626 | enum htt_srng_ring_id *htt_ring_id) |
627 | { |
628 | int ret = 0; |
629 | |
630 | switch (ring_type) { |
631 | case HAL_RXDMA_BUF: |
632 | /* for some targets, host fills rx buffer to fw and fw fills to |
633 | * rxbuf ring for each rxdma |
634 | */ |
635 | if (!ab->hw_params->rx_mac_buf_ring) { |
636 | if (!(ring_id == HAL_SRNG_SW2RXDMA_BUF0 || |
637 | ring_id == HAL_SRNG_SW2RXDMA_BUF1)) { |
638 | ret = -EINVAL; |
639 | } |
640 | *htt_ring_id = HTT_RXDMA_HOST_BUF_RING; |
641 | *htt_ring_type = HTT_SW_TO_HW_RING; |
642 | } else { |
643 | if (ring_id == HAL_SRNG_SW2RXDMA_BUF0) { |
644 | *htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING; |
645 | *htt_ring_type = HTT_SW_TO_SW_RING; |
646 | } else { |
647 | *htt_ring_id = HTT_RXDMA_HOST_BUF_RING; |
648 | *htt_ring_type = HTT_SW_TO_HW_RING; |
649 | } |
650 | } |
651 | break; |
652 | case HAL_RXDMA_DST: |
653 | *htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; |
654 | *htt_ring_type = HTT_HW_TO_SW_RING; |
655 | break; |
656 | case HAL_RXDMA_MONITOR_BUF: |
657 | *htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING; |
658 | *htt_ring_type = HTT_SW_TO_HW_RING; |
659 | break; |
660 | case HAL_RXDMA_MONITOR_STATUS: |
661 | *htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING; |
662 | *htt_ring_type = HTT_SW_TO_HW_RING; |
663 | break; |
664 | case HAL_RXDMA_MONITOR_DST: |
665 | *htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING; |
666 | *htt_ring_type = HTT_HW_TO_SW_RING; |
667 | break; |
668 | case HAL_RXDMA_MONITOR_DESC: |
669 | *htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING; |
670 | *htt_ring_type = HTT_SW_TO_HW_RING; |
671 | break; |
672 | case HAL_TX_MONITOR_BUF: |
673 | *htt_ring_id = HTT_TX_MON_HOST2MON_BUF_RING; |
674 | *htt_ring_type = HTT_SW_TO_HW_RING; |
675 | break; |
676 | case HAL_TX_MONITOR_DST: |
677 | *htt_ring_id = HTT_TX_MON_MON2HOST_DEST_RING; |
678 | *htt_ring_type = HTT_HW_TO_SW_RING; |
679 | break; |
680 | default: |
681 | ath12k_warn(ab, fmt: "Unsupported ring type in DP :%d\n" , ring_type); |
682 | ret = -EINVAL; |
683 | } |
684 | return ret; |
685 | } |
686 | |
687 | int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id, |
688 | int mac_id, enum hal_ring_type ring_type) |
689 | { |
690 | struct htt_srng_setup_cmd *cmd; |
691 | struct hal_srng *srng = &ab->hal.srng_list[ring_id]; |
692 | struct hal_srng_params params; |
693 | struct sk_buff *skb; |
694 | u32 ring_entry_sz; |
695 | int len = sizeof(*cmd); |
696 | dma_addr_t hp_addr, tp_addr; |
697 | enum htt_srng_ring_type htt_ring_type; |
698 | enum htt_srng_ring_id htt_ring_id; |
699 | int ret; |
700 | |
701 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
702 | if (!skb) |
703 | return -ENOMEM; |
704 | |
705 | memset(¶ms, 0, sizeof(params)); |
706 | ath12k_hal_srng_get_params(ab, srng, params: ¶ms); |
707 | |
708 | hp_addr = ath12k_hal_srng_get_hp_addr(ab, srng); |
709 | tp_addr = ath12k_hal_srng_get_tp_addr(ab, srng); |
710 | |
711 | ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, |
712 | ring_type, htt_ring_type: &htt_ring_type, |
713 | htt_ring_id: &htt_ring_id); |
714 | if (ret) |
715 | goto err_free; |
716 | |
717 | skb_put(skb, len); |
718 | cmd = (struct htt_srng_setup_cmd *)skb->data; |
719 | cmd->info0 = le32_encode_bits(v: HTT_H2T_MSG_TYPE_SRING_SETUP, |
720 | HTT_SRNG_SETUP_CMD_INFO0_MSG_TYPE); |
721 | if (htt_ring_type == HTT_SW_TO_HW_RING || |
722 | htt_ring_type == HTT_HW_TO_SW_RING) |
723 | cmd->info0 |= le32_encode_bits(DP_SW2HW_MACID(mac_id), |
724 | HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID); |
725 | else |
726 | cmd->info0 |= le32_encode_bits(v: mac_id, |
727 | HTT_SRNG_SETUP_CMD_INFO0_PDEV_ID); |
728 | cmd->info0 |= le32_encode_bits(v: htt_ring_type, |
729 | HTT_SRNG_SETUP_CMD_INFO0_RING_TYPE); |
730 | cmd->info0 |= le32_encode_bits(v: htt_ring_id, |
731 | HTT_SRNG_SETUP_CMD_INFO0_RING_ID); |
732 | |
733 | cmd->ring_base_addr_lo = cpu_to_le32(params.ring_base_paddr & |
734 | HAL_ADDR_LSB_REG_MASK); |
735 | |
736 | cmd->ring_base_addr_hi = cpu_to_le32((u64)params.ring_base_paddr >> |
737 | HAL_ADDR_MSB_REG_SHIFT); |
738 | |
739 | ret = ath12k_hal_srng_get_entrysize(ab, ring_type); |
740 | if (ret < 0) |
741 | goto err_free; |
742 | |
743 | ring_entry_sz = ret; |
744 | |
745 | ring_entry_sz >>= 2; |
746 | cmd->info1 = le32_encode_bits(v: ring_entry_sz, |
747 | HTT_SRNG_SETUP_CMD_INFO1_RING_ENTRY_SIZE); |
748 | cmd->info1 |= le32_encode_bits(v: params.num_entries * ring_entry_sz, |
749 | HTT_SRNG_SETUP_CMD_INFO1_RING_SIZE); |
750 | cmd->info1 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP), |
751 | HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_MSI_SWAP); |
752 | cmd->info1 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP), |
753 | HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_TLV_SWAP); |
754 | cmd->info1 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_RING_PTR_SWAP), |
755 | HTT_SRNG_SETUP_CMD_INFO1_RING_FLAGS_HOST_FW_SWAP); |
756 | if (htt_ring_type == HTT_SW_TO_HW_RING) |
757 | cmd->info1 |= cpu_to_le32(HTT_SRNG_SETUP_CMD_INFO1_RING_LOOP_CNT_DIS); |
758 | |
759 | cmd->ring_head_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(hp_addr)); |
760 | cmd->ring_head_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(hp_addr)); |
761 | |
762 | cmd->ring_tail_off32_remote_addr_lo = cpu_to_le32(lower_32_bits(tp_addr)); |
763 | cmd->ring_tail_off32_remote_addr_hi = cpu_to_le32(upper_32_bits(tp_addr)); |
764 | |
765 | cmd->ring_msi_addr_lo = cpu_to_le32(lower_32_bits(params.msi_addr)); |
766 | cmd->ring_msi_addr_hi = cpu_to_le32(upper_32_bits(params.msi_addr)); |
767 | cmd->msi_data = cpu_to_le32(params.msi_data); |
768 | |
769 | cmd->intr_info = |
770 | le32_encode_bits(v: params.intr_batch_cntr_thres_entries * ring_entry_sz, |
771 | HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH); |
772 | cmd->intr_info |= |
773 | le32_encode_bits(v: params.intr_timer_thres_us >> 3, |
774 | HTT_SRNG_SETUP_CMD_INTR_INFO_INTR_TIMER_THRESH); |
775 | |
776 | cmd->info2 = 0; |
777 | if (params.flags & HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN) { |
778 | cmd->info2 = le32_encode_bits(v: params.low_threshold, |
779 | HTT_SRNG_SETUP_CMD_INFO2_INTR_LOW_THRESH); |
780 | } |
781 | |
782 | ath12k_dbg(ab, ATH12K_DBG_HAL, |
783 | "%s msi_addr_lo:0x%x, msi_addr_hi:0x%x, msi_data:0x%x\n" , |
784 | __func__, cmd->ring_msi_addr_lo, cmd->ring_msi_addr_hi, |
785 | cmd->msi_data); |
786 | |
787 | ath12k_dbg(ab, ATH12K_DBG_HAL, |
788 | "ring_id:%d, ring_type:%d, intr_info:0x%x, flags:0x%x\n" , |
789 | ring_id, ring_type, cmd->intr_info, cmd->info2); |
790 | |
791 | ret = ath12k_htc_send(htc: &ab->htc, eid: ab->dp.eid, packet: skb); |
792 | if (ret) |
793 | goto err_free; |
794 | |
795 | return 0; |
796 | |
797 | err_free: |
798 | dev_kfree_skb_any(skb); |
799 | |
800 | return ret; |
801 | } |
802 | |
803 | #define HTT_TARGET_VERSION_TIMEOUT_HZ (3 * HZ) |
804 | |
805 | int ath12k_dp_tx_htt_h2t_ver_req_msg(struct ath12k_base *ab) |
806 | { |
807 | struct ath12k_dp *dp = &ab->dp; |
808 | struct sk_buff *skb; |
809 | struct htt_ver_req_cmd *cmd; |
810 | int len = sizeof(*cmd); |
811 | int ret; |
812 | |
813 | init_completion(x: &dp->htt_tgt_version_received); |
814 | |
815 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
816 | if (!skb) |
817 | return -ENOMEM; |
818 | |
819 | skb_put(skb, len); |
820 | cmd = (struct htt_ver_req_cmd *)skb->data; |
821 | cmd->ver_reg_info = le32_encode_bits(v: HTT_H2T_MSG_TYPE_VERSION_REQ, |
822 | HTT_VER_REQ_INFO_MSG_ID); |
823 | |
824 | ret = ath12k_htc_send(htc: &ab->htc, eid: dp->eid, packet: skb); |
825 | if (ret) { |
826 | dev_kfree_skb_any(skb); |
827 | return ret; |
828 | } |
829 | |
830 | ret = wait_for_completion_timeout(x: &dp->htt_tgt_version_received, |
831 | HTT_TARGET_VERSION_TIMEOUT_HZ); |
832 | if (ret == 0) { |
833 | ath12k_warn(ab, fmt: "htt target version request timed out\n" ); |
834 | return -ETIMEDOUT; |
835 | } |
836 | |
837 | if (dp->htt_tgt_ver_major != HTT_TARGET_VERSION_MAJOR) { |
838 | ath12k_err(ab, fmt: "unsupported htt major version %d supported version is %d\n" , |
839 | dp->htt_tgt_ver_major, HTT_TARGET_VERSION_MAJOR); |
840 | return -EOPNOTSUPP; |
841 | } |
842 | |
843 | return 0; |
844 | } |
845 | |
846 | int ath12k_dp_tx_htt_h2t_ppdu_stats_req(struct ath12k *ar, u32 mask) |
847 | { |
848 | struct ath12k_base *ab = ar->ab; |
849 | struct ath12k_dp *dp = &ab->dp; |
850 | struct sk_buff *skb; |
851 | struct htt_ppdu_stats_cfg_cmd *cmd; |
852 | int len = sizeof(*cmd); |
853 | u8 pdev_mask; |
854 | int ret; |
855 | int i; |
856 | |
857 | for (i = 0; i < ab->hw_params->num_rxmda_per_pdev; i++) { |
858 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
859 | if (!skb) |
860 | return -ENOMEM; |
861 | |
862 | skb_put(skb, len); |
863 | cmd = (struct htt_ppdu_stats_cfg_cmd *)skb->data; |
864 | cmd->msg = le32_encode_bits(v: HTT_H2T_MSG_TYPE_PPDU_STATS_CFG, |
865 | HTT_PPDU_STATS_CFG_MSG_TYPE); |
866 | |
867 | pdev_mask = 1 << (i + 1); |
868 | cmd->msg |= le32_encode_bits(v: pdev_mask, HTT_PPDU_STATS_CFG_PDEV_ID); |
869 | cmd->msg |= le32_encode_bits(v: mask, HTT_PPDU_STATS_CFG_TLV_TYPE_BITMASK); |
870 | |
871 | ret = ath12k_htc_send(htc: &ab->htc, eid: dp->eid, packet: skb); |
872 | if (ret) { |
873 | dev_kfree_skb_any(skb); |
874 | return ret; |
875 | } |
876 | } |
877 | |
878 | return 0; |
879 | } |
880 | |
881 | int ath12k_dp_tx_htt_rx_filter_setup(struct ath12k_base *ab, u32 ring_id, |
882 | int mac_id, enum hal_ring_type ring_type, |
883 | int rx_buf_size, |
884 | struct htt_rx_ring_tlv_filter *tlv_filter) |
885 | { |
886 | struct htt_rx_ring_selection_cfg_cmd *cmd; |
887 | struct hal_srng *srng = &ab->hal.srng_list[ring_id]; |
888 | struct hal_srng_params params; |
889 | struct sk_buff *skb; |
890 | int len = sizeof(*cmd); |
891 | enum htt_srng_ring_type htt_ring_type; |
892 | enum htt_srng_ring_id htt_ring_id; |
893 | int ret; |
894 | |
895 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
896 | if (!skb) |
897 | return -ENOMEM; |
898 | |
899 | memset(¶ms, 0, sizeof(params)); |
900 | ath12k_hal_srng_get_params(ab, srng, params: ¶ms); |
901 | |
902 | ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, |
903 | ring_type, htt_ring_type: &htt_ring_type, |
904 | htt_ring_id: &htt_ring_id); |
905 | if (ret) |
906 | goto err_free; |
907 | |
908 | skb_put(skb, len); |
909 | cmd = (struct htt_rx_ring_selection_cfg_cmd *)skb->data; |
910 | cmd->info0 = le32_encode_bits(v: HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG, |
911 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE); |
912 | if (htt_ring_type == HTT_SW_TO_HW_RING || |
913 | htt_ring_type == HTT_HW_TO_SW_RING) |
914 | cmd->info0 |= |
915 | le32_encode_bits(DP_SW2HW_MACID(mac_id), |
916 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID); |
917 | else |
918 | cmd->info0 |= |
919 | le32_encode_bits(v: mac_id, |
920 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID); |
921 | cmd->info0 |= le32_encode_bits(v: htt_ring_id, |
922 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_RING_ID); |
923 | cmd->info0 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP), |
924 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_SS); |
925 | cmd->info0 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP), |
926 | HTT_RX_RING_SELECTION_CFG_CMD_INFO0_PS); |
927 | cmd->info0 |= le32_encode_bits(v: tlv_filter->offset_valid, |
928 | HTT_RX_RING_SELECTION_CFG_CMD_OFFSET_VALID); |
929 | cmd->info1 = le32_encode_bits(v: rx_buf_size, |
930 | HTT_RX_RING_SELECTION_CFG_CMD_INFO1_BUF_SIZE); |
931 | cmd->pkt_type_en_flags0 = cpu_to_le32(tlv_filter->pkt_filter_flags0); |
932 | cmd->pkt_type_en_flags1 = cpu_to_le32(tlv_filter->pkt_filter_flags1); |
933 | cmd->pkt_type_en_flags2 = cpu_to_le32(tlv_filter->pkt_filter_flags2); |
934 | cmd->pkt_type_en_flags3 = cpu_to_le32(tlv_filter->pkt_filter_flags3); |
935 | cmd->rx_filter_tlv = cpu_to_le32(tlv_filter->rx_filter); |
936 | |
937 | if (tlv_filter->offset_valid) { |
938 | cmd->rx_packet_offset = |
939 | le32_encode_bits(v: tlv_filter->rx_packet_offset, |
940 | HTT_RX_RING_SELECTION_CFG_RX_PACKET_OFFSET); |
941 | |
942 | cmd->rx_packet_offset |= |
943 | le32_encode_bits(v: tlv_filter->rx_header_offset, |
944 | HTT_RX_RING_SELECTION_CFG_RX_HEADER_OFFSET); |
945 | |
946 | cmd->rx_mpdu_offset = |
947 | le32_encode_bits(v: tlv_filter->rx_mpdu_end_offset, |
948 | HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_OFFSET); |
949 | |
950 | cmd->rx_mpdu_offset |= |
951 | le32_encode_bits(v: tlv_filter->rx_mpdu_start_offset, |
952 | HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_OFFSET); |
953 | |
954 | cmd->rx_msdu_offset = |
955 | le32_encode_bits(v: tlv_filter->rx_msdu_end_offset, |
956 | HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_OFFSET); |
957 | |
958 | cmd->rx_msdu_offset |= |
959 | le32_encode_bits(v: tlv_filter->rx_msdu_start_offset, |
960 | HTT_RX_RING_SELECTION_CFG_RX_MSDU_START_OFFSET); |
961 | |
962 | cmd->rx_attn_offset = |
963 | le32_encode_bits(v: tlv_filter->rx_attn_offset, |
964 | HTT_RX_RING_SELECTION_CFG_RX_ATTENTION_OFFSET); |
965 | } |
966 | |
967 | if (tlv_filter->rx_mpdu_start_wmask > 0 && |
968 | tlv_filter->rx_msdu_end_wmask > 0) { |
969 | cmd->info2 |= |
970 | le32_encode_bits(v: true, |
971 | HTT_RX_RING_SELECTION_CFG_WORD_MASK_COMPACT_SET); |
972 | cmd->rx_mpdu_start_end_mask = |
973 | le32_encode_bits(v: tlv_filter->rx_mpdu_start_wmask, |
974 | HTT_RX_RING_SELECTION_CFG_RX_MPDU_START_MASK); |
975 | /* mpdu_end is not used for any hardwares so far |
976 | * please assign it in future if any chip is |
977 | * using through hal ops |
978 | */ |
979 | cmd->rx_mpdu_start_end_mask |= |
980 | le32_encode_bits(v: tlv_filter->rx_mpdu_end_wmask, |
981 | HTT_RX_RING_SELECTION_CFG_RX_MPDU_END_MASK); |
982 | cmd->rx_msdu_end_word_mask = |
983 | le32_encode_bits(v: tlv_filter->rx_msdu_end_wmask, |
984 | HTT_RX_RING_SELECTION_CFG_RX_MSDU_END_MASK); |
985 | } |
986 | |
987 | ret = ath12k_htc_send(htc: &ab->htc, eid: ab->dp.eid, packet: skb); |
988 | if (ret) |
989 | goto err_free; |
990 | |
991 | return 0; |
992 | |
993 | err_free: |
994 | dev_kfree_skb_any(skb); |
995 | |
996 | return ret; |
997 | } |
998 | |
999 | int |
1000 | ath12k_dp_tx_htt_h2t_ext_stats_req(struct ath12k *ar, u8 type, |
1001 | struct htt_ext_stats_cfg_params *cfg_params, |
1002 | u64 cookie) |
1003 | { |
1004 | struct ath12k_base *ab = ar->ab; |
1005 | struct ath12k_dp *dp = &ab->dp; |
1006 | struct sk_buff *skb; |
1007 | struct htt_ext_stats_cfg_cmd *cmd; |
1008 | int len = sizeof(*cmd); |
1009 | int ret; |
1010 | |
1011 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
1012 | if (!skb) |
1013 | return -ENOMEM; |
1014 | |
1015 | skb_put(skb, len); |
1016 | |
1017 | cmd = (struct htt_ext_stats_cfg_cmd *)skb->data; |
1018 | memset(cmd, 0, sizeof(*cmd)); |
1019 | cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_EXT_STATS_CFG; |
1020 | |
1021 | cmd->hdr.pdev_mask = 1 << ar->pdev->pdev_id; |
1022 | |
1023 | cmd->hdr.stats_type = type; |
1024 | cmd->cfg_param0 = cpu_to_le32(cfg_params->cfg0); |
1025 | cmd->cfg_param1 = cpu_to_le32(cfg_params->cfg1); |
1026 | cmd->cfg_param2 = cpu_to_le32(cfg_params->cfg2); |
1027 | cmd->cfg_param3 = cpu_to_le32(cfg_params->cfg3); |
1028 | cmd->cookie_lsb = cpu_to_le32(lower_32_bits(cookie)); |
1029 | cmd->cookie_msb = cpu_to_le32(upper_32_bits(cookie)); |
1030 | |
1031 | ret = ath12k_htc_send(htc: &ab->htc, eid: dp->eid, packet: skb); |
1032 | if (ret) { |
1033 | ath12k_warn(ab, fmt: "failed to send htt type stats request: %d" , |
1034 | ret); |
1035 | dev_kfree_skb_any(skb); |
1036 | return ret; |
1037 | } |
1038 | |
1039 | return 0; |
1040 | } |
1041 | |
1042 | int ath12k_dp_tx_htt_monitor_mode_ring_config(struct ath12k *ar, bool reset) |
1043 | { |
1044 | struct ath12k_base *ab = ar->ab; |
1045 | int ret; |
1046 | |
1047 | ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset); |
1048 | if (ret) { |
1049 | ath12k_err(ab, fmt: "failed to setup tx monitor filter %d\n" , ret); |
1050 | return ret; |
1051 | } |
1052 | |
1053 | ret = ath12k_dp_tx_htt_tx_monitor_mode_ring_config(ar, reset); |
1054 | if (ret) { |
1055 | ath12k_err(ab, fmt: "failed to setup rx monitor filter %d\n" , ret); |
1056 | return ret; |
1057 | } |
1058 | |
1059 | return 0; |
1060 | } |
1061 | |
1062 | int ath12k_dp_tx_htt_rx_monitor_mode_ring_config(struct ath12k *ar, bool reset) |
1063 | { |
1064 | struct ath12k_base *ab = ar->ab; |
1065 | struct ath12k_dp *dp = &ab->dp; |
1066 | struct htt_rx_ring_tlv_filter tlv_filter = {0}; |
1067 | int ret, ring_id; |
1068 | |
1069 | ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; |
1070 | tlv_filter.offset_valid = false; |
1071 | |
1072 | if (!reset) { |
1073 | tlv_filter.rx_filter = HTT_RX_MON_FILTER_TLV_FLAGS_MON_BUF_RING; |
1074 | tlv_filter.pkt_filter_flags0 = |
1075 | HTT_RX_MON_FP_MGMT_FILTER_FLAGS0 | |
1076 | HTT_RX_MON_MO_MGMT_FILTER_FLAGS0; |
1077 | tlv_filter.pkt_filter_flags1 = |
1078 | HTT_RX_MON_FP_MGMT_FILTER_FLAGS1 | |
1079 | HTT_RX_MON_MO_MGMT_FILTER_FLAGS1; |
1080 | tlv_filter.pkt_filter_flags2 = |
1081 | HTT_RX_MON_FP_CTRL_FILTER_FLASG2 | |
1082 | HTT_RX_MON_MO_CTRL_FILTER_FLASG2; |
1083 | tlv_filter.pkt_filter_flags3 = |
1084 | HTT_RX_MON_FP_CTRL_FILTER_FLASG3 | |
1085 | HTT_RX_MON_MO_CTRL_FILTER_FLASG3 | |
1086 | HTT_RX_MON_FP_DATA_FILTER_FLASG3 | |
1087 | HTT_RX_MON_MO_DATA_FILTER_FLASG3; |
1088 | } |
1089 | |
1090 | if (ab->hw_params->rxdma1_enable) { |
1091 | ret = ath12k_dp_tx_htt_rx_filter_setup(ab: ar->ab, ring_id, mac_id: 0, |
1092 | ring_type: HAL_RXDMA_MONITOR_BUF, |
1093 | DP_RXDMA_REFILL_RING_SIZE, |
1094 | tlv_filter: &tlv_filter); |
1095 | if (ret) { |
1096 | ath12k_err(ab, |
1097 | fmt: "failed to setup filter for monitor buf %d\n" , ret); |
1098 | return ret; |
1099 | } |
1100 | } |
1101 | |
1102 | return 0; |
1103 | } |
1104 | |
1105 | int ath12k_dp_tx_htt_tx_filter_setup(struct ath12k_base *ab, u32 ring_id, |
1106 | int mac_id, enum hal_ring_type ring_type, |
1107 | int tx_buf_size, |
1108 | struct htt_tx_ring_tlv_filter *htt_tlv_filter) |
1109 | { |
1110 | struct htt_tx_ring_selection_cfg_cmd *cmd; |
1111 | struct hal_srng *srng = &ab->hal.srng_list[ring_id]; |
1112 | struct hal_srng_params params; |
1113 | struct sk_buff *skb; |
1114 | int len = sizeof(*cmd); |
1115 | enum htt_srng_ring_type htt_ring_type; |
1116 | enum htt_srng_ring_id htt_ring_id; |
1117 | int ret; |
1118 | |
1119 | skb = ath12k_htc_alloc_skb(ar: ab, size: len); |
1120 | if (!skb) |
1121 | return -ENOMEM; |
1122 | |
1123 | memset(¶ms, 0, sizeof(params)); |
1124 | ath12k_hal_srng_get_params(ab, srng, params: ¶ms); |
1125 | |
1126 | ret = ath12k_dp_tx_get_ring_id_type(ab, mac_id, ring_id, |
1127 | ring_type, htt_ring_type: &htt_ring_type, |
1128 | htt_ring_id: &htt_ring_id); |
1129 | |
1130 | if (ret) |
1131 | goto err_free; |
1132 | |
1133 | skb_put(skb, len); |
1134 | cmd = (struct htt_tx_ring_selection_cfg_cmd *)skb->data; |
1135 | cmd->info0 = le32_encode_bits(v: HTT_H2T_MSG_TYPE_TX_MONITOR_CFG, |
1136 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_MSG_TYPE); |
1137 | if (htt_ring_type == HTT_SW_TO_HW_RING || |
1138 | htt_ring_type == HTT_HW_TO_SW_RING) |
1139 | cmd->info0 |= |
1140 | le32_encode_bits(DP_SW2HW_MACID(mac_id), |
1141 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID); |
1142 | else |
1143 | cmd->info0 |= |
1144 | le32_encode_bits(v: mac_id, |
1145 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PDEV_ID); |
1146 | cmd->info0 |= le32_encode_bits(v: htt_ring_id, |
1147 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_RING_ID); |
1148 | cmd->info0 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_MSI_SWAP), |
1149 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_SS); |
1150 | cmd->info0 |= le32_encode_bits(v: !!(params.flags & HAL_SRNG_FLAGS_DATA_TLV_SWAP), |
1151 | HTT_TX_RING_SELECTION_CFG_CMD_INFO0_PS); |
1152 | |
1153 | cmd->info1 |= |
1154 | le32_encode_bits(v: tx_buf_size, |
1155 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_RING_BUFF_SIZE); |
1156 | |
1157 | if (htt_tlv_filter->tx_mon_mgmt_filter) { |
1158 | cmd->info1 |= |
1159 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT, |
1160 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE); |
1161 | cmd->info1 |= |
1162 | le32_encode_bits(v: htt_tlv_filter->tx_mon_pkt_dma_len, |
1163 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_MGMT); |
1164 | cmd->info2 |= |
1165 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_MGMT, |
1166 | HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG); |
1167 | } |
1168 | |
1169 | if (htt_tlv_filter->tx_mon_data_filter) { |
1170 | cmd->info1 |= |
1171 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL, |
1172 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE); |
1173 | cmd->info1 |= |
1174 | le32_encode_bits(v: htt_tlv_filter->tx_mon_pkt_dma_len, |
1175 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_CTRL); |
1176 | cmd->info2 |= |
1177 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_CTRL, |
1178 | HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG); |
1179 | } |
1180 | |
1181 | if (htt_tlv_filter->tx_mon_ctrl_filter) { |
1182 | cmd->info1 |= |
1183 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA, |
1184 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_PKT_TYPE); |
1185 | cmd->info1 |= |
1186 | le32_encode_bits(v: htt_tlv_filter->tx_mon_pkt_dma_len, |
1187 | HTT_TX_RING_SELECTION_CFG_CMD_INFO1_CONF_LEN_DATA); |
1188 | cmd->info2 |= |
1189 | le32_encode_bits(HTT_STATS_FRAME_CTRL_TYPE_DATA, |
1190 | HTT_TX_RING_SELECTION_CFG_CMD_INFO2_PKT_TYPE_EN_FLAG); |
1191 | } |
1192 | |
1193 | cmd->tlv_filter_mask_in0 = |
1194 | cpu_to_le32(htt_tlv_filter->tx_mon_downstream_tlv_flags); |
1195 | cmd->tlv_filter_mask_in1 = |
1196 | cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags0); |
1197 | cmd->tlv_filter_mask_in2 = |
1198 | cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags1); |
1199 | cmd->tlv_filter_mask_in3 = |
1200 | cpu_to_le32(htt_tlv_filter->tx_mon_upstream_tlv_flags2); |
1201 | |
1202 | ret = ath12k_htc_send(htc: &ab->htc, eid: ab->dp.eid, packet: skb); |
1203 | if (ret) |
1204 | goto err_free; |
1205 | |
1206 | return 0; |
1207 | |
1208 | err_free: |
1209 | dev_kfree_skb_any(skb); |
1210 | return ret; |
1211 | } |
1212 | |
1213 | int ath12k_dp_tx_htt_tx_monitor_mode_ring_config(struct ath12k *ar, bool reset) |
1214 | { |
1215 | struct ath12k_base *ab = ar->ab; |
1216 | struct ath12k_dp *dp = &ab->dp; |
1217 | struct htt_tx_ring_tlv_filter tlv_filter = {0}; |
1218 | int ret, ring_id; |
1219 | |
1220 | ring_id = dp->tx_mon_buf_ring.refill_buf_ring.ring_id; |
1221 | |
1222 | /* TODO: Need to set upstream/downstream tlv filters |
1223 | * here |
1224 | */ |
1225 | |
1226 | if (ab->hw_params->rxdma1_enable) { |
1227 | ret = ath12k_dp_tx_htt_tx_filter_setup(ab: ar->ab, ring_id, mac_id: 0, |
1228 | ring_type: HAL_TX_MONITOR_BUF, |
1229 | DP_RXDMA_REFILL_RING_SIZE, |
1230 | htt_tlv_filter: &tlv_filter); |
1231 | if (ret) { |
1232 | ath12k_err(ab, |
1233 | fmt: "failed to setup filter for monitor buf %d\n" , ret); |
1234 | return ret; |
1235 | } |
1236 | } |
1237 | |
1238 | return 0; |
1239 | } |
1240 | |