From cd24570a65eabff276057dd20d17e55f78c3781a Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Mon, 15 Jul 2024 14:57:08 +0530 Subject: [PATCH 01/34] drivers: wifi: Option for Qos NULL frame based power save [SHEL-2947] QoS null frame based legacy power save support. Signed-off-by: Ajay Parida --- drivers/wifi/nrf700x/Kconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 524f4d0e2c28..7dadce839a11 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -620,3 +620,15 @@ config NRF_WIFI_AP_DEAD_DETECT_TIMEOUT help The number of seconds after which AP is declared dead if no beacons are received from the AP. Used to detect AP silently going down e.g., power off. + +choice NRF_WIFI_PS_DATA_RETRIEVAL_MODE + prompt "Power save data retrieval mode" + default NRF_WIFI_PS_POLL_BASED_RETRIEVAL + help + Select the mechanism to retrieve buffered data from AP. +config NRF_WIFI_PS_POLL_BASED_RETRIEVAL + bool "PS-Poll based mechanism to retrieve buffered data from AP" +config NRF_WIFI_QOS_NULL_BASED_RETRIEVAL + bool "QoS null frame based mechanism to retrieve buffered data from AP" + +endchoice From 667618758d9a9abe1184f495f4144a45b3693ae3 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Mon, 29 Jul 2024 15:21:21 +0530 Subject: [PATCH 02/34] drivers: wifi: Change mode to mechanism [SHEL-2947] Changing naming of power save mode to mechanism(Text change). Signed-off-by: Ajay Parida --- drivers/wifi/nrf700x/Kconfig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 7dadce839a11..cf00f4743d5c 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -621,14 +621,25 @@ config NRF_WIFI_AP_DEAD_DETECT_TIMEOUT The number of seconds after which AP is declared dead if no beacons are received from the AP. Used to detect AP silently going down e.g., power off. -choice NRF_WIFI_PS_DATA_RETRIEVAL_MODE - prompt "Power save data retrieval mode" +choice NRF_WIFI_PS_DATA_RETRIEVAL_MECHANISM + prompt "Power save data retrieval mechanism" default NRF_WIFI_PS_POLL_BASED_RETRIEVAL help Select the mechanism to retrieve buffered data from AP. + config NRF_WIFI_PS_POLL_BASED_RETRIEVAL - bool "PS-Poll based mechanism to retrieve buffered data from AP" + bool "PS-Poll frame based mechanism to retrieve buffered data from AP" + help + When AP notifies about availability of buffered data, the STA stays in power save + and retrieves the frames one-by-one, this conserved more power but adds latency + to the traffic. Ideal for minimum number of frames. + config NRF_WIFI_QOS_NULL_BASED_RETRIEVAL bool "QoS null frame based mechanism to retrieve buffered data from AP" + help + When AP notifies about availability of buffered data, the STA comes out of + power save and then AP can deliver all buffered frames without any additional + overhead or latency, but STA enters power save after a delay costing more power + depending on the delay. Ideal for heavy buffered traffic. endchoice From 806d7d187a83ad0cd217536fe41f3c2609af64e5 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 15 May 2024 23:51:29 +0530 Subject: [PATCH 03/34] drivers: wifi: Implement RPU recovery callbacks FMAC relies on these callbacks to perform a RPU recovery i.e., coldboot the device in a clean way, this is achieved by performing an interface down and then up, this properly cleans up the driver, performs a cold boot and either through NET_IF events (for scan only) or WPA_S events (for full Wi-Fi) notifies the applications. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/inc/fmac_main.h | 4 ++ drivers/wifi/nrf700x/src/fmac_main.c | 1 + drivers/wifi/nrf700x/src/net_if.c | 59 +++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 6e2a2210e940..78fd77baa3f7 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -81,6 +81,7 @@ struct nrf_wifi_vif_ctx_zep { unsigned long rssi_record_timestamp_us; signed short rssi; #endif /* CONFIG_NRF700X_STA_MODE */ + struct k_work nrf_wifi_rpu_recovery_work; }; struct nrf_wifi_vif_ctx_map { @@ -123,5 +124,8 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep); enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx); struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface); +void nrf_wifi_rpu_recovery_cb(void *vif_ctx, + void *event_data, + unsigned int event_len); #endif /* __ZEPHYR_FMAC_MAIN_H__ */ diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 6a2a6d0bfa02..0d4bf867f69f 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -689,6 +689,7 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) rx_buf_pools[1].buf_sz = rx2_buf_sz; rx_buf_pools[2].buf_sz = rx3_buf_sz; + callbk_fns.rpu_recovery_callbk_fn = nrf_wifi_rpu_recovery_cb; callbk_fns.scan_start_callbk_fn = nrf_wifi_event_proc_scan_start_zep; callbk_fns.scan_done_callbk_fn = nrf_wifi_event_proc_scan_done_zep; callbk_fns.reg_change_callbk_fn = reg_change_callbk_fn; diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 1261e837f294..e04f582da904 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -41,22 +41,75 @@ void nrf_wifi_set_iface_event_handler(void *os_vif_ctx, if (!os_vif_ctx) { LOG_ERR("%s: Invalid parameters", __func__); - goto out; + return; } if (!event) { LOG_ERR("%s: event is NULL", __func__); - goto out; + return; } + (void)event_len; vif_ctx_zep = os_vif_ctx; vif_ctx_zep->set_if_event_received = true; vif_ctx_zep->set_if_status = event->return_value; +} + +static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) +{ + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = CONTAINER_OF(work, + struct nrf_wifi_vif_ctx_zep, + nrf_wifi_rpu_recovery_work); + + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL", __func__); + return; + } + + if (!vif_ctx_zep->zep_net_if_ctx) { + LOG_ERR("%s: zep_net_if_ctx is NULL", __func__); + return; + } + + LOG_DBG("%s: Bringing the interface down", __func__); + /* This indirectly does a cold-boot of RPU */ + net_if_down(vif_ctx_zep->zep_net_if_ctx); + k_msleep(10); + LOG_DBG("%s: Bringing the interface up", __func__); + net_if_up(vif_ctx_zep->zep_net_if_ctx); +} + +void nrf_wifi_rpu_recovery_cb(void *vif_ctx_handle, + void *event_data, + unsigned int event_len) +{ + struct nrf_wifi_fmac_vif_ctx *vif_ctx = vif_ctx_handle; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_fmac_dev_ctx_def *def_dev_ctx = NULL; + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + + if (!vif_ctx) { + LOG_ERR("%s: vif_ctx is NULL", + __func__); + goto out; + } + + fmac_dev_ctx = vif_ctx->fmac_dev_ctx; + def_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + if (!def_dev_ctx) { + LOG_ERR("%s: def_dev_ctx is NULL", + __func__); + goto out; + } + + vif_ctx_zep = vif_ctx->os_vif_ctx; + (void)event_data; + k_work_submit(&vif_ctx_zep->nrf_wifi_rpu_recovery_work); out: return; } @@ -510,6 +563,8 @@ void nrf_wifi_if_init_zep(struct net_if *iface) nrf_wifi_net_iface_work_handler); #endif /* CONFIG_NRF700X_DATA_TX */ + k_work_init(&vif_ctx_zep->nrf_wifi_rpu_recovery_work, + nrf_wifi_rpu_recovery_work_handler); #if !defined(CONFIG_NRF_WIFI_IF_AUTO_START) net_if_flag_set(iface, NET_IF_NO_AUTO_START); #endif /* CONFIG_NRF_WIFI_IF_AUTO_START */ From 4f82b1d3fa0dfe68e79f8860fa2edf789d0676ec Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 00:29:40 +0530 Subject: [PATCH 04/34] drivers: wifi: Implement locking for recovery In case we get multiple watchdog timers in succession, we need to sequentialize the recovery. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/inc/fmac_main.h | 1 + drivers/wifi/nrf700x/src/fmac_main.c | 2 ++ drivers/wifi/nrf700x/src/net_if.c | 9 +++++++++ 3 files changed, 12 insertions(+) diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 78fd77baa3f7..0b87eff53d14 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -105,6 +105,7 @@ struct nrf_wifi_ctx_zep { #endif /* CONFIG_NRF700X_RADIO_TEST */ unsigned char *extended_capa, *extended_capa_mask; unsigned int extended_capa_len; + struct k_mutex rpu_lock; }; struct nrf_wifi_drv_priv_zep { diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 0d4bf867f69f..26a43a95eeda 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -625,6 +625,8 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv goto err; } + k_mutex_init(&rpu_ctx_zep->rpu_lock); + return status; err: if (rpu_ctx) { diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index e04f582da904..02aed6e98111 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -64,6 +64,7 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = CONTAINER_OF(work, struct nrf_wifi_vif_ctx_zep, nrf_wifi_rpu_recovery_work); + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; if (!vif_ctx_zep) { LOG_ERR("%s: vif_ctx_zep is NULL", __func__); @@ -75,12 +76,20 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) { + LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); + return; + } + + k_mutex_lock(&rpu_ctx_zep->rpu_lock, K_FOREVER); LOG_DBG("%s: Bringing the interface down", __func__); /* This indirectly does a cold-boot of RPU */ net_if_down(vif_ctx_zep->zep_net_if_ctx); k_msleep(10); LOG_DBG("%s: Bringing the interface up", __func__); net_if_up(vif_ctx_zep->zep_net_if_ctx); + k_mutex_unlock(&rpu_ctx_zep->rpu_lock); } void nrf_wifi_rpu_recovery_cb(void *vif_ctx_handle, From 9379fecb11507d96ae765cc3fa6e530d76ce038b Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 00:36:48 +0530 Subject: [PATCH 05/34] drivers: wifi: Add a feature flag for RPU recovery In some scenarios esp. while debugging nRF70, this feature should be disabled, so, provide a feature flag and mark it as experimental. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 11 +++++++++++ drivers/wifi/nrf700x/inc/fmac_main.h | 2 ++ drivers/wifi/nrf700x/src/fmac_main.c | 2 ++ drivers/wifi/nrf700x/src/net_if.c | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index cf00f4743d5c..1391095cf28a 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -643,3 +643,14 @@ config NRF_WIFI_QOS_NULL_BASED_RETRIEVAL depending on the delay. Ideal for heavy buffered traffic. endchoice + +config NRF_WIFI_RPU_RECOVERY + bool "Enable RPU recovery mechanism" + select EXPERIMENTAL + default y + help + Enable RPU recovery mechanism to recover from RPU (nRF70) hang. + This feature performs an interface reset (down and up) which triggers + a RPU coldboot. Application's network connection will be lost during + the recovery process and it is application's responsibility to + re-establish the network connection. diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 0b87eff53d14..bd26724d5362 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -81,7 +81,9 @@ struct nrf_wifi_vif_ctx_zep { unsigned long rssi_record_timestamp_us; signed short rssi; #endif /* CONFIG_NRF700X_STA_MODE */ +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY struct k_work nrf_wifi_rpu_recovery_work; +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ }; struct nrf_wifi_vif_ctx_map { diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 26a43a95eeda..be856552728f 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -691,7 +691,9 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) rx_buf_pools[1].buf_sz = rx2_buf_sz; rx_buf_pools[2].buf_sz = rx3_buf_sz; +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY callbk_fns.rpu_recovery_callbk_fn = nrf_wifi_rpu_recovery_cb; +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ callbk_fns.scan_start_callbk_fn = nrf_wifi_event_proc_scan_start_zep; callbk_fns.scan_done_callbk_fn = nrf_wifi_event_proc_scan_done_zep; callbk_fns.reg_change_callbk_fn = reg_change_callbk_fn; diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 02aed6e98111..aa9ee5b18704 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -59,6 +59,7 @@ void nrf_wifi_set_iface_event_handler(void *os_vif_ctx, vif_ctx_zep->set_if_status = event->return_value; } +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = CONTAINER_OF(work, @@ -122,6 +123,7 @@ void nrf_wifi_rpu_recovery_cb(void *vif_ctx_handle, out: return; } +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ #ifdef CONFIG_NRF700X_DATA_TX static void nrf_wifi_net_iface_work_handler(struct k_work *work) @@ -572,8 +574,11 @@ void nrf_wifi_if_init_zep(struct net_if *iface) nrf_wifi_net_iface_work_handler); #endif /* CONFIG_NRF700X_DATA_TX */ +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY k_work_init(&vif_ctx_zep->nrf_wifi_rpu_recovery_work, nrf_wifi_rpu_recovery_work_handler); +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ + #if !defined(CONFIG_NRF_WIFI_IF_AUTO_START) net_if_flag_set(iface, NET_IF_NO_AUTO_START); #endif /* CONFIG_NRF_WIFI_IF_AUTO_START */ From d852a65db0b2c1edf7fc55c3e390638cad53ca8e Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 00:43:34 +0530 Subject: [PATCH 06/34] drivers: wifi: Add configuration option for propagation delay This delay ensures that the applications have enough time to perform any cleanup and be prepared once the RPU is powered on again. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 12 ++++++++++++ drivers/wifi/nrf700x/src/net_if.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 1391095cf28a..b02db9106d62 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -654,3 +654,15 @@ config NRF_WIFI_RPU_RECOVERY a RPU coldboot. Application's network connection will be lost during the recovery process and it is application's responsibility to re-establish the network connection. + +if NRF_WIFI_RPU_RECOVERY + +config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS + int "RPU recovery propagation delay in milliseconds" + default 10 + help + Propagation delay in milliseconds to wait after RPU is powered down + before powering it up. This delay is required to ensure that the recovery + is propagted to all the applications and stack and have enough time to + clean up the resources. +endif diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index aa9ee5b18704..8bded56791c3 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -87,7 +87,7 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) LOG_DBG("%s: Bringing the interface down", __func__); /* This indirectly does a cold-boot of RPU */ net_if_down(vif_ctx_zep->zep_net_if_ctx); - k_msleep(10); + k_msleep(CONFIG_NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS); LOG_DBG("%s: Bringing the interface up", __func__); net_if_up(vif_ctx_zep->zep_net_if_ctx); k_mutex_unlock(&rpu_ctx_zep->rpu_lock); From f038e1373f58471b0e31afe63f87c4513983db96 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 00:46:47 +0530 Subject: [PATCH 07/34] drivers: wifi: Increase net management events This is necessary as recovery involves calling down and up in a rapid succession. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index b02db9106d62..d02cd4007f8d 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -665,4 +665,8 @@ config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS before powering it up. This delay is required to ensure that the recovery is propagted to all the applications and stack and have enough time to clean up the resources. + +config NET_MGMT_EVENT_QUEUE_SIZE + # Doing interface down and up even with delay puts a lot of events in the queue + default 16 endif From 4771c8a55c715e3b6f44dee6b46a7ecf635afa8e Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 16 May 2024 01:01:49 +0530 Subject: [PATCH 08/34] drivers: wifi: Add a test command for RPU recovery This helps us verify the recovery mechanism. Implements SHEL-2726. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/wifi_util.c | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/drivers/wifi/nrf700x/src/wifi_util.c b/drivers/wifi/nrf700x/src/wifi_util.c index cee09ba60795..c7af2c5bb030 100644 --- a/drivers/wifi/nrf700x/src/wifi_util.c +++ b/drivers/wifi/nrf700x/src/wifi_util.c @@ -887,6 +887,39 @@ static int nrf_wifi_util_dump_rpu_stats(const struct shell *shell, } #endif /* CONFIG_NRF700X_RADIO_TEST */ +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY +static int nrf_wifi_util_trigger_rpu_recovery(const struct shell *shell, + size_t argc, + const char *argv[]) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + + if (!ctx || !ctx->rpu_ctx) { + shell_fprintf(shell, + SHELL_ERROR, + "RPU context not initialized\n"); + return -ENOEXEC; + } + + fmac_dev_ctx = ctx->rpu_ctx; + + status = nrf_wifi_fmac_rpu_recovery_callback(fmac_dev_ctx, NULL, 0); + if (status != NRF_WIFI_STATUS_SUCCESS) { + shell_fprintf(shell, + SHELL_ERROR, + "Failed to trigger RPU recovery\n"); + return -ENOEXEC; + } + + shell_fprintf(shell, + SHELL_INFO, + "RPU recovery triggered\n"); + + return 0; +} +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ + SHELL_STATIC_SUBCMD_SET_CREATE( nrf_wifi_util_subcmds, SHELL_CMD_ARG(he_ltf, @@ -982,6 +1015,14 @@ SHELL_STATIC_SUBCMD_SET_CREATE( 1, 1), #endif /* CONFIG_NRF700X_RADIO_TEST */ +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY + SHELL_CMD_ARG(rpu_recovery_test, + NULL, + "Trigger RPU recovery", + nrf_wifi_util_trigger_rpu_recovery, + 1, + 0), +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ SHELL_SUBCMD_SET_END); From 5c15eee495d7684ea8481fbf0af2d97e06f44ec4 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Mon, 8 Jul 2024 22:42:56 +0530 Subject: [PATCH 09/34] drivers: wifi: Fix RPU recovery not being triggered During watchdog (or any) interrupt processing, RPU accesses are being made and they assert the wakeup_now flag this causes RPU recovery to not trigger. New false or true recovery detection algo: Check the time difference b/w last de-assert and assert, and if it exceeds minimum time needed for RPU to enter sleep, then not the timestamp. This timestamp will be used to compare when a watchdog interrupt is received and see if during the last window if host has given a chance for RPU to attempt sleep, if yes, then attempt recovery else ignore watchdog. Also, add a Kconfig for the 10s active time that triggers recovery, this needs to be passed to the FW (once we have enough patch memory). Also, add a Kconfig for the minimum time needed for RPU to attempt sleep in positive case. Also, add a new _ms API for time stamp fetch, this is to avoid precision loss when converting to and from ms to us and also makes code readable by avoiding *1000 and /1000. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 16 ++++++++++++++++ drivers/wifi/nrf700x/src/shim.c | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index d02cd4007f8d..8e98bec05125 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -666,6 +666,22 @@ config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS is propagted to all the applications and stack and have enough time to clean up the resources. +config NRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS + int "RPU recovery power save active timeout in milliseconds" + default 10000 + help + Power save active timeout in milliseconds after which RPU recovery + mechanism will be triggered. This timeout is used to ensure that the + RPU attempts to enter power save mode in case of inactivity. + +config NRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS + int "Minimum idle time to enter sleep in milliseconds" + range 100 5000 + default 1000 + help + Minimum time the host should de-assert WAKEUP_NOW and let RPU enter + sleep mode, assuming there is no activity. + config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 diff --git a/drivers/wifi/nrf700x/src/shim.c b/drivers/wifi/nrf700x/src/shim.c index 42bc6bc005f0..22d80b29c5f1 100644 --- a/drivers/wifi/nrf700x/src/shim.c +++ b/drivers/wifi/nrf700x/src/shim.c @@ -626,6 +626,20 @@ static unsigned int zep_shim_time_elapsed_us(unsigned long start_time_us) return curr_time_us - start_time_us; } +static unsigned long zep_shim_time_get_curr_ms(void) +{ + return k_uptime_get(); +} + +static unsigned int zep_shim_time_elapsed_ms(unsigned long start_time_ms) +{ + unsigned long curr_time_ms = 0; + + curr_time_ms = zep_shim_time_get_curr_ms(); + + return curr_time_ms - start_time_ms; +} + static enum nrf_wifi_status zep_shim_bus_qspi_dev_init(void *os_qspi_dev_ctx) { ARG_UNUSED(os_qspi_dev_ctx); @@ -938,6 +952,8 @@ static const struct nrf_wifi_osal_ops nrf_wifi_os_zep_ops = { .delay_us = k_usleep, .time_get_curr_us = zep_shim_time_get_curr_us, .time_elapsed_us = zep_shim_time_elapsed_us, + .time_get_curr_ms = zep_shim_time_get_curr_ms, + .time_elapsed_ms = zep_shim_time_elapsed_ms, .bus_qspi_init = zep_shim_bus_qspi_init, .bus_qspi_deinit = zep_shim_bus_qspi_deinit, From 7041f3649635199eb7613ea9b9ea58a1cda55331 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 9 Jul 2024 22:51:15 +0530 Subject: [PATCH 10/34] drivers: wifi: nrf700x: Ignore all failures in iface down In case RPU is stuck and need a recovery, the failures in interface down should be ignored as they are expected and we should proceed with device removal that in turn removes power to the RPU. TODO: This works for single VIF, but needs more thought for multi-VIF. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/net_if.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 8bded56791c3..3e2a3421249e 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -779,14 +779,14 @@ int nrf_wifi_if_stop_zep(const struct device *dev) ret = k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER); if (ret != 0) { LOG_ERR("%s: Failed to lock vif_lock", __func__); - goto out; + goto unlock; } rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; if (!rpu_ctx_zep) { LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); - goto out; + goto unlock; } #ifdef CONFIG_NRF700X_STA_MODE @@ -798,7 +798,6 @@ int nrf_wifi_if_stop_zep(const struct device *dev) if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: nrf_wifi_fmac_set_power_save failed", __func__); - goto unlock; } #endif /* CONFIG_NRF_WIFI_LOW_POWER */ #endif /* CONFIG_NRF700X_STA_MODE */ @@ -817,7 +816,6 @@ int nrf_wifi_if_stop_zep(const struct device *dev) if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: nrf_wifi_fmac_chg_vif_state failed", __func__); - goto unlock; } status = nrf_wifi_fmac_del_vif(rpu_ctx_zep->rpu_ctx, @@ -826,11 +824,8 @@ int nrf_wifi_if_stop_zep(const struct device *dev) if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: nrf_wifi_fmac_del_vif failed", __func__); - goto unlock; } - vif_ctx_zep->if_op_state = NRF_WIFI_FMAC_IF_OP_STATE_DOWN; - if (nrf_wifi_fmac_get_num_vifs(rpu_ctx_zep->rpu_ctx) == 0) { nrf_wifi_fmac_dev_rem_zep(&rpu_drv_priv_zep); } From 29881b9033d88b270315799bbf6801dd9203c613 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 10 Jul 2024 00:51:59 +0530 Subject: [PATCH 11/34] drivers: wifi: Add a sanity check for RPU comms Before proceeding with RPU bringup, do a sanity check by reading a known signature to make sure the Host-RPU comms are operational. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/qspi/src/rpu_hw_if.c | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/wifi/nrf700x/src/qspi/src/rpu_hw_if.c b/drivers/wifi/nrf700x/src/qspi/src/rpu_hw_if.c index 2b9ec91027c7..f65a05e9b0cd 100644 --- a/drivers/wifi/nrf700x/src/qspi/src/rpu_hw_if.c +++ b/drivers/wifi/nrf700x/src/qspi/src/rpu_hw_if.c @@ -462,6 +462,31 @@ int rpu_clks_on(void) return 0; } +#define RPU_EXP_SIG 0x42000020 +/* Read a known value from RPU memory to validate RPU communication */ +int rpu_validate_comms(void) +{ + uint32_t rpu_test; + int ret; + + /* UCCP_SOC_FAB_MST_READ_IDLE - HW reset value */ + ret = rpu_read(0x0005C, &rpu_test, 4); + if (ret) { + LOG_ERR("Error: RPU comms test: read failed\n"); + return ret; + } + + if (rpu_test != RPU_EXP_SIG) { + LOG_ERR("Error: RPU comms test: sig failed: expected 0x%x, got 0x%x\n", + RPU_EXP_SIG, rpu_test); + return -1; + } + + LOG_DBG("RPU comms test passed\n"); + + return 0; +} + #define CALL_RPU_FUNC(func, ...) \ do { \ ret = func(__VA_ARGS__); \ @@ -514,6 +539,11 @@ int rpu_enable(void) goto rpu_pwroff; } + ret = rpu_validate_comms(); + if (ret) { + goto rpu_pwroff; + } + return 0; rpu_pwroff: rpu_pwroff(); From 58a3b1f9f5dc17058987c7f9a1e62dc485c6fc58 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Wed, 10 Jul 2024 00:56:32 +0530 Subject: [PATCH 12/34] drivers: wifi: Add support for separate debugs for RPU recovery These are helpful for debugging RPU recovery only. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 5 +++++ drivers/wifi/nrf700x/src/net_if.c | 30 ++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 8e98bec05125..d77cc277f856 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -682,6 +682,11 @@ config NRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS Minimum time the host should de-assert WAKEUP_NOW and let RPU enter sleep mode, assuming there is no activity. +config NRF_WIFI_RPU_RECOVERY_DEBUG + bool "Enable RPU recovery debug logs" + help + Enable RPU recovery debug logs to help debug RPU recovery mechanism. + config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 3e2a3421249e..37df01b64fb6 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -66,6 +66,7 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) struct nrf_wifi_vif_ctx_zep, nrf_wifi_rpu_recovery_work); struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + int ret; if (!vif_ctx_zep) { LOG_ERR("%s: vif_ctx_zep is NULL", __func__); @@ -83,14 +84,39 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: Starting RPU recovery", __func__); +#else + LOG_DBG("%s: Starting RPU recovery", __func__); +#endif k_mutex_lock(&rpu_ctx_zep->rpu_lock, K_FOREVER); +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: Bringing the interface down", __func__); +#else LOG_DBG("%s: Bringing the interface down", __func__); +#endif /* This indirectly does a cold-boot of RPU */ - net_if_down(vif_ctx_zep->zep_net_if_ctx); + ret = net_if_down(vif_ctx_zep->zep_net_if_ctx); + if (ret) { + LOG_ERR("%s: net_if_down failed: %d", __func__, ret); + /* Continue with the recovery */ + } k_msleep(CONFIG_NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS); +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: Bringing the interface up", __func__); +#else LOG_DBG("%s: Bringing the interface up", __func__); - net_if_up(vif_ctx_zep->zep_net_if_ctx); +#endif + ret = net_if_up(vif_ctx_zep->zep_net_if_ctx); + if (ret) { + LOG_ERR("%s: net_if_up failed: %d", __func__, ret); + } k_mutex_unlock(&rpu_ctx_zep->rpu_lock); +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: RPU recovery done", __func__); +#else + LOG_DBG("%s: RPU recovery done", __func__); +#endif } void nrf_wifi_rpu_recovery_cb(void *vif_ctx_handle, From fd768b670a1ecd2ba25cd5504ff29e05e8e84ae3 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 11 Jul 2024 13:07:32 +0530 Subject: [PATCH 13/34] drivers: wifi: Increase the propogation delay In order for the interface down to propagate and cleanup it needs more time, using Shell 10ms was working due to human delay, but programatically this needs higher delay. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index d77cc277f856..fa712406b4bc 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -659,7 +659,7 @@ if NRF_WIFI_RPU_RECOVERY config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS int "RPU recovery propagation delay in milliseconds" - default 10 + default 2000 help Propagation delay in milliseconds to wait after RPU is powered down before powering it up. This delay is required to ensure that the recovery From 50e5c798006270f37034a6148af0965812a2913c Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 30 May 2024 16:01:29 +0530 Subject: [PATCH 14/34] drivers: wifi: Remove per-interface extended capabilities RPU is only providing the per-wiphy (RPU) extended capabilities, so, remove storing of per-VIF extended capabilities. BTW, there is a memory leak here when doing interface down and up. Fixes SHEL-2738. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/inc/fmac_main.h | 5 ---- drivers/wifi/nrf700x/src/wpa_supp_if.c | 41 -------------------------- 2 files changed, 46 deletions(-) diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index bd26724d5362..c9e7faa01c93 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -69,11 +69,6 @@ struct nrf_wifi_vif_ctx_zep { struct wifi_ps_config *ps_info; bool ps_config_info_evnt; bool authorized; - struct nrf_wifi_ext_capa { - enum nrf_wifi_iftype iftype; - unsigned char *ext_capa, *ext_capa_mask; - unsigned int ext_capa_len; - } iface_ext_capa; bool cookie_resp_received; #ifdef CONFIG_NRF700X_DATA_TX struct k_work nrf_wifi_net_iface_work; diff --git a/drivers/wifi/nrf700x/src/wpa_supp_if.c b/drivers/wifi/nrf700x/src/wpa_supp_if.c index 24a0e2074d5e..35537fc56c32 100644 --- a/drivers/wifi/nrf700x/src/wpa_supp_if.c +++ b/drivers/wifi/nrf700x/src/wpa_supp_if.c @@ -1550,41 +1550,6 @@ enum nrf_wifi_status nrf_wifi_parse_sband( return WLAN_STATUS_SUCCESS; } -void *nrf_wifi_memdup(const void *src, size_t len) -{ - void *r = malloc(len); - - if (r && src) { - memcpy(r, src, len); - } - return r; -} - -static void nrf_wifi_wiphy_info_extended_capab_cfg(struct nrf_wifi_ext_capa *capa, - struct nrf_wifi_event_get_wiphy *wiphy_info) -{ - unsigned int len; - - capa->iftype = NRF_WIFI_IFTYPE_STATION; - - len = wiphy_info->extended_capabilities_len; - - capa->ext_capa = nrf_wifi_memdup(&wiphy_info->extended_capabilities[0], len); - - if (!capa->ext_capa) - return; - - capa->ext_capa_len = len; - - len = wiphy_info->extended_capabilities_len; - - capa->ext_capa_mask = - nrf_wifi_memdup(&wiphy_info->extended_capabilities_mask[0], len); - - if (!capa->ext_capa_mask) - return; -} - void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv, struct nrf_wifi_event_get_wiphy *wiphy_info, unsigned int event_len) @@ -1636,8 +1601,6 @@ void nrf_wifi_wpa_supp_event_get_wiphy(void *if_priv, } } - nrf_wifi_wiphy_info_extended_capab_cfg(&vif_ctx_zep->iface_ext_capa, wiphy_info); - if (vif_ctx_zep->supp_drv_if_ctx && vif_ctx_zep->supp_callbk_fns.get_wiphy_res) { vif_ctx_zep->supp_callbk_fns.get_wiphy_res(vif_ctx_zep->supp_drv_if_ctx, NULL); } @@ -1799,10 +1762,6 @@ int nrf_wifi_supp_get_capa(void *if_priv, struct wpa_driver_capa *capa) capa->extended_capa = rpu_ctx_zep->extended_capa; capa->extended_capa_mask = rpu_ctx_zep->extended_capa_mask; capa->extended_capa_len = rpu_ctx_zep->extended_capa_len; - - capa->extended_capa = vif_ctx_zep->iface_ext_capa.ext_capa; - capa->extended_capa_mask = vif_ctx_zep->iface_ext_capa.ext_capa_mask; - capa->extended_capa_len = vif_ctx_zep->iface_ext_capa.ext_capa_len; } out: k_mutex_unlock(&vif_ctx_zep->vif_lock); From 9a065231e93a8ea676a55fbcedf12831b388cc46 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 30 May 2024 16:08:17 +0530 Subject: [PATCH 15/34] drivers: wifi: Fix memory leak The extended capabilities are not freed causing a leak on interface down and up. Fixes SHEL-2738. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/fmac_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index be856552728f..d433df6c78b1 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -653,6 +653,11 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv nrf_wifi_fmac_dev_rem(rpu_ctx_zep->rpu_ctx); #endif /* CONFIG_NRF700X_RADIO_TEST */ + free(rpu_ctx_zep->extended_capa); + rpu_ctx_zep->extended_capa = NULL; + free(rpu_ctx_zep->extended_capa_mask); + rpu_ctx_zep->extended_capa_mask = NULL; + rpu_ctx_zep->rpu_ctx = NULL; LOG_DBG("%s: FMAC device removed", __func__); From 8112f34a1631c6f523f07445ac1acdaf17c08fed Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sat, 13 Jul 2024 21:32:50 +0530 Subject: [PATCH 16/34] drivers: wifi: Ignore parallel recovery requests During recovery we might get further watchdog interrupts causing multiple recovery requests, ignore them if a recovery is already in progress. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/inc/fmac_main.h | 3 +++ drivers/wifi/nrf700x/src/net_if.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index c9e7faa01c93..1f43dfc6e373 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -103,6 +103,9 @@ struct nrf_wifi_ctx_zep { unsigned char *extended_capa, *extended_capa_mask; unsigned int extended_capa_len; struct k_mutex rpu_lock; +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY + bool rpu_recovery_in_progress; +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ }; struct nrf_wifi_drv_priv_zep { diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 37df01b64fb6..d7692eaf184b 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -84,12 +84,22 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } + if (rpu_ctx_zep->rpu_recovery_in_progress) { +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: RPU recovery already in progress", __func__); +#else + LOG_DBG("%s: RPU recovery already in progress", __func__); +#endif + return; + } + #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Starting RPU recovery", __func__); #else LOG_DBG("%s: Starting RPU recovery", __func__); #endif k_mutex_lock(&rpu_ctx_zep->rpu_lock, K_FOREVER); + rpu_ctx_zep->rpu_recovery_in_progress = true; #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Bringing the interface down", __func__); #else @@ -111,6 +121,7 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) if (ret) { LOG_ERR("%s: net_if_up failed: %d", __func__, ret); } + rpu_ctx_zep->rpu_recovery_in_progress = false; k_mutex_unlock(&rpu_ctx_zep->rpu_lock); #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: RPU recovery done", __func__); From cb8df06c29ca451833311da27669066b61c246c5 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 14 Jul 2024 01:20:59 +0530 Subject: [PATCH 17/34] drivers: wifi: Add quiet period for RPU recovery This is to avoid successive recoveries in case we get successive watchdog interrupts from the RPU. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 7 +++++++ drivers/wifi/nrf700x/inc/fmac_main.h | 1 + drivers/wifi/nrf700x/src/net_if.c | 15 +++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index fa712406b4bc..b92fbdfbea3b 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -687,6 +687,13 @@ config NRF_WIFI_RPU_RECOVERY_DEBUG help Enable RPU recovery debug logs to help debug RPU recovery mechanism. +config NRF_WIFI_RPU_RECOVERY_QUIET_PERIOD_MS + int "RPU recovery quiet period in milliseconds" + default 5000 + help + Quiet period in milliseconds after RPU recovery is triggered. During + this period, no new RPU recovery will be triggered. + config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 1f43dfc6e373..e5d3e656622d 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -105,6 +105,7 @@ struct nrf_wifi_ctx_zep { struct k_mutex rpu_lock; #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY bool rpu_recovery_in_progress; + unsigned long last_rpu_recovery_time_ms; #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ }; diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index d7692eaf184b..0c18674f647b 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -93,6 +93,20 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } + if (rpu_ctx_zep->last_rpu_recovery_time_ms && + ((k_uptime_get() - rpu_ctx_zep->last_rpu_recovery_time_ms) < + CONFIG_NRF_WIFI_RPU_RECOVERY_QUIET_PERIOD_MS)) { +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG + LOG_ERR("%s: In quiet period (last_rpu_recovery_time_ms=%ld), ignoring", + __func__, rpu_ctx_zep->last_rpu_recovery_time_ms); +#else + LOG_DBG("%s: In quiet period (last_rpu_recovery_time_ms=%ld), ignoring", + __func__, rpu_ctx_zep->last_rpu_recovery_time_ms); +#endif + return; + } + + #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Starting RPU recovery", __func__); #else @@ -122,6 +136,7 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) LOG_ERR("%s: net_if_up failed: %d", __func__, ret); } rpu_ctx_zep->rpu_recovery_in_progress = false; + rpu_ctx_zep->last_rpu_recovery_time_ms = k_uptime_get(); k_mutex_unlock(&rpu_ctx_zep->rpu_lock); #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: RPU recovery done", __func__); From ad8d2309f6d4ff310661b4569c49237652dd4a74 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 14 Jul 2024 01:43:43 +0530 Subject: [PATCH 18/34] drivers: wifi: Fix the NULL check Check for RPU context as well. To fix this properly we need more fixes to be backported, but this should suffice for now. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/fmac_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index d433df6c78b1..23f617731101 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -249,8 +249,8 @@ static void nrf_wifi_process_rssi_from_rx(void *vif_ctx, rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; - if (!rpu_ctx_zep) { - LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); + if (!rpu_ctx_zep || !rpu_ctx_zep->rpu_ctx) { + LOG_ERR("%s: rpu_ctx_zep is NULL\n", __func__); return; } From c1561655b4a97b3d50956aba201e6fe816b4d9dc Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 14 Jul 2024 01:57:29 +0530 Subject: [PATCH 19/34] drivers: wifi: Add RPU recovery retry mechanism In case RPU is stuck in consecutive recovery over a time period then that means it's not recoverable through RPU recovery, only thing left to do is to trigger a system reboot. This feature is disabled by default, so, either application can do their own implementatio or enable this feature in the driver along with configurable retries and window period. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 16 ++++++++++++++++ drivers/wifi/nrf700x/inc/fmac_main.h | 1 + drivers/wifi/nrf700x/src/net_if.c | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index b92fbdfbea3b..3117ca6cdb91 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -694,6 +694,22 @@ config NRF_WIFI_RPU_RECOVERY_QUIET_PERIOD_MS Quiet period in milliseconds after RPU recovery is triggered. During this period, no new RPU recovery will be triggered. +config NRF_WIFI_RPU_RECOVERY_MAX_RETRIES + int "Maximum number of consecutive RPU recovery retries, 0 to disable" + default 0 + help + Maximum number of consecutive RPU recovery retries before giving up + and resetting the system. Set to 0 to keep retrying indefinitely. + +config NRF_WIFI_RPU_RECOVERY_RETRY_WINDOW_S + int "RPU recovery retry window in seconds" + default 900 + help + Window in seconds during which the number of consecutive RPU recovery + retries are counted. If the number of consecutive RPU recovery retries + exceeds NRF_WIFI_RPU_RECOVERY_MAX_RETRIES within this window, the system + will be reset. + config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index e5d3e656622d..0b573c8c7f85 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -106,6 +106,7 @@ struct nrf_wifi_ctx_zep { #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY bool rpu_recovery_in_progress; unsigned long last_rpu_recovery_time_ms; + unsigned int rpu_recovery_retries; #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ }; diff --git a/drivers/wifi/nrf700x/src/net_if.c b/drivers/wifi/nrf700x/src/net_if.c index 0c18674f647b..44a463eb941b 100644 --- a/drivers/wifi/nrf700x/src/net_if.c +++ b/drivers/wifi/nrf700x/src/net_if.c @@ -14,6 +14,8 @@ #include LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF700X_LOG_LEVEL); +#include + #include "net_private.h" #include "util.h" @@ -106,13 +108,27 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } - #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Starting RPU recovery", __func__); #else LOG_DBG("%s: Starting RPU recovery", __func__); #endif k_mutex_lock(&rpu_ctx_zep->rpu_lock, K_FOREVER); +#if CONFIG_NRF_WIFI_RPU_RECOVERY_MAX_RETRIES > 0 + if (!rpu_ctx_zep->last_rpu_recovery_time_ms || + (k_uptime_get() - rpu_ctx_zep->last_rpu_recovery_time_ms) < + CONFIG_NRF_WIFI_RPU_RECOVERY_RETRY_WINDOW_S * MSEC_PER_SEC) { + if (rpu_ctx_zep->rpu_recovery_retries >= + CONFIG_NRF_WIFI_RPU_RECOVERY_MAX_RETRIES) { + LOG_ERR("%s: Maximum recovery retries reached, rebooting system", + __func__); + sys_reboot(SYS_REBOOT_COLD); + } + rpu_ctx_zep->rpu_recovery_retries++; + } else { + rpu_ctx_zep->rpu_recovery_retries = 0; + } +#endif rpu_ctx_zep->rpu_recovery_in_progress = true; #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Bringing the interface down", __func__); From 865f59e8633da63c42f3130c6a25499e875b4630 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 25 Feb 2024 22:28:38 +0530 Subject: [PATCH 20/34] drivers: wifi: Add de-initialization for SPI Though this is no-op for now, it would lead to crash if BAL de-init is called which will be in the upcoming commits. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/qspi/inc/spi_if.h | 2 ++ drivers/wifi/nrf700x/src/qspi/src/spi_if.c | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/drivers/wifi/nrf700x/src/qspi/inc/spi_if.h b/drivers/wifi/nrf700x/src/qspi/inc/spi_if.h index f5cce2e50d8b..93ae191d7ea5 100644 --- a/drivers/wifi/nrf700x/src/qspi/inc/spi_if.h +++ b/drivers/wifi/nrf700x/src/qspi/inc/spi_if.h @@ -13,6 +13,8 @@ int spim_init(struct qspi_config *config); +int spim_deinit(void); + int spim_write(unsigned int addr, const void *data, int len); int spim_read(unsigned int addr, void *data, int len); diff --git a/drivers/wifi/nrf700x/src/qspi/src/spi_if.c b/drivers/wifi/nrf700x/src/qspi/src/spi_if.c index 3c569fc57f42..51180ad03287 100644 --- a/drivers/wifi/nrf700x/src/qspi/src/spi_if.c +++ b/drivers/wifi/nrf700x/src/qspi/src/spi_if.c @@ -243,6 +243,13 @@ int spim_init(struct qspi_config *config) return 0; } +int spim_deinit(void) +{ + LOG_DBG("TODO : %s", __func__); + + return 0; +} + static void spim_addr_check(unsigned int addr, const void *data, unsigned int len) { if ((addr % 4 != 0) || (((unsigned int)data) % 4 != 0) || (len % 4 != 0)) { From 7da1e0513c44a7713c8febf87005016d7c888f31 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Sun, 25 Feb 2024 22:29:37 +0530 Subject: [PATCH 21/34] drivers: wifi: Assign de-initialization implementation ops BAL de-init was never called, so, these weren't caught. In upcoming commits BAL de-init will be used, so, assign here to avoid crashes. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/qspi/src/device.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/wifi/nrf700x/src/qspi/src/device.c b/drivers/wifi/nrf700x/src/qspi/src/device.c index c68c1ee89e63..86cd724b0b9e 100644 --- a/drivers/wifi/nrf700x/src/qspi/src/device.c +++ b/drivers/wifi/nrf700x/src/qspi/src/device.c @@ -21,15 +21,21 @@ static struct qspi_config config; #if defined(CONFIG_NRF700X_ON_QSPI) -static struct qspi_dev qspi = { .init = qspi_init, - .read = qspi_read, - .write = qspi_write, - .hl_read = qspi_hl_read}; +static struct qspi_dev qspi = { + .init = qspi_init, + .deinit = qspi_deinit, + .read = qspi_read, + .write = qspi_write, + .hl_read = qspi_hl_read +}; #else -static struct qspi_dev spim = { .init = spim_init, - .read = spim_read, - .write = spim_write, - .hl_read = spim_hl_read}; +static struct qspi_dev spim = { + .init = spim_init, + .deinit = spim_deinit, + .read = spim_read, + .write = spim_write, + .hl_read = spim_hl_read +}; #endif struct qspi_config *qspi_defconfig(void) From af4a8ed7c2b06c1a8edd79bfafa1df0daf74c911 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 26 Mar 2024 01:26:38 +0530 Subject: [PATCH 22/34] drivers: wifi: Fix NULL check for FMAC context This can lead to crash in case driver initialization fails e.g. flashing wrong build (5340 on 7002) or if this API is called too early before the driver is initialized. Fixes SHEL-2576. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/fmac_main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/wifi/nrf700x/src/fmac_main.c b/drivers/wifi/nrf700x/src/fmac_main.c index 23f617731101..0630344975d7 100644 --- a/drivers/wifi/nrf700x/src/fmac_main.c +++ b/drivers/wifi/nrf700x/src/fmac_main.c @@ -306,6 +306,7 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do { enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; struct nrf_wifi_fmac_reg_info reg_domain_info = {0}; struct wifi_reg_chan_info *chan_info = NULL; @@ -333,12 +334,18 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do goto err; } + fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + if (!fmac_dev_ctx) { + LOG_ERR("%s: fmac_dev_ctx is NULL", __func__); + goto err; + } + if (reg_domain->oper == WIFI_MGMT_SET) { memcpy(reg_domain_info.alpha2, reg_domain->country_code, WIFI_COUNTRY_CODE_LEN); reg_domain_info.force = reg_domain->force; - status = nrf_wifi_fmac_set_reg(rpu_ctx_zep->rpu_ctx, ®_domain_info); + status = nrf_wifi_fmac_set_reg(fmac_dev_ctx, ®_domain_info); if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: Failed to set regulatory domain", __func__); goto err; @@ -350,9 +357,9 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do goto err; } - status = nrf_wifi_fmac_get_reg(rpu_ctx_zep->rpu_ctx, ®_domain_info); + status = nrf_wifi_fmac_get_reg(fmac_dev_ctx, ®_domain_info); if (status != NRF_WIFI_STATUS_SUCCESS) { - LOG_ERR("%s: Failed to get regulatory domain", __func__); + LOG_ERR("%s: Failed to get regulatory domain\n", __func__); goto err; } From 66a4781eea66817908afe0669ad22edcf106ac18 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 31 May 2024 01:24:52 +0530 Subject: [PATCH 23/34] drivers: wifi: Fix de-init handle extraction The QSPI dev context has it's own structure, so, need to be extract the QSPI dev ops from the context, this has been implemented improperly, but as it's not been used till date hadn't caused any problems. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/shim.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/wifi/nrf700x/src/shim.c b/drivers/wifi/nrf700x/src/shim.c index 22d80b29c5f1..0e54e0d5db62 100644 --- a/drivers/wifi/nrf700x/src/shim.c +++ b/drivers/wifi/nrf700x/src/shim.c @@ -647,11 +647,10 @@ static enum nrf_wifi_status zep_shim_bus_qspi_dev_init(void *os_qspi_dev_ctx) return NRF_WIFI_STATUS_SUCCESS; } -static void zep_shim_bus_qspi_dev_deinit(void *os_qspi_dev_ctx) +static void zep_shim_bus_qspi_dev_deinit(void *priv) { - struct qspi_dev *dev = NULL; - - dev = os_qspi_dev_ctx; + struct zep_shim_bus_qspi_priv *qspi_priv = priv; + struct qspi_dev *dev = qspi_priv->qspi_dev; dev->deinit(); } @@ -659,7 +658,7 @@ static void zep_shim_bus_qspi_dev_deinit(void *os_qspi_dev_ctx) static void *zep_shim_bus_qspi_dev_add(void *os_qspi_priv, void *osal_qspi_dev_ctx) { struct zep_shim_bus_qspi_priv *zep_qspi_priv = os_qspi_priv; - struct qspi_dev *qdev = qspi_dev(); + struct qspi_dev *dev = qspi_dev(); int ret; enum nrf_wifi_status status; @@ -669,7 +668,7 @@ static void *zep_shim_bus_qspi_dev_add(void *os_qspi_priv, void *osal_qspi_dev_c return NULL; } - status = qdev->init(qspi_defconfig()); + status = dev->init(qspi_defconfig()); if (status != NRF_WIFI_STATUS_SUCCESS) { LOG_ERR("%s: QSPI device init failed", __func__); return NULL; @@ -680,17 +679,18 @@ static void *zep_shim_bus_qspi_dev_add(void *os_qspi_priv, void *osal_qspi_dev_c LOG_ERR("%s: RPU enable failed with error %d", __func__, ret); return NULL; } - zep_qspi_priv->qspi_dev = qdev; + zep_qspi_priv->qspi_dev = dev; zep_qspi_priv->dev_added = true; return zep_qspi_priv; } -static void zep_shim_bus_qspi_dev_rem(void *os_qspi_dev_ctx) +static void zep_shim_bus_qspi_dev_rem(void *priv) { - struct qspi_dev *dev = NULL; + struct zep_shim_bus_qspi_priv *qspi_priv = priv; + struct qspi_dev *dev = qspi_priv->qspi_dev; - dev = os_qspi_dev_ctx; + ARG_UNUSED(dev); /* TODO: Make qspi_dev a dynamic instance and remove it here */ rpu_disable(); From d9cdfb29f65ba1f77ddd3fe8a356474e42b93e38 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 18 Jul 2024 00:14:16 +0530 Subject: [PATCH 24/34] drivers: wifi: Fix RPU recovery disabled build failures Fix RPU recovery protection to solve build failures when RPU recovery is disabled. As recovery is primarily based on power-management, add a Kconfig dependency to enforce, this simplies the macros to protect the code. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 1 + drivers/wifi/nrf700x/inc/fmac_main.h | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 3117ca6cdb91..73b1cb357189 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -646,6 +646,7 @@ endchoice config NRF_WIFI_RPU_RECOVERY bool "Enable RPU recovery mechanism" + depends on NRF_WIFI_LOW_POWER select EXPERIMENTAL default y help diff --git a/drivers/wifi/nrf700x/inc/fmac_main.h b/drivers/wifi/nrf700x/inc/fmac_main.h index 0b573c8c7f85..53b5f713fc06 100644 --- a/drivers/wifi/nrf700x/inc/fmac_main.h +++ b/drivers/wifi/nrf700x/inc/fmac_main.h @@ -127,8 +127,10 @@ enum nrf_wifi_status nrf_wifi_fmac_dev_add_zep(struct nrf_wifi_drv_priv_zep *drv enum nrf_wifi_status nrf_wifi_fmac_dev_rem_zep(struct nrf_wifi_drv_priv_zep *drv_priv_zep); enum nrf_wifi_status nrf_wifi_fw_load(void *rpu_ctx); struct nrf_wifi_vif_ctx_zep *nrf_wifi_get_vif_ctx(struct net_if *iface); +#ifdef CONFIG_NRF_WIFI_RPU_RECOVERY void nrf_wifi_rpu_recovery_cb(void *vif_ctx, void *event_data, unsigned int event_len); +#endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ #endif /* __ZEPHYR_FMAC_MAIN_H__ */ From c0ef6abe5d1cc2f70c051e51f976e67348eaa3ca Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 18 Jul 2024 01:02:57 +0530 Subject: [PATCH 25/34] drivers: wifi: Fix TX buffers leak During interface down in case TX has pending buffers in either TXQ or Pending_Q then they are not freed instead the Q itself is freed. Fix by traversing the Q and freeing all members. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/src/shim.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/wifi/nrf700x/src/shim.c b/drivers/wifi/nrf700x/src/shim.c index 0e54e0d5db62..e8d05804252f 100644 --- a/drivers/wifi/nrf700x/src/shim.c +++ b/drivers/wifi/nrf700x/src/shim.c @@ -238,9 +238,8 @@ static void *zep_shim_nbuf_alloc(unsigned int size) static void zep_shim_nbuf_free(void *nbuf) { - struct nwb *nwb; - - nwb = nbuf; + if (!nbuf) + return; k_free(((struct nwb *)nbuf)->priv); From ed659877d16e469625d68d1cd51ed94ff9b515e2 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 11 Jul 2024 11:45:48 +0530 Subject: [PATCH 26/34] net: lib: Add Wi-Fi ready lib This library should be used samples to manage Wi-Fi usage dynamically. Signed-off-by: Chaitanya Tata --- doc/nrf/libraries/networking/wifi_ready.rst | 30 +++ .../releases/release-notes-changelog.rst | 2 +- include/net/wifi_ready.h | 75 +++++++ subsys/net/lib/CMakeLists.txt | 1 + subsys/net/lib/Kconfig | 1 + subsys/net/lib/wifi_ready/CMakeLists.txt | 8 + subsys/net/lib/wifi_ready/Kconfig | 35 +++ subsys/net/lib/wifi_ready/wifi_ready.c | 202 ++++++++++++++++++ 8 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 doc/nrf/libraries/networking/wifi_ready.rst create mode 100644 include/net/wifi_ready.h create mode 100644 subsys/net/lib/wifi_ready/CMakeLists.txt create mode 100644 subsys/net/lib/wifi_ready/Kconfig create mode 100644 subsys/net/lib/wifi_ready/wifi_ready.c diff --git a/doc/nrf/libraries/networking/wifi_ready.rst b/doc/nrf/libraries/networking/wifi_ready.rst new file mode 100644 index 000000000000..9e7a595f9b96 --- /dev/null +++ b/doc/nrf/libraries/networking/wifi_ready.rst @@ -0,0 +1,30 @@ +.. _lib_wifi_ready: + +Wi-Fi ready +########### + +.. contents:: + :local: + :depth: 2 + +The Wi-Fi ready library manages Wi-FiĀ® readiness for applications by handling supplicant ready and not ready events. + +Overview +******** + +The Wi-Fi ready library informs applications of Wi-Fi readiness by managing supplicant events, indicating when Wi-Fi is available for use. + +Configuration +************* + +To use this library, enable the :kconfig:option:`CONFIG_WIFI_READY_LIB` Kconfig option. + +API documentation +***************** + +| Header file: :file:`include/net/wifi_ready.h` +| Source files: :file:`subsys/net/lib/wifi_ready` + +.. doxygengroup:: wifi_ready + :project: nrf + :members: diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 7c24143e800e..76fe2b576ba3 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -335,7 +335,7 @@ Modem libraries Libraries for networking ------------------------ -|no_changes_yet_note| +* Added the :ref:`lib_wifi_ready` library. Libraries for NFC ----------------- diff --git a/include/net/wifi_ready.h b/include/net/wifi_ready.h new file mode 100644 index 000000000000..3db6738e118e --- /dev/null +++ b/include/net/wifi_ready.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + + +#ifndef __LIB_WIFI_READY_H__ +#define __LIB_WIFI_READY_H__ + +#include + +/** + * @defgroup wifi_ready Wi-Fi ready library + * @brief Library for handling Wi-Fi ready events. + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Structure for storing a callback function to be called when the Wi-Fi is ready. + */ +typedef struct { + /** Callback function to be called when the Wi-Fi is ready. */ + void (*wifi_ready_cb)(bool wifi_ready); + /** Interface to which the callback is registered. */ + struct net_if *iface; + /** Only for internal use. */ + struct k_work item; +} wifi_ready_callback_t; + +/** + * @brief Register a callback to be called when the Wi-Fi is ready. + * + * @param cb Callback function to be called when the Wi-Fi is ready. + * The callback is called from NET_MGMT thread, so, care should be taken + * to avoid blocking the thread and also stack size should be considered. + * @param iface (optional) Interface to which the callback is registered. + * + * @return 0 if the callback was successfully registered, or a negative error code + * if the callback could not be registered. + * + * @retval -EINVAL if the callback is NULL. + * @retval -ENOMEM if the callback array is full. + * @retval -EALREADY if the callback is already registered. + */ + +int register_wifi_ready_callback(wifi_ready_callback_t cb, struct net_if *iface); +/** + * @brief Unregister a callback that was registered to be called when the Wi-Fi is ready. + * + * @param cb Callback function to be unregistered. + * @param iface (optional) Interface to which the callback is registered. + * + * @return 0 if the callback was successfully unregistered, or a negative error code + * if the callback could not be unregistered. + * + * @retval -EINVAL if the callback is NULL. + * @retval -ENOENT if the callback is not registered. + */ +int unregister_wifi_ready_callback(wifi_ready_callback_t cb, struct net_if *iface); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __LIB_WIFI_READY_H__*/ diff --git a/subsys/net/lib/CMakeLists.txt b/subsys/net/lib/CMakeLists.txt index aadddf332be7..46fffeede2fb 100644 --- a/subsys/net/lib/CMakeLists.txt +++ b/subsys/net/lib/CMakeLists.txt @@ -33,3 +33,4 @@ add_subdirectory_ifdef(CONFIG_WIFI_MGMT_EXT wifi_mgmt_ext) add_subdirectory_ifdef(CONFIG_MQTT_HELPER mqtt_helper) add_subdirectory_ifdef(CONFIG_NRF_PROVISIONING nrf_provisioning) add_subdirectory_ifdef(CONFIG_NRF_MCUMGR_SMP_CLIENT mcumgr_smp_client) +add_subdirectory_ifdef(CONFIG_WIFI_READY_LIB wifi_ready) diff --git a/subsys/net/lib/Kconfig b/subsys/net/lib/Kconfig index d73fae46c8ab..cd90f328ddad 100644 --- a/subsys/net/lib/Kconfig +++ b/subsys/net/lib/Kconfig @@ -45,5 +45,6 @@ rsource "wifi_mgmt_ext/Kconfig" rsource "mqtt_helper/Kconfig" rsource "nrf_provisioning/Kconfig" rsource "mcumgr_smp_client/Kconfig" +rsource "wifi_ready/Kconfig" endmenu diff --git a/subsys/net/lib/wifi_ready/CMakeLists.txt b/subsys/net/lib/wifi_ready/CMakeLists.txt new file mode 100644 index 000000000000..f757eb5ac460 --- /dev/null +++ b/subsys/net/lib/wifi_ready/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +zephyr_library_named(WIFI_READY_LIB) +zephyr_library_sources(wifi_ready.c) diff --git a/subsys/net/lib/wifi_ready/Kconfig b/subsys/net/lib/wifi_ready/Kconfig new file mode 100644 index 000000000000..9e90c442a158 --- /dev/null +++ b/subsys/net/lib/wifi_ready/Kconfig @@ -0,0 +1,35 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause +# + +menuconfig WIFI_READY_LIB + bool "Wi-Fi ready event handling library" + select EXPERIMENTAL + depends on WPA_SUPP + depends on NET_MGMT + help + Enable WiFi ready management subsystem that allows the application to + register callbacks that are called when the WiFi is ready to be used and + when the WiFi is not ready to be used. + +if WIFI_READY_LIB + +module = WIFI_READY_LIB +module-str = wifi_ready_lib +source "subsys/logging/Kconfig.template.log_config" + +config WIFI_READY_MAX_CALLBACKS + int "Maximum number of Wi-Fi ready callbacks" + default 2 + help + Set the maximum number of Wi-Fi ready callbacks that can be registered + by the application. + +config WIFI_READY_INIT_PRIORITY + int "Wi-Fi ready initialization priority" + default 90 + help + Set the initialization priority of the Wi-Fi ready subsystem. +endif diff --git a/subsys/net/lib/wifi_ready/wifi_ready.c b/subsys/net/lib/wifi_ready/wifi_ready.c new file mode 100644 index 000000000000..cbe21e6e5631 --- /dev/null +++ b/subsys/net/lib/wifi_ready/wifi_ready.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(wifi_ready, CONFIG_WIFI_READY_LIB_LOG_LEVEL); + +static wifi_ready_callback_t wifi_ready_callbacks[CONFIG_WIFI_READY_MAX_CALLBACKS]; +static unsigned char callback_count; +static K_MUTEX_DEFINE(wifi_ready_mutex); + +#define WPA_SUPP_EVENTS (NET_EVENT_WPA_SUPP_READY) | \ + (NET_EVENT_WPA_SUPP_NOT_READY) + +static struct net_mgmt_event_callback net_wpa_supp_cb; + +/* In case Wi-Fi is already ready, call the callbacks */ +static void wifi_ready_work_handler(struct k_work *item); + +static void call_wifi_ready_callbacks(bool ready, struct net_if *iface) +{ + int i; + + k_mutex_lock(&wifi_ready_mutex, K_FOREVER); + for (i = 0; i < ARRAY_SIZE(wifi_ready_callbacks); i++) { + if (wifi_ready_callbacks[i].wifi_ready_cb && + ((wifi_ready_callbacks[i].iface && + (wifi_ready_callbacks[i].iface == iface)) || + !wifi_ready_callbacks[i].iface)) { + wifi_ready_callbacks[i].wifi_ready_cb(ready); + } + } + k_mutex_unlock(&wifi_ready_mutex); +} + +static void wifi_ready_work_handler(struct k_work *item) +{ + wifi_ready_callback_t *cb = CONTAINER_OF(item, wifi_ready_callback_t, item); + + call_wifi_ready_callbacks(true, cb->iface); +} + +static void handle_wpa_supp_event(struct net_if *iface, bool ready) +{ + LOG_DBG("Supplicant event %s for iface %p", + ready ? "ready" : "not ready", iface); + + call_wifi_ready_callbacks(ready, iface); +} + +static void wpa_supp_event_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + ARG_UNUSED(cb); + + LOG_DBG("Event received: %d", mgmt_event); + switch (mgmt_event) { + case NET_EVENT_WPA_SUPP_READY: + handle_wpa_supp_event(iface, true); + break; + case NET_EVENT_WPA_SUPP_NOT_READY: + handle_wpa_supp_event(iface, false); + break; + default: + LOG_DBG("Unhandled event (%d)", mgmt_event); + break; + } +} + +int register_wifi_ready_callback(wifi_ready_callback_t cb, struct net_if *iface) +{ + int ret = 0, i; + unsigned int next_avail_idx = CONFIG_WIFI_READY_MAX_CALLBACKS; + struct net_if *wpas_iface = NULL; + + k_mutex_lock(&wifi_ready_mutex, K_FOREVER); + + if (!cb.wifi_ready_cb) { + LOG_ERR("Callback is NULL"); + ret = -EINVAL; + goto out; + } + + for (i = 0; i < ARRAY_SIZE(wifi_ready_callbacks); i++) { + if (wifi_ready_callbacks[i].wifi_ready_cb == NULL) { + next_avail_idx = i; + break; + } + } + + if (next_avail_idx == CONFIG_WIFI_READY_MAX_CALLBACKS) { + LOG_ERR("Reject callback registration, maximum count %d reached", + CONFIG_WIFI_READY_MAX_CALLBACKS); + ret = -ENOMEM; + goto out; + } + + /* Check if callback has already been registered for iface */ + for (i = 0; i < ARRAY_SIZE(wifi_ready_callbacks); i++) { + if (wifi_ready_callbacks[i].iface == iface && + wifi_ready_callbacks[i].wifi_ready_cb == cb.wifi_ready_cb) { + LOG_ERR("Callback has already registered for iface"); + ret = -EALREADY; + goto out; + } + } + + wifi_ready_callbacks[next_avail_idx].wifi_ready_cb = cb.wifi_ready_cb; + wifi_ready_callbacks[next_avail_idx].iface = iface; + + if (++callback_count == 1) { + net_mgmt_init_event_callback(&net_wpa_supp_cb, + wpa_supp_event_handler, WPA_SUPP_EVENTS); + net_mgmt_add_event_callback(&net_wpa_supp_cb); + } + + if (iface) { + wpas_iface = iface; + } else { + wpas_iface = net_if_get_first_wifi(); + if (!wpas_iface) { + LOG_ERR("Failed to get Wi-Fi interface"); + ret = -ENODEV; + goto out; + } + } + + /* In case Wi-Fi is already ready, call the callback */ + if (wifi_nm_get_instance_iface(wpas_iface)) { + k_work_submit(&wifi_ready_callbacks[next_avail_idx].item); + } + +out: + k_mutex_unlock(&wifi_ready_mutex); + return ret; + +} + + +int unregister_wifi_ready_callback(wifi_ready_callback_t cb, struct net_if *iface) +{ + int ret = 0, i; + bool found = false; + + k_mutex_lock(&wifi_ready_mutex, K_FOREVER); + + if (!cb.wifi_ready_cb) { + LOG_ERR("Callback is NULL"); + ret = -EINVAL; + goto out; + } + + for (i = 0; i < ARRAY_SIZE(wifi_ready_callbacks); i++) { + if (wifi_ready_callbacks[i].iface == iface && + wifi_ready_callbacks[i].wifi_ready_cb == cb.wifi_ready_cb) { + wifi_ready_callbacks[i].wifi_ready_cb = NULL; + wifi_ready_callbacks[i].iface = NULL; + found = true; + } + } + + if (!found) { + ret = -ENOENT; + goto out; + } + + if (--callback_count == 0) { + net_mgmt_del_event_callback(&net_wpa_supp_cb); + } + +out: + if (ret < 0) { + LOG_ERR("Failed to unregister callback: %d", ret); + } + k_mutex_unlock(&wifi_ready_mutex); + return ret; +} + +static int wifi_ready_init(void) +{ + /* Initialize the work items */ + for (int i = 0; i < ARRAY_SIZE(wifi_ready_callbacks); i++) { + k_work_init(&wifi_ready_callbacks[i].item, wifi_ready_work_handler); + } + + return 0; +} + +SYS_INIT(wifi_ready_init, APPLICATION, CONFIG_WIFI_READY_INIT_PRIORITY); From 6896ec408819d868c1a4e81f4898f0589e42f32b Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 11 Jul 2024 11:48:40 +0530 Subject: [PATCH 27/34] samples: wifi: sta: Use Wi-Fi ready lib Use Wi-Fi ready library to manage Wi-Fi. Signed-off-by: Chaitanya Tata --- samples/wifi/sta/Kconfig | 6 + samples/wifi/sta/README.rst | 61 ++++-- .../wifi/sta/boards/nrf52840dk_nrf52840.conf | 1 + samples/wifi/sta/prj.conf | 23 +-- samples/wifi/sta/sample.yaml | 14 +- samples/wifi/sta/src/main.c | 190 ++++++++++++------ 6 files changed, 200 insertions(+), 95 deletions(-) create mode 100644 samples/wifi/sta/boards/nrf52840dk_nrf52840.conf diff --git a/samples/wifi/sta/Kconfig b/samples/wifi/sta/Kconfig index 8b7c04bba40a..f66ca4d475d1 100644 --- a/samples/wifi/sta/Kconfig +++ b/samples/wifi/sta/Kconfig @@ -63,4 +63,10 @@ config STA_CONN_TIMEOUT_SEC Specify the connection timeout, in seconds. This is the overall timeout i.e., time to be waited for a station to connect and get an IP address. DHCP retries should be taken into account when setting this value. If the timeout is set to 0, the connection will not timeout. + +config STA_SAMPLE_START_WIFI_THREAD_STACK_SIZE + int "Stack size for Wi-Fi start thread" + default 4096 + help + Set the stack size for the Wi-Fi start thread. endmenu diff --git a/samples/wifi/sta/README.rst b/samples/wifi/sta/README.rst index e1d71304b95a..ac0c04f58209 100644 --- a/samples/wifi/sta/README.rst +++ b/samples/wifi/sta/README.rst @@ -23,6 +23,9 @@ The sample can perform Wi-Fi operations such as connect and disconnect in the 2. Using this sample, the development kit can connect to the specified access point in :abbr:`STA (Station)` mode. +The sample uses the :ref:`lib_wifi_ready` library to check Wi-Fi readiness. +To use the :ref:`lib_wifi_ready` library, enable the :kconfig:option:`CONFIG_WIFI_READY_LIB` Kconfig option. + User interface ************** @@ -38,32 +41,26 @@ Configuration |config| -You must configure the following Wi-Fi credentials in the :file:`prj.conf` file: - -* Network name (SSID) -* Key management -* Password - -.. note:: - You can also use ``menuconfig`` to enable ``Key management`` option. - -See :ref:`zephyr:menuconfig` in the Zephyr documentation for instructions on how to run ``menuconfig``. - Configuration options ===================== -The following sample-specific Kconfig option is used in this sample (located in :file:`samples/wifi/sta/Kconfig`): +The following sample-specific Kconfig options are used in this sample (located in :file:`samples/wifi/sta/Kconfig`): + +.. options-from-kconfig:: + :show-type: -.. _CONFIG_NRF700X_QSPI_ENCRYPTION_KEY: +You must configure the following Wi-Fi credentials in the :file:`prj.conf` file: -CONFIG_NRF700X_QSPI_ENCRYPTION_KEY - This option specifies the QSPI encryption key. +.. note:: + You can also use ``menuconfig`` to configure ``Wi-Fi credentials``. + +See :ref:`zephyr:menuconfig` in the Zephyr documentation for instructions on how to run ``menuconfig``. Quad Serial Peripheral Interface (QSPI) encryption ************************************************** This sample demonstrates QSPI encryption API usage. -You can set the key using the :ref:`CONFIG_NRF700X_QSPI_ENCRYPTION_KEY ` Kconfig option. +You can set the key using the :kconfig:option:`CONFIG_NRF700X_QSPI_ENCRYPTION_KEY` Kconfig option. If encryption of the QSPI traffic is required for the production devices, matching keys must be programmed in both the nRF7002 OTP and non-volatile storage associated with the host. The key from non-volatile storage must be set as the encryption key using the APIs. @@ -97,12 +94,12 @@ Building and running Currently, only the nRF7002 DK is supported. -To build for the nRF7002 DK, use the ``nrf7002dk_nrf5340_cpuapp`` build target. +To build for the nRF7002 DK, use the ``nrf7002dk/nrf5340/cpuapp`` board target. The following is an example of the CLI command: .. code-block:: console - west build -b nrf7002dk_nrf5340_cpuapp + west build -b nrf7002dk/nrf5340/cpuapp Testing ======= @@ -184,6 +181,30 @@ Testing [00:00:07.720,245] sta: RSSI: -57 [00:00:07.720,245] sta: Static IP address: +RPU recovery +************ + +The RPU recovery mechanism is used to recover from the RPU (nRF70) hang. +This feature performs an interface reset (down and up), which triggers a RPU cold boot. +Application's network connection will be lost during the recovery process, and it is application's responsibility to reestablish the network connection. + +Testing +======= + +To test RPU recovery, you must build the sample with :kconfig:option:`CONFIG_SHELL` and :kconfig:option:`CONFIG_NRF700X_UTIL` Kconfig options. + +#. Trigger RPU recovery using the following command: + + .. code-block:: console + + wifi_util rpu_recovery_test + + If RPU recovery is triggered, you should see an output similar to the following: + + .. code-block:: console + + RPU recovery triggered + Power management testing ************************ @@ -199,6 +220,8 @@ See :ref:`app_power_opt` for more information on power management testing and us Dependencies ************ -This sample uses the following library: +This sample uses the following |NCS| libraries: * :ref:`nrf_security` +* :ref:`lib_wifi_ready` +* :ref:`lib_wifi_credentials` diff --git a/samples/wifi/sta/boards/nrf52840dk_nrf52840.conf b/samples/wifi/sta/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 000000000000..2e3d175efa06 --- /dev/null +++ b/samples/wifi/sta/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1 @@ +CONFIG_WIFI_READY_LIB=n diff --git a/samples/wifi/sta/prj.conf b/samples/wifi/sta/prj.conf index 0c9f56023f92..f4d0cd845e57 100644 --- a/samples/wifi/sta/prj.conf +++ b/samples/wifi/sta/prj.conf @@ -8,18 +8,14 @@ CONFIG_WIFI_NRF700X=y # WPA supplicant CONFIG_WPA_SUPP=y +CONFIG_WIFI_READY_LIB=y +CONFIG_NRF_WIFI_RPU_RECOVERY=y -# Below configs need to be modified based on security -# CONFIG_STA_KEY_MGMT_NONE=y -# CONFIG_STA_KEY_MGMT_WPA2=y -# CONFIG_STA_KEY_MGMT_WPA2_256=y -# CONFIG_STA_KEY_MGMT_WPA3=y -CONFIG_STA_SAMPLE_SSID="Myssid" -CONFIG_STA_SAMPLE_PASSWORD="Mypassword" - -# System settings -CONFIG_NEWLIB_LIBC=y -CONFIG_NEWLIB_LIBC_NANO=n +CONFIG_WIFI_MGMT_EXT=y +CONFIG_WIFI_CREDENTIALS=y +CONFIG_WIFI_CREDENTIALS_STATIC=y +CONFIG_WIFI_CREDENTIALS_STATIC_SSID="Myssid" +CONFIG_WIFI_CREDENTIALS_STATIC_PASSWORD="Mypassword" # Networking CONFIG_NETWORKING=y @@ -35,10 +31,11 @@ CONFIG_NET_PKT_TX_COUNT=8 # Below section is the primary contributor to SRAM and is currently # tuned for performance, but this will be revisited in the future. -CONFIG_NET_BUF_RX_COUNT=16 +CONFIG_NET_BUF_RX_COUNT=8 CONFIG_NET_BUF_TX_COUNT=16 CONFIG_NET_BUF_DATA_SIZE=128 -CONFIG_HEAP_MEM_POOL_SIZE=153600 +CONFIG_NRF700X_RX_NUM_BUFS=16 +CONFIG_HEAP_MEM_POOL_SIZE=90000 CONFIG_NET_TC_TX_COUNT=1 CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1 diff --git a/samples/wifi/sta/sample.yaml b/samples/wifi/sta/sample.yaml index 2c927a8a471e..97e269b424da 100644 --- a/samples/wifi/sta/sample.yaml +++ b/samples/wifi/sta/sample.yaml @@ -9,6 +9,13 @@ tests: - nrf7002dk_nrf5340_cpuapp platform_allow: nrf7002dk_nrf5340_cpuapp tags: ci_build + sample.nrf7002.sta.no_wifi_ready: + build_only: true + extra_args: CONFIG_WIFI_READY_LIB=n + integration_platforms: + - nrf7002dk_nrf5340_cpuapp + platform_allow: nrf7002dk_nrf5340_cpuapp + tags: ci_build sample.nrf7001.sta: build_only: true integration_platforms: @@ -21,8 +28,10 @@ tests: extra_args: SHIELD=nrf7002ek integration_platforms: - nrf5340dk_nrf5340_cpuapp - - nrf52840dk_nrf52840 platform_allow: nrf5340dk_nrf5340_cpuapp nrf52840dk_nrf52840 + extra_configs: + - CONFIG_NET_TX_STACK_SIZE=3700 + - CONFIG_NET_RX_STACK_SIZE=3700 tags: ci_build sample.nrf7001_eks.sta: build_only: true @@ -31,6 +40,9 @@ tests: - nrf5340dk_nrf5340_cpuapp - nrf52840dk_nrf52840 platform_allow: nrf5340dk_nrf5340_cpuapp nrf52840dk_nrf52840 + extra_configs: + - CONFIG_NET_TX_STACK_SIZE=3700 + - CONFIG_NET_RX_STACK_SIZE=3700 tags: ci_build sample.nrf7002_eb.thingy53.sta: build_only: true diff --git a/samples/wifi/sta/src/main.c b/samples/wifi/sta/src/main.c index 83ccd49843fb..5e1cc71a9d75 100644 --- a/samples/wifi/sta/src/main.c +++ b/samples/wifi/sta/src/main.c @@ -24,6 +24,9 @@ LOG_MODULE_REGISTER(sta, CONFIG_LOG_DEFAULT_LEVEL); #include #include +#include +#include + #include #include "net_private.h" @@ -50,6 +53,11 @@ static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); static struct net_mgmt_event_callback wifi_shell_mgmt_cb; static struct net_mgmt_event_callback net_shell_mgmt_cb; +#ifdef CONFIG_WIFI_READY_LIB +static K_SEM_DEFINE(wifi_ready_state_changed_sem, 0, 1); +static bool wifi_ready_status; +#endif /* CONFIG_WIFI_READY_LIB */ + static struct { const struct shell *sh; union { @@ -207,54 +215,14 @@ static void net_mgmt_event_handler(struct net_mgmt_event_callback *cb, } } -static int __wifi_args_to_params(struct wifi_connect_req_params *params) -{ - - params->timeout = CONFIG_STA_CONN_TIMEOUT_SEC * MSEC_PER_SEC; - - if (params->timeout == 0) { - params->timeout = SYS_FOREVER_MS; - } - - /* Defaults */ - params->band = WIFI_FREQ_BAND_UNKNOWN; - params->channel = WIFI_CHANNEL_ANY; - params->security = WIFI_SECURITY_TYPE_NONE; - params->mfp = WIFI_MFP_OPTIONAL; - - /* SSID */ - params->ssid = CONFIG_STA_SAMPLE_SSID; - params->ssid_length = strlen(params->ssid); - -#if defined(CONFIG_STA_KEY_MGMT_WPA2) - params->security = 1; -#elif defined(CONFIG_STA_KEY_MGMT_WPA2_256) - params->security = 2; -#elif defined(CONFIG_STA_KEY_MGMT_WPA3) - params->security = 3; -#else - params->security = 0; -#endif - -#if !defined(CONFIG_STA_KEY_MGMT_NONE) - params->psk = CONFIG_STA_SAMPLE_PASSWORD; - params->psk_length = strlen(params->psk); -#endif - - return 0; -} - static int wifi_connect(void) { - struct net_if *iface = net_if_get_default(); - static struct wifi_connect_req_params cnx_params; + struct net_if *iface = net_if_get_first_wifi(); context.connected = false; context.connect_result = false; - __wifi_args_to_params(&cnx_params); - if (net_mgmt(NET_REQUEST_WIFI_CONNECT, iface, - &cnx_params, sizeof(struct wifi_connect_req_params))) { + if (net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, NULL, 0)) { LOG_ERR("Connection request failed"); return -ENOEXEC; @@ -285,31 +253,13 @@ int bytes_from_str(const char *str, uint8_t *bytes, size_t bytes_len) return 0; } -int main(void) +int start_app(void) { - memset(&context, 0, sizeof(context)); - - net_mgmt_init_event_callback(&wifi_shell_mgmt_cb, - wifi_mgmt_event_handler, - WIFI_SHELL_MGMT_EVENTS); - - net_mgmt_add_event_callback(&wifi_shell_mgmt_cb); - - - net_mgmt_init_event_callback(&net_shell_mgmt_cb, - net_mgmt_event_handler, - NET_EVENT_IPV4_DHCP_BOUND); - - net_mgmt_add_event_callback(&net_shell_mgmt_cb); - - LOG_INF("Starting %s with CPU frequency: %d MHz", CONFIG_BOARD, SystemCoreClock/MHZ(1)); - k_sleep(K_SECONDS(1)); - #if defined(CONFIG_BOARD_NRF7002DK_NRF7001_NRF5340_CPUAPP) || \ defined(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP) if (strlen(CONFIG_NRF700X_QSPI_ENCRYPTION_KEY)) { - char key[QSPI_KEY_LEN_BYTES]; int ret; + char key[QSPI_KEY_LEN_BYTES]; ret = bytes_from_str(CONFIG_NRF700X_QSPI_ENCRYPTION_KEY, key, sizeof(key)); if (ret) { @@ -340,18 +290,134 @@ int main(void) CONFIG_NET_CONFIG_MY_IPV4_GW); while (1) { +#ifdef CONFIG_WIFI_READY_LIB + int ret; + + LOG_INF("Waiting for Wi-Fi to be ready"); + ret = k_sem_take(&wifi_ready_state_changed_sem, K_FOREVER); + if (ret) { + LOG_ERR("Failed to take semaphore: %d", ret); + return ret; + } + +check_wifi_ready: + if (!wifi_ready_status) { + LOG_INF("Wi-Fi is not ready"); + /* Perform any cleanup and stop using Wi-Fi and wait for + * Wi-Fi to be ready + */ + continue; + } +#endif /* CONFIG_WIFI_READY_LIB */ wifi_connect(); while (!context.connect_result) { cmd_wifi_status(); +#ifdef CONFIG_WIFI_READY_LIB + if (!wifi_ready_status) { + goto check_wifi_ready; + } +#endif /* CONFIG_WIFI_READY_LIB */ k_sleep(K_MSEC(STATUS_POLLING_MS)); } if (context.connected) { cmd_wifi_status(); +#ifdef CONFIG_WIFI_READY_LIB + ret = k_sem_take(&wifi_ready_state_changed_sem, K_FOREVER); + if (ret) { + LOG_ERR("Failed to take semaphore: %d", ret); + return ret; + } + goto check_wifi_ready; +#else k_sleep(K_FOREVER); +#endif /* CONFIG_WIFI_READY_LIB */ } } return 0; } + +#ifdef CONFIG_WIFI_READY_LIB +void start_wifi_thread(void); +#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1) +K_THREAD_DEFINE(start_wifi_thread_id, CONFIG_STA_SAMPLE_START_WIFI_THREAD_STACK_SIZE, + start_wifi_thread, NULL, NULL, NULL, + THREAD_PRIORITY, 0, -1); + +void start_wifi_thread(void) +{ + start_app(); +} + +void wifi_ready_cb(bool wifi_ready) +{ + LOG_DBG("Is Wi-Fi ready?: %s", wifi_ready ? "yes" : "no"); + wifi_ready_status = wifi_ready; + k_sem_give(&wifi_ready_state_changed_sem); +} +#endif /* CONFIG_WIFI_READY_LIB */ + +void net_mgmt_callback_init(void) +{ + memset(&context, 0, sizeof(context)); + + net_mgmt_init_event_callback(&wifi_shell_mgmt_cb, + wifi_mgmt_event_handler, + WIFI_SHELL_MGMT_EVENTS); + + net_mgmt_add_event_callback(&wifi_shell_mgmt_cb); + + net_mgmt_init_event_callback(&net_shell_mgmt_cb, + net_mgmt_event_handler, + NET_EVENT_IPV4_DHCP_BOUND); + + net_mgmt_add_event_callback(&net_shell_mgmt_cb); + + LOG_INF("Starting %s with CPU frequency: %d MHz", CONFIG_BOARD, SystemCoreClock/MHZ(1)); + k_sleep(K_SECONDS(1)); +} + +#ifdef CONFIG_WIFI_READY_LIB +static int register_wifi_ready(void) +{ + int ret = 0; + wifi_ready_callback_t cb; + struct net_if *iface = net_if_get_first_wifi(); + + if (!iface) { + LOG_ERR("Failed to get Wi-Fi interface"); + return -1; + } + + cb.wifi_ready_cb = wifi_ready_cb; + + LOG_DBG("Registering Wi-Fi ready callbacks"); + ret = register_wifi_ready_callback(cb, iface); + if (ret) { + LOG_ERR("Failed to register Wi-Fi ready callbacks %s", strerror(ret)); + return ret; + } + + return ret; +} +#endif /* CONFIG_WIFI_READY_LIB */ + +int main(void) +{ + int ret = 0; + + net_mgmt_callback_init(); + +#ifdef CONFIG_WIFI_READY_LIB + ret = register_wifi_ready(); + if (ret) { + return ret; + } + k_thread_start(start_wifi_thread_id); +#else + start_app(); +#endif /* CONFIG_WIFI_READY_LIB */ + return ret; +} From f993249b28358057dbe0dbb348d81c50256e40ad Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 18 Jul 2024 20:52:19 +0530 Subject: [PATCH 28/34] drivers: wifi: Add PS state debugs These are very frequent, so, a separate debug is added for debugging host RPU recovery logic. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 73b1cb357189..bc7f2f2fa404 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -711,6 +711,12 @@ config NRF_WIFI_RPU_RECOVERY_RETRY_WINDOW_S exceeds NRF_WIFI_RPU_RECOVERY_MAX_RETRIES within this window, the system will be reset. +config NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG + bool "Enable RPU recovery power save state debug logs" + help + Enable RPU recovery power save state debug logs to help debug RPU recovery mechanism. + + config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 From 66be9cfe63d80692f3b54dfccd4485cf4575647b Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 18 Jul 2024 21:24:53 +0530 Subject: [PATCH 29/34] drivers: wifi: Add command and event logging This is useful to understand the reason for comms trigger b/w host and RPU. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index bc7f2f2fa404..bb5b4e84f8f8 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -656,6 +656,10 @@ config NRF_WIFI_RPU_RECOVERY the recovery process and it is application's responsibility to re-establish the network connection. +config NRF_WIFI_CMD_EVENT_LOG + bool "Enable command event logging" + help + Enable command event logging to help debug Wi-Fi command events. if NRF_WIFI_RPU_RECOVERY config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS From d77bb2820efeeca53c30a6e0e94ebdbb9cb1e450 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Fri, 19 Jul 2024 00:55:35 +0530 Subject: [PATCH 30/34] doc: changelog: Add an entry for RPU recovery Mention RPU recovery feature, there are no docs yet, so, no links. Signed-off-by: Chaitanya Tata --- .../releases_and_maturity/releases/release-notes-changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst index 76fe2b576ba3..2be4b67b22b6 100644 --- a/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst +++ b/doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst @@ -295,7 +295,7 @@ This section provides detailed lists of changes by :ref:`driver `. Wi-Fi drivers ------------- -|no_changes_yet_note| +* Added a new feature to recover nRF70 chip. Libraries ========= From c1eda2724097053c4467219e801881ef0e6cd51f Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Thu, 18 Jul 2024 17:40:46 +0530 Subject: [PATCH 31/34] drivers: wifi: Enable management buffers offload With this offload, host doesn't need to manage RX buffers for management frames, and this saves Host-RPU comms and thus giving RPU to sleep more often and is essential to test RPU recovery. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index bb5b4e84f8f8..186b64d62238 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -644,6 +644,10 @@ config NRF_WIFI_QOS_NULL_BASED_RETRIEVAL endchoice +config NRF_WIFI_MGMT_BUFF_OFFLOAD + bool "Enable management buffer offload" + default y + config NRF_WIFI_RPU_RECOVERY bool "Enable RPU recovery mechanism" depends on NRF_WIFI_LOW_POWER From c209f78c98c66f0c4b10b5fbc9263af82ede6820 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 6 Aug 2024 20:30:58 +0530 Subject: [PATCH 32/34] drivers: wifi: Increase default PS active timeout interval In crowded environments RPU is active for more than 10s due to too many retries and this triggers a false RPU recovery. To avoid this, increase the default to 50s to handle corner cases, as this will only impact the recovery triggered case, higher timeout doesn't have any impact in normal cases. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 186b64d62238..97bc297148e6 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -677,7 +677,7 @@ config NRF_WIFI_RPU_RECOVERY_PROPAGATION_DELAY_MS config NRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS int "RPU recovery power save active timeout in milliseconds" - default 10000 + default 50000 help Power save active timeout in milliseconds after which RPU recovery mechanism will be triggered. This timeout is used to ensure that the From 45b74a3529139ed6025782232f74f82712b955b1 Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 6 Aug 2024 21:10:39 +0530 Subject: [PATCH 33/34] drivers: wifi: Add support for keepalive To handle interoperability issue with few APs, add a feature to keep sending keepalive frames periodically to avoid AP disconnecting the STA. This is disabled by default to avoid unnecessary power consumption as it's only seen with few old APs. Signed-off-by: Chaitanya Tata --- drivers/wifi/nrf700x/Kconfig | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 97bc297148e6..87822b5abd7c 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -729,3 +729,21 @@ config NET_MGMT_EVENT_QUEUE_SIZE # Doing interface down and up even with delay puts a lot of events in the queue default 16 endif + +config NRF_WIFI_FEAT_KEEPALIVE + bool "Enable Wi-Fi keepalive feature" + depends on NRF700X_STA_MODE + help + Enable Wi-Fi keepalive feature to keep the connection alive by sending + keepalive packets to the AP. Primarily intended to interoperate with APs + that disconnect idle clients without any explicit checks. Slightly increases + power consumption. + +if NRF_WIFI_FEAT_KEEPALIVE +config NRF_WIFI_KEEPALIVE_PERIOD_S + int "Keepalive period in seconds" + range 30 3600 + default 60 + help + Keepalive period in seconds to send keepalive packets to the AP. +endif From 6e8d78881b2e08974954d2fd9af51df76fddd6eb Mon Sep 17 00:00:00 2001 From: Chaitanya Tata Date: Tue, 20 Aug 2024 20:30:28 +0530 Subject: [PATCH 34/34] manifest: nrfxlib: Pull latest fixes Pull latest fixes backported to 2.6 branch. Signed-off-by: Chaitanya Tata --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 984f5f551a1d..f95a26df8f66 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: - name: nrfxlib repo-path: sdk-nrfxlib path: nrfxlib - revision: 4bd894ac9a9fd32d1bcdddbded6be12f068013b6 + revision: 3cb1a198735889c7d01ece0aa295bc316b4840f8 - name: trusted-firmware-m repo-path: sdk-trusted-firmware-m path: modules/tee/tf-m/trusted-firmware-m