diff --git a/drivers/wifi/nrf700x/Kconfig b/drivers/wifi/nrf700x/Kconfig index 84a337bec246..bbf1dd6d79df 100644 --- a/drivers/wifi/nrf700x/Kconfig +++ b/drivers/wifi/nrf700x/Kconfig @@ -418,7 +418,7 @@ config NRF_WIFI_PS_POLL_BASED_RETRIEVAL 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" + 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 @@ -427,6 +427,15 @@ config NRF_WIFI_QOS_NULL_BASED_RETRIEVAL endchoice +if NRF_WIFI_QOS_NULL_BASED_RETRIEVAL +config NRF_WIFI_QOS_NULL_FRAME_INTERVAL_MS + int "QoS NULL frame interval in milli-seconds" + range 1 100 + default 10 + help + QoS NULL frame interval in milli-seconds. +endif + config NRF_WIFI_MGMT_BUFF_OFFLOAD bool "Enable management buffer offload" diff --git a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_api_common.h b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_api_common.h index a53ba3fc85c3..e9fed796d29f 100644 --- a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_api_common.h +++ b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_api_common.h @@ -226,6 +226,21 @@ enum nrf_wifi_status nrf_wifi_fmac_get_reg(struct nrf_wifi_fmac_dev_ctx *fmac_de enum nrf_wifi_status nrf_wifi_fmac_get_power_save_info(void *fmac_dev_ctx, unsigned char if_idx); +/** + * @brief Configure power save data retrieval info. + * @param fmac_dev_ctx Pointer to the UMAC IF context for a RPU WLAN device. + * @param ps_data_retrieval_mech PS data retrieval mechanism. + * @param ps_data_retrieval_frame_interval_ms PS data retrieval frame interval in ms. + * + * This function is used to send a command to RPU + * to configure PS data retrieval mechanism and frame interval. + * + * @return Command execution status + */ +enum nrf_wifi_status nrf_wifi_fmac_set_ps_data_retrieval_info( + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + unsigned int ps_data_retrieval_mech, + unsigned int ps_data_retrieval_frame_interval_ms); /** * @} */ diff --git a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_cmd.h b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_cmd.h index 90519cc3d55f..fccd4f41535f 100644 --- a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_cmd.h +++ b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fmac_cmd.h @@ -71,4 +71,8 @@ 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_data_retrieval_info(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + enum data_retrieve_mechanism ps_data_retrieval_mech, + unsigned int ps_data_retrieval_frame_interval_ms); + #endif /* __FMAC_CMD_H__ */ diff --git a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fw/host_rpu_sys_if.h b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fw/host_rpu_sys_if.h index b0ff524c3524..71e3df3099ed 100644 --- a/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fw/host_rpu_sys_if.h +++ b/drivers/wifi/nrf700x/osal/fw_if/umac_if/inc/fw/host_rpu_sys_if.h @@ -153,6 +153,8 @@ enum nrf_wifi_sys_commands { NRF_WIFI_CMD_RT_REQ_SET_REG, /** Command to enable/disable fixed data rate in regular mode */ NRF_WIFI_CMD_TX_FIX_DATA_RATE, + /** Command to specify ps data retrieval mechanism */ + NRF_WIFI_CMD_PS_DATA_RETRIEVAL_INFO, }; /** @@ -862,6 +864,11 @@ struct nrf_wifi_cmd_sys_init { * alive frame. */ unsigned int keep_alive_period; + /** The RPU uses this value (in seconds) to determine the time interval between + * a null frame sent after a TIM indication beacon with the PWR MGT flag set to + * 0 and a null frame with the PWR MGT flag set to 1. + */ + unsigned int qos_null_frame_interval; } __NRF_WIFI_PKD; /** @@ -1018,6 +1025,10 @@ struct rpu_conf_params { unsigned char country_code[NRF_WIFI_COUNTRY_CODE_LEN]; /** Contention window value to be configured */ unsigned int tx_pkt_cw; + /** Power save data mechanism */ + unsigned char ps_data_retrieval_mech; + /** Power save data retrieval frame interval */ + unsigned int ps_data_retrieval_frame_interval; } __NRF_WIFI_PKD; /** @@ -1378,4 +1389,13 @@ struct nrf_wifi_event_deinit_done { struct nrf_wifi_sys_head sys_head; } __NRF_WIFI_PKD; +struct nrf_wifi_cmd_ps_data_retrieval_info { + /** UMAC header, see &nrf_wifi_sys_head */ + struct nrf_wifi_sys_head sys_head; + /** Power save data retrieval mechanism */ + unsigned char ps_data_retrieval_mech; + /** Power save data retrieval duration */ + unsigned int qos_null_frame_interval; +} __NRF_WIFI_PKD; + #endif /* __HOST_RPU_SYS_IF_H__ */ diff --git a/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/cmd.c b/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/cmd.c index c269b706e9a7..c20311edb199 100644 --- a/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/cmd.c +++ b/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/cmd.c @@ -215,6 +215,7 @@ enum nrf_wifi_status umac_cmd_init(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, #if defined(CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL) umac_cmd_data->ps_data_retrieval_mech = QOS_NULL_FRAME; + umac_cmd_data->qos_null_frame_interval = CONFIG_NRF_WIFI_QOS_NULL_FRAME_INTERVAL_MS; #else umac_cmd_data->ps_data_retrieval_mech = PS_POLL_FRAME; #endif /* CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL */ @@ -552,3 +553,39 @@ enum nrf_wifi_status umac_cmd_prog_stats_get(struct nrf_wifi_fmac_dev_ctx *fmac_ out: return status; } + +enum nrf_wifi_status umac_cmd_set_ps_data_retrieval_info(struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + enum data_retrieve_mechanism ps_data_retrieval_mech, + unsigned int ps_data_retrieval_frame_interval) +{ + struct host_rpu_msg *umac_cmd = NULL; + struct nrf_wifi_cmd_ps_data_retrieval_info *umac_cmd_data = NULL; + int len = 0; + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + + len = sizeof(*umac_cmd_data); + + umac_cmd = umac_cmd_alloc(fmac_dev_ctx, NRF_WIFI_HOST_RPU_MSG_TYPE_SYSTEM, len); + + if (!umac_cmd) { + nrf_wifi_osal_log_err(fmac_dev_ctx->fpriv->opriv, + "%s: umac_cmd_alloc failed", + __func__); + goto out; + } + + umac_cmd_data = (struct nrf_wifi_cmd_ps_data_retrieval_info *)(umac_cmd->msg); + + umac_cmd_data->sys_head.cmd_event = NRF_WIFI_CMD_PS_DATA_RETRIEVAL_INFO; + umac_cmd_data->sys_head.len = len; + + umac_cmd_data->ps_data_retrieval_mech = ps_data_retrieval_mech; +#if defined(CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL) + umac_cmd_data->qos_null_frame_interval = ps_data_retrieval_frame_interval; +#endif + + status = nrf_wifi_hal_ctrl_cmd_send(fmac_dev_ctx->hal_dev_ctx, umac_cmd, + (sizeof(*umac_cmd) + len)); +out: + return status; +} diff --git a/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/fmac_api_common.c b/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/fmac_api_common.c index a1d4af84c43f..cb72dd3eda1b 100644 --- a/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/fmac_api_common.c +++ b/drivers/wifi/nrf700x/osal/fw_if/umac_if/src/fmac_api_common.c @@ -751,4 +751,18 @@ enum nrf_wifi_status nrf_wifi_fmac_get_host_rpu_ps_ctrl_state(void *dev_ctx, return status; } #endif /* CONFIG_NRF_WIFI_LOW_POWER */ + +enum nrf_wifi_status nrf_wifi_fmac_set_ps_data_retrieval_info( + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx, + unsigned int ps_data_retrieval_mech, + unsigned int ps_data_retrieval_frame_interval) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + + status = umac_cmd_set_ps_data_retrieval_info(fmac_dev_ctx, + ps_data_retrieval_mech, + ps_data_retrieval_frame_interval); + return status; +} + #endif /* CONFIG_NRF700X_UTIL */ diff --git a/drivers/wifi/nrf700x/zephyr/src/zephyr_wifi_util.c b/drivers/wifi/nrf700x/zephyr/src/zephyr_wifi_util.c index 4df90ac6546e..b43d45a68299 100644 --- a/drivers/wifi/nrf700x/zephyr/src/zephyr_wifi_util.c +++ b/drivers/wifi/nrf700x/zephyr/src/zephyr_wifi_util.c @@ -76,6 +76,13 @@ int nrf_wifi_util_conf_init(struct rpu_conf_params *conf_params) /* Initialize values which are other than 0 */ conf_params->he_ltf = -1; conf_params->he_gi = -1; +#if defined(CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL) + conf_params->ps_data_retrieval_mech = QOS_NULL_FRAME; + conf_params->ps_data_retrieval_frame_interval = + CONFIG_NRF_WIFI_QOS_NULL_FRAME_INTERVAL_MS; +#else + conf_params->ps_data_retrieval_mech = PS_POLL_FRAME; +#endif /* CONFIG_NRF_WIFI_QOS_NULL_BASED_RETRIEVAL */ return 0; } @@ -298,6 +305,19 @@ static int nrf_wifi_util_show_cfg(const struct shell *shell, "rate_flag = %d, rate_val = %d\n", ctx->conf_params.tx_pkt_tput_mode, ctx->conf_params.tx_pkt_rate); + shell_fprintf(shell, + SHELL_INFO, + "ps_data_retrieval_mech = %s\n", + ctx->conf_params.ps_data_retrieval_mech ? + "QOS_NULL_FRAME" : "PS_POLL_FRAME"); + + if (ctx->conf_params.ps_data_retrieval_mech == 1) { + shell_fprintf(shell, + SHELL_INFO, + "ps_data_retrieval_frame_interval = %d\n", + ctx->conf_params.ps_data_retrieval_frame_interval); + } + return 0; } @@ -919,6 +939,53 @@ static int nrf_wifi_util_trigger_rpu_recovery(const struct shell *shell, } #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ +static int nrf_wifi_util_set_ps_data_retrival_info(const struct shell *shell, size_t argc, + const char *argv[]) +{ + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + char *ptr = NULL; + unsigned long ps_data_retrieval_mech = 0; + unsigned long ps_data_retrieval_frame_interval_ms = 0; + + ps_data_retrieval_mech = strtoul(argv[1], &ptr, 10); + + if (ps_data_retrieval_mech > 1) { + shell_fprintf(shell, + SHELL_ERROR, + "Invalid value(%lu).\n", ps_data_retrieval_mech); + shell_help(shell); + return -ENOEXEC; + } + + if (ps_data_retrieval_mech == 1) { + if ((argc == 3) && argv[2]) { + ps_data_retrieval_frame_interval_ms = strtoul(argv[2], &ptr, 10); + } else { + ps_data_retrieval_frame_interval_ms = + ctx->conf_params.ps_data_retrieval_frame_interval; + } + } + + status = nrf_wifi_fmac_set_ps_data_retrieval_info(ctx->rpu_ctx, + ps_data_retrieval_mech, + ps_data_retrieval_frame_interval_ms); + if (status != NRF_WIFI_STATUS_SUCCESS) { + shell_fprintf(shell, + SHELL_ERROR, + "Programming data retrival info failed\n"); + return -ENOEXEC; + } + + ctx->conf_params.ps_data_retrieval_mech = ps_data_retrieval_mech; + + if (ps_data_retrieval_mech == 1) { + ctx->conf_params.ps_data_retrieval_frame_interval = + ps_data_retrieval_frame_interval_ms; + } + + return 0; +} + SHELL_STATIC_SUBCMD_SET_CREATE( nrf_wifi_util_subcmds, SHELL_CMD_ARG(he_ltf, @@ -1022,6 +1089,18 @@ SHELL_STATIC_SUBCMD_SET_CREATE( 1, 0), #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ + SHELL_CMD_ARG(ps_data_retrival_info, + NULL, + "Sets power save date retrieval mechanism and frame interval (in ms)\n" + "Parameters:\n" + " : The power save data retrieval mechanism:\n" + " 0 - PS_POLL_FRAME\n" + " 1 - QOS_NULL_FRAME\n" + " :\n" + " The power save data rerieval frame interval in ms.\n", + nrf_wifi_util_set_ps_data_retrival_info, + 2, + 1), SHELL_SUBCMD_SET_END);