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