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