1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @brief File containing TX data path specific function definitions for the
9 * FMAC IF Layer of the Wi-Fi driver.
10 */
11
12 #include "list.h"
13 #include "queue.h"
14 #include "system/hal_api.h"
15 #include "system/fmac_tx.h"
16 #include "system/fmac_api.h"
17 #include "system/fmac_peer.h"
18 #include "common/hal_structs_common.h"
19 #include "common/hal_mem.h"
20 #include "common/fmac_util.h"
21
is_twt_emergency_pkt(void * nwb)22 static bool is_twt_emergency_pkt(void *nwb)
23 {
24 unsigned char priority = nrf_wifi_osal_nbuf_get_priority(nwb);
25
26 return priority == NRF_WIFI_AC_TWT_PRIORITY_EMERGENCY;
27 }
28
29 /* Can be extended for other cases as well */
can_xmit(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * nwb)30 static bool can_xmit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
31 void *nwb)
32 {
33 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
34
35 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
36
37 return is_twt_emergency_pkt(nwb) ||
38 sys_dev_ctx->twt_sleep_status == NRF_WIFI_FMAC_TWT_STATE_AWAKE;
39 }
40
41 /* Set the coresponding bit of access category.
42 * First 4 bits(0 to 3) represenst first spare desc access cateogories
43 * Second 4 bits(4 to 7) represenst second spare desc access cateogories and so on
44 */
set_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc,int tx_done_q)45 static void set_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
46 unsigned int desc,
47 int tx_done_q)
48 {
49 unsigned short spare_desc_indx = 0;
50 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
51 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
52
53 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
54 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
55
56 nrf_wifi_osal_assert(sys_fpriv->num_tx_tokens_per_ac,
57 0,
58 NRF_WIFI_ASSERT_NOT_EQUAL_TO,
59 "num_tx_tokens_per_ac is zero");
60
61 spare_desc_indx = (desc % (sys_fpriv->num_tx_tokens_per_ac *
62 NRF_WIFI_FMAC_AC_MAX));
63
64 sys_dev_ctx->tx_config.spare_desc_queue_map |=
65 (1 << ((spare_desc_indx * SPARE_DESC_Q_MAP_SIZE) + tx_done_q));
66 }
67
68
69 /* Clear the coresponding bit of access category.
70 * First 4 bits(0 to 3) represenst first spare desc access cateogories
71 * Second 4 bits(4 to 7) represenst second spare desc access cateogories and so on
72 */
clear_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc,int tx_done_q)73 static void clear_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
74 unsigned int desc,
75 int tx_done_q)
76 {
77 unsigned short spare_desc_indx = 0;
78 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
79 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
80
81 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
82 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
83
84 nrf_wifi_osal_assert(sys_fpriv->num_tx_tokens_per_ac,
85 0,
86 NRF_WIFI_ASSERT_NOT_EQUAL_TO,
87 "num_tx_tokens_per_ac is zero");
88
89 spare_desc_indx = (desc % (sys_fpriv->num_tx_tokens_per_ac *
90 NRF_WIFI_FMAC_AC_MAX));
91
92 sys_dev_ctx->tx_config.spare_desc_queue_map &=
93 ~(1 << ((spare_desc_indx * SPARE_DESC_Q_MAP_SIZE) + tx_done_q));
94 }
95
96 /*Get the spare descriptor queue map */
get_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc)97 static unsigned short get_spare_desc_q_map(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
98 unsigned int desc)
99 {
100 unsigned short spare_desc_indx = 0;
101 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
102 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
103
104 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
105 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
106
107 spare_desc_indx = (desc % (sys_fpriv->num_tx_tokens_per_ac *
108 NRF_WIFI_FMAC_AC_MAX));
109
110 return (sys_dev_ctx->tx_config.spare_desc_queue_map >> (spare_desc_indx *
111 SPARE_DESC_Q_MAP_SIZE)) & 0x000F;
112 }
113
114
nrf_wifi_get_dest(void * nwb)115 static unsigned char *nrf_wifi_get_dest(void *nwb)
116 {
117 return nrf_wifi_osal_nbuf_data_get(nwb);
118 }
119
120
nrf_wifi_get_src(void * nwb)121 static unsigned char *nrf_wifi_get_src(void *nwb)
122 {
123 return (unsigned char *)nrf_wifi_osal_nbuf_data_get(nwb) + NRF_WIFI_FMAC_ETH_ADDR_LEN;
124 }
125
nrf_wifi_get_tid(void * nwb)126 static int nrf_wifi_get_tid(void *nwb)
127 {
128 unsigned short ether_type = 0;
129 int priority = 0;
130 unsigned short vlan_tci = 0;
131 unsigned char vlan_priority = 0;
132 unsigned int mpls_hdr = 0;
133 unsigned char mpls_tc_qos = 0;
134 unsigned char tos = 0;
135 unsigned char dscp = 0;
136 unsigned short ipv6_hdr = 0;
137 void *nwb_data = NULL;
138
139 nwb_data = nrf_wifi_osal_nbuf_data_get(nwb);
140
141 ether_type = nrf_wifi_util_tx_get_eth_type(nwb_data);
142
143 nwb_data = (unsigned char *)nrf_wifi_osal_nbuf_data_get(nwb) + NRF_WIFI_FMAC_ETH_HDR_LEN;
144
145 switch (ether_type & NRF_WIFI_FMAC_ETH_TYPE_MASK) {
146 /* If VLAN 802.1Q (0x8100) ||
147 * 802.1AD(0x88A8) FRAME calculate priority accordingly
148 */
149 case NRF_WIFI_FMAC_ETH_P_8021Q:
150 case NRF_WIFI_FMAC_ETH_P_8021AD:
151 vlan_tci = (((unsigned char *)nwb_data)[4] << 8) |
152 (((unsigned char *)nwb_data)[5]);
153 vlan_priority = ((vlan_tci & NRF_WIFI_FMAC_VLAN_PRIO_MASK)
154 >> NRF_WIFI_FMAC_VLAN_PRIO_SHIFT);
155 priority = vlan_priority;
156 break;
157 /* If MPLS MC(0x8840) / UC(0x8847) frame calculate priority
158 * accordingly
159 */
160 case NRF_WIFI_FMAC_ETH_P_MPLS_UC:
161 case NRF_WIFI_FMAC_ETH_P_MPLS_MC:
162 mpls_hdr = (((unsigned char *)nwb_data)[0] << 24) |
163 (((unsigned char *)nwb_data)[1] << 16) |
164 (((unsigned char *)nwb_data)[2] << 8) |
165 (((unsigned char *)nwb_data)[3]);
166 mpls_tc_qos = (mpls_hdr & (NRF_WIFI_FMAC_MPLS_LS_TC_MASK)
167 >> NRF_WIFI_FMAC_MPLS_LS_TC_SHIFT);
168 priority = mpls_tc_qos;
169 break;
170 /* If IP (0x0800) frame calculate priority accordingly */
171 case NRF_WIFI_FMAC_ETH_P_IP:
172 /*get the tos filed*//*DA+SA+ETH+(VER+IHL)*/
173 tos = (((unsigned char *)nwb_data)[1]);
174 /*get the dscp value */
175 dscp = (tos & 0xfc);
176 priority = dscp >> 5;
177 break;
178 case NRF_WIFI_FMAC_ETH_P_IPV6:
179 /* Get the TOS filled DA+SA+ETH */
180 ipv6_hdr = (((unsigned char *)nwb_data)[0] << 8) |
181 ((unsigned char *)nwb_data)[1];
182 dscp = (((ipv6_hdr & NRF_WIFI_FMAC_IPV6_TOS_MASK)
183 >> NRF_WIFI_FMAC_IPV6_TOS_SHIFT) & 0xfc);
184 priority = dscp >> 5;
185 break;
186 /* If Media Independent (0x8917)
187 * frame calculate priority accordingly.
188 */
189 case NRF_WIFI_FMAC_ETH_P_80221:
190 /* 802.21 is always network control traffic */
191 priority = 0x07;
192 break;
193 default:
194 priority = 0;
195 }
196
197 return priority;
198 }
199
200
pending_frames_count(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int peer_id)201 int pending_frames_count(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
202 int peer_id)
203 {
204 int count = 0;
205 int ac = 0;
206 void *queue = NULL;
207 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
208
209 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
210
211 for (ac = NRF_WIFI_FMAC_AC_VO; ac >= 0; --ac) {
212 queue = sys_dev_ctx->tx_config.data_pending_txq[peer_id][ac];
213 count += nrf_wifi_utils_q_len(queue);
214 }
215
216 return count;
217 }
218
219
update_pend_q_bmp(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int ac,int peer_id)220 static enum nrf_wifi_status update_pend_q_bmp(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
221 unsigned int ac,
222 int peer_id)
223 {
224 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
225 struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
226 void *pend_pkt_q = NULL;
227 int len = 0;
228 unsigned char vif_id = 0;
229 unsigned char *bmp = NULL;
230 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
231
232 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
233
234 if (!fmac_dev_ctx) {
235 goto out;
236 }
237
238 vif_id = sys_dev_ctx->tx_config.peers[peer_id].if_idx;
239 vif_ctx = sys_dev_ctx->vif_ctx[vif_id];
240
241 if (vif_ctx->if_type == NRF_WIFI_IFTYPE_AP &&
242 peer_id < MAX_PEERS) {
243 const unsigned int bitmap_offset = offsetof(struct sap_client_pend_frames_bitmap,
244 pend_frames_bitmap);
245 const unsigned char *rpu_addr = (unsigned char *)RPU_MEM_UMAC_PEND_Q_BMP +
246 (sizeof(struct sap_client_pend_frames_bitmap) * peer_id) +
247 bitmap_offset;
248
249 bmp = &sys_dev_ctx->tx_config.peers[peer_id].pend_q_bmp;
250 pend_pkt_q = sys_dev_ctx->tx_config.data_pending_txq[peer_id][ac];
251
252 len = nrf_wifi_utils_q_len(pend_pkt_q);
253
254 if (len == 0) {
255 *bmp = *bmp & ~(1 << ac);
256 } else {
257 *bmp = *bmp | (1 << ac);
258 }
259
260 status = hal_rpu_mem_write(fmac_dev_ctx->hal_dev_ctx,
261 (unsigned long)rpu_addr,
262 bmp,
263 4); /* For alignment */
264 } else {
265 status = NRF_WIFI_STATUS_SUCCESS;
266 }
267 out:
268 return status;
269 }
270
271
tx_desc_free(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc,int queue)272 static void tx_desc_free(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
273 unsigned int desc,
274 int queue)
275 {
276 struct nrf_wifi_fmac_priv *fpriv = NULL;
277 int bit = -1;
278 int pool_id = -1;
279 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
280 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
281
282 fpriv = fmac_dev_ctx->fpriv;
283
284 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
285 sys_fpriv = wifi_fmac_priv(fpriv);
286
287 bit = (desc % TX_DESC_BUCKET_BOUND);
288 pool_id = (desc / TX_DESC_BUCKET_BOUND);
289
290 if (!(sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] & (1 << bit))) {
291 return;
292 }
293
294 sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] &= (~(1 << bit));
295
296 sys_dev_ctx->tx_config.outstanding_descs[queue]--;
297
298 if (desc >= (sys_fpriv->num_tx_tokens_per_ac * NRF_WIFI_FMAC_AC_MAX)) {
299 clear_spare_desc_q_map(fmac_dev_ctx, desc, queue);
300 }
301
302 }
303
304
tx_desc_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int queue)305 unsigned int tx_desc_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
306 int queue)
307 {
308 struct nrf_wifi_fmac_priv *fpriv = NULL;
309 unsigned int cnt = 0;
310 int curr_bit = 0;
311 unsigned int desc = 0;
312 int pool_id = 0;
313 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
314 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
315
316 fpriv = fmac_dev_ctx->fpriv;
317 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
318 sys_fpriv = wifi_fmac_priv(fpriv);
319
320 desc = sys_fpriv->num_tx_tokens;
321
322 /* First search for a reserved desc */
323
324 for (cnt = 0; cnt < sys_fpriv->num_tx_tokens_per_ac; cnt++) {
325 curr_bit = ((queue + (NRF_WIFI_FMAC_AC_MAX * cnt)));
326 curr_bit = ((queue + (NRF_WIFI_FMAC_AC_MAX * cnt)) % TX_DESC_BUCKET_BOUND);
327 pool_id = ((queue + (NRF_WIFI_FMAC_AC_MAX * cnt)) / TX_DESC_BUCKET_BOUND);
328
329 if ((((sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] >>
330 curr_bit)) & 1)) {
331 continue;
332 } else {
333 sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] |=
334 (1 << curr_bit);
335 desc = queue + (NRF_WIFI_FMAC_AC_MAX * cnt);
336 sys_dev_ctx->tx_config.outstanding_descs[queue]++;
337 break;
338 }
339 }
340
341 /* If reserved desc is not found search for a spare desc
342 * (only for non beacon queues)
343 */
344 if (cnt == sys_fpriv->num_tx_tokens_per_ac) {
345 for (desc = sys_fpriv->num_tx_tokens_per_ac * NRF_WIFI_FMAC_AC_MAX;
346 desc < sys_fpriv->num_tx_tokens;
347 desc++) {
348 curr_bit = (desc % TX_DESC_BUCKET_BOUND);
349 pool_id = (desc / TX_DESC_BUCKET_BOUND);
350
351 if ((sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] >> curr_bit) & 1) {
352 continue;
353 } else {
354 sys_dev_ctx->tx_config.buf_pool_bmp_p[pool_id] |=
355 (1 << curr_bit);
356 sys_dev_ctx->tx_config.outstanding_descs[queue]++;
357 /* Keep a note which queue has been assigned the
358 * spare desc. Need for processing of TX_DONE
359 * event as queue number is not being provided
360 * by UMAC.
361 * First nibble epresent first spare desc
362 * (B3B2B1B0: VO-VI-BE-BK)
363 * Second nibble represent second spare desc
364 * (B7B6B5B4 : V0-VI-BE-BK)
365 * Third nibble represent second spare desc
366 * (B11B10B9B8 : V0-VI-BE-BK)
367 * Fourth nibble represent second spare desc
368 * (B15B14B13B12 : V0-VI-BE-BK)
369 */
370 set_spare_desc_q_map(fmac_dev_ctx, desc, queue);
371 break;
372 }
373 }
374 }
375
376
377 return desc;
378 }
379
380
tx_aggr_check(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * first_nwb,int ac,int peer)381 static int tx_aggr_check(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
382 void *first_nwb,
383 int ac,
384 int peer)
385 {
386 void *nwb = NULL;
387 void *pending_pkt_queue = NULL;
388 bool aggr = true;
389 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
390
391 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
392
393 if (sys_dev_ctx->tx_config.peers[peer].is_legacy) {
394 return false;
395 }
396
397 #ifdef NRF70_RAW_DATA_TX
398 if (sys_dev_ctx->raw_tx_config.raw_tx_flag) {
399 return false;
400 }
401 #endif /* NRF70_RAW_DATA_TX */
402
403 pending_pkt_queue = sys_dev_ctx->tx_config.data_pending_txq[peer][ac];
404
405 if (nrf_wifi_utils_q_len(pending_pkt_queue) == 0) {
406 return false;
407 }
408
409 nwb = nrf_wifi_utils_q_peek(pending_pkt_queue);
410
411 if (nwb) {
412 if (!nrf_wifi_util_ether_addr_equal(nrf_wifi_get_dest(nwb),
413 nrf_wifi_get_dest(first_nwb))) {
414 aggr = false;
415 }
416
417 if (!nrf_wifi_util_ether_addr_equal(nrf_wifi_get_src(nwb),
418 nrf_wifi_get_src(first_nwb))) {
419 aggr = false;
420 }
421 }
422
423
424 return aggr;
425 }
426
427
get_peer_from_wakeup_q(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int ac)428 static int get_peer_from_wakeup_q(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
429 unsigned int ac)
430 {
431 int peer_id = -1;
432 struct peers_info *peer = NULL;
433 void *pend_q = NULL;
434 unsigned int pend_q_len;
435 void *client_q = NULL;
436 void *list_node = NULL;
437 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
438
439 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
440
441 client_q = sys_dev_ctx->tx_config.wakeup_client_q;
442
443 list_node = nrf_wifi_osal_llist_get_node_head(client_q);
444
445 while (list_node) {
446 peer = nrf_wifi_osal_llist_node_data_get(list_node);
447
448 if (peer != NULL && peer->ps_token_count) {
449
450 pend_q = sys_dev_ctx->tx_config.data_pending_txq[peer->peer_id][ac];
451 pend_q_len = nrf_wifi_utils_q_len(pend_q);
452
453 if (pend_q_len) {
454 peer->ps_token_count--;
455 return peer->peer_id;
456 }
457 }
458
459 list_node = nrf_wifi_osal_llist_get_node_nxt(client_q,
460 list_node);
461 }
462
463 return peer_id;
464 }
465
466
tx_curr_peer_opp_get(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int ac)467 static int tx_curr_peer_opp_get(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
468 unsigned int ac)
469 {
470 unsigned int i = 0;
471 unsigned int curr_peer_opp = 0;
472 unsigned int init_peer_opp = 0;
473 unsigned int pend_q_len;
474 void *pend_q = NULL;
475 int peer_id = -1;
476 unsigned char ps_state = 0;
477 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
478
479 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
480
481 if (ac == NRF_WIFI_FMAC_AC_MC) {
482 return MAX_PEERS;
483 }
484
485 #ifdef NRF70_RAW_DATA_TX
486 if (sys_dev_ctx->raw_tx_config.raw_tx_flag) {
487 return MAX_PEERS;
488 }
489 #endif /* NRF70_RAW_DATA_TX */
490
491 peer_id = get_peer_from_wakeup_q(fmac_dev_ctx, ac);
492
493 if (peer_id != -1) {
494 return peer_id;
495 }
496
497 init_peer_opp = sys_dev_ctx->tx_config.curr_peer_opp[ac];
498
499 for (i = 0; i < MAX_PEERS; i++) {
500 curr_peer_opp = (init_peer_opp + i) % MAX_PEERS;
501
502 ps_state = sys_dev_ctx->tx_config.peers[curr_peer_opp].ps_state;
503
504 if (ps_state == NRF_WIFI_CLIENT_PS_MODE) {
505 continue;
506 }
507
508 pend_q = sys_dev_ctx->tx_config.data_pending_txq[curr_peer_opp][ac];
509 pend_q_len = nrf_wifi_utils_q_len(pend_q);
510
511 if (pend_q_len) {
512 sys_dev_ctx->tx_config.curr_peer_opp[ac] =
513 (curr_peer_opp + 1) % MAX_PEERS;
514 break;
515 }
516 }
517
518 if (i != MAX_PEERS) {
519 peer_id = curr_peer_opp;
520 }
521
522 return peer_id;
523 }
524
_tx_pending_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc,unsigned int ac)525 static size_t _tx_pending_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
526 unsigned int desc,
527 unsigned int ac)
528 {
529 int len = 0;
530 void *pend_pkt_q = NULL;
531 void *txq = NULL;
532 struct tx_pkt_info *pkt_info = NULL;
533 int peer_id = -1;
534 void *nwb = NULL;
535 void *first_nwb = NULL;
536
537 int max_txq_len, avail_ampdu_len_per_token;
538 int ampdu_len = 0;
539 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
540 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
541
542 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
543 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
544
545 max_txq_len = sys_fpriv->data_config.max_tx_aggregation;
546 avail_ampdu_len_per_token = sys_fpriv->avail_ampdu_len_per_token;
547
548 peer_id = tx_curr_peer_opp_get(fmac_dev_ctx, ac);
549
550 /* No pending frames for any peer in that AC. */
551 if (peer_id == -1) {
552 return 0;
553 }
554
555 pend_pkt_q = sys_dev_ctx->tx_config.data_pending_txq[peer_id][ac];
556
557 if (nrf_wifi_utils_q_len(pend_pkt_q) == 0) {
558 return 0;
559 }
560
561 pkt_info = &sys_dev_ctx->tx_config.pkt_info_p[desc];
562 txq = pkt_info->pkt;
563
564 /* Aggregate Only MPDU's with same RA, same Rate,
565 * same Rate flags, same Tx Info flags
566 */
567 if (nrf_wifi_utils_q_len(pend_pkt_q)) {
568 first_nwb = nrf_wifi_utils_q_peek(pend_pkt_q);
569 }
570
571 while (nrf_wifi_utils_q_len(pend_pkt_q)) {
572 nwb = nrf_wifi_utils_q_peek(pend_pkt_q);
573
574 ampdu_len += TX_BUF_HEADROOM +
575 nrf_wifi_osal_nbuf_data_size((void *)nwb);
576
577 if (ampdu_len >= avail_ampdu_len_per_token) {
578 break;
579 }
580
581 if (!can_xmit(fmac_dev_ctx, nwb) ||
582 (!tx_aggr_check(fmac_dev_ctx, first_nwb, ac, peer_id)) ||
583 (nrf_wifi_utils_q_len(txq) >= max_txq_len)) {
584 break;
585 }
586
587 nwb = nrf_wifi_utils_q_dequeue(pend_pkt_q);
588
589 nrf_wifi_utils_list_add_tail(txq,
590 nwb);
591 }
592
593 /* If our criterion rejects all pending frames, or
594 * pend_q is empty, send only 1
595 */
596 if (!nrf_wifi_utils_q_len(txq)) {
597 nwb = nrf_wifi_utils_q_peek(pend_pkt_q);
598
599 if (!nwb || !can_xmit(fmac_dev_ctx, nwb)) {
600 return 0;
601 }
602
603 nwb = nrf_wifi_utils_q_dequeue(pend_pkt_q);
604
605 nrf_wifi_utils_list_add_tail(txq,
606 nwb);
607 }
608
609 len = nrf_wifi_utils_q_len(txq);
610
611 if (len > 0) {
612 sys_dev_ctx->tx_config.pkt_info_p[desc].peer_id = peer_id;
613 }
614
615 update_pend_q_bmp(fmac_dev_ctx, ac, peer_id);
616
617 return len;
618 }
619
620 #ifdef NRF70_RAW_DATA_TX
rawtx_cmd_prep_callbk_fn(void * callbk_data,void * nbuf)621 enum nrf_wifi_status rawtx_cmd_prep_callbk_fn(void *callbk_data,
622 void *nbuf)
623 {
624 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
625 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
626 struct nrf_wifi_fmac_buf_map_info *tx_buf_info = NULL;
627 unsigned long nwb = 0;
628 unsigned long nwb_data = 0;
629 unsigned long phy_addr = 0;
630 struct tx_cmd_prep_raw_info *info = NULL;
631 struct nrf_wifi_cmd_raw_tx *config = NULL;
632 unsigned int desc_id = 0;
633 unsigned int buf_len = 0;
634 unsigned char frame_indx = 0;
635 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
636 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
637
638 info = (struct tx_cmd_prep_raw_info *)callbk_data;
639 fmac_dev_ctx = info->fmac_dev_ctx;
640 config = info->raw_config;
641 frame_indx = info->num_tx_pkts;
642
643 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
644 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
645 nwb = (unsigned long)nbuf;
646 desc_id = (config->raw_tx_info.desc_num *
647 sys_fpriv->data_config.max_tx_aggregation) + frame_indx;
648
649 tx_buf_info = &sys_dev_ctx->tx_buf_info[desc_id];
650 if (tx_buf_info->mapped) {
651 nrf_wifi_osal_log_err("%s: Raw init_TX cmd called for already mapped TX buffer(%d)",
652 __func__,
653 desc_id);
654
655 status = NRF_WIFI_STATUS_FAIL;
656 goto out;
657 }
658
659 nwb_data = (unsigned long)nrf_wifi_osal_nbuf_data_get((void *)nwb);
660 buf_len = nrf_wifi_osal_nbuf_data_size((void *)nwb);
661
662 phy_addr = nrf_wifi_sys_hal_buf_map_tx(fmac_dev_ctx->hal_dev_ctx,
663 nwb_data,
664 buf_len,
665 desc_id,
666 config->raw_tx_info.desc_num,
667 frame_indx);
668 if (!phy_addr) {
669 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_map_tx failed",
670 __func__);
671 status = NRF_WIFI_STATUS_FAIL;
672 goto out;
673 }
674
675 tx_buf_info->nwb = nwb;
676 tx_buf_info->mapped = true;
677 config->raw_tx_info.frame_ddr_pointer = (unsigned long long)phy_addr;
678 config->raw_tx_info.pkt_length = buf_len;
679 info->num_tx_pkts++;
680
681 status = NRF_WIFI_STATUS_SUCCESS;
682 out:
683 return status;
684 }
685 #endif /* NRF70_RAW_DATA_TX */
686
tx_cmd_prep_callbk_fn(void * callbk_data,void * nbuf)687 static enum nrf_wifi_status tx_cmd_prep_callbk_fn(void *callbk_data,
688 void *nbuf)
689 {
690 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
691 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
692 struct nrf_wifi_fmac_buf_map_info *tx_buf_info = NULL;
693 unsigned long nwb = 0;
694 unsigned long nwb_data = 0;
695 unsigned long phy_addr = 0;
696 struct tx_cmd_prep_info *info = NULL;
697 struct nrf_wifi_tx_buff *config = NULL;
698 unsigned int desc_id = 0;
699 unsigned int buf_len = 0;
700 unsigned char frame_indx = 0;
701 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
702 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
703
704 info = (struct tx_cmd_prep_info *)callbk_data;
705 fmac_dev_ctx = info->fmac_dev_ctx;
706
707 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
708 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
709
710 config = info->config;
711 frame_indx = config->num_tx_pkts;
712
713 nwb = (unsigned long)nbuf;
714
715 desc_id = (config->tx_desc_num *
716 sys_fpriv->data_config.max_tx_aggregation) + frame_indx;
717
718 tx_buf_info = &sys_dev_ctx->tx_buf_info[desc_id];
719
720 if (tx_buf_info->mapped) {
721 nrf_wifi_osal_log_err("%s: Init_TX cmd called for already mapped TX buffer(%d)",
722 __func__,
723 desc_id);
724
725 status = NRF_WIFI_STATUS_FAIL;
726 goto out;
727 }
728
729 nwb_data = (unsigned long)nrf_wifi_osal_nbuf_data_get((void *)nwb);
730
731 buf_len = nrf_wifi_osal_nbuf_data_size((void *)nwb);
732
733 phy_addr = nrf_wifi_sys_hal_buf_map_tx(fmac_dev_ctx->hal_dev_ctx,
734 nwb_data,
735 buf_len,
736 desc_id,
737 config->tx_desc_num,
738 frame_indx);
739
740 if (!phy_addr) {
741 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_map_tx failed",
742 __func__);
743 status = NRF_WIFI_STATUS_FAIL;
744 goto out;
745 }
746
747 tx_buf_info->nwb = nwb;
748 tx_buf_info->mapped = true;
749
750 config->tx_buff_info[frame_indx].ddr_ptr =
751 (unsigned long long)phy_addr;
752
753 config->tx_buff_info[frame_indx].pkt_length = buf_len;
754 config->num_tx_pkts++;
755
756 status = NRF_WIFI_STATUS_SUCCESS;
757 out:
758 return status;
759 }
760
761 #ifdef NRF70_RAW_DATA_TX
rawtx_cmd_prepare(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct host_rpu_msg * umac_cmd,int desc,void * txq,int peer_id)762 enum nrf_wifi_status rawtx_cmd_prepare(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
763 struct host_rpu_msg *umac_cmd,
764 int desc,
765 void *txq,
766 int peer_id)
767 {
768 struct nrf_wifi_cmd_raw_tx *config = NULL;
769 int len = 0;
770 void *nwb = NULL;
771 unsigned int txq_len = 0;
772 struct tx_cmd_prep_raw_info info;
773 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
774 unsigned char vif_id;
775 struct nrf_wifi_fmac_vif_ctx *vif_ctx;
776 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
777
778 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
779 vif_id = sys_dev_ctx->tx_config.peers[peer_id].if_idx;
780 vif_ctx = sys_dev_ctx->vif_ctx[vif_id];
781
782 txq_len = nrf_wifi_utils_list_len(txq);
783 if (txq_len == 0) {
784 nrf_wifi_osal_log_err("%s: txq_len = %d\n",
785 __func__,
786 txq_len);
787 goto err;
788 }
789
790 nwb = nrf_wifi_utils_list_peek(txq);
791 /**
792 * Pull the Raw packet header and only send the buffer to the UMAC
793 * with the parameters configured to the UMAC
794 */
795 nrf_wifi_osal_nbuf_data_pull(nwb,
796 sizeof(struct raw_tx_pkt_header));
797
798 sys_dev_ctx->tx_config.send_pkt_coalesce_count_p[desc] = txq_len;
799 config = (struct nrf_wifi_cmd_raw_tx *)(umac_cmd->msg);
800 len = nrf_wifi_osal_nbuf_data_size(nwb);
801
802 config->sys_head.cmd_event = NRF_WIFI_CMD_RAW_TX_PKT;
803 config->sys_head.len = sizeof(*config);
804 config->if_index = vif_id;
805 config->raw_tx_info.desc_num = desc;
806 config->raw_tx_info.queue_num = sys_dev_ctx->raw_tx_config.queue;
807 if (len != sys_dev_ctx->raw_tx_config.packet_length) {
808 goto err;
809 }
810 config->raw_tx_info.pkt_length = len;
811 config->raw_tx_info.rate = sys_dev_ctx->raw_tx_config.data_rate;
812 config->raw_tx_info.rate_flags = sys_dev_ctx->raw_tx_config.tx_mode;
813
814 info.fmac_dev_ctx = fmac_dev_ctx;
815 info.raw_config = config;
816 info.num_tx_pkts = 0;
817
818 status = nrf_wifi_utils_list_traverse(txq,
819 &info,
820 rawtx_cmd_prep_callbk_fn);
821 if (status != NRF_WIFI_STATUS_SUCCESS) {
822 nrf_wifi_osal_log_err("%s: failed",
823 __func__);
824 goto err;
825 }
826 sys_dev_ctx->host_stats.total_tx_pkts += info.num_tx_pkts;
827
828 return NRF_WIFI_STATUS_SUCCESS;
829 err:
830 return NRF_WIFI_STATUS_FAIL;
831 }
832 #endif /* NRF70_RAW_DATA_TX */
833
tx_cmd_prepare(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct host_rpu_msg * umac_cmd,int desc,void * txq,int peer_id)834 static enum nrf_wifi_status tx_cmd_prepare(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
835 struct host_rpu_msg *umac_cmd,
836 int desc,
837 void *txq,
838 int peer_id)
839 {
840 struct nrf_wifi_tx_buff *config = NULL;
841 int len = 0;
842 void *nwb = NULL;
843 void *nwb_data = NULL;
844 unsigned int txq_len = 0;
845 unsigned char *data = NULL;
846 struct tx_cmd_prep_info info;
847 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
848 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
849 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
850 unsigned char vif_id;
851 struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
852
853 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
854 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
855
856 vif_id = sys_dev_ctx->tx_config.peers[peer_id].if_idx;
857 vif_ctx = sys_dev_ctx->vif_ctx[vif_id];
858
859 txq_len = nrf_wifi_utils_list_len(txq);
860
861 if (txq_len == 0) {
862 nrf_wifi_osal_log_err("%s: txq_len = %d",
863 __func__,
864 txq_len);
865 goto err;
866 }
867
868 nwb = nrf_wifi_utils_list_peek(txq);
869
870 sys_dev_ctx->tx_config.send_pkt_coalesce_count_p[desc] = txq_len;
871
872 config = (struct nrf_wifi_tx_buff *)(umac_cmd->msg);
873
874 data = nrf_wifi_osal_nbuf_data_get(nwb);
875
876 len = nrf_wifi_osal_nbuf_data_size(nwb);
877
878 config->umac_head.cmd = NRF_WIFI_CMD_TX_BUFF;
879
880 config->umac_head.len += sizeof(struct nrf_wifi_tx_buff);
881 config->umac_head.len += sizeof(struct nrf_wifi_tx_buff_info) * txq_len;
882
883 config->tx_desc_num = desc;
884
885 nrf_wifi_osal_mem_cpy(config->mac_hdr_info.dest,
886 nrf_wifi_get_dest(nwb),
887 NRF_WIFI_ETH_ADDR_LEN);
888
889 nrf_wifi_osal_mem_cpy(config->mac_hdr_info.src,
890 nrf_wifi_get_src(nwb),
891 NRF_WIFI_ETH_ADDR_LEN);
892
893 nwb_data = nrf_wifi_osal_nbuf_data_get(nwb);
894 config->mac_hdr_info.etype =
895 nrf_wifi_util_tx_get_eth_type(nwb_data);
896
897 config->mac_hdr_info.tx_flags =
898 nrf_wifi_get_tid(nwb) & NRF_WIFI_TX_FLAGS_DSCP_TOS_MASK;
899
900 if (is_twt_emergency_pkt(nwb)) {
901 config->mac_hdr_info.tx_flags |= NRF_WIFI_TX_FLAG_TWT_EMERGENCY_TX;
902 }
903
904 if (nrf_wifi_osal_nbuf_get_chksum_done(nwb)) {
905 config->mac_hdr_info.tx_flags |= NRF_WIFI_TX_FLAG_CHKSUM_AVAILABLE;
906 }
907
908 config->num_tx_pkts = 0;
909
910 info.fmac_dev_ctx = fmac_dev_ctx;
911 info.config = config;
912
913 status = nrf_wifi_utils_list_traverse(txq,
914 &info,
915 tx_cmd_prep_callbk_fn);
916
917 if (status != NRF_WIFI_STATUS_SUCCESS) {
918 nrf_wifi_osal_log_err("%s: build_mac80211_hdr failed",
919 __func__);
920 goto err;
921 }
922
923 sys_dev_ctx->host_stats.total_tx_pkts += config->num_tx_pkts;
924 config->wdev_id = sys_dev_ctx->tx_config.peers[peer_id].if_idx;
925
926 if ((vif_ctx->if_type == NRF_WIFI_IFTYPE_AP ||
927 vif_ctx->if_type == NRF_WIFI_IFTYPE_AP_VLAN ||
928 vif_ctx->if_type == NRF_WIFI_IFTYPE_MESH_POINT) &&
929 pending_frames_count(fmac_dev_ctx, peer_id) != 0) {
930 config->mac_hdr_info.more_data = 1;
931 }
932
933 if (sys_dev_ctx->tx_config.peers[peer_id].ps_token_count == 0) {
934 nrf_wifi_utils_list_del_node(sys_dev_ctx->tx_config.wakeup_client_q,
935 &sys_dev_ctx->tx_config.peers[peer_id]);
936
937 config->mac_hdr_info.eosp = 1;
938
939 } else {
940 config->mac_hdr_info.eosp = 0;
941 }
942
943 return NRF_WIFI_STATUS_SUCCESS;
944 err:
945 return NRF_WIFI_STATUS_FAIL;
946 }
947
948 #ifdef NRF70_RAW_DATA_TX
rawtx_cmd_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * txq,int desc,int peer_id)949 enum nrf_wifi_status rawtx_cmd_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
950 void *txq,
951 int desc,
952 int peer_id)
953 {
954 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
955 struct host_rpu_msg *umac_cmd = NULL;
956 unsigned int len = 0;
957 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
958
959 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
960
961 len += sizeof(struct nrf_wifi_cmd_raw_tx);
962 len *= nrf_wifi_utils_list_len(txq);
963
964 umac_cmd = umac_cmd_alloc(fmac_dev_ctx,
965 NRF_WIFI_HOST_RPU_MSG_TYPE_SYSTEM,
966 len);
967
968 status = rawtx_cmd_prepare(fmac_dev_ctx,
969 umac_cmd,
970 desc,
971 txq,
972 peer_id);
973 if (status != NRF_WIFI_STATUS_SUCCESS) {
974 nrf_wifi_osal_log_err("%s: rawtx_cmd_prepare failed",
975 __func__);
976
977 goto out;
978 }
979
980 status = nrf_wifi_hal_ctrl_cmd_send(fmac_dev_ctx->hal_dev_ctx,
981 umac_cmd,
982 (sizeof(*umac_cmd) + len));
983
984 /* clear the raw tx config data */
985 nrf_wifi_osal_mem_set(&sys_dev_ctx->raw_tx_config,
986 0, sizeof(struct raw_tx_pkt_header));
987 out:
988 return status;
989 }
990 #endif /* NRF70_RAW_DATA_TX */
991
tx_cmd_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * txq,int desc,int peer_id)992 enum nrf_wifi_status tx_cmd_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
993 void *txq,
994 int desc,
995 int peer_id)
996 {
997 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
998 struct host_rpu_msg *umac_cmd = NULL;
999 unsigned int len = 0;
1000
1001 len += sizeof(struct nrf_wifi_tx_buff_info);
1002 len *= nrf_wifi_utils_list_len(txq);
1003
1004 len += sizeof(struct nrf_wifi_tx_buff);
1005
1006 umac_cmd = umac_cmd_alloc(fmac_dev_ctx,
1007 NRF_WIFI_HOST_RPU_MSG_TYPE_DATA,
1008 len);
1009
1010 status = tx_cmd_prepare(fmac_dev_ctx,
1011 umac_cmd,
1012 desc,
1013 txq,
1014 peer_id);
1015
1016 if (status != NRF_WIFI_STATUS_SUCCESS) {
1017 nrf_wifi_osal_log_err("%s: tx_cmd_prepare failed",
1018 __func__);
1019
1020 goto out;
1021 }
1022
1023 status = nrf_wifi_sys_hal_data_cmd_send(fmac_dev_ctx->hal_dev_ctx,
1024 NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_TX,
1025 umac_cmd,
1026 sizeof(*umac_cmd) + len,
1027 desc,
1028 0);
1029
1030 nrf_wifi_osal_mem_free(umac_cmd);
1031 out:
1032 return status;
1033 }
1034
1035
tx_pending_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc,unsigned int ac)1036 enum nrf_wifi_status tx_pending_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1037 unsigned int desc,
1038 unsigned int ac)
1039 {
1040 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1041 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1042
1043 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1044
1045 if (!fmac_dev_ctx) {
1046 nrf_wifi_osal_log_err("%s: Invalid params",
1047 __func__);
1048 goto out;
1049 }
1050
1051 if (_tx_pending_process(fmac_dev_ctx, desc, ac)) {
1052 #ifdef NRF70_RAW_DATA_TX
1053 if (!sys_dev_ctx->raw_tx_config.raw_tx_flag) {
1054 #endif
1055 status = tx_cmd_init(fmac_dev_ctx,
1056 sys_dev_ctx->tx_config.pkt_info_p[desc].pkt,
1057 desc,
1058 sys_dev_ctx->tx_config.pkt_info_p[desc].peer_id);
1059 #ifdef NRF70_RAW_DATA_TX
1060 } else {
1061 status = rawtx_cmd_init(fmac_dev_ctx,
1062 sys_dev_ctx->tx_config.pkt_info_p[desc].pkt,
1063 desc,
1064 sys_dev_ctx->tx_config.pkt_info_p[desc].peer_id);
1065 }
1066 #endif
1067 } else {
1068 tx_desc_free(fmac_dev_ctx,
1069 desc,
1070 ac);
1071
1072 status = NRF_WIFI_STATUS_SUCCESS;
1073 }
1074
1075 out:
1076 return status;
1077 }
1078
1079
tx_enqueue(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,void * nwb,unsigned int ac,unsigned int peer_id)1080 static enum nrf_wifi_status tx_enqueue(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1081 void *nwb,
1082 unsigned int ac,
1083 unsigned int peer_id)
1084 {
1085 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1086 void *queue = NULL;
1087 int qlen = 0;
1088 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1089
1090 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1091
1092 if (!fmac_dev_ctx || !nwb) {
1093 nrf_wifi_osal_log_err("%s: Invalid params",
1094 __func__);
1095 goto out;
1096 }
1097
1098 queue = sys_dev_ctx->tx_config.data_pending_txq[peer_id][ac];
1099
1100 qlen = nrf_wifi_utils_q_len(queue);
1101
1102 if (qlen >= NRF70_MAX_TX_PENDING_QLEN) {
1103 goto out;
1104 }
1105
1106 if (is_twt_emergency_pkt(nwb)) {
1107 nrf_wifi_utils_q_enqueue_head(queue,
1108 nwb);
1109 } else {
1110 nrf_wifi_utils_q_enqueue(queue,
1111 nwb);
1112 }
1113
1114 status = update_pend_q_bmp(fmac_dev_ctx, ac, peer_id);
1115
1116 out:
1117 return status;
1118 }
1119
1120
tx_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char if_idx,void * nbuf,unsigned int ac,unsigned int peer_id)1121 static enum nrf_wifi_fmac_tx_status tx_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1122 unsigned char if_idx,
1123 void *nbuf,
1124 unsigned int ac,
1125 unsigned int peer_id)
1126 {
1127 enum nrf_wifi_fmac_tx_status status;
1128 struct nrf_wifi_fmac_priv *fpriv = NULL;
1129 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1130 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1131 void *pend_pkt_q = NULL;
1132 void *first_nwb = NULL;
1133 unsigned char ps_state = 0;
1134 bool aggr_status = false;
1135 int max_cmds = 0;
1136
1137 fpriv = fmac_dev_ctx->fpriv;
1138 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1139 sys_fpriv = wifi_fmac_priv(fpriv);
1140
1141 status = (enum nrf_wifi_fmac_tx_status)tx_enqueue(fmac_dev_ctx,
1142 nbuf,
1143 ac,
1144 peer_id);
1145
1146 if (status != NRF_WIFI_FMAC_TX_STATUS_SUCCESS) {
1147 goto err;
1148 }
1149
1150 ps_state = sys_dev_ctx->tx_config.peers[peer_id].ps_state;
1151
1152 if (ps_state == NRF_WIFI_CLIENT_PS_MODE) {
1153 goto out;
1154 }
1155
1156 pend_pkt_q = sys_dev_ctx->tx_config.data_pending_txq[peer_id][ac];
1157
1158 /* If outstanding_descs for a particular
1159 * access category >= NUM_TX_DESCS_PER_AC means there are already
1160 * pending packets for that access category. So now see if frames
1161 * can be aggregated depending upon access category depending
1162 * upon SA, RA & AC
1163 */
1164
1165 if ((sys_dev_ctx->tx_config.outstanding_descs[ac]) >= sys_fpriv->num_tx_tokens_per_ac) {
1166 if (nrf_wifi_utils_q_len(pend_pkt_q)) {
1167 first_nwb = nrf_wifi_utils_q_peek(pend_pkt_q);
1168
1169 aggr_status = true;
1170
1171 if (!nrf_wifi_util_ether_addr_equal(nrf_wifi_get_dest(nbuf),
1172 nrf_wifi_get_dest(first_nwb))) {
1173 aggr_status = false;
1174 }
1175
1176 if (!nrf_wifi_util_ether_addr_equal(nrf_wifi_get_src(nbuf),
1177 nrf_wifi_get_src(first_nwb))) {
1178 aggr_status = false;
1179 }
1180 }
1181
1182 if (aggr_status) {
1183 max_cmds = sys_fpriv->data_config.max_tx_aggregation;
1184
1185 if (nrf_wifi_utils_q_len(pend_pkt_q) < max_cmds) {
1186 goto out;
1187 }
1188 }
1189 }
1190 return NRF_WIFI_FMAC_TX_STATUS_SUCCESS;
1191 out:
1192 return NRF_WIFI_FMAC_TX_STATUS_QUEUED;
1193 err:
1194 return NRF_WIFI_FMAC_TX_STATUS_FAIL;
1195 }
1196
1197
tx_buff_req_free(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int tx_desc_num,unsigned char * ac)1198 unsigned int tx_buff_req_free(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1199 unsigned int tx_desc_num,
1200 unsigned char *ac)
1201 {
1202 unsigned int pkts_pend = 0;
1203 unsigned int desc = tx_desc_num;
1204 int tx_done_q = 0, start_ac, end_ac, cnt = 0;
1205 unsigned short tx_done_spare_desc_q_map = 0;
1206 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1207 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1208
1209 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1210 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
1211
1212 /* Determine the Queue from the descriptor */
1213 /* Reserved desc */
1214 if (desc < (sys_fpriv->num_tx_tokens_per_ac * NRF_WIFI_FMAC_AC_MAX)) {
1215 tx_done_q = (desc % NRF_WIFI_FMAC_AC_MAX);
1216 start_ac = end_ac = tx_done_q;
1217 } else {
1218 /* Derive the queue here as it is not given by UMAC. */
1219 if (desc >= (sys_fpriv->num_tx_tokens_per_ac * NRF_WIFI_FMAC_AC_MAX)) {
1220 tx_done_spare_desc_q_map = get_spare_desc_q_map(fmac_dev_ctx, desc);
1221
1222 if (tx_done_spare_desc_q_map & (1 << NRF_WIFI_FMAC_AC_BK))
1223 tx_done_q = NRF_WIFI_FMAC_AC_BK;
1224 else if (tx_done_spare_desc_q_map & (1 << NRF_WIFI_FMAC_AC_BE))
1225 tx_done_q = NRF_WIFI_FMAC_AC_BE;
1226 else if (tx_done_spare_desc_q_map & (1 << NRF_WIFI_FMAC_AC_VI))
1227 tx_done_q = NRF_WIFI_FMAC_AC_VI;
1228 else if (tx_done_spare_desc_q_map & (1 << NRF_WIFI_FMAC_AC_VO))
1229 tx_done_q = NRF_WIFI_FMAC_AC_VO;
1230 }
1231
1232 /* Spare desc:
1233 * Loop through all AC's
1234 */
1235 start_ac = NRF_WIFI_FMAC_AC_VO;
1236 end_ac = NRF_WIFI_FMAC_AC_BK;
1237 }
1238
1239 for (cnt = start_ac; cnt >= end_ac; cnt--) {
1240 pkts_pend = _tx_pending_process(fmac_dev_ctx, desc, cnt);
1241
1242 if (pkts_pend) {
1243 *ac = (unsigned char)cnt;
1244
1245 /* Spare Token Case*/
1246 if (tx_done_q != *ac) {
1247 /* Adjust the counters */
1248 sys_dev_ctx->tx_config.outstanding_descs[tx_done_q]--;
1249 sys_dev_ctx->tx_config.outstanding_descs[*ac]++;
1250
1251 /* Update the queue_map */
1252 /* Clear the last access category. */
1253 clear_spare_desc_q_map(fmac_dev_ctx, desc, tx_done_q);
1254 /* Set the new access category. */
1255 set_spare_desc_q_map(fmac_dev_ctx, desc, *ac);
1256 }
1257 break;
1258 }
1259 }
1260
1261 if (!pkts_pend) {
1262 /* Mark the desc as available */
1263 tx_desc_free(fmac_dev_ctx,
1264 desc,
1265 tx_done_q);
1266 }
1267
1268 return pkts_pend;
1269 }
1270
1271
tx_done_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned char tx_desc_num)1272 static enum nrf_wifi_status tx_done_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1273 unsigned char tx_desc_num)
1274 {
1275 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1276 struct nrf_wifi_fmac_priv *fpriv = NULL;
1277 void *nwb = NULL;
1278 void *nwb_list = NULL;
1279 unsigned int desc = 0;
1280 unsigned int frame = 0;
1281 unsigned int desc_id = 0;
1282 unsigned long virt_addr = 0;
1283 struct nrf_wifi_fmac_buf_map_info *tx_buf_info = NULL;
1284 struct tx_pkt_info *pkt_info = NULL;
1285 unsigned int pkt = 0;
1286 unsigned int pkts_pending = 0;
1287 unsigned char queue = 0;
1288 void *txq = NULL;
1289 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1290 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1291
1292 fpriv = fmac_dev_ctx->fpriv;
1293
1294 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1295 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
1296
1297 desc = tx_desc_num;
1298
1299 if (desc > sys_fpriv->num_tx_tokens) {
1300 nrf_wifi_osal_log_err("Invalid desc");
1301 goto out;
1302 }
1303
1304 pkt_info = &sys_dev_ctx->tx_config.pkt_info_p[desc];
1305 nwb_list = pkt_info->pkt;
1306
1307 for (frame = 0;
1308 frame < sys_dev_ctx->tx_config.send_pkt_coalesce_count_p[desc];
1309 frame++) {
1310 desc_id = (desc * sys_fpriv->data_config.max_tx_aggregation) + frame;
1311
1312 tx_buf_info = &sys_dev_ctx->tx_buf_info[desc_id];
1313
1314 if (!tx_buf_info->mapped) {
1315 nrf_wifi_osal_log_err("%s: Deinit_TX cmd called for unmapped TX buf(%d)",
1316 __func__,
1317 desc_id);
1318 status = NRF_WIFI_STATUS_FAIL;
1319 goto out;
1320 }
1321
1322 virt_addr = nrf_wifi_sys_hal_buf_unmap_tx(fmac_dev_ctx->hal_dev_ctx,
1323 desc_id);
1324
1325 if (!virt_addr) {
1326 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_unmap_tx failed",
1327 __func__);
1328 status = NRF_WIFI_STATUS_FAIL;
1329 goto out;
1330 }
1331
1332 /* TODO: See why we can't free the nwb here itself instead of
1333 * later as is being done now
1334 */
1335 tx_buf_info->nwb = 0;
1336 tx_buf_info->mapped = false;
1337 }
1338
1339 pkt = 0;
1340
1341 while (nrf_wifi_utils_q_len(nwb_list)) {
1342 nwb = nrf_wifi_utils_q_dequeue(nwb_list);
1343
1344 if (!nwb) {
1345 continue;
1346 }
1347
1348 nrf_wifi_osal_nbuf_free(nwb);
1349 pkt++;
1350 }
1351
1352 sys_dev_ctx->host_stats.total_tx_done_pkts += pkt;
1353
1354 pkts_pending = tx_buff_req_free(fmac_dev_ctx, tx_desc_num, &queue);
1355
1356 if (pkts_pending) {
1357 #ifdef NRF70_RAW_DATA_TX
1358 unsigned char *data = NULL;
1359 struct nrf_wifi_fmac_vif_ctx *vif_ctx;
1360 unsigned char if_idx;
1361
1362 pkt_info = &sys_dev_ctx->tx_config.pkt_info_p[desc];
1363 txq = pkt_info->pkt;
1364
1365 /**
1366 * we need to peek into the pending buffer to determine if
1367 * packet is a raw packet or not
1368 */
1369 nwb = nrf_wifi_utils_list_peek(txq);
1370 data = nrf_wifi_osal_nbuf_data_get(nwb);
1371
1372 if (*(unsigned int *)data != NRF_WIFI_MAGIC_NUM_RAWTX) {
1373 #endif /* NRF70_RAW_DATA_TX */
1374 if (sys_dev_ctx->twt_sleep_status ==
1375 NRF_WIFI_FMAC_TWT_STATE_AWAKE) {
1376 pkt_info = &sys_dev_ctx->tx_config.pkt_info_p[desc];
1377 txq = pkt_info->pkt;
1378 status = tx_cmd_init(fmac_dev_ctx,
1379 txq,
1380 desc,
1381 pkt_info->peer_id);
1382 } else {
1383 status = NRF_WIFI_STATUS_SUCCESS;
1384 }
1385 #ifdef NRF70_RAW_DATA_TX
1386 } else {
1387 nrf_wifi_osal_mem_cpy(&sys_dev_ctx->raw_tx_config,
1388 data,
1389 sizeof(struct raw_tx_pkt_header));
1390
1391 /**
1392 * check if the if_type is STA_TX_INJECTOR
1393 * if so, we need to check for TWT_SLEEP.
1394 * for RAW TX, we use MAX-PEERS queue presently
1395 */
1396 if_idx = sys_dev_ctx->tx_config.peers[MAX_PEERS].if_idx;
1397 vif_ctx = sys_dev_ctx->vif_ctx[if_idx];
1398 if ((vif_ctx->if_type == NRF_WIFI_STA_TX_INJECTOR) &&
1399 (sys_dev_ctx->twt_sleep_status == NRF_WIFI_FMAC_TWT_STATE_SLEEP)) {
1400 status = NRF_WIFI_STATUS_SUCCESS;
1401 } else {
1402 status = rawtx_cmd_init(fmac_dev_ctx,
1403 txq,
1404 desc,
1405 pkt_info->peer_id);
1406 }
1407 }
1408 #endif /* NRF70_RAW_DATA_TX */
1409 } else {
1410 status = NRF_WIFI_STATUS_SUCCESS;
1411 }
1412 out:
1413 return status;
1414 }
1415
1416 #ifdef NRF70_TX_DONE_WQ_ENABLED
tx_done_tasklet_fn(unsigned long data)1417 static void tx_done_tasklet_fn(unsigned long data)
1418 {
1419 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = (struct nrf_wifi_fmac_dev_ctx *)data;
1420 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx;
1421 void *tx_done_tasklet_event_q;
1422 enum NRF_WIFI_HAL_STATUS hal_status;
1423
1424 nrf_wifi_sys_hal_lock_rx(fmac_dev_ctx->hal_dev_ctx);
1425 hal_status = nrf_wifi_hal_status_unlocked(fmac_dev_ctx->hal_dev_ctx);
1426 if (hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
1427 goto out;
1428 }
1429
1430 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1431 tx_done_tasklet_event_q = sys_dev_ctx->tx_done_tasklet_event_q;
1432
1433 struct nrf_wifi_tx_buff_done *config = nrf_wifi_utils_q_dequeue(
1434 tx_done_tasklet_event_q);
1435
1436 if (!config) {
1437 nrf_wifi_osal_log_err("%s: TX done event Q is empty",
1438 __func__);
1439 return;
1440 }
1441
1442 (void) nrf_wifi_fmac_tx_done_event_process(fmac_dev_ctx, config);
1443
1444 nrf_wifi_osal_mem_free(config);
1445 out:
1446 nrf_wifi_sys_hal_unlock_rx(fmac_dev_ctx->hal_dev_ctx);
1447 }
1448 #endif /* NRF70_TX_DONE_WQ_ENABLED */
1449
1450 #ifdef NRF70_RAW_DATA_TX
nrf_wifi_fmac_rawtx_done_event_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_event_raw_tx_done * config)1451 enum nrf_wifi_status nrf_wifi_fmac_rawtx_done_event_process(
1452 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1453 struct nrf_wifi_event_raw_tx_done *config)
1454 {
1455 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1456 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1457
1458 if (!fmac_dev_ctx || !config) {
1459 nrf_wifi_osal_log_err("%s: Invalid parameters",
1460 __func__);
1461 goto out;
1462 }
1463
1464 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1465 if (!sys_dev_ctx || !sys_dev_ctx->tx_config.tx_lock) {
1466 /* This is a valid case when the TX_DONE event is received
1467 * during the driver deinit, so, silently ignore the failure.
1468 */
1469 return NRF_WIFI_STATUS_SUCCESS;
1470 }
1471
1472 nrf_wifi_osal_spinlock_take(sys_dev_ctx->tx_config.tx_lock);
1473
1474 if (config->status == NRF_WIFI_STATUS_FAIL) {
1475 /**
1476 * If the status indicates failure,
1477 * increment raw TX failure count. The TX buffers
1478 * still need to be freed. */
1479 sys_dev_ctx->raw_pkt_stats.raw_pkt_send_failure += 1;
1480 }
1481
1482 status = tx_done_process(fmac_dev_ctx,
1483 config->desc_num);
1484
1485 if (status != NRF_WIFI_STATUS_SUCCESS) {
1486 nrf_wifi_osal_log_err("%s: Process raw tx done failed",
1487 __func__);
1488 goto unlock;
1489 }
1490 unlock:
1491 nrf_wifi_osal_spinlock_rel(sys_dev_ctx->tx_config.tx_lock);
1492 out:
1493 return status;
1494 }
1495 #endif
1496
nrf_wifi_status(nrf_wifi_fmac_tx_done_event_process)1497 enum nrf_wifi_status (nrf_wifi_fmac_tx_done_event_process)(
1498 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1499 struct nrf_wifi_tx_buff_done *config)
1500 {
1501 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1502 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1503
1504 if (!fmac_dev_ctx || !config) {
1505 nrf_wifi_osal_log_err("%s: Invalid parameters",
1506 __func__);
1507 goto out;
1508 }
1509
1510 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1511 if (!sys_dev_ctx || !sys_dev_ctx->tx_config.tx_lock) {
1512 /* This is a valid case when the TX_DONE event is received
1513 * during the driver deinit, so, silently ignore the failure.
1514 */
1515 return NRF_WIFI_STATUS_SUCCESS;
1516 }
1517
1518
1519 nrf_wifi_osal_spinlock_take(sys_dev_ctx->tx_config.tx_lock);
1520
1521 status = tx_done_process(fmac_dev_ctx,
1522 config->tx_desc_num);
1523
1524 nrf_wifi_osal_spinlock_rel(sys_dev_ctx->tx_config.tx_lock);
1525
1526 out:
1527 if (status != NRF_WIFI_STATUS_SUCCESS) {
1528 nrf_wifi_osal_log_err("%s: Failed",
1529 __func__);
1530 }
1531
1532 return status;
1533 }
1534
1535
nrf_wifi_fmac_tx(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,int if_id,void * nbuf,unsigned int ac,unsigned int peer_id)1536 static enum nrf_wifi_fmac_tx_status nrf_wifi_fmac_tx(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
1537 int if_id,
1538 void *nbuf,
1539 unsigned int ac,
1540 unsigned int peer_id)
1541 {
1542 enum nrf_wifi_fmac_tx_status status = NRF_WIFI_FMAC_TX_STATUS_FAIL;
1543 unsigned int desc = 0;
1544 struct nrf_wifi_fmac_priv *fpriv = NULL;
1545 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1546 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1547
1548 fpriv = fmac_dev_ctx->fpriv;
1549 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1550 sys_fpriv = wifi_fmac_priv(fpriv);
1551
1552 nrf_wifi_osal_spinlock_take(sys_dev_ctx->tx_config.tx_lock);
1553
1554
1555 if (sys_fpriv->num_tx_tokens == 0) {
1556 goto out;
1557 }
1558
1559 status = tx_process(fmac_dev_ctx,
1560 if_id,
1561 nbuf,
1562 ac,
1563 peer_id);
1564
1565 if (status != NRF_WIFI_FMAC_TX_STATUS_SUCCESS) {
1566 goto out;
1567 }
1568
1569 status = NRF_WIFI_FMAC_TX_STATUS_QUEUED;
1570
1571 if (!can_xmit(fmac_dev_ctx, nbuf)) {
1572 goto out;
1573 }
1574
1575 desc = tx_desc_get(fmac_dev_ctx, ac);
1576
1577 if (desc == sys_fpriv->num_tx_tokens) {
1578 goto out;
1579 }
1580
1581 status = (enum nrf_wifi_fmac_tx_status)tx_pending_process(fmac_dev_ctx,
1582 desc,
1583 ac);
1584 out:
1585 nrf_wifi_osal_spinlock_rel(sys_dev_ctx->tx_config.tx_lock);
1586
1587 return status;
1588 }
1589
1590
tx_init(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)1591 enum nrf_wifi_status tx_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
1592 {
1593 struct nrf_wifi_fmac_priv *fpriv = NULL;
1594 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1595 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1596 void *q_ptr = NULL;
1597 unsigned int i = 0;
1598 unsigned int j = 0;
1599
1600 if (!fmac_dev_ctx) {
1601 goto out;
1602 }
1603
1604 fpriv = fmac_dev_ctx->fpriv;
1605 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1606 sys_fpriv = wifi_fmac_priv(fpriv);
1607
1608 sys_dev_ctx->tx_config.send_pkt_coalesce_count_p =
1609 nrf_wifi_osal_mem_zalloc((sizeof(unsigned int) *
1610 sys_fpriv->num_tx_tokens));
1611
1612 if (!sys_dev_ctx->tx_config.send_pkt_coalesce_count_p) {
1613 nrf_wifi_osal_log_err("%s: Unable to allocate send_pkt_coalesce_count_p",
1614 __func__);
1615 goto out;
1616 }
1617
1618 for (i = 0; i < NRF_WIFI_FMAC_AC_MAX; i++) {
1619 for (j = 0; j < MAX_SW_PEERS; j++) {
1620 sys_dev_ctx->tx_config.data_pending_txq[j][i] =
1621 nrf_wifi_utils_q_alloc();
1622
1623 if (!sys_dev_ctx->tx_config.data_pending_txq[j][i]) {
1624 nrf_wifi_osal_log_err("%s: Unable to allocate data_pending_txq",
1625 __func__);
1626 goto coal_q_free;
1627 }
1628 }
1629
1630 sys_dev_ctx->tx_config.outstanding_descs[i] = 0;
1631 }
1632
1633 /* Used to store the address of tx'ed skb and len of 802.11 hdr
1634 * it will be used in tx complete.
1635 */
1636 sys_dev_ctx->tx_config.pkt_info_p = nrf_wifi_osal_mem_zalloc((sizeof(struct tx_pkt_info) *
1637 sys_fpriv->num_tx_tokens));
1638
1639 if (!sys_dev_ctx->tx_config.pkt_info_p) {
1640 nrf_wifi_osal_log_err("%s: Unable to allocate pkt_info_p",
1641 __func__);
1642 goto tx_q_free;
1643 }
1644
1645 for (i = 0; i < sys_fpriv->num_tx_tokens; i++) {
1646 sys_dev_ctx->tx_config.pkt_info_p[i].pkt = nrf_wifi_utils_list_alloc();
1647
1648 if (!sys_dev_ctx->tx_config.pkt_info_p[i].pkt) {
1649 nrf_wifi_osal_log_err("%s: Unable to allocate pkt list",
1650 __func__);
1651 goto tx_q_setup_free;
1652 }
1653 }
1654
1655 for (j = 0; j < NRF_WIFI_FMAC_AC_MAX; j++) {
1656 sys_dev_ctx->tx_config.curr_peer_opp[j] = 0;
1657 }
1658
1659 sys_dev_ctx->tx_config.buf_pool_bmp_p =
1660 nrf_wifi_osal_mem_zalloc((sizeof(unsigned long) *
1661 (sys_fpriv->num_tx_tokens/TX_DESC_BUCKET_BOUND) + 1));
1662
1663 if (!sys_dev_ctx->tx_config.buf_pool_bmp_p) {
1664 nrf_wifi_osal_log_err("%s: Unable to allocate buf_pool_bmp_p",
1665 __func__);
1666 goto tx_pkt_info_free;
1667 }
1668
1669 nrf_wifi_osal_mem_set(sys_dev_ctx->tx_config.buf_pool_bmp_p,
1670 0,
1671 sizeof(long)*((sys_fpriv->num_tx_tokens/TX_DESC_BUCKET_BOUND) + 1));
1672
1673 for (i = 0; i < MAX_PEERS; i++) {
1674 sys_dev_ctx->tx_config.peers[i].peer_id = -1;
1675 }
1676
1677 sys_dev_ctx->tx_config.tx_lock = nrf_wifi_osal_spinlock_alloc();
1678
1679 if (!sys_dev_ctx->tx_config.tx_lock) {
1680 nrf_wifi_osal_log_err("%s: Unable to allocate TX lock",
1681 __func__);
1682 goto tx_buff_map_free;
1683 }
1684
1685 nrf_wifi_osal_spinlock_init(sys_dev_ctx->tx_config.tx_lock);
1686
1687 sys_dev_ctx->tx_config.wakeup_client_q = nrf_wifi_utils_q_alloc();
1688
1689 if (!sys_dev_ctx->tx_config.wakeup_client_q) {
1690 nrf_wifi_osal_log_err("%s: Unable to allocate Wakeup Client List",
1691 __func__);
1692 goto tx_spin_lock_free;
1693 }
1694
1695 sys_dev_ctx->twt_sleep_status = NRF_WIFI_FMAC_TWT_STATE_AWAKE;
1696
1697 #ifdef NRF70_TX_DONE_WQ_ENABLED
1698 sys_dev_ctx->tx_done_tasklet = nrf_wifi_osal_tasklet_alloc(NRF_WIFI_TASKLET_TYPE_TX_DONE);
1699 if (!sys_dev_ctx->tx_done_tasklet) {
1700 nrf_wifi_osal_log_err("%s: Unable to allocate tx_done_tasklet",
1701 __func__);
1702 goto wakeup_client_q_free;
1703 }
1704 sys_dev_ctx->tx_config.tx_done_tasklet_event_q = nrf_wifi_utils_q_alloc();
1705 if (!sys_dev_ctx->tx_config.tx_done_tasklet_event_q) {
1706 nrf_wifi_osal_log_err("%s: Unable to allocate tx_done_tasklet_event_q",
1707 __func__);
1708 goto tx_done_tasklet_free;
1709 }
1710
1711 nrf_wifi_osal_tasklet_init(sys_dev_ctx->tx_done_tasklet,
1712 tx_done_tasklet_fn,
1713 (unsigned long)fmac_dev_ctx);
1714 #endif /* NRF70_TX_DONE_WQ_ENABLED */
1715 return NRF_WIFI_STATUS_SUCCESS;
1716 #ifdef NRF70_TX_DONE_WQ_ENABLED
1717 tx_done_tasklet_free:
1718 nrf_wifi_osal_tasklet_free(sys_dev_ctx->tx_done_tasklet);
1719 wakeup_client_q_free:
1720 nrf_wifi_utils_q_free(sys_dev_ctx->tx_config.wakeup_client_q);
1721 #endif /* NRF70_TX_DONE_WQ_ENABLED */
1722 tx_spin_lock_free:
1723 nrf_wifi_osal_spinlock_free(sys_dev_ctx->tx_config.tx_lock);
1724 tx_buff_map_free:
1725 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.buf_pool_bmp_p);
1726 tx_pkt_info_free:
1727 for (i = 0; i < sys_fpriv->num_tx_tokens; i++) {
1728 nrf_wifi_utils_list_free(sys_dev_ctx->tx_config.pkt_info_p[i].pkt);
1729 }
1730 tx_q_setup_free:
1731 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.pkt_info_p);
1732 tx_q_free:
1733 for (i = 0; i < NRF_WIFI_FMAC_AC_MAX; i++) {
1734 for (j = 0; j < MAX_SW_PEERS; j++) {
1735 q_ptr = sys_dev_ctx->tx_config.data_pending_txq[j][i];
1736
1737 nrf_wifi_utils_q_free(q_ptr);
1738 }
1739 }
1740 coal_q_free:
1741 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.send_pkt_coalesce_count_p);
1742 out:
1743 return NRF_WIFI_STATUS_FAIL;
1744 }
1745
1746
tx_deinit(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx)1747 void tx_deinit(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx)
1748 {
1749 struct nrf_wifi_fmac_priv *fpriv = NULL;
1750 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1751 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
1752 unsigned int i = 0;
1753 unsigned int j = 0;
1754
1755 fpriv = fmac_dev_ctx->fpriv;
1756
1757 sys_fpriv = wifi_fmac_priv(fpriv);
1758 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1759
1760 #ifdef NRF70_TX_DONE_WQ_ENABLED
1761 /* TODO: Need to deinit network buffers? */
1762 nrf_wifi_osal_tasklet_free(sys_dev_ctx->tx_done_tasklet);
1763 nrf_wifi_utils_q_free(sys_dev_ctx->tx_config.tx_done_tasklet_event_q);
1764 #endif /* NRF70_TX_DONE_WQ_ENABLED */
1765 nrf_wifi_utils_q_free(sys_dev_ctx->tx_config.wakeup_client_q);
1766
1767 nrf_wifi_osal_spinlock_free(sys_dev_ctx->tx_config.tx_lock);
1768
1769 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.buf_pool_bmp_p);
1770
1771 for (i = 0; i < sys_fpriv->num_tx_tokens; i++) {
1772 if (sys_dev_ctx->tx_config.pkt_info_p) {
1773 while (nrf_wifi_utils_q_len(sys_dev_ctx->tx_config.pkt_info_p[i].pkt)) {
1774 nrf_wifi_osal_nbuf_free(
1775 nrf_wifi_utils_q_dequeue(sys_dev_ctx->tx_config.pkt_info_p[i].pkt));
1776 }
1777 nrf_wifi_utils_list_free(
1778 sys_dev_ctx->tx_config.pkt_info_p[i].pkt);
1779 }
1780 }
1781
1782 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.pkt_info_p);
1783
1784 for (i = 0; i < NRF_WIFI_FMAC_AC_MAX; i++) {
1785 for (j = 0; j < MAX_SW_PEERS; j++) {
1786 while (nrf_wifi_utils_q_len(sys_dev_ctx->tx_config.data_pending_txq[j][i])) {
1787 nrf_wifi_osal_nbuf_free(
1788 nrf_wifi_utils_q_dequeue(sys_dev_ctx->tx_config.data_pending_txq[j][i]));
1789 }
1790 nrf_wifi_utils_q_free(
1791 sys_dev_ctx->tx_config.data_pending_txq[j][i]);
1792 }
1793 }
1794
1795 nrf_wifi_osal_mem_free(sys_dev_ctx->tx_config.send_pkt_coalesce_count_p);
1796
1797 nrf_wifi_osal_mem_set(&sys_dev_ctx->tx_config,
1798 0,
1799 sizeof(struct tx_config));
1800 }
1801
1802
map_ac_from_tid(int tid)1803 static int map_ac_from_tid(int tid)
1804 {
1805 const int map_1d_to_ac[8] = {
1806 NRF_WIFI_FMAC_AC_BE, /*UP 0, 802.1D(BE), AC(BE) */
1807 NRF_WIFI_FMAC_AC_BK, /*UP 1, 802.1D(BK), AC(BK) */
1808 NRF_WIFI_FMAC_AC_BK, /*UP 2, 802.1D(BK), AC(BK) */
1809 NRF_WIFI_FMAC_AC_BE, /*UP 3, 802.1D(EE), AC(BE) */
1810 NRF_WIFI_FMAC_AC_VI, /*UP 4, 802.1D(CL), AC(VI) */
1811 NRF_WIFI_FMAC_AC_VI, /*UP 5, 802.1D(VI), AC(VI) */
1812 NRF_WIFI_FMAC_AC_VO, /*UP 6, 802.1D(VO), AC(VO) */
1813 NRF_WIFI_FMAC_AC_VO /*UP 7, 802.1D(NC), AC(VO) */
1814 };
1815
1816 return map_1d_to_ac[tid & 7];
1817 }
1818
1819
get_ac(unsigned int tid,unsigned char * ra)1820 static int get_ac(unsigned int tid,
1821 unsigned char *ra)
1822 {
1823 if (nrf_wifi_util_is_multicast_addr(ra)) {
1824 return NRF_WIFI_FMAC_AC_MC;
1825 }
1826
1827 return map_ac_from_tid(tid);
1828 }
1829
1830
nrf_wifi_util_get_ra(struct nrf_wifi_fmac_vif_ctx * vif,void * nwb)1831 unsigned char *nrf_wifi_util_get_ra(struct nrf_wifi_fmac_vif_ctx *vif,
1832 void *nwb)
1833 {
1834 if ((vif->if_type == NRF_WIFI_IFTYPE_STATION)
1835 #ifdef NRF70_RAW_DATA_TX
1836 || (vif->if_type == NRF_WIFI_STA_TX_INJECTOR)
1837 #endif /* NRF70_RAW_DATA_TX */
1838 #ifdef NRF70_PROMISC_DATA_RX
1839 || (vif->if_type == NRF_WIFI_STA_PROMISC)
1840 || (vif->if_type == NRF_WIFI_STA_PROMISC_TX_INJECTOR)
1841 #endif
1842 ) {
1843 return vif->bssid;
1844 }
1845
1846 return nrf_wifi_osal_nbuf_data_get(nwb);
1847 }
1848
1849
1850 #ifdef NRF70_RAW_DATA_TX
nrf_wifi_raw_pkt_mode_enabled(struct nrf_wifi_fmac_vif_ctx * vif)1851 static bool nrf_wifi_raw_pkt_mode_enabled(struct nrf_wifi_fmac_vif_ctx *vif)
1852 {
1853 if ((vif->if_type == NRF_WIFI_STA_TX_INJECTOR) ||
1854 (vif->if_type == NRF_WIFI_MONITOR_TX_INJECTOR) ||
1855 (vif->if_type == NRF_WIFI_STA_PROMISC_TX_INJECTOR)) {
1856 return true;
1857 }
1858 return false;
1859 }
1860
nrf_wifi_fmac_start_rawpkt_xmit(void * dev_ctx,unsigned char if_idx,void * nwb)1861 enum nrf_wifi_status nrf_wifi_fmac_start_rawpkt_xmit(void *dev_ctx,
1862 unsigned char if_idx,
1863 void *nwb)
1864 {
1865 enum nrf_wifi_fmac_tx_status tx_status = NRF_WIFI_FMAC_TX_STATUS_FAIL;
1866 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
1867 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1868 void *nwb_data = NULL;
1869 int ac;
1870 int peer_id;
1871
1872 if (!nwb || !dev_ctx) {
1873 /**
1874 * Handling an abnormal case.
1875 * return failure as network buffer and device
1876 * context are NULL
1877 */
1878 goto fail;
1879 }
1880
1881 fmac_dev_ctx = (struct nrf_wifi_fmac_dev_ctx *)dev_ctx;
1882 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1883
1884 /**
1885 * only allow raw packet to be transmitted if interface type allows it
1886 * do not queue the packet if interface type does not allow raw tx
1887 */
1888 if (!nrf_wifi_raw_pkt_mode_enabled(sys_dev_ctx->vif_ctx[if_idx])) {
1889 nrf_wifi_osal_log_err("%s: raw_packet mode is not enabled",
1890 __func__);
1891 goto out;
1892 }
1893
1894 nwb_data = nrf_wifi_osal_nbuf_data_get(nwb);
1895 nrf_wifi_osal_mem_cpy(&sys_dev_ctx->raw_tx_config,
1896 nwb_data,
1897 sizeof(struct raw_tx_pkt_header));
1898
1899 sys_dev_ctx->raw_tx_config.raw_tx_flag = 1;
1900 peer_id = MAX_PEERS;
1901 ac = sys_dev_ctx->raw_tx_config.queue;
1902
1903 tx_status = nrf_wifi_fmac_tx(fmac_dev_ctx,
1904 if_idx,
1905 nwb,
1906 ac,
1907 peer_id);
1908 if (tx_status == NRF_WIFI_FMAC_TX_STATUS_FAIL) {
1909 nrf_wifi_osal_log_dbg("%s: Failed to send packet\n",
1910 __func__);
1911 /** Increment failure count */
1912 sys_dev_ctx->raw_pkt_stats.raw_pkt_send_failure += 1;
1913 } else {
1914 /**
1915 * Increment success count.
1916 * can be added to shell command to obtain statistics
1917 */
1918 sys_dev_ctx->raw_pkt_stats.raw_pkt_send_success += 1;
1919 }
1920
1921 /**
1922 * Always silently drop the RAW packet and not send Failure.
1923 * The network stack might think interface is down
1924 */
1925 out:
1926 sys_dev_ctx->raw_pkt_stats.raw_pkts_sent += 1;
1927 return NRF_WIFI_STATUS_SUCCESS;
1928 fail:
1929 return NRF_WIFI_STATUS_FAIL;
1930 }
1931 #endif /* NRF70_RAW_DATA_TX */
1932
nrf_wifi_fmac_start_xmit(void * dev_ctx,unsigned char if_idx,void * nbuf)1933 enum nrf_wifi_status nrf_wifi_fmac_start_xmit(void *dev_ctx,
1934 unsigned char if_idx,
1935 void *nbuf)
1936 {
1937 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1938 enum nrf_wifi_fmac_tx_status tx_status = NRF_WIFI_FMAC_TX_STATUS_FAIL;
1939 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
1940 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1941 unsigned char *ra = NULL;
1942 int tid = 0;
1943 int ac = 0;
1944 int peer_id = -1;
1945
1946 if (!nbuf) {
1947 goto out;
1948 }
1949
1950 fmac_dev_ctx = dev_ctx;
1951 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1952
1953 if (nrf_wifi_osal_nbuf_data_size(nbuf) < NRF_WIFI_FMAC_ETH_HDR_LEN) {
1954 goto out;
1955 }
1956
1957 ra = nrf_wifi_util_get_ra(sys_dev_ctx->vif_ctx[if_idx], nbuf);
1958
1959 peer_id = nrf_wifi_fmac_peer_get_id(fmac_dev_ctx, ra);
1960
1961 if (peer_id == -1) {
1962 nrf_wifi_osal_log_err("%s: Got packet for unknown PEER",
1963 __func__);
1964
1965 goto out;
1966 } else if (peer_id == MAX_PEERS) {
1967 ac = NRF_WIFI_FMAC_AC_MC;
1968 } else {
1969 if (sys_dev_ctx->tx_config.peers[peer_id].qos_supported) {
1970 tid = nrf_wifi_get_tid(nbuf);
1971 ac = get_ac(tid, ra);
1972 } else {
1973 ac = NRF_WIFI_FMAC_AC_BE;
1974 }
1975 }
1976
1977 tx_status = nrf_wifi_fmac_tx(fmac_dev_ctx,
1978 if_idx,
1979 nbuf,
1980 ac,
1981 peer_id);
1982
1983 if (tx_status == NRF_WIFI_FMAC_TX_STATUS_FAIL) {
1984 nrf_wifi_osal_log_dbg("%s: Failed to send packet",
1985 __func__);
1986 goto out;
1987 }
1988
1989 return NRF_WIFI_STATUS_SUCCESS;
1990 out:
1991 if (nbuf) {
1992 nrf_wifi_osal_nbuf_free(nbuf);
1993 }
1994 return status;
1995 }
1996