1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /**
8 * @brief File containing RX data path specific function definitions for the
9 * FMAC IF Layer of the Wi-Fi driver.
10 */
11
12 #include "system/hal_api.h"
13 #include "system/fmac_rx.h"
14 #include "common/fmac_util.h"
15 #include "system/fmac_promisc.h"
16
17 static enum nrf_wifi_status
nrf_wifi_fmac_map_desc_to_pool(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,unsigned int desc_id,struct nrf_wifi_fmac_rx_pool_map_info * pool_info)18 nrf_wifi_fmac_map_desc_to_pool(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
19 unsigned int desc_id,
20 struct nrf_wifi_fmac_rx_pool_map_info *pool_info)
21 {
22 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
23 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
24 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
25 unsigned int pool_id = 0;
26
27 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
28 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
29
30 for (pool_id = 0; pool_id < MAX_NUM_OF_RX_QUEUES; pool_id++) {
31 if ((desc_id >= sys_fpriv->rx_desc[pool_id]) &&
32 (desc_id < (sys_fpriv->rx_desc[pool_id] +
33 sys_fpriv->rx_buf_pools[pool_id].num_bufs))) {
34 pool_info->pool_id = pool_id;
35 pool_info->buf_id = (desc_id - sys_fpriv->rx_desc[pool_id]);
36 status = NRF_WIFI_STATUS_SUCCESS;
37 goto out;
38 }
39 }
40 out:
41 return status;
42 }
43
44 #ifdef NRF70_STA_MODE
nrf_wifi_get_skip_header_bytes(unsigned short eth_type)45 int nrf_wifi_get_skip_header_bytes(unsigned short eth_type)
46 {
47 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
48 unsigned char llc_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
49 /* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
50 static unsigned char aarp_ipx_header[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8};
51 int skip_header_bytes = 0;
52
53 skip_header_bytes = sizeof(eth_type);
54
55 if (eth_type == NRF_WIFI_FMAC_ETH_P_AARP ||
56 eth_type == NRF_WIFI_FMAC_ETH_P_IPX) {
57 skip_header_bytes += sizeof(aarp_ipx_header);
58 } else if (eth_type >= NRF_WIFI_FMAC_ETH_P_802_3_MIN) {
59 skip_header_bytes += sizeof(llc_header);
60 }
61
62 return skip_header_bytes;
63 }
64
nrf_wifi_convert_amsdu_to_eth(void * nwb)65 static void nrf_wifi_convert_amsdu_to_eth(void *nwb)
66 {
67 struct nrf_wifi_fmac_eth_hdr *ehdr = NULL;
68 struct nrf_wifi_fmac_amsdu_hdr amsdu_hdr;
69 unsigned int len = 0;
70 unsigned short eth_type = 0;
71 void *nwb_data = NULL;
72 unsigned char amsdu_hdr_len = 0;
73
74 amsdu_hdr_len = sizeof(struct nrf_wifi_fmac_amsdu_hdr);
75
76 nrf_wifi_osal_mem_cpy(&amsdu_hdr,
77 nrf_wifi_osal_nbuf_data_get(nwb),
78 amsdu_hdr_len);
79
80 nwb_data = (unsigned char *)nrf_wifi_osal_nbuf_data_get(nwb) + amsdu_hdr_len;
81
82 eth_type = nrf_wifi_util_rx_get_eth_type(nwb_data);
83
84 nrf_wifi_osal_nbuf_data_pull(nwb,
85 (amsdu_hdr_len +
86 nrf_wifi_get_skip_header_bytes(eth_type)));
87
88 len = nrf_wifi_osal_nbuf_data_size(nwb);
89
90 ehdr = (struct nrf_wifi_fmac_eth_hdr *)
91 nrf_wifi_osal_nbuf_data_push(nwb,
92 sizeof(struct nrf_wifi_fmac_eth_hdr));
93
94 nrf_wifi_osal_mem_cpy(ehdr->src,
95 amsdu_hdr.src,
96 NRF_WIFI_FMAC_ETH_ADDR_LEN);
97
98 nrf_wifi_osal_mem_cpy(ehdr->dst,
99 amsdu_hdr.dst,
100 NRF_WIFI_FMAC_ETH_ADDR_LEN);
101
102 if (eth_type >= NRF_WIFI_FMAC_ETH_P_802_3_MIN) {
103 ehdr->proto = ((eth_type >> 8) | (eth_type << 8));
104 } else {
105 ehdr->proto = len;
106 }
107 }
108
nrf_wifi_convert_to_eth(void * nwb,struct nrf_wifi_fmac_ieee80211_hdr * hdr,unsigned short eth_type)109 static void nrf_wifi_convert_to_eth(void *nwb,
110 struct nrf_wifi_fmac_ieee80211_hdr *hdr,
111 unsigned short eth_type)
112 {
113
114 struct nrf_wifi_fmac_eth_hdr *ehdr = NULL;
115 unsigned int len = 0;
116
117 len = nrf_wifi_osal_nbuf_data_size(nwb);
118
119 ehdr = (struct nrf_wifi_fmac_eth_hdr *)
120 nrf_wifi_osal_nbuf_data_push(nwb,
121 sizeof(struct nrf_wifi_fmac_eth_hdr));
122
123 switch (hdr->fc & (NRF_WIFI_FCTL_TODS | NRF_WIFI_FCTL_FROMDS)) {
124 case (NRF_WIFI_FCTL_TODS | NRF_WIFI_FCTL_FROMDS):
125 nrf_wifi_osal_mem_cpy(ehdr->src,
126 hdr->addr_4,
127 NRF_WIFI_FMAC_ETH_ADDR_LEN);
128
129 nrf_wifi_osal_mem_cpy(ehdr->dst,
130 hdr->addr_1,
131 NRF_WIFI_FMAC_ETH_ADDR_LEN);
132 break;
133 case (NRF_WIFI_FCTL_FROMDS):
134 nrf_wifi_osal_mem_cpy(ehdr->src,
135 hdr->addr_3,
136 NRF_WIFI_FMAC_ETH_ADDR_LEN);
137 nrf_wifi_osal_mem_cpy(ehdr->dst,
138 hdr->addr_1,
139 NRF_WIFI_FMAC_ETH_ADDR_LEN);
140 break;
141 case (NRF_WIFI_FCTL_TODS):
142 nrf_wifi_osal_mem_cpy(ehdr->src,
143 hdr->addr_2,
144 NRF_WIFI_FMAC_ETH_ADDR_LEN);
145 nrf_wifi_osal_mem_cpy(ehdr->dst,
146 hdr->addr_3,
147 NRF_WIFI_FMAC_ETH_ADDR_LEN);
148 break;
149 default:
150 /* Both FROM and TO DS bit is zero*/
151 nrf_wifi_osal_mem_cpy(ehdr->src,
152 hdr->addr_2,
153 NRF_WIFI_FMAC_ETH_ADDR_LEN);
154 nrf_wifi_osal_mem_cpy(ehdr->dst,
155 hdr->addr_1,
156 NRF_WIFI_FMAC_ETH_ADDR_LEN);
157
158 }
159
160 if (eth_type >= NRF_WIFI_FMAC_ETH_P_802_3_MIN) {
161 ehdr->proto = ((eth_type >> 8) | (eth_type << 8));
162 } else {
163 ehdr->proto = len;
164 }
165 }
166 #endif /* NRF70_STA_MODE */
167
nrf_wifi_fmac_rx_cmd_send(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,enum nrf_wifi_fmac_rx_cmd_type cmd_type,unsigned int desc_id)168 enum nrf_wifi_status nrf_wifi_fmac_rx_cmd_send(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
169 enum nrf_wifi_fmac_rx_cmd_type cmd_type,
170 unsigned int desc_id)
171 {
172 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
173 struct nrf_wifi_fmac_buf_map_info *rx_buf_info = NULL;
174 struct host_rpu_rx_buf_info rx_cmd;
175 struct nrf_wifi_fmac_rx_pool_map_info pool_info;
176 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
177 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
178 unsigned long nwb = 0;
179 unsigned long nwb_data = 0;
180 unsigned long phy_addr = 0;
181 unsigned int buf_len = 0;
182
183 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
184 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
185
186 status = nrf_wifi_fmac_map_desc_to_pool(fmac_dev_ctx,
187 desc_id,
188 &pool_info);
189
190 if (status != NRF_WIFI_STATUS_SUCCESS) {
191 nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_map_desc_to_pool failed",
192 __func__);
193 goto out;
194 }
195
196 rx_buf_info = &sys_dev_ctx->rx_buf_info[desc_id];
197
198 buf_len = sys_fpriv->rx_buf_pools[pool_info.pool_id].buf_sz + RX_BUF_HEADROOM;
199
200 if (cmd_type == NRF_WIFI_FMAC_RX_CMD_TYPE_INIT) {
201 if (rx_buf_info->mapped) {
202 nrf_wifi_osal_log_err("%s: RX init called for mapped RX buffer(%d)",
203 __func__,
204 desc_id);
205 status = NRF_WIFI_STATUS_FAIL;
206 goto out;
207 }
208
209 nwb = (unsigned long)nrf_wifi_osal_nbuf_alloc(buf_len);
210
211 if (!nwb) {
212 nrf_wifi_osal_log_err("%s: No space for allocating RX buffer",
213 __func__);
214 status = NRF_WIFI_STATUS_FAIL;
215 goto out;
216 }
217
218 nwb_data = (unsigned long)nrf_wifi_osal_nbuf_data_get((void *)nwb);
219
220 *(unsigned int *)(nwb_data) = desc_id;
221
222 phy_addr = nrf_wifi_sys_hal_buf_map_rx(fmac_dev_ctx->hal_dev_ctx,
223 nwb_data,
224 buf_len,
225 pool_info.pool_id,
226 pool_info.buf_id);
227
228 if (!phy_addr) {
229 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_map_rx failed",
230 __func__);
231 status = NRF_WIFI_STATUS_FAIL;
232 goto out;
233 }
234
235 rx_buf_info->nwb = nwb;
236 rx_buf_info->mapped = true;
237
238 nrf_wifi_osal_mem_set(&rx_cmd,
239 0x0,
240 sizeof(rx_cmd));
241
242 rx_cmd.addr = (unsigned int)phy_addr;
243
244 status = nrf_wifi_sys_hal_data_cmd_send(fmac_dev_ctx->hal_dev_ctx,
245 NRF_WIFI_HAL_MSG_TYPE_CMD_DATA_RX,
246 &rx_cmd,
247 sizeof(rx_cmd),
248 desc_id,
249 pool_info.pool_id);
250 } else if (cmd_type == NRF_WIFI_FMAC_RX_CMD_TYPE_DEINIT) {
251 /* TODO: Need to initialize a command and send it to LMAC
252 * when LMAC is capable of handling deinit command
253 */
254 if (!rx_buf_info->mapped) {
255 nrf_wifi_osal_log_err("%s: RX deinit called for unmapped RX buffer(%d)",
256 __func__,
257 desc_id);
258 status = NRF_WIFI_STATUS_FAIL;
259 goto out;
260 }
261
262 nwb_data = nrf_wifi_sys_hal_buf_unmap_rx(fmac_dev_ctx->hal_dev_ctx,
263 0,
264 pool_info.pool_id,
265 pool_info.buf_id);
266
267 if (!nwb_data) {
268 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_unmap_rx failed",
269 __func__);
270 goto out;
271 }
272
273 nrf_wifi_osal_nbuf_free((void *)rx_buf_info->nwb);
274 rx_buf_info->nwb = 0;
275 rx_buf_info->mapped = false;
276 status = NRF_WIFI_STATUS_SUCCESS;
277 } else {
278 nrf_wifi_osal_log_err("%s: Unknown cmd_type (%d)",
279 __func__,
280 cmd_type);
281 goto out;
282 }
283 out:
284 return status;
285 }
286
287
288 #ifdef NRF70_RX_WQ_ENABLED
nrf_wifi_fmac_rx_tasklet(void * data)289 void nrf_wifi_fmac_rx_tasklet(void *data)
290 {
291 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = (struct nrf_wifi_fmac_dev_ctx *)data;
292 struct nrf_wifi_rx_buff *config = NULL;
293 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
294 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
295 enum NRF_WIFI_HAL_STATUS hal_status;
296
297 nrf_wifi_sys_hal_lock_rx(fmac_dev_ctx->hal_dev_ctx);
298 hal_status = nrf_wifi_hal_status_unlocked(fmac_dev_ctx->hal_dev_ctx);
299 if (hal_status != NRF_WIFI_HAL_STATUS_ENABLED) {
300 goto out;
301 }
302
303 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
304
305 config = (struct nrf_wifi_rx_buff *)nrf_wifi_utils_q_dequeue(
306 sys_dev_ctx->rx_tasklet_event_q);
307
308 if (!config) {
309 nrf_wifi_osal_log_err("%s: No RX config available",
310 __func__);
311 goto out;
312 }
313
314 status = nrf_wifi_fmac_rx_event_process(fmac_dev_ctx,
315 config);
316
317 if (status != NRF_WIFI_STATUS_SUCCESS) {
318 nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_rx_event_process failed",
319 __func__);
320 goto out;
321 }
322 out:
323 nrf_wifi_osal_mem_free(config);
324 nrf_wifi_sys_hal_unlock_rx(fmac_dev_ctx->hal_dev_ctx);
325 }
326 #endif /* NRF70_RX_WQ_ENABLED */
327
nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx * fmac_dev_ctx,struct nrf_wifi_rx_buff * config)328 enum nrf_wifi_status nrf_wifi_fmac_rx_event_process(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx,
329 struct nrf_wifi_rx_buff *config)
330 {
331 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
332 struct nrf_wifi_fmac_vif_ctx *vif_ctx = NULL;
333 struct nrf_wifi_fmac_buf_map_info *rx_buf_info = NULL;
334 struct nrf_wifi_fmac_rx_pool_map_info pool_info;
335 #if defined(NRF70_RAW_DATA_RX) || defined(NRF70_PROMISC_DATA_RX)
336 struct raw_rx_pkt_header raw_rx_hdr;
337 #if defined(NRF70_PROMISC_DATA_RX)
338 unsigned short frame_control;
339 #endif
340 #endif /* NRF70_RAW_DATA_RX || NRF70_PROMISC_DATA_RX */
341 void *nwb = NULL;
342 void *nwb_data = NULL;
343 unsigned int num_pkts = 0;
344 unsigned int desc_id = 0;
345 unsigned int i = 0;
346 unsigned int pkt_len = 0;
347 #ifdef NRF70_STA_MODE
348 struct nrf_wifi_fmac_ieee80211_hdr hdr;
349 unsigned short eth_type = 0;
350 unsigned int size = 0;
351 #endif /* NRF70_STA_MODE */
352 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
353 struct nrf_wifi_sys_fmac_priv *sys_fpriv = NULL;
354
355 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
356 sys_fpriv = wifi_fmac_priv(fmac_dev_ctx->fpriv);
357
358 vif_ctx = sys_dev_ctx->vif_ctx[config->wdev_id];
359
360 #ifdef NRF70_STA_MODE
361 if (config->rx_pkt_type != NRF_WIFI_RAW_RX_PKT) {
362 sys_fpriv->callbk_fns.process_rssi_from_rx(vif_ctx->os_vif_ctx,
363 config->signal);
364 }
365 #endif /* NRF70_STA_MODE */
366 num_pkts = config->rx_pkt_cnt;
367
368 for (i = 0; i < num_pkts; i++) {
369 desc_id = config->rx_buff_info[i].descriptor_id;
370 pkt_len = config->rx_buff_info[i].rx_pkt_len;
371
372 if (desc_id >= sys_fpriv->num_rx_bufs) {
373 nrf_wifi_osal_log_err("%s: Invalid desc_id %d",
374 __func__,
375 desc_id);
376 status = NRF_WIFI_STATUS_FAIL;
377 continue;
378 }
379
380 status = nrf_wifi_fmac_map_desc_to_pool(fmac_dev_ctx,
381 desc_id,
382 &pool_info);
383
384 if (status != NRF_WIFI_STATUS_SUCCESS) {
385 nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_map_desc_to_pool failed",
386 __func__);
387 status = NRF_WIFI_STATUS_FAIL;
388 continue;
389 }
390
391 nwb_data = (void *)nrf_wifi_sys_hal_buf_unmap_rx(fmac_dev_ctx->hal_dev_ctx,
392 pkt_len,
393 pool_info.pool_id,
394 pool_info.buf_id);
395
396 if (!nwb_data) {
397 nrf_wifi_osal_log_err("%s: nrf_wifi_sys_hal_buf_unmap_rx failed",
398 __func__);
399 status = NRF_WIFI_STATUS_FAIL;
400 continue;
401 }
402
403 rx_buf_info = &sys_dev_ctx->rx_buf_info[desc_id];
404 nwb = (void *)rx_buf_info->nwb;
405
406 nrf_wifi_osal_nbuf_data_put(nwb,
407 pkt_len + RX_BUF_HEADROOM);
408 nrf_wifi_osal_nbuf_data_pull(nwb,
409 RX_BUF_HEADROOM);
410 nwb_data = nrf_wifi_osal_nbuf_data_get(nwb);
411
412 rx_buf_info->nwb = 0;
413 rx_buf_info->mapped = false;
414
415 #ifdef NRF70_PROMISC_DATA_RX
416 nrf_wifi_osal_mem_cpy(&frame_control,
417 nwb_data,
418 sizeof(unsigned short));
419 #endif
420
421 if (config->rx_pkt_type == NRF_WIFI_RX_PKT_DATA) {
422 #ifdef NRF70_PROMISC_DATA_RX
423 if (vif_ctx->promisc_mode) {
424 raw_rx_hdr.frequency = config->frequency;
425 raw_rx_hdr.signal = config->signal;
426 raw_rx_hdr.rate_flags = config->rate_flags;
427 raw_rx_hdr.rate = config->rate;
428 if (nrf_wifi_util_check_filt_setting(vif_ctx, &frame_control)) {
429 sys_fpriv->callbk_fns.sniffer_callbk_fn(vif_ctx->os_vif_ctx,
430 nwb,
431 &raw_rx_hdr,
432 false);
433 }
434 }
435 #endif
436 #ifdef NRF70_STA_MODE
437 switch (config->rx_buff_info[i].pkt_type) {
438 case PKT_TYPE_MPDU:
439 nrf_wifi_osal_mem_cpy(&hdr,
440 nwb_data,
441 sizeof(struct nrf_wifi_fmac_ieee80211_hdr));
442
443 eth_type = nrf_wifi_util_rx_get_eth_type(((char *)nwb_data +
444 config->mac_header_len));
445
446 size = config->mac_header_len +
447 nrf_wifi_get_skip_header_bytes(eth_type);
448
449 /* Remove hdr len and llc header/length */
450 nrf_wifi_osal_nbuf_data_pull(nwb,
451 size);
452
453 nrf_wifi_convert_to_eth(nwb,
454 &hdr,
455 eth_type);
456 break;
457 case PKT_TYPE_MSDU_WITH_MAC:
458 nrf_wifi_osal_nbuf_data_pull(nwb,
459 config->mac_header_len);
460
461 nrf_wifi_convert_amsdu_to_eth(nwb);
462 break;
463 case PKT_TYPE_MSDU:
464 nrf_wifi_convert_amsdu_to_eth(nwb);
465 break;
466 default:
467 nrf_wifi_osal_log_err("%s: Invalid pkt_type=%d",
468 __func__,
469 (config->rx_buff_info[i].pkt_type));
470 status = NRF_WIFI_STATUS_FAIL;
471 continue;
472 }
473 sys_fpriv->callbk_fns.rx_frm_callbk_fn(vif_ctx->os_vif_ctx,
474 nwb);
475 #endif /* NRF70_STA_MODE */
476 } else if (config->rx_pkt_type == NRF_WIFI_RX_PKT_BCN_PRB_RSP) {
477 #ifdef WIFI_MGMT_RAW_SCAN_RESULTS
478 sys_fpriv->callbk_fns.rx_bcn_prb_resp_callbk_fn(
479 vif_ctx->os_vif_ctx,
480 nwb,
481 config->frequency,
482 config->signal);
483 #endif /* WIFI_MGMT_RAW_SCAN_RESULTS */
484 nrf_wifi_osal_nbuf_free(nwb);
485 #ifdef NRF_WIFI_MGMT_BUFF_OFFLOAD
486 continue;
487 #endif /* NRF_WIFI_MGMT_BUFF_OFFLOAD */
488 }
489 #if defined(NRF70_RAW_DATA_RX) || defined(NRF70_PROMISC_DATA_RX)
490 else if (config->rx_pkt_type == NRF_WIFI_RAW_RX_PKT) {
491 raw_rx_hdr.frequency = config->frequency;
492 raw_rx_hdr.signal = config->signal;
493 raw_rx_hdr.rate_flags = config->rate_flags;
494 raw_rx_hdr.rate = config->rate;
495 #if defined(NRF70_PROMISC_DATA_RX)
496 if (nrf_wifi_util_check_filt_setting(vif_ctx, &frame_control))
497 #endif
498 {
499 sys_fpriv->callbk_fns.sniffer_callbk_fn(vif_ctx->os_vif_ctx,
500 nwb,
501 &raw_rx_hdr,
502 true);
503 }
504 #if defined(NRF70_PROMISC_DATA_RX)
505 /**
506 * In the case of Monitor mode, the sniffer callback function
507 * will free the packet. For promiscuous mode, if the packet
508 * is not meant to be sent up the stack, the packet needs
509 * to be freed here.
510 */
511 else {
512 nrf_wifi_osal_nbuf_free(nwb);
513 }
514 #endif
515 }
516 #endif /* NRF70_RAW_DATA_RX || NRF70_PROMISC_DATA_RX */
517 else {
518 nrf_wifi_osal_log_err("%s: Invalid frame type received %d",
519 __func__,
520 config->rx_pkt_type);
521 status = NRF_WIFI_STATUS_FAIL;
522 nrf_wifi_osal_nbuf_free(nwb);
523 continue;
524 }
525
526 status = nrf_wifi_fmac_rx_cmd_send(fmac_dev_ctx,
527 NRF_WIFI_FMAC_RX_CMD_TYPE_INIT,
528 desc_id);
529
530 if (status != NRF_WIFI_STATUS_SUCCESS) {
531 nrf_wifi_osal_log_err("%s: nrf_wifi_fmac_rx_cmd_send failed",
532 __func__);
533 continue;
534 }
535 }
536
537 /* A single failure returns failure for the entire event */
538 return status;
539 }
540