1 /*
2 * Copyright (c) 2024 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @brief File containing netowrk stack interface specific definitions for the
9 * Zephyr OS layer of the Wi-Fi driver.
10 */
11
12 #include <stdlib.h>
13
14 #ifdef CONFIG_WIFI_RANDOM_MAC_ADDRESS
15 #include <zephyr/random/random.h>
16 #endif
17
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL);
20
21 #include <zephyr/sys/reboot.h>
22
23 #include "net_private.h"
24
25 #include "util.h"
26 #include "common/fmac_util.h"
27 #include "shim.h"
28 #include "fmac_main.h"
29 #include "wpa_supp_if.h"
30 #include "net_if.h"
31
32 extern char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,
33 char *buf, int buflen);
34
35 #ifdef CONFIG_NRF70_STA_MODE
36 static struct net_if_mcast_monitor mcast_monitor;
37 #endif /* CONFIG_NRF70_STA_MODE */
38
nrf_wifi_set_iface_event_handler(void * os_vif_ctx,struct nrf_wifi_umac_event_set_interface * event,unsigned int event_len)39 void nrf_wifi_set_iface_event_handler(void *os_vif_ctx,
40 struct nrf_wifi_umac_event_set_interface *event,
41 unsigned int event_len)
42 {
43 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
44
45 if (!os_vif_ctx) {
46 LOG_ERR("%s: Invalid parameters",
47 __func__);
48 goto out;
49 }
50
51 if (!event) {
52 LOG_ERR("%s: event is NULL",
53 __func__);
54 goto out;
55 }
56
57 (void)event_len;
58
59 vif_ctx_zep = os_vif_ctx;
60
61 vif_ctx_zep->set_if_event_received = true;
62 vif_ctx_zep->set_if_status = event->return_value;
63
64 out:
65 return;
66 }
67
68 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
nrf_wifi_rpu_recovery_work_handler(struct k_work * work)69 static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work)
70 {
71 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = CONTAINER_OF(work,
72 struct nrf_wifi_vif_ctx_zep,
73 nrf_wifi_rpu_recovery_work);
74 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
75 int ret;
76 bool recovery_fail = false;
77
78 if (!vif_ctx_zep) {
79 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
80 return;
81 }
82
83 if (!vif_ctx_zep->zep_net_if_ctx) {
84 LOG_ERR("%s: zep_net_if_ctx is NULL", __func__);
85 return;
86 }
87
88 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
89 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
90 LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
91 return;
92 }
93
94 if (rpu_ctx_zep->rpu_recovery_in_progress) {
95 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
96 LOG_ERR("%s: RPU recovery already in progress", __func__);
97 #else
98 LOG_DBG("%s: RPU recovery already in progress", __func__);
99 #endif
100 return;
101 }
102
103 if (rpu_ctx_zep->last_rpu_recovery_time_ms &&
104 ((k_uptime_get() - rpu_ctx_zep->last_rpu_recovery_time_ms) <
105 CONFIG_NRF_WIFI_RPU_RECOVERY_QUIET_PERIOD_MS)) {
106 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
107 LOG_ERR("%s: In quiet period (last_rpu_recovery_time_ms=%ld), ignoring",
108 __func__, rpu_ctx_zep->last_rpu_recovery_time_ms);
109 #else
110 LOG_DBG("%s: In quiet period (last_rpu_recovery_time_ms=%ld), ignoring",
111 __func__, rpu_ctx_zep->last_rpu_recovery_time_ms);
112 #endif
113 return;
114 }
115
116 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
117 LOG_ERR("%s: Starting RPU recovery", __func__);
118 #else
119 LOG_DBG("%s: Starting RPU recovery", __func__);
120 #endif
121 k_mutex_lock(&rpu_ctx_zep->rpu_lock, K_FOREVER);
122 #if CONFIG_NRF_WIFI_RPU_RECOVERY_MAX_RETRIES > 0
123 if (!rpu_ctx_zep->last_rpu_recovery_time_ms ||
124 (k_uptime_get() - rpu_ctx_zep->last_rpu_recovery_time_ms) <
125 CONFIG_NRF_WIFI_RPU_RECOVERY_RETRY_WINDOW_S * MSEC_PER_SEC) {
126 if (rpu_ctx_zep->rpu_recovery_retries >=
127 CONFIG_NRF_WIFI_RPU_RECOVERY_MAX_RETRIES) {
128 LOG_ERR("%s: Maximum recovery retries reached, rebooting system",
129 __func__);
130 sys_reboot(SYS_REBOOT_COLD);
131 }
132 rpu_ctx_zep->rpu_recovery_retries++;
133 } else {
134 rpu_ctx_zep->rpu_recovery_retries = 0;
135 }
136 #endif
137 rpu_ctx_zep->rpu_recovery_in_progress = true;
138 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
139 LOG_ERR("%s: Bringing the interface down", __func__);
140 #else
141 LOG_DBG("%s: Bringing the interface down", __func__);
142 #endif
143 /* This indirectly does a cold-boot of RPU */
144 ret = net_if_down(vif_ctx_zep->zep_net_if_ctx);
145 if (ret) {
146 rpu_ctx_zep->rpu_recovery_failure++;
147 recovery_fail = true;
148 LOG_ERR("%s: net_if_down failed: %d", __func__, ret);
149 /* Continue with the recovery */
150 }
151 k_msleep(CONFIG_NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS);
152 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
153 LOG_ERR("%s: Bringing the interface up", __func__);
154 #else
155 LOG_DBG("%s: Bringing the interface up", __func__);
156 #endif
157 ret = net_if_up(vif_ctx_zep->zep_net_if_ctx);
158 if (ret) {
159 LOG_ERR("%s: net_if_up failed: %d", __func__, ret);
160 }
161 rpu_ctx_zep->rpu_recovery_in_progress = false;
162 rpu_ctx_zep->last_rpu_recovery_time_ms = k_uptime_get();
163 if (!recovery_fail) {
164 rpu_ctx_zep->rpu_recovery_success++;
165 }
166 k_mutex_unlock(&rpu_ctx_zep->rpu_lock);
167 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG
168 LOG_ERR("%s: RPU recovery done", __func__);
169 #else
170 LOG_DBG("%s: RPU recovery done", __func__);
171 #endif
172 }
173
nrf_wifi_rpu_recovery_cb(void * vif_ctx_handle,void * event_data,unsigned int event_len)174 void nrf_wifi_rpu_recovery_cb(void *vif_ctx_handle,
175 void *event_data,
176 unsigned int event_len)
177 {
178 struct nrf_wifi_fmac_vif_ctx *vif_ctx = vif_ctx_handle;
179 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
180 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
181 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
182
183 if (!vif_ctx) {
184 LOG_ERR("%s: vif_ctx is NULL",
185 __func__);
186 goto out;
187 }
188
189 fmac_dev_ctx = vif_ctx->fmac_dev_ctx;
190 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
191 if (!sys_dev_ctx) {
192 LOG_ERR("%s: sys_dev_ctx is NULL",
193 __func__);
194 goto out;
195 }
196
197 vif_ctx_zep = vif_ctx->os_vif_ctx;
198 (void)event_data;
199
200 k_work_submit(&vif_ctx_zep->nrf_wifi_rpu_recovery_work);
201 out:
202 return;
203 }
204 #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */
205
206 #ifdef CONFIG_NRF70_DATA_TX
nrf_wifi_net_iface_work_handler(struct k_work * work)207 static void nrf_wifi_net_iface_work_handler(struct k_work *work)
208 {
209 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = CONTAINER_OF(work,
210 struct nrf_wifi_vif_ctx_zep,
211 nrf_wifi_net_iface_work);
212
213 if (!vif_ctx_zep) {
214 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
215 return;
216 }
217
218 if (!vif_ctx_zep->zep_net_if_ctx) {
219 LOG_ERR("%s: zep_net_if_ctx is NULL", __func__);
220 return;
221 }
222
223 if (vif_ctx_zep->if_carr_state == NRF_WIFI_FMAC_IF_CARR_STATE_ON) {
224 net_if_dormant_off(vif_ctx_zep->zep_net_if_ctx);
225 } else if (vif_ctx_zep->if_carr_state == NRF_WIFI_FMAC_IF_CARR_STATE_OFF) {
226 net_if_dormant_on(vif_ctx_zep->zep_net_if_ctx);
227 }
228 }
229
230 #if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX)
nrf_wifi_if_sniffer_rx_frm(void * os_vif_ctx,void * frm,struct raw_rx_pkt_header * raw_rx_hdr,bool pkt_free)231 void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx, void *frm,
232 struct raw_rx_pkt_header *raw_rx_hdr,
233 bool pkt_free)
234 {
235 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx;
236 struct net_if *iface = vif_ctx_zep->zep_net_if_ctx;
237 struct net_pkt *pkt;
238 struct nrf_wifi_ctx_zep *rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
239 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
240 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
241 int ret;
242
243 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
244
245 pkt = net_raw_pkt_from_nbuf(iface, frm, sizeof(struct raw_rx_pkt_header),
246 raw_rx_hdr,
247 pkt_free);
248 if (!pkt) {
249 LOG_DBG("Failed to allocate net_pkt");
250 return;
251 }
252
253 net_capture_pkt(iface, pkt);
254
255 ret = net_recv_data(iface, pkt);
256 if (ret < 0) {
257 LOG_DBG("RCV Packet dropped by NET stack: %d", ret);
258 net_pkt_unref(pkt);
259 }
260 }
261 #endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */
262
nrf_wifi_if_rx_frm(void * os_vif_ctx,void * frm)263 void nrf_wifi_if_rx_frm(void *os_vif_ctx, void *frm)
264 {
265 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx;
266 struct net_if *iface = vif_ctx_zep->zep_net_if_ctx;
267 struct net_pkt *pkt;
268 int status;
269 struct nrf_wifi_ctx_zep *rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
270 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
271 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
272 struct rpu_host_stats *host_stats = NULL;
273
274 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
275 host_stats = &sys_dev_ctx->host_stats;
276 host_stats->total_rx_pkts++;
277
278 pkt = net_pkt_from_nbuf(iface, frm);
279 if (!pkt) {
280 LOG_DBG("Failed to allocate net_pkt");
281 host_stats->total_rx_drop_pkts++;
282 return;
283 }
284
285 status = net_recv_data(iface, pkt);
286
287 if (status < 0) {
288 LOG_DBG("RCV Packet dropped by NET stack: %d", status);
289 host_stats->total_rx_drop_pkts++;
290 net_pkt_unref(pkt);
291 }
292 }
293
nrf_wifi_if_carr_state_chg(void * os_vif_ctx,enum nrf_wifi_fmac_if_carr_state carr_state)294 enum nrf_wifi_status nrf_wifi_if_carr_state_chg(void *os_vif_ctx,
295 enum nrf_wifi_fmac_if_carr_state carr_state)
296 {
297 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
298 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
299
300 if (!os_vif_ctx) {
301 LOG_ERR("%s: Invalid parameters",
302 __func__);
303 goto out;
304 }
305
306 vif_ctx_zep = os_vif_ctx;
307
308 vif_ctx_zep->if_carr_state = carr_state;
309
310 LOG_DBG("%s: Carrier state: %d", __func__, carr_state);
311
312 k_work_submit(&vif_ctx_zep->nrf_wifi_net_iface_work);
313
314 status = NRF_WIFI_STATUS_SUCCESS;
315
316 out:
317 return status;
318 }
319
is_eapol(struct net_pkt * pkt)320 static bool is_eapol(struct net_pkt *pkt)
321 {
322 struct net_eth_hdr *hdr;
323 uint16_t ethertype;
324
325 hdr = NET_ETH_HDR(pkt);
326 ethertype = ntohs(hdr->type);
327
328 return ethertype == NET_ETH_PTYPE_EAPOL;
329 }
330 #endif /* CONFIG_NRF70_DATA_TX */
331
nrf_wifi_if_caps_get(const struct device * dev)332 enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev)
333 {
334 enum ethernet_hw_caps caps = (ETHERNET_LINK_10BASE_T |
335 ETHERNET_LINK_100BASE_T | ETHERNET_LINK_1000BASE_T);
336
337 #ifdef CONFIG_NRF70_TCP_IP_CHECKSUM_OFFLOAD
338 caps |= ETHERNET_HW_TX_CHKSUM_OFFLOAD |
339 ETHERNET_HW_RX_CHKSUM_OFFLOAD;
340 #endif /* CONFIG_NRF70_TCP_IP_CHECKSUM_OFFLOAD */
341
342 #ifdef CONFIG_NRF70_RAW_DATA_TX
343 caps |= ETHERNET_TXINJECTION_MODE;
344 #endif
345 #ifdef CONFIG_NRF70_PROMISC_DATA_RX
346 caps |= ETHERNET_PROMISC_MODE;
347 #endif
348 return caps;
349 }
350
nrf_wifi_if_send(const struct device * dev,struct net_pkt * pkt)351 int nrf_wifi_if_send(const struct device *dev,
352 struct net_pkt *pkt)
353 {
354 int ret = -1;
355 #ifdef CONFIG_NRF70_DATA_TX
356 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
357 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
358 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
359 struct rpu_host_stats *host_stats = NULL;
360 void *nbuf = NULL;
361
362 if (!dev || !pkt) {
363 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
364 goto out;
365 }
366
367 vif_ctx_zep = dev->data;
368
369 if (!vif_ctx_zep) {
370 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
371 goto out;
372 }
373
374 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
375 if (ret != 0) {
376 LOG_ERR("%s: Failed to lock vif_lock", __func__);
377 goto out;
378 }
379
380 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
381 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
382 goto unlock;
383 }
384
385 sys_dev_ctx = wifi_dev_priv(rpu_ctx_zep->rpu_ctx);
386 host_stats = &sys_dev_ctx->host_stats;
387 nbuf = net_pkt_to_nbuf(pkt);
388 if (!nbuf) {
389 LOG_DBG("Failed to allocate net_pkt");
390 host_stats->total_tx_drop_pkts++;
391 goto out;
392 }
393
394 #ifdef CONFIG_NRF70_RAW_DATA_TX
395 if ((*(unsigned int *)pkt->frags->data) == NRF_WIFI_MAGIC_NUM_RAWTX) {
396 if (vif_ctx_zep->if_carr_state != NRF_WIFI_FMAC_IF_CARR_STATE_ON) {
397 goto drop;
398 }
399
400 ret = nrf_wifi_fmac_start_rawpkt_xmit(rpu_ctx_zep->rpu_ctx,
401 vif_ctx_zep->vif_idx,
402 nbuf);
403 } else {
404 #endif /* CONFIG_NRF70_RAW_DATA_TX */
405 if ((vif_ctx_zep->if_carr_state != NRF_WIFI_FMAC_IF_CARR_STATE_ON) ||
406 (!vif_ctx_zep->authorized && !is_eapol(pkt))) {
407 goto drop;
408 }
409
410 ret = nrf_wifi_fmac_start_xmit(rpu_ctx_zep->rpu_ctx,
411 vif_ctx_zep->vif_idx,
412 nbuf);
413 #ifdef CONFIG_NRF70_RAW_DATA_TX
414 }
415 #endif /* CONFIG_NRF70_RAW_DATA_TX */
416 goto unlock;
417 drop:
418 host_stats->total_tx_drop_pkts++;
419 nrf_wifi_osal_nbuf_free(nbuf);
420 unlock:
421 k_mutex_unlock(&vif_ctx_zep->vif_lock);
422 #else
423 ARG_UNUSED(dev);
424 ARG_UNUSED(pkt);
425 goto out;
426 #endif /* CONFIG_NRF70_DATA_TX */
427
428 out:
429 return ret;
430 }
431
432 #ifdef CONFIG_NRF70_STA_MODE
ip_maddr_event_handler(struct net_if * iface,const struct net_addr * addr,bool is_joined)433 static void ip_maddr_event_handler(struct net_if *iface,
434 const struct net_addr *addr, bool is_joined)
435 {
436 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
437 struct net_eth_addr mac_addr;
438 struct nrf_wifi_umac_mcast_cfg *mcast_info = NULL;
439 enum nrf_wifi_status status;
440 uint8_t mac_string_buf[sizeof("xx:xx:xx:xx:xx:xx")];
441 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
442 int ret;
443
444 vif_ctx_zep = nrf_wifi_get_vif_ctx(iface);
445 if (!vif_ctx_zep) {
446 return;
447 }
448
449 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
450 if (ret != 0) {
451 LOG_ERR("%s: Failed to lock vif_lock", __func__);
452 return;
453 }
454
455 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
456 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
457 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
458 __func__);
459 goto unlock;
460 }
461
462 mcast_info = nrf_wifi_osal_mem_zalloc(sizeof(*mcast_info));
463
464 if (!mcast_info) {
465 LOG_ERR("%s: Unable to allocate memory of size %d "
466 "for mcast_info", __func__, sizeof(*mcast_info));
467 goto unlock;
468 }
469
470 switch (addr->family) {
471 case AF_INET:
472 net_eth_ipv4_mcast_to_mac_addr(&addr->in_addr, &mac_addr);
473 break;
474 case AF_INET6:
475 net_eth_ipv6_mcast_to_mac_addr(&addr->in6_addr, &mac_addr);
476 break;
477 default:
478 LOG_ERR("%s: Invalid address family %d", __func__, addr->family);
479 break;
480 }
481
482 if (is_joined) {
483 mcast_info->type = MCAST_ADDR_ADD;
484 } else {
485 mcast_info->type = MCAST_ADDR_DEL;
486 }
487
488 memcpy(((char *)(mcast_info->mac_addr)),
489 &mac_addr,
490 NRF_WIFI_ETH_ADDR_LEN);
491
492 status = nrf_wifi_sys_fmac_set_mcast_addr(rpu_ctx_zep->rpu_ctx,
493 vif_ctx_zep->vif_idx,
494 mcast_info);
495 if (status == NRF_WIFI_STATUS_FAIL) {
496 LOG_ERR("%s: nrf_wifi_fmac_set_multicast failed for"
497 " mac addr=%s",
498 __func__,
499 net_sprint_ll_addr_buf(mac_addr.addr,
500 WIFI_MAC_ADDR_LEN, mac_string_buf,
501 sizeof(mac_string_buf)));
502 }
503 unlock:
504 nrf_wifi_osal_mem_free(mcast_info);
505 k_mutex_unlock(&vif_ctx_zep->vif_lock);
506 }
507 #endif /* CONFIG_NRF70_STA_MODE */
508
509 #ifdef CONFIG_WIFI_FIXED_MAC_ADDRESS_ENABLED
510 BUILD_ASSERT(sizeof(CONFIG_WIFI_FIXED_MAC_ADDRESS) - 1 == ((WIFI_MAC_ADDR_LEN * 2) + 5),
511 "Invalid fixed MAC address length");
512 #endif
513
nrf_wifi_get_mac_addr(struct nrf_wifi_vif_ctx_zep * vif_ctx_zep)514 enum nrf_wifi_status nrf_wifi_get_mac_addr(struct nrf_wifi_vif_ctx_zep *vif_ctx_zep)
515 {
516 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
517 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
518 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
519 int ret;
520
521 if (!vif_ctx_zep) {
522 LOG_ERR("%s: vif_ctx_zep is NULL",
523 __func__);
524 goto out;
525 }
526
527 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
528 if (ret != 0) {
529 LOG_ERR("%s: Failed to lock vif_lock", __func__);
530 goto out;
531 }
532
533 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
534 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
535 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
536 __func__);
537 goto unlock;
538 }
539
540 fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
541
542 #ifdef CONFIG_WIFI_FIXED_MAC_ADDRESS_ENABLED
543 char fixed_mac_addr[WIFI_MAC_ADDR_LEN];
544
545 ret = net_bytes_from_str(fixed_mac_addr,
546 WIFI_MAC_ADDR_LEN,
547 CONFIG_WIFI_FIXED_MAC_ADDRESS);
548 if (ret < 0) {
549 LOG_ERR("%s: Failed to parse MAC address: %s",
550 __func__,
551 CONFIG_WIFI_FIXED_MAC_ADDRESS);
552 goto unlock;
553 }
554
555 memcpy(vif_ctx_zep->mac_addr.addr,
556 fixed_mac_addr,
557 WIFI_MAC_ADDR_LEN);
558 #elif CONFIG_WIFI_RANDOM_MAC_ADDRESS
559 char random_mac_addr[WIFI_MAC_ADDR_LEN];
560
561 sys_rand_get(random_mac_addr, WIFI_MAC_ADDR_LEN);
562 random_mac_addr[0] = (random_mac_addr[0] & UNICAST_MASK) | LOCAL_BIT;
563
564 memcpy(vif_ctx_zep->mac_addr.addr,
565 random_mac_addr,
566 WIFI_MAC_ADDR_LEN);
567 #elif CONFIG_WIFI_OTP_MAC_ADDRESS
568 status = nrf_wifi_fmac_otp_mac_addr_get(fmac_dev_ctx,
569 vif_ctx_zep->vif_idx,
570 vif_ctx_zep->mac_addr.addr);
571 if (status != NRF_WIFI_STATUS_SUCCESS) {
572 LOG_ERR("%s: Fetching of MAC address from OTP failed",
573 __func__);
574 goto unlock;
575 }
576 #endif
577
578 if (!nrf_wifi_utils_is_mac_addr_valid(vif_ctx_zep->mac_addr.addr)) {
579 LOG_ERR("%s: Invalid MAC address: %s",
580 __func__,
581 net_sprint_ll_addr(vif_ctx_zep->mac_addr.addr,
582 WIFI_MAC_ADDR_LEN));
583 status = NRF_WIFI_STATUS_FAIL;
584 memset(vif_ctx_zep->mac_addr.addr,
585 0,
586 WIFI_MAC_ADDR_LEN);
587 goto unlock;
588 }
589 status = NRF_WIFI_STATUS_SUCCESS;
590 unlock:
591 k_mutex_unlock(&vif_ctx_zep->vif_lock);
592 out:
593 return status;
594 }
595
nrf_wifi_if_init_zep(struct net_if * iface)596 void nrf_wifi_if_init_zep(struct net_if *iface)
597 {
598 const struct device *dev = NULL;
599 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
600 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
601 struct ethernet_context *eth_ctx = net_if_l2_data(iface);
602
603 if (!iface) {
604 LOG_ERR("%s: Invalid parameters",
605 __func__);
606 return;
607 }
608
609 dev = net_if_get_device(iface);
610
611 if (!dev) {
612 LOG_ERR("%s: Invalid dev",
613 __func__);
614 return;
615 }
616
617 vif_ctx_zep = dev->data;
618
619 if (!vif_ctx_zep) {
620 LOG_ERR("%s: vif_ctx_zep is NULL",
621 __func__);
622 return;
623 }
624
625 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
626
627 if (!rpu_ctx_zep) {
628 LOG_ERR("%s: rpu_ctx_zep is NULL",
629 __func__);
630 return;
631 }
632
633 vif_ctx_zep->zep_net_if_ctx = iface;
634 vif_ctx_zep->zep_dev_ctx = dev;
635
636 eth_ctx->eth_if_type = L2_ETH_IF_TYPE_WIFI;
637 ethernet_init(iface);
638 net_eth_carrier_on(iface);
639 net_if_dormant_on(iface);
640
641 #ifdef CONFIG_NRF70_STA_MODE
642 net_if_mcast_mon_register(&mcast_monitor, iface, ip_maddr_event_handler);
643 #endif /* CONFIG_NRF70_STA_MODE */
644 #ifdef CONFIG_NRF70_DATA_TX
645 k_work_init(&vif_ctx_zep->nrf_wifi_net_iface_work,
646 nrf_wifi_net_iface_work_handler);
647 #endif /* CONFIG_NRF70_DATA_TX */
648
649 #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY
650 k_work_init(&vif_ctx_zep->nrf_wifi_rpu_recovery_work,
651 nrf_wifi_rpu_recovery_work_handler);
652 #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */
653
654 #if !defined(CONFIG_NRF_WIFI_IF_AUTO_START)
655 net_if_flag_set(iface, NET_IF_NO_AUTO_START);
656 #endif /* CONFIG_NRF_WIFI_IF_AUTO_START */
657 net_if_flag_set(iface, NET_IF_NO_TX_LOCK);
658 }
659
660 /* Board-specific Wi-Fi startup code to run before the Wi-Fi device is started */
nrf_wifi_if_zep_start_board(const struct device * dev)661 __weak int nrf_wifi_if_zep_start_board(const struct device *dev)
662 {
663 ARG_UNUSED(dev);
664 return 0;
665 }
666
667 /* Board-specific Wi-Fi shutdown code to run after the Wi-Fi device is stopped */
nrf_wifi_if_zep_stop_board(const struct device * dev)668 __weak int nrf_wifi_if_zep_stop_board(const struct device *dev)
669 {
670 ARG_UNUSED(dev);
671 return 0;
672 }
673
nrf_wifi_if_start_zep(const struct device * dev)674 int nrf_wifi_if_start_zep(const struct device *dev)
675 {
676 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
677 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
678 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
679 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
680 struct nrf_wifi_umac_chg_vif_state_info vif_info;
681 struct nrf_wifi_umac_add_vif_info add_vif_info;
682 char *mac_addr = NULL;
683 unsigned int mac_addr_len = 0;
684 int ret = -1;
685 bool fmac_dev_added = false;
686
687 if (!dev) {
688 LOG_ERR("%s: Invalid parameters",
689 __func__);
690 goto out;
691 }
692
693 if (!device_is_ready(dev)) {
694 LOG_ERR("%s: Device %s is not ready",
695 __func__, dev->name);
696 goto out;
697 }
698
699 ret = nrf_wifi_if_zep_start_board(dev);
700 if (ret) {
701 LOG_ERR("nrf_wifi_if_zep_start_board failed with error: %d",
702 ret);
703 goto out;
704 }
705
706 vif_ctx_zep = dev->data;
707
708 if (!vif_ctx_zep) {
709 LOG_ERR("%s: vif_ctx_zep is NULL",
710 __func__);
711 goto out;
712 }
713
714 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
715
716 if (!rpu_ctx_zep) {
717 LOG_ERR("%s: rpu_ctx_zep is NULL",
718 __func__);
719 goto out;
720 }
721
722 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
723 if (ret != 0) {
724 LOG_ERR("%s: Failed to lock vif_lock", __func__);
725 goto out;
726 }
727
728 if (!rpu_ctx_zep->rpu_ctx) {
729 status = nrf_wifi_fmac_dev_add_zep(&rpu_drv_priv_zep);
730
731 if (status != NRF_WIFI_STATUS_SUCCESS) {
732 LOG_ERR("%s: nrf_wifi_fmac_dev_add_zep failed",
733 __func__);
734 goto out;
735 }
736 fmac_dev_added = true;
737 LOG_DBG("%s: FMAC device added", __func__);
738 }
739
740 fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
741
742 memset(&add_vif_info,
743 0,
744 sizeof(add_vif_info));
745
746 /* TODO: This should be configurable */
747 add_vif_info.iftype = NRF_WIFI_IFTYPE_STATION;
748
749 memcpy(add_vif_info.ifacename,
750 dev->name,
751 strlen(dev->name));
752
753 vif_ctx_zep->vif_idx = nrf_wifi_sys_fmac_add_vif(fmac_dev_ctx,
754 vif_ctx_zep,
755 &add_vif_info);
756 if (vif_ctx_zep->vif_idx >= MAX_NUM_VIFS) {
757 LOG_ERR("%s: FMAC returned invalid interface index",
758 __func__);
759 goto dev_rem;
760 }
761
762 k_mutex_init(&vif_ctx_zep->vif_lock);
763 rpu_ctx_zep->vif_ctx_zep[vif_ctx_zep->vif_idx].if_type =
764 add_vif_info.iftype;
765
766 /* Check if user has provided a valid MAC address, if not
767 * fetch it from OTP.
768 */
769 mac_addr = net_if_get_link_addr(vif_ctx_zep->zep_net_if_ctx)->addr;
770 mac_addr_len = net_if_get_link_addr(vif_ctx_zep->zep_net_if_ctx)->len;
771
772 if (!nrf_wifi_utils_is_mac_addr_valid(mac_addr)) {
773 status = nrf_wifi_get_mac_addr(vif_ctx_zep);
774 if (status != NRF_WIFI_STATUS_SUCCESS) {
775 LOG_ERR("%s: Failed to get MAC address",
776 __func__);
777 goto del_vif;
778 }
779 net_if_set_link_addr(vif_ctx_zep->zep_net_if_ctx,
780 vif_ctx_zep->mac_addr.addr,
781 WIFI_MAC_ADDR_LEN,
782 NET_LINK_ETHERNET);
783 mac_addr = vif_ctx_zep->mac_addr.addr;
784 mac_addr_len = WIFI_MAC_ADDR_LEN;
785 }
786
787 status = nrf_wifi_sys_fmac_set_vif_macaddr(rpu_ctx_zep->rpu_ctx,
788 vif_ctx_zep->vif_idx,
789 mac_addr);
790
791 if (status != NRF_WIFI_STATUS_SUCCESS) {
792 LOG_ERR("%s: MAC address change failed",
793 __func__);
794 goto del_vif;
795 }
796
797 memset(&vif_info,
798 0,
799 sizeof(vif_info));
800
801 vif_info.state = NRF_WIFI_FMAC_IF_OP_STATE_UP;
802 vif_info.if_index = vif_ctx_zep->vif_idx;
803
804 memcpy(vif_ctx_zep->ifname,
805 dev->name,
806 strlen(dev->name));
807
808 status = nrf_wifi_sys_fmac_chg_vif_state(rpu_ctx_zep->rpu_ctx,
809 vif_ctx_zep->vif_idx,
810 &vif_info);
811
812 if (status != NRF_WIFI_STATUS_SUCCESS) {
813 LOG_ERR("%s: nrf_wifi_sys_fmac_chg_vif_state failed",
814 __func__);
815 goto del_vif;
816 }
817
818 #ifdef CONFIG_NRF70_STA_MODE
819 nrf_wifi_wpa_supp_event_mac_chgd(vif_ctx_zep);
820
821 #ifdef CONFIG_NRF_WIFI_LOW_POWER
822 status = nrf_wifi_sys_fmac_set_power_save(rpu_ctx_zep->rpu_ctx,
823 vif_ctx_zep->vif_idx,
824 NRF_WIFI_PS_ENABLED);
825
826 if (status != NRF_WIFI_STATUS_SUCCESS) {
827 LOG_ERR("%s: nrf_wifi_sys_fmac_set_power_save failed",
828 __func__);
829 goto dev_rem;
830 }
831 #endif /* CONFIG_NRF_WIFI_LOW_POWER */
832 #endif /* CONFIG_NRF70_STA_MODE */
833
834 vif_ctx_zep->if_op_state = NRF_WIFI_FMAC_IF_OP_STATE_UP;
835
836 ret = 0;
837
838 goto out;
839 del_vif:
840 status = nrf_wifi_sys_fmac_del_vif(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx);
841 if (status != NRF_WIFI_STATUS_SUCCESS) {
842 LOG_ERR("%s: nrf_wifi_sys_fmac_del_vif failed",
843 __func__);
844 }
845 dev_rem:
846 /* Free only if we added above i.e., for 1st VIF */
847 if (fmac_dev_added) {
848 nrf_wifi_fmac_dev_rem_zep(&rpu_drv_priv_zep);
849 }
850 out:
851 k_mutex_unlock(&vif_ctx_zep->vif_lock);
852 return ret;
853 }
854
855
nrf_wifi_if_stop_zep(const struct device * dev)856 int nrf_wifi_if_stop_zep(const struct device *dev)
857 {
858 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
859 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
860 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
861 struct nrf_wifi_umac_chg_vif_state_info vif_info;
862 int ret = -1;
863
864 if (!dev) {
865 LOG_ERR("%s: Invalid parameters",
866 __func__);
867 goto out;
868 }
869
870 vif_ctx_zep = dev->data;
871
872 if (!vif_ctx_zep) {
873 LOG_ERR("%s: vif_ctx_zep is NULL",
874 __func__);
875 goto out;
876 }
877
878 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
879 if (ret != 0) {
880 LOG_ERR("%s: Failed to lock vif_lock", __func__);
881 goto unlock;
882 }
883
884 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
885 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
886 LOG_ERR("%s: rpu_ctx_zep is NULL",
887 __func__);
888 goto unlock;
889 }
890
891 #ifdef CONFIG_NRF70_STA_MODE
892 #ifdef CONFIG_NRF_WIFI_LOW_POWER
893 status = nrf_wifi_sys_fmac_set_power_save(rpu_ctx_zep->rpu_ctx,
894 vif_ctx_zep->vif_idx,
895 NRF_WIFI_PS_DISABLED);
896
897 if (status != NRF_WIFI_STATUS_SUCCESS) {
898 LOG_ERR("%s: nrf_wifi_sys_fmac_set_power_save failed",
899 __func__);
900 }
901 #endif /* CONFIG_NRF_WIFI_LOW_POWER */
902 #endif /* CONFIG_NRF70_STA_MODE */
903
904 memset(&vif_info,
905 0,
906 sizeof(vif_info));
907
908 vif_info.state = NRF_WIFI_FMAC_IF_OP_STATE_DOWN;
909 vif_info.if_index = vif_ctx_zep->vif_idx;
910
911 status = nrf_wifi_sys_fmac_chg_vif_state(rpu_ctx_zep->rpu_ctx,
912 vif_ctx_zep->vif_idx,
913 &vif_info);
914
915 if (status != NRF_WIFI_STATUS_SUCCESS) {
916 LOG_ERR("%s: nrf_wifi_sys_fmac_chg_vif_state failed",
917 __func__);
918 }
919
920 status = nrf_wifi_sys_fmac_del_vif(rpu_ctx_zep->rpu_ctx,
921 vif_ctx_zep->vif_idx);
922
923 if (status != NRF_WIFI_STATUS_SUCCESS) {
924 LOG_ERR("%s: nrf_wifi_sys_fmac_del_vif failed",
925 __func__);
926 }
927
928 if (nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx) == 0) {
929 nrf_wifi_fmac_dev_rem_zep(&rpu_drv_priv_zep);
930 }
931 ret = 0;
932 unlock:
933 k_mutex_unlock(&vif_ctx_zep->vif_lock);
934
935 ret = nrf_wifi_if_zep_stop_board(dev);
936 if (ret) {
937 LOG_ERR("nrf_wifi_if_zep_stop_board failed with error: %d",
938 ret);
939 }
940 out:
941 return ret;
942 }
943
nrf_wifi_if_get_config_zep(const struct device * dev,enum ethernet_config_type type,struct ethernet_config * config)944 int nrf_wifi_if_get_config_zep(const struct device *dev,
945 enum ethernet_config_type type,
946 struct ethernet_config *config)
947 {
948 int ret = -1;
949 #ifdef CONFIG_NRF70_RAW_DATA_TX
950 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
951 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
952 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
953 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
954
955 if (!dev || !config) {
956 LOG_ERR("%s: Invalid parameters",
957 __func__);
958 goto out;
959 }
960
961 vif_ctx_zep = dev->data;
962 if (!vif_ctx_zep) {
963 LOG_ERR("%s: vif_ctx_zep is NULL",
964 __func__);
965 goto out;
966 }
967
968 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
969 if (ret != 0) {
970 LOG_ERR("%s: Failed to lock vif_lock", __func__);
971 goto out;
972 }
973
974 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
975 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
976 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
977 __func__);
978 goto unlock;
979 }
980 fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
981 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
982 if (!sys_dev_ctx) {
983 LOG_ERR("%s: sys_dev_ctx is NULL",
984 __func__);
985 goto unlock;
986 }
987
988 memset(config, 0, sizeof(struct ethernet_config));
989
990 if (type == ETHERNET_CONFIG_TYPE_TXINJECTION_MODE) {
991 config->txinjection_mode =
992 sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->txinjection_mode;
993 }
994 #ifdef CONFIG_NRF70_TCP_IP_CHECKSUM_OFFLOAD
995 if (type == ETHERNET_CONFIG_TYPE_TX_CHECKSUM_SUPPORT ||
996 type == ETHERNET_CONFIG_TYPE_RX_CHECKSUM_SUPPORT) {
997 config->chksum_support = ETHERNET_CHECKSUM_SUPPORT_IPV4_HEADER |
998 ETHERNET_CHECKSUM_SUPPORT_IPV4_ICMP |
999 ETHERNET_CHECKSUM_SUPPORT_IPV6_HEADER |
1000 ETHERNET_CHECKSUM_SUPPORT_IPV6_ICMP |
1001 ETHERNET_CHECKSUM_SUPPORT_TCP |
1002 ETHERNET_CHECKSUM_SUPPORT_UDP;
1003 }
1004 #endif
1005 ret = 0;
1006 unlock:
1007 k_mutex_unlock(&vif_ctx_zep->vif_lock);
1008 out:
1009 #endif
1010 return ret;
1011 }
1012
nrf_wifi_if_set_config_zep(const struct device * dev,enum ethernet_config_type type,const struct ethernet_config * config)1013 int nrf_wifi_if_set_config_zep(const struct device *dev,
1014 enum ethernet_config_type type,
1015 const struct ethernet_config *config)
1016 {
1017 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
1018 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
1019 struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL;
1020 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1021 int ret = -1;
1022
1023 if (!dev) {
1024 LOG_ERR("%s: Invalid parameters",
1025 __func__);
1026 goto out;
1027 }
1028
1029 vif_ctx_zep = dev->data;
1030 if (!vif_ctx_zep) {
1031 LOG_ERR("%s: vif_ctx_zep is NULL",
1032 __func__);
1033 goto out;
1034 }
1035
1036 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
1037 if (ret != 0) {
1038 LOG_ERR("%s: Failed to lock vif_lock", __func__);
1039 goto out;
1040 }
1041
1042 /* Commands without FMAC interaction */
1043 if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
1044 if (!net_eth_is_addr_valid((struct net_eth_addr *)&config->mac_address)) {
1045 LOG_ERR("%s: Invalid MAC address",
1046 __func__);
1047 goto unlock;
1048 }
1049 memcpy(vif_ctx_zep->mac_addr.addr,
1050 config->mac_address.addr,
1051 sizeof(vif_ctx_zep->mac_addr.addr));
1052
1053 net_if_set_link_addr(vif_ctx_zep->zep_net_if_ctx,
1054 vif_ctx_zep->mac_addr.addr,
1055 sizeof(vif_ctx_zep->mac_addr.addr),
1056 NET_LINK_ETHERNET);
1057 ret = 0;
1058 goto unlock;
1059 }
1060
1061 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
1062 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
1063 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
1064 __func__);
1065 goto unlock;
1066 }
1067
1068 fmac_dev_ctx = rpu_ctx_zep->rpu_ctx;
1069 sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx);
1070 if (!sys_dev_ctx) {
1071 LOG_ERR("%s: sys_dev_ctx is NULL",
1072 __func__);
1073 goto unlock;
1074 }
1075
1076 #ifdef CONFIG_NRF70_RAW_DATA_TX
1077 if (type == ETHERNET_CONFIG_TYPE_TXINJECTION_MODE) {
1078 unsigned char mode;
1079
1080 if (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->txinjection_mode ==
1081 config->txinjection_mode) {
1082 LOG_INF("%s: Driver TX injection setting is same as configured setting",
1083 __func__);
1084 goto unlock;
1085 }
1086 /**
1087 * Since UMAC wishes to use the same mode command as previously
1088 * used for mode, `OR` the primary mode with TX-Injection mode and
1089 * send it to the UMAC. That way UMAC can still maintain code
1090 * as is
1091 */
1092 if (config->txinjection_mode) {
1093 mode = (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) |
1094 (NRF_WIFI_TX_INJECTION_MODE);
1095 } else {
1096 mode = (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) ^
1097 (NRF_WIFI_TX_INJECTION_MODE);
1098 }
1099
1100 ret = nrf_wifi_sys_fmac_set_mode(rpu_ctx_zep->rpu_ctx,
1101 vif_ctx_zep->vif_idx, mode);
1102
1103 if (ret != NRF_WIFI_STATUS_SUCCESS) {
1104 LOG_ERR("%s: Mode set operation failed", __func__);
1105 goto unlock;
1106 }
1107 }
1108 #endif
1109 #ifdef CONFIG_NRF70_PROMISC_DATA_RX
1110 else if (type == ETHERNET_CONFIG_TYPE_PROMISC_MODE) {
1111 unsigned char mode;
1112
1113 if (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->promisc_mode ==
1114 config->promisc_mode) {
1115 LOG_ERR("%s: Driver promisc mode setting is same as configured setting",
1116 __func__);
1117 goto out;
1118 }
1119
1120 if (config->promisc_mode) {
1121 mode = (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) |
1122 (NRF_WIFI_PROMISCUOUS_MODE);
1123 } else {
1124 mode = (sys_dev_ctx->vif_ctx[vif_ctx_zep->vif_idx]->mode) ^
1125 (NRF_WIFI_PROMISCUOUS_MODE);
1126 }
1127
1128 ret = nrf_wifi_sys_fmac_set_mode(rpu_ctx_zep->rpu_ctx,
1129 vif_ctx_zep->vif_idx, mode);
1130
1131 if (ret != NRF_WIFI_STATUS_SUCCESS) {
1132 LOG_ERR("%s: mode set operation failed", __func__);
1133 goto out;
1134 }
1135 }
1136 #endif
1137 ret = 0;
1138 unlock:
1139 k_mutex_unlock(&vif_ctx_zep->vif_lock);
1140 out:
1141 return ret;
1142 }
1143
1144 #ifdef CONFIG_NET_STATISTICS_ETHERNET
nrf_wifi_eth_stats_get(const struct device * dev)1145 struct net_stats_eth *nrf_wifi_eth_stats_get(const struct device *dev)
1146 {
1147 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
1148
1149 if (!dev) {
1150 LOG_ERR("%s Device not found", __func__);
1151 goto out;
1152 }
1153
1154 vif_ctx_zep = dev->data;
1155 if (!vif_ctx_zep) {
1156 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
1157 goto out;
1158 }
1159
1160 return &vif_ctx_zep->eth_stats;
1161 out:
1162 return NULL;
1163 }
1164 #endif /* CONFIG_NET_STATISTICS_ETHERNET */
1165
1166 #ifdef CONFIG_NET_STATISTICS_WIFI
nrf_wifi_stats_get(const struct device * dev,struct net_stats_wifi * zstats)1167 int nrf_wifi_stats_get(const struct device *dev, struct net_stats_wifi *zstats)
1168 {
1169 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1170 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
1171 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
1172 #ifdef CONFIG_NRF70_RAW_DATA_TX
1173 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1174 #endif /* CONFIG_NRF70_RAW_DATA_TX */
1175 struct rpu_sys_op_stats stats;
1176 int ret = -1;
1177
1178 if (!dev) {
1179 LOG_ERR("%s Device not found", __func__);
1180 goto out;
1181 }
1182
1183 if (!zstats) {
1184 LOG_ERR("%s Stats buffer not allocated", __func__);
1185 goto out;
1186 }
1187
1188 vif_ctx_zep = dev->data;
1189 if (!vif_ctx_zep) {
1190 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
1191 goto out;
1192 }
1193
1194 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
1195 if (ret != 0) {
1196 LOG_ERR("%s: Failed to lock vif_lock", __func__);
1197 goto out;
1198 }
1199 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
1200 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
1201 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
1202 __func__);
1203 goto unlock;
1204 }
1205
1206 memset(&stats, 0, sizeof(struct rpu_sys_op_stats));
1207 status = nrf_wifi_sys_fmac_stats_get(rpu_ctx_zep->rpu_ctx, 0, &stats);
1208 if (status != NRF_WIFI_STATUS_SUCCESS) {
1209 LOG_ERR("%s: nrf_wifi_fmac_stats_get failed", __func__);
1210 goto unlock;
1211 }
1212
1213 zstats->pkts.tx = stats.host.total_tx_pkts;
1214 zstats->pkts.rx = stats.host.total_rx_pkts;
1215 zstats->errors.tx = stats.host.total_tx_drop_pkts;
1216 zstats->errors.rx = stats.host.total_rx_drop_pkts +
1217 stats.fw.umac.interface_data_stats.rx_checksum_error_count;
1218 zstats->bytes.received = stats.fw.umac.interface_data_stats.rx_bytes;
1219 zstats->bytes.sent = stats.fw.umac.interface_data_stats.tx_bytes;
1220 zstats->sta_mgmt.beacons_rx = stats.fw.umac.interface_data_stats.rx_beacon_success_count;
1221 zstats->sta_mgmt.beacons_miss = stats.fw.umac.interface_data_stats.rx_beacon_miss_count;
1222 zstats->broadcast.rx = stats.fw.umac.interface_data_stats.rx_broadcast_pkt_count;
1223 zstats->broadcast.tx = stats.fw.umac.interface_data_stats.tx_broadcast_pkt_count;
1224 zstats->multicast.rx = stats.fw.umac.interface_data_stats.rx_multicast_pkt_count;
1225 zstats->multicast.tx = stats.fw.umac.interface_data_stats.tx_multicast_pkt_count;
1226 zstats->unicast.rx = stats.fw.umac.interface_data_stats.rx_unicast_pkt_count;
1227 zstats->unicast.tx = stats.fw.umac.interface_data_stats.tx_unicast_pkt_count;
1228 zstats->overrun_count = stats.host.total_tx_drop_pkts + stats.host.total_rx_drop_pkts;
1229
1230 #ifdef CONFIG_NRF70_RAW_DATA_TX
1231 sys_dev_ctx = wifi_dev_priv(rpu_ctx_zep->rpu_ctx);
1232 zstats->errors.tx += sys_dev_ctx->raw_pkt_stats.raw_pkt_send_failure;
1233 #endif /* CONFIG_NRF70_RAW_DATA_TX */
1234 ret = 0;
1235 unlock:
1236 k_mutex_unlock(&vif_ctx_zep->vif_lock);
1237 out:
1238 return ret;
1239 }
1240
nrf_wifi_stats_reset(const struct device * dev)1241 int nrf_wifi_stats_reset(const struct device *dev)
1242 {
1243 enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
1244 struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
1245 struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
1246 struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL;
1247 int ret = -1;
1248
1249 if (!dev) {
1250 LOG_ERR("%s Device not found", __func__);
1251 goto out;
1252 }
1253
1254 vif_ctx_zep = dev->data;
1255 if (!vif_ctx_zep) {
1256 LOG_ERR("%s: vif_ctx_zep is NULL", __func__);
1257 goto out;
1258 }
1259
1260 ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
1261 if (ret != 0) {
1262 LOG_ERR("%s: Failed to lock vif_lock", __func__);
1263 goto out;
1264 }
1265
1266 rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
1267 if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) {
1268 LOG_DBG("%s: rpu_ctx_zep or rpu_ctx is NULL",
1269 __func__);
1270 goto unlock;
1271 }
1272
1273 status = nrf_wifi_fmac_stats_reset(rpu_ctx_zep->rpu_ctx);
1274 if (status != NRF_WIFI_STATUS_SUCCESS) {
1275 LOG_ERR("%s: nrf_wifi_fmac_stats_reset failed", __func__);
1276 goto unlock;
1277 }
1278
1279 sys_dev_ctx = wifi_dev_priv(rpu_ctx_zep->rpu_ctx);
1280 memset(&sys_dev_ctx->host_stats, 0, sizeof(struct rpu_host_stats));
1281
1282 ret = 0;
1283 unlock:
1284 k_mutex_unlock(&vif_ctx_zep->vif_lock);
1285 out:
1286 return ret;
1287 }
1288 #endif /* CONFIG_NET_STATISTICS_WIFI */
1289