diff --git a/nrf_wifi/fw_bins/default/nrf70.bin b/nrf_wifi/fw_bins/default/nrf70.bin index 901da75b52..7cb49d0ab5 100644 Binary files a/nrf_wifi/fw_bins/default/nrf70.bin and b/nrf_wifi/fw_bins/default/nrf70.bin differ diff --git a/nrf_wifi/fw_bins/radio_test/nrf70.bin b/nrf_wifi/fw_bins/radio_test/nrf70.bin index 100c6d65c6..6feac77e6e 100644 Binary files a/nrf_wifi/fw_bins/radio_test/nrf70.bin and b/nrf_wifi/fw_bins/radio_test/nrf70.bin differ diff --git a/nrf_wifi/fw_bins/scan_only/nrf70.bin b/nrf_wifi/fw_bins/scan_only/nrf70.bin index 909aaf50f8..c061d331f3 100644 Binary files a/nrf_wifi/fw_bins/scan_only/nrf70.bin and b/nrf_wifi/fw_bins/scan_only/nrf70.bin differ diff --git a/nrf_wifi/fw_if/umac_if/inc/default/fmac_api.h b/nrf_wifi/fw_if/umac_if/inc/default/fmac_api.h index 34eb6a4f37..aeb0a906d9 100644 --- a/nrf_wifi/fw_if/umac_if/inc/default/fmac_api.h +++ b/nrf_wifi/fw_if/umac_if/inc/default/fmac_api.h @@ -983,6 +983,22 @@ enum nrf_wifi_status nrf_wifi_fmac_set_ps_wakeup_mode(void *fmac_dev_ctx, unsigned char if_idx, bool ps_wakeup_mode); +/** + * @brief Configure power save exit strategy. + * @param fmac_dev_ctx Pointer to the UMAC IF context for a RPU WLAN device. + * @param if_idx Index of the interface on which power management is to be set. + * @param ps_exit_strategy PS exit strategy to be configured in RPU. + * + * This function is used to send a command to RPU + * to configure PS exit strategy in RPU. + * + * @return Command execution status + */ +enum nrf_wifi_status nrf_wifi_fmac_set_ps_exit_strategy( + void *fmac_dev_ctx, + unsigned char if_idx, + unsigned int ps_exit_strategy); + #ifdef CONFIG_NRF700X_RAW_DATA_TX /** * @brief Transmit a raw unaltered frame to the RPU. diff --git a/nrf_wifi/fw_if/umac_if/inc/fmac_cmd.h b/nrf_wifi/fw_if/umac_if/inc/fmac_cmd.h index 1632b6cc6a..075b57e004 100644 --- a/nrf_wifi/fw_if/umac_if/inc/fmac_cmd.h +++ b/nrf_wifi/fw_if/umac_if/inc/fmac_cmd.h @@ -72,4 +72,6 @@ enum nrf_wifi_status umac_cmd_prog_stats_get(struct nrf_wifi_fmac_dev_ctx *fmac_ #endif /* CONFIG_NRF700X_RADIO_TEST */ int stat_type); +enum nrf_wifi_status umac_cmd_set_ps_exit_strategy(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + enum ps_exit_strategy ps_exit_strategy); #endif /* __FMAC_CMD_H__ */ diff --git a/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_sys_if.h b/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_sys_if.h index f20ab5c289..069f9989e3 100644 --- a/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_sys_if.h +++ b/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_sys_if.h @@ -832,7 +832,7 @@ enum op_band { * @brief This enum defines keep alive state * */ -enum keep_alive_status { +enum nrf_wifi_keep_alive_status { /** Keep alive feature disabled */ KEEP_ALIVE_DISABLED = 0, /** Keep alive feature enabled */ @@ -843,13 +843,13 @@ enum keep_alive_status { * @brief This enum specifies the type of frames used to retrieve buffered data * from the AP in power save mode. */ -enum data_retrieve_mechanism { - /** Retrieves data from the AP using a PS-Poll frame */ - PS_POLL_FRAME, - /** Retrieves data from the AP using a QoS Null frame */ - QOS_NULL_FRAME, - /** For future implementation. The RPU will decide which frame to use */ - AUTOMATIC +enum ps_exit_strategy { + /** Uses an intelligent algo and decide whether to + * stay or exit power save mode to receive buffered frames. + */ + INT_PS = 0, + /** Exits power save mode for every TIM */ + EVERY_TIM }; #define TWT_EXTEND_SP_EDCA 0x1 @@ -897,9 +897,9 @@ struct nrf_wifi_cmd_sys_init { */ unsigned int discon_timeout; /** RPU uses QoS null frame or PS-Poll frame to retrieve buffered frames - * from the AP in power save @ref data_retrieve_mechanism. + * from the AP in power save @ref ps_exit_strategy. */ - unsigned char ps_data_retrieval_mech; + unsigned char ps_exit_strategy; /** The RPU uses this value to configure watchdog timer */ unsigned int watchdog_timer_val; /** The RPU uses this value to decide whether keep alive diff --git a/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_umac_if.h b/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_umac_if.h index 0fa6ed52e2..180bea0916 100644 --- a/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_umac_if.h +++ b/nrf_wifi/fw_if/umac_if/inc/fw/host_rpu_umac_if.h @@ -143,7 +143,9 @@ enum nrf_wifi_umac_commands { /** Set listen interval @ref nrf_wifi_umac_cmd_set_listen_interval */ NRF_WIFI_UMAC_CMD_SET_LISTEN_INTERVAL, /** Configure extended power save @ref nrf_wifi_umac_cmd_config_extended_ps */ - NRF_WIFI_UMAC_CMD_CONFIG_EXTENDED_PS + NRF_WIFI_UMAC_CMD_CONFIG_EXTENDED_PS, + /** Command to specify power save exit strategy */ + NRF_WIFI_UMAC_CMD_PS_EXIT_STRATEGY, }; /** @@ -2924,6 +2926,8 @@ struct nrf_wifi_umac_event_power_save_info { unsigned int ps_timeout; /** Listen interval value */ unsigned short listen_interval; + /** Power save exit strategy */ + unsigned char ps_exit_strategy; /** Number TWT flows */ unsigned char num_twt_flows; /** TWT info of each flow @ref nrf_wifi_umac_config_twt_info */ @@ -3499,4 +3503,16 @@ struct nrf_wifi_umac_event_cmd_status { unsigned int cmd_status; } __NRF_WIFI_PKD; +/** + * @brief This structure defines the command used to configure the power save exit + * strategy for retrieving buffered data from the AP in power save mode. + * + */ +struct nrf_wifi_cmd_ps_exit_strategy { + /** Header @ref nrf_wifi_umac_hdr */ + struct nrf_wifi_umac_hdr umac_hdr; + /** Power save exit strategy */ + unsigned char ps_exit_strategy; +} __NRF_WIFI_PKD; + #endif /* __HOST_RPU_UMAC_IF_H */ diff --git a/nrf_wifi/fw_if/umac_if/src/cmd.c b/nrf_wifi/fw_if/umac_if/src/cmd.c index 063c520599..91a5ea70f2 100644 --- a/nrf_wifi/fw_if/umac_if/src/cmd.c +++ b/nrf_wifi/fw_if/umac_if/src/cmd.c @@ -222,11 +222,11 @@ enum nrf_wifi_status umac_cmd_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, umac_cmd_data->disable_beamforming = 1; } -#if defined(CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL) - umac_cmd_data->ps_data_retrieval_mech = QOS_NULL_FRAME; +#if defined(CONFIG_NRF_WIFI_PS_INT_PS) + umac_cmd_data->ps_exit_strategy = INT_PS; #else - umac_cmd_data->ps_data_retrieval_mech = PS_POLL_FRAME; -#endif /* CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL */ + umac_cmd_data->ps_exit_strategy = EVERY_TIM; +#endif /* CONFIG_NRF_WIFI_PS_INT_PS */ status = nrf_wifi_hal_ctrl_cmd_send(fmac_dev_ctx->hal_dev_ctx, umac_cmd, diff --git a/nrf_wifi/fw_if/umac_if/src/default/fmac_api.c b/nrf_wifi/fw_if/umac_if/src/default/fmac_api.c index dc9ee7b8c0..cf9ba2b427 100644 --- a/nrf_wifi/fw_if/umac_if/src/default/fmac_api.c +++ b/nrf_wifi/fw_if/umac_if/src/default/fmac_api.c @@ -3160,4 +3160,44 @@ enum nrf_wifi_status nrf_wifi_fmac_set_ps_wakeup_mode(void *dev_ctx, return status; } + + +enum nrf_wifi_status nrf_wifi_fmac_set_ps_exit_strategy(void *dev_ctx, + unsigned char if_idx, + unsigned int ps_exit_strategy) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + struct nrf_wifi_cmd_ps_exit_strategy *set_ps_exit_strategy_cmd = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + + (void)if_idx; + + fmac_dev_ctx = dev_ctx; + + set_ps_exit_strategy_cmd = nrf_wifi_osal_mem_zalloc(fmac_dev_ctx->fpriv->opriv, + sizeof(*set_ps_exit_strategy_cmd)); + + if (!set_ps_exit_strategy_cmd) { + nrf_wifi_osal_log_err(fmac_dev_ctx->fpriv->opriv, + "%s: Unable to allocate memory\n", __func__); + goto out; + } + + set_ps_exit_strategy_cmd->umac_hdr.cmd_evnt = NRF_WIFI_UMAC_CMD_PS_EXIT_STRATEGY; + set_ps_exit_strategy_cmd->umac_hdr.ids.wdev_id = if_idx; + set_ps_exit_strategy_cmd->umac_hdr.ids.valid_fields |= + NRF_WIFI_INDEX_IDS_WDEV_ID_VALID; + set_ps_exit_strategy_cmd->ps_exit_strategy = ps_exit_strategy; + + status = umac_cmd_cfg(fmac_dev_ctx, + set_ps_exit_strategy_cmd, + sizeof(*set_ps_exit_strategy_cmd)); +out: + if (set_ps_exit_strategy_cmd) { + nrf_wifi_osal_mem_free(fmac_dev_ctx->fpriv->opriv, + set_ps_exit_strategy_cmd); + } + + return status; +} #endif /* CONFIG_NRF700X_STA_MODE */ diff --git a/nrf_wifi/hw_if/hal/inc/hal_structs.h b/nrf_wifi/hw_if/hal/inc/hal_structs.h index ba81691d8c..e03f3ce6f5 100644 --- a/nrf_wifi/hw_if/hal/inc/hal_structs.h +++ b/nrf_wifi/hw_if/hal/inc/hal_structs.h @@ -237,7 +237,6 @@ struct nrf_wifi_hal_dev_ctx { void *rpu_ps_timer; void *rpu_ps_lock; bool dbg_enable; - bool irq_ctx; bool rpu_fw_booted; #endif /* CONFIG_NRF_WIFI_LOW_POWER */ char *event_data; diff --git a/nrf_wifi/hw_if/hal/src/hal_api.c b/nrf_wifi/hw_if/hal/src/hal_api.c index c886dc248a..c16b691e4b 100644 --- a/nrf_wifi/hw_if/hal/src/hal_api.c +++ b/nrf_wifi/hw_if/hal/src/hal_api.c @@ -414,11 +414,9 @@ enum nrf_wifi_status hal_rpu_ps_wake(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx) #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY_PS_STATE_DEBUG */ out: - if (!hal_dev_ctx->irq_ctx) { - nrf_wifi_osal_timer_schedule(hal_dev_ctx->hpriv->opriv, - hal_dev_ctx->rpu_ps_timer, - CONFIG_NRF700X_RPU_PS_IDLE_TIMEOUT_MS); - } + nrf_wifi_osal_timer_schedule(hal_dev_ctx->hpriv->opriv, + hal_dev_ctx->rpu_ps_timer, + CONFIG_NRF700X_RPU_PS_IDLE_TIMEOUT_MS); return status; } @@ -506,13 +504,6 @@ static void hal_rpu_ps_deinit(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx) hal_dev_ctx->rpu_ps_lock); } - -static void hal_rpu_ps_set_state(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, - enum RPU_PS_STATE ps_state) -{ - hal_dev_ctx->rpu_ps_state = ps_state; -} - enum nrf_wifi_status nrf_wifi_hal_get_rpu_ps_state( struct nrf_wifi_hal_dev_ctx *hal_dev_ctx, int *rpu_ps_ctrl_state) @@ -1566,9 +1557,6 @@ enum nrf_wifi_status nrf_wifi_hal_irq_handler(void *data) struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL; enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; unsigned long flags = 0; -#ifdef CONFIG_NRF_WIFI_LOW_POWER - enum RPU_PS_STATE ps_state = RPU_PS_STATE_ASLEEP; -#endif /* CONFIG_NRF_WIFI_LOW_POWER */ bool do_rpu_recovery = false; hal_dev_ctx = (struct nrf_wifi_hal_dev_ctx *)data; @@ -1588,25 +1576,8 @@ enum nrf_wifi_status nrf_wifi_hal_irq_handler(void *data) goto unlock; } -#ifdef CONFIG_NRF_WIFI_LOW_POWER - ps_state = hal_dev_ctx->rpu_ps_state; - hal_rpu_ps_set_state(hal_dev_ctx, - RPU_PS_STATE_AWAKE); -#ifdef CONFIG_NRF_WIFI_LOW_POWER_DBG - hal_dev_ctx->irq_ctx = true; -#endif /* CONFIG_NRF_WIFI_LOW_POWER_DBG */ -#endif /* CONFIG_NRF_WIFI_LOW_POWER */ - status = hal_rpu_irq_process(hal_dev_ctx, &do_rpu_recovery); -#ifdef CONFIG_NRF_WIFI_LOW_POWER - hal_rpu_ps_set_state(hal_dev_ctx, - ps_state); -#ifdef CONFIG_NRF_WIFI_LOW_POWER_DBG - hal_dev_ctx->irq_ctx = false; -#endif /* CONFIG_NRF_WIFI_LOW_POWER_DBG */ -#endif /* CONFIG_NRF_WIFI_LOW_POWER */ - if (status != NRF_WIFI_STATUS_SUCCESS) { goto unlock; } diff --git a/nrf_wifi/hw_if/hal/src/hal_interrupt.c b/nrf_wifi/hw_if/hal/src/hal_interrupt.c index 22419b7cd9..227f84612e 100644 --- a/nrf_wifi/hw_if/hal/src/hal_interrupt.c +++ b/nrf_wifi/hw_if/hal/src/hal_interrupt.c @@ -134,15 +134,35 @@ static bool hal_rpu_irq_wdog_chk(struct nrf_wifi_hal_dev_ctx *hal_dev_ctx) enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; unsigned int val = 0; bool ret = false; + unsigned int i, max_read_retries = 10; - status = hal_rpu_reg_read(hal_dev_ctx, - &val, - RPU_REG_MIPS_MCU_UCCP_INT_STATUS); + for (i = 0; i < max_read_retries; i++) { + status = hal_rpu_reg_read(hal_dev_ctx, + &val, + RPU_REG_MIPS_MCU_UCCP_INT_STATUS); + + if (status != NRF_WIFI_STATUS_SUCCESS) { + nrf_wifi_osal_log_err(hal_dev_ctx->hpriv->opriv, + "%s: Reading from interrupt status register failed\n", + __func__); + goto out; + } + + if (val != 0xAAAAAAAA) { + break; + } - if (status != NRF_WIFI_STATUS_SUCCESS) { nrf_wifi_osal_log_err(hal_dev_ctx->hpriv->opriv, - "%s: Reading from interrupt status register failed", - __func__); + "%s: Reading from interrupt status register failed 0x%x\n", + __func__, + val); + } + + if (i == max_read_retries) { + nrf_wifi_osal_log_err(hal_dev_ctx->hpriv->opriv, + "%s: Reading from interrupt status register failed 0x%x\n", + __func__, + val); goto out; }