From 090547835b50fc910abb58d4bf026203b9dbac05 Mon Sep 17 00:00:00 2001 From: Ajay Parida Date: Tue, 3 Sep 2024 19:03:55 +0530 Subject: [PATCH] [nrf noup] wifi_mgmt: Add support for configuring PS exit strategy If AP indicates the presence of buffered traffic, then it is up to the STA to decide whether to stay in PS or come out of PS, add configuration options that can be used at runtime to choose this. This is tagged as "noup" because it's a backport and "fromlist" cannot be used as it won't apply cleanly. Signed-off-by: Ajay Parida --- include/zephyr/net/wifi.h | 22 +++++++++++++++++ include/zephyr/net/wifi_mgmt.h | 2 ++ subsys/net/l2/wifi/wifi_mgmt.c | 19 ++++++++++++++ subsys/net/l2/wifi/wifi_shell.c | 44 +++++++++++++++++++++++++++++++++ 4 files changed, 87 insertions(+) diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index 303a61270ad..e81a96aa00c 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -398,6 +398,8 @@ enum wifi_ps_param_type { WIFI_PS_PARAM_WAKEUP_MODE, /** Power save mode. */ WIFI_PS_PARAM_MODE, + /** Power save exit strategy. */ + WIFI_PS_PARAM_EXIT_STRATEGY, /** Power save timeout. */ WIFI_PS_PARAM_TIMEOUT, }; @@ -413,6 +415,24 @@ enum wifi_ps_wakeup_mode { /** Helper function to get user-friendly ps wakeup mode name. */ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); +/** + * Wi-Fi power save exit strategy + */ +enum wifi_ps_exit_strategy { + /** PS-Poll frame based */ + WIFI_PS_EXIT_CUSTOM_ALGO = 0, + /** QoS NULL frame based */ + WIFI_PS_EXIT_EVERY_TIM, + + /** Last value */ + WIFI_PS_EXIT_LAST, + /** Maximum value */ + WIFI_PS_EXIT_MAX = WIFI_PS_EXIT_LAST - 1, +}; + +/** Helper function to get user-friendly ps exit strategy name. */ +const char * const wifi_ps_exit_strategy_txt(enum wifi_ps_exit_strategy ps_exit_strategy); + /** Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { /** Unspecified error */ @@ -429,6 +449,8 @@ enum wifi_config_ps_param_fail_reason { WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED, /** Listen interval out of range */ WIFI_PS_PARAM_LISTEN_INTERVAL_RANGE_INVALID, + /** Invalid exit strategy */ + WIFI_PS_PARAM_FAIL_INVALID_EXIT_STRATEGY, }; /** @cond INTERNAL_HIDDEN */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 06638167690..d51979b6881 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -482,6 +482,8 @@ struct wifi_ps_params { enum wifi_ps_param_type type; /** Wi-Fi power save fail reason */ enum wifi_config_ps_param_fail_reason fail_reason; + /** Wi-Fi power save exit strategy */ + enum wifi_ps_exit_strategy exit_strategy; }; /** Wi-Fi TWT parameters */ diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index 7974059625e..6e4ce100f43 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -235,6 +235,18 @@ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode) } } +const char * const wifi_ps_exit_strategy_txt(enum wifi_ps_exit_strategy ps_exit_strategy) +{ + switch (ps_exit_strategy) { + case WIFI_PS_EXIT_EVERY_TIM: + return "Every TIM"; + case WIFI_PS_EXIT_CUSTOM_ALGO: + return "Custom algorithm"; + default: + return "UNKNOWN"; + } +} + static const struct wifi_mgmt_ops *const get_wifi_api(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); @@ -515,6 +527,13 @@ static int wifi_set_power_save(uint32_t mgmt_request, struct net_if *iface, case WIFI_PS_PARAM_WAKEUP_MODE: case WIFI_PS_PARAM_TIMEOUT: break; + case WIFI_PS_PARAM_EXIT_STRATEGY: + if (ps_params->exit_strategy > WIFI_PS_EXIT_MAX) { + ps_params->fail_reason = + WIFI_PS_PARAM_FAIL_INVALID_EXIT_STRATEGY; + return -EINVAL; + } + break; default: ps_params->fail_reason = WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED; diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 77d23fd5c0e..c5dc2d8edc0 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -915,6 +915,9 @@ static int cmd_wifi_ps(const struct shell *sh, size_t argc, char *argv[]) PR("PS timeout: disabled\n"); } + shell_fprintf(sh, SHELL_NORMAL, "PS exit strategy: %s\n", + wifi_ps_exit_strategy_txt(config.ps_params.exit_strategy)); + if (config.num_twt_flows == 0) { PR("No TWT flows\n"); } else { @@ -1482,6 +1485,40 @@ static int cmd_wifi_ps_wakeup_mode(const struct shell *sh, size_t argc, char *ar return 0; } +static int cmd_wifi_ps_exit_strategy(const struct shell *sh, size_t argc, + char *argv[]) +{ + struct net_if *iface = net_if_get_first_wifi(); + struct wifi_ps_params params = { 0 }; + + context.sh = sh; + + if (!strncmp(argv[1], "tim", 3)) { + params.exit_strategy = WIFI_PS_EXIT_EVERY_TIM; + } else if (!strncmp(argv[1], "custom", 6)) { + params.exit_strategy = WIFI_PS_EXIT_CUSTOM_ALGO; + } else { + shell_fprintf(sh, SHELL_WARNING, "Invalid argument\n"); + shell_fprintf(sh, SHELL_INFO, "Valid argument : / \n"); + return -ENOEXEC; + } + + params.type = WIFI_PS_PARAM_EXIT_STRATEGY; + + if (net_mgmt(NET_REQUEST_WIFI_PS, iface, ¶ms, sizeof(params))) { + shell_fprintf(sh, SHELL_WARNING, + "Setting PS exit strategy to %s failed..Reason :%s\n", + wifi_ps_exit_strategy_txt(params.exit_strategy), + wifi_ps_get_config_err_code_str(params.fail_reason)); + return -ENOEXEC; + } + + shell_fprintf(sh, SHELL_NORMAL, "%s\n", + wifi_ps_exit_strategy_txt(params.exit_strategy)); + + return 0; +} + void parse_mode_args_to_params(const struct shell *sh, int argc, char *argv[], struct wifi_mode_info *mode, bool *do_mode_oper) @@ -1977,6 +2014,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(wifi_commands, cmd_wifi_ps_wakeup_mode, 2, 0), + SHELL_CMD_ARG(ps_exit_strategy, + NULL, + " : Set PS exit strategy to Every TIM\n" + " : Set PS exit strategy to Custom", + cmd_wifi_ps_exit_strategy, + 2, + 0), SHELL_SUBCMD_SET_END );