diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index e695186546..d5d95402de 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -1193,11 +1193,15 @@ static void mlme_init_he_cap_in_cfg(struct wlan_objmgr_psoc *psoc, static void mlme_init_twt_cfg(struct wlan_objmgr_psoc *psoc, struct wlan_mlme_cfg_twt *twt_cfg) { + uint32_t bcast_conf = cfg_get(psoc, CFG_BCAST_TWT_REQ_RESP); + twt_cfg->is_twt_bcast_enabled = cfg_get(psoc, CFG_BCAST_TWT); twt_cfg->is_twt_enabled = cfg_get(psoc, CFG_ENABLE_TWT); twt_cfg->is_twt_responder_enabled = cfg_get(psoc, CFG_TWT_RESPONDER); twt_cfg->is_twt_requestor_enabled = cfg_get(psoc, CFG_TWT_REQUESTOR); twt_cfg->twt_congestion_timeout = cfg_get(psoc, CFG_TWT_CONGESTION_TIMEOUT); + twt_cfg->is_bcast_requestor_enabled = CFG_TWT_GET_BCAST_REQ(bcast_conf); + twt_cfg->is_bcast_responder_enabled = CFG_TWT_GET_BCAST_RES(bcast_conf); } #ifdef WLAN_FEATURE_SAE diff --git a/components/mlme/dispatcher/inc/cfg_mlme_twt.h b/components/mlme/dispatcher/inc/cfg_mlme_twt.h index 2bbaf6a94a..b19da46a71 100644 --- a/components/mlme/dispatcher/inc/cfg_mlme_twt.h +++ b/components/mlme/dispatcher/inc/cfg_mlme_twt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -28,7 +28,7 @@ * twt_requestor - twt requestor. * @Min: 0 * @Max: 1 - * @Default: 0 + * @Default: 1 * * This cfg is used to store twt requestor config. * @@ -42,14 +42,14 @@ */ #define CFG_TWT_REQUESTOR CFG_INI_BOOL( \ "twt_requestor", \ - 0, \ + 1, \ "TWT requestor") /* * * twt_responder - twt responder. * @Min: 0 * @Max: 1 - * @Default: 0 + * @Default: 1 * * This cfg is used to store twt responder config. * @@ -63,7 +63,7 @@ */ #define CFG_TWT_RESPONDER CFG_INI_BOOL( \ "twt_responder", \ - 0, \ + 1, \ "TWT responder") /* @@ -138,12 +138,58 @@ 100, \ CFG_VALUE_OR_DEFAULT, \ "twt congestion timeout") +/* + * + * twt_bcast_req_resp_config - To enable broadcast twt requestor and responder. + * @Min: 0 Disable the extended twt capability + * @Max: 3 + * @Default: 0 + * + * This cfg is used to configure the broadcast TWT requestor and responder. + * Bitmap for enabling the broadcast twt requestor and responder. + * BIT 0: Enable/Disable broadcast twt requestor. + * BIT 1: Enable/Disable broadcast twt responder. + * BIT 2-31: Reserved + * + * Related: CFG_ENABLE_TWT + * Related: CFG_TWT_RESPONDER + * Related: CFG_TWT_REQUESTOR + * + * Supported Feature: 11AX + * + * Usage: External + * + * + */ +/* defines to extract the requestor/responder capabilities from cfg */ +#define TWT_BCAST_REQ_INDEX 0 +#define TWT_BCAST_REQ_BITS 1 +#define TWT_BCAST_RES_INDEX 1 +#define TWT_BCAST_RES_BITS 1 + +#define CFG_BCAST_TWT_REQ_RESP CFG_INI_UINT( \ + "twt_bcast_req_resp_config", \ + 0, \ + 3, \ + 0, \ + CFG_VALUE_OR_DEFAULT, \ + "BROADCAST TWT CAPABILITY") + +#define CFG_TWT_GET_BCAST_REQ(_bcast_conf) \ + QDF_GET_BITS(_bcast_conf, \ + TWT_BCAST_REQ_INDEX, \ + TWT_BCAST_REQ_BITS) + +#define CFG_TWT_GET_BCAST_RES(_bcast_conf) \ + QDF_GET_BITS(_bcast_conf, \ + TWT_BCAST_RES_INDEX, \ + TWT_BCAST_RES_BITS) #define CFG_TWT_ALL \ CFG(CFG_BCAST_TWT) \ CFG(CFG_ENABLE_TWT) \ CFG(CFG_TWT_REQUESTOR) \ CFG(CFG_TWT_RESPONDER) \ - CFG(CFG_TWT_CONGESTION_TIMEOUT) - + CFG(CFG_TWT_CONGESTION_TIMEOUT) \ + CFG(CFG_BCAST_TWT_REQ_RESP) #endif /* __CFG_MLME_TWT_H */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index cdb2acf75d..6b433dbf73 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1396,6 +1396,8 @@ struct wlan_mlme_acs { * @is_twt_enabled: global twt configuration * @is_twt_responder_enabled: twt responder * @is_twt_requestor_enabled: twt requestor + * @is_bcast_responder_enabled: bcast responder enable/disable + * @is_bcast_requestor_enabled: bcast requestor enable/disable * @twt_congestion_timeout: congestion timeout value */ struct wlan_mlme_cfg_twt { @@ -1403,6 +1405,8 @@ struct wlan_mlme_cfg_twt { bool is_twt_enabled; bool is_twt_responder_enabled; bool is_twt_requestor_enabled; + bool is_bcast_responder_enabled; + bool is_bcast_requestor_enabled; uint32_t twt_congestion_timeout; }; diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 06bb14cc87..9cd6a1fd8d 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -889,6 +889,7 @@ QDF_STATUS ucfg_mlme_set_pmkid_modes(struct wlan_objmgr_psoc *psoc, uint32_t val); +#ifdef WLAN_SUPPORT_TWT /** * ucfg_mlme_get_twt_requestor() - Get twt requestor * @psoc: pointer to psoc object @@ -999,6 +1000,154 @@ QDF_STATUS ucfg_mlme_set_enable_twt(struct wlan_objmgr_psoc *psoc, bool val); +/** + * ucfg_mlme_get_twt_bcast_requestor() - Get twt requestor enabled + * @psoc: pointer to psoc object + * @val: Pointer to the value which will be filled for the caller + * + * Return: QDF Status + */ +QDF_STATUS +ucfg_mlme_get_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool *val); + +/** + * ucfg_mlme_set_twt_bcast_requestor() - Set Global twt bcast requestor support + * @psoc: pointer to psoc object + * @val: Value to be set to config + * + * Return: QDF Status + */ +QDF_STATUS +ucfg_mlme_set_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool val); +/** + * ucfg_mlme_get_twt_bcast_responder() - Get twt responder enabled + * @psoc: pointer to psoc object + * @val: Pointer to the value which will be filled for the caller + * + * Return: QDF Status + */ +QDF_STATUS +ucfg_mlme_get_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool *val); + +/** + * ucfg_mlme_set_twt_bcast_responder() - Set Global twt bcast responder support + * @psoc: pointer to psoc object + * @val: Value to be set to config + * + * Return: QDF Status + */ +QDF_STATUS +ucfg_mlme_set_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool val); +#else +static inline QDF_STATUS +ucfg_mlme_get_twt_requestor(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_twt_requestor(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_twt_responder(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_twt_responder(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_bcast_twt(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_bcast_twt(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_twt_congestion_timeout(struct wlan_objmgr_psoc *psoc, + uint32_t *val) +{ + *val = 0; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_twt_congestion_timeout(struct wlan_objmgr_psoc *psoc, + uint32_t val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_enable_twt(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_enable_twt(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_get_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + *val = false; + return QDF_STATUS_E_NOSUPPORT; +} + +static inline QDF_STATUS +ucfg_mlme_set_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool val) +{ + return QDF_STATUS_E_NOSUPPORT; +} +#endif /** * ucfg_mlme_get_dot11p_mode() - Get the setting about 802.11p mode * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c index 5ac49133d6..0ff011da25 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c @@ -508,6 +508,7 @@ ucfg_mlme_set_pmkid_modes(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +#ifdef WLAN_SUPPORT_TWT QDF_STATUS ucfg_mlme_get_twt_requestor(struct wlan_objmgr_psoc *psoc, bool *val) @@ -668,6 +669,77 @@ ucfg_mlme_set_enable_twt(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS +ucfg_mlme_get_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + uint32_t b_req_res; + + b_req_res = cfg_default(CFG_BCAST_TWT_REQ_RESP); + *val = CFG_TWT_GET_BCAST_REQ(b_req_res); + return QDF_STATUS_E_INVAL; + } + + *val = mlme_obj->cfg.twt_cfg.is_bcast_requestor_enabled; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +ucfg_mlme_get_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool *val) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) { + uint32_t b_req_res; + + b_req_res = cfg_default(CFG_BCAST_TWT_REQ_RESP); + *val = CFG_TWT_GET_BCAST_RES(b_req_res); + return QDF_STATUS_E_INVAL; + } + + *val = mlme_obj->cfg.twt_cfg.is_bcast_responder_enabled; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +ucfg_mlme_set_twt_bcast_requestor(struct wlan_objmgr_psoc *psoc, + bool val) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_INVAL; + + mlme_obj->cfg.twt_cfg.is_bcast_requestor_enabled = val; + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +ucfg_mlme_set_twt_bcast_responder(struct wlan_objmgr_psoc *psoc, + bool val) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_INVAL; + + mlme_obj->cfg.twt_cfg.is_bcast_responder_enabled = val; + + return QDF_STATUS_SUCCESS; +} +#endif + QDF_STATUS ucfg_mlme_get_dot11p_mode(struct wlan_objmgr_psoc *psoc, enum dot11p_mode *out_mode) diff --git a/core/hdd/inc/wlan_hdd_twt.h b/core/hdd/inc/wlan_hdd_twt.h index cf1ef0f22e..60ee83353d 100644 --- a/core/hdd/inc/wlan_hdd_twt.h +++ b/core/hdd/inc/wlan_hdd_twt.h @@ -42,6 +42,29 @@ struct wmi_twt_resume_dialog_cmd_param; extern const struct nla_policy wlan_hdd_wifi_twt_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX + 1]; +/** + * enum twt_role - TWT role definitions + * @TWT_REQUESTOR: Individual/Bcast TWT requestor role + * @TWT_REQUESTOR_INDV: Individual TWT requestor role + * @TWT_REQUESTOR_BCAST: Broadcast TWT requestor role + * @TWT_RESPONDER: Individual/Bcast TWT responder role + * @TWT_RESPONDER_INDV: Individual TWT responder role + * @TWT_RESPONDER_BCAST: Broadcast TWT responder role + * @TWT_ROLE_ALL: All TWT roles + */ +enum twt_role { + TWT_REQUESTOR, + TWT_REQUESTOR_INDV, + /* Bcast alone cannot be enabled, but can be disabled */ + TWT_REQUESTOR_BCAST, + TWT_RESPONDER, + TWT_RESPONDER_INDV, + /* Bcast alone cannot be enabled, but can be disabled */ + TWT_RESPONDER_BCAST, + TWT_ROLE_ALL, + TWT_ROLE_MAX, +}; + #ifdef WLAN_SUPPORT_TWT /** * enum twt_status - TWT target state @@ -165,6 +188,16 @@ int hdd_test_config_twt_setup_session(struct hdd_adapter *adapter, */ int hdd_test_config_twt_terminate_session(struct hdd_adapter *adapter, struct nlattr **tb); +/** + * hdd_send_twt_role_disable_cmd() - Send a specific TWT role + * disable to firmware + * @hdd_ctx: hdd context pointer + * @role : TWT role to be disabled + * + * Return: None + */ +void hdd_send_twt_role_disable_cmd(struct hdd_context *hdd_ctx, + enum twt_role role); #define FEATURE_VENDOR_SUBCMD_WIFI_CONFIG_TWT \ { \ @@ -216,6 +249,11 @@ int hdd_test_config_twt_terminate_session(struct hdd_adapter *adapter, return -EINVAL; } +static inline +void hdd_send_twt_role_disable_cmd(struct hdd_context *hdd_ctx, + enum twt_role role) +{ +} #define FEATURE_VENDOR_SUBCMD_WIFI_CONFIG_TWT #endif diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index d0b98877c5..665c54bb25 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -905,6 +905,7 @@ static void hdd_clean_up_interface(struct hdd_context *hdd_ctx, hdd_stop_adapter(hdd_ctx, adapter); hdd_deinit_adapter(hdd_ctx, adapter, true); hdd_close_adapter(hdd_ctx, adapter, true); + hdd_send_twt_enable_cmd(hdd_ctx); } int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) @@ -1201,6 +1202,12 @@ int wlan_hdd_set_power_save(struct hdd_adapter *adapter, status = ucfg_p2p_set_ps(psoc, ps_config); hdd_debug("p2p set power save, status:%d", status); + /* P2P-GO-NOA and TWT do not go hand in hand */ + if (ps_config->duration) + hdd_send_twt_role_disable_cmd(hdd_ctx, TWT_RESPONDER); + else + hdd_send_twt_enable_cmd(hdd_ctx); + return qdf_status_to_os_return(status); } diff --git a/core/hdd/src/wlan_hdd_twt.c b/core/hdd/src/wlan_hdd_twt.c index 81b455d985..3bd57a76cd 100644 --- a/core/hdd/src/wlan_hdd_twt.c +++ b/core/hdd/src/wlan_hdd_twt.c @@ -33,6 +33,7 @@ #include "wma_twt.h" #include "osif_sync.h" #include "wlan_osif_request_manager.h" +#include "cfg_ucfg_api.h" #include #define TWT_SETUP_COMPLETE_TIMEOUT 4000 @@ -1998,51 +1999,134 @@ void hdd_update_tgt_twt_cap(struct hdd_context *hdd_ctx, struct wma_tgt_cfg *cfg) { struct wma_tgt_services *services = &cfg->services; - bool enable_twt = false; + bool twt_bcast_req; + bool twt_bcast_res; + bool enable_twt; + bool twt_req; + bool twt_res; ucfg_mlme_get_enable_twt(hdd_ctx->psoc, &enable_twt); - hdd_debug("TWT: enable_twt=%d, tgt Req=%d, Res=%d", - enable_twt, services->twt_requestor, - services->twt_responder); + + ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &twt_req); + + ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &twt_res); + + ucfg_mlme_get_twt_bcast_requestor(hdd_ctx->psoc, + &twt_bcast_req); + + ucfg_mlme_get_twt_bcast_responder(hdd_ctx->psoc, + &twt_bcast_res); + + hdd_debug("ini: enable_twt=%d, bcast_req=%d, bcast_res=%d", + enable_twt, twt_bcast_req, twt_bcast_res); + hdd_debug("ini: twt_req=%d, twt_res=%d", twt_req, twt_res); + hdd_debug("svc: req=%d, res=%d, bcast_req=%d, bcast_res=%d", + services->twt_requestor, services->twt_responder, + cfg->twt_bcast_req_support, cfg->twt_bcast_res_support); ucfg_mlme_set_twt_requestor(hdd_ctx->psoc, QDF_MIN(services->twt_requestor, - enable_twt)); + (enable_twt && twt_req))); ucfg_mlme_set_twt_responder(hdd_ctx->psoc, QDF_MIN(services->twt_responder, - enable_twt)); + (enable_twt && twt_res))); + + twt_req = enable_twt && twt_bcast_req; + ucfg_mlme_set_twt_bcast_requestor(hdd_ctx->psoc, + QDF_MIN(cfg->twt_bcast_req_support, + twt_req)); + + twt_res = enable_twt && twt_bcast_res; + ucfg_mlme_set_twt_bcast_responder(hdd_ctx->psoc, + QDF_MIN(cfg->twt_bcast_res_support, + twt_res)); } void hdd_send_twt_enable_cmd(struct hdd_context *hdd_ctx) { uint8_t pdev_id = hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id; - bool req_val = 0, resp_val = 0, bcast_val = 0; - uint32_t congestion_timeout = 0; + struct twt_enable_disable_conf twt_en_dis = {0}; + bool is_requestor_en; + bool is_responder_en; + bool twt_bcast_en; - ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &req_val); - ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &resp_val); - ucfg_mlme_get_bcast_twt(hdd_ctx->psoc, &bcast_val); + /* Get MLME TWT config */ + ucfg_mlme_get_twt_requestor(hdd_ctx->psoc, &is_requestor_en); + ucfg_mlme_get_twt_responder(hdd_ctx->psoc, &is_responder_en); + ucfg_mlme_get_bcast_twt(hdd_ctx->psoc, &twt_en_dis.bcast_en); ucfg_mlme_get_twt_congestion_timeout(hdd_ctx->psoc, - &congestion_timeout); + &twt_en_dis.congestion_timeout); + hdd_debug("TWT mlme cfg:req: %d, res:%d, bcast:%d, cong:%d, pdev:%d", + is_requestor_en, is_responder_en, twt_en_dis.bcast_en, + twt_en_dis.congestion_timeout, pdev_id); - hdd_debug("TWT cfg req:%d, responder:%d, bcast:%d, pdev:%d, cong:%d", - req_val, resp_val, bcast_val, pdev_id, congestion_timeout); + /* The below code takes care of the following : + * If user wants to separately enable requestor and responder roles, + * and also the broadcast TWT capaibilities separately for each role. + * This is done by reusing the INI configuration to indicate the user + * preference and sending the command accordingly. + * Legacy targets did not provide this. Newer targets provide this. + * + * 1. The MLME config holds the intersection of fw cap and user config + * 2. This may result in two enable commands sent for legacy, but + * that's fine, since the firmware returns harmlessly for the + * second command. + * 3. The new two parameters in the enable command are ignored + * by legacy targets, and honored by new targets. + */ - if (req_val || resp_val || bcast_val) - wma_send_twt_enable_cmd(pdev_id, congestion_timeout, bcast_val); + /* If requestor configured, send requestor bcast/ucast config */ + if (is_requestor_en) { + twt_en_dis.role = WMI_TWT_ROLE_REQUESTOR; + twt_en_dis.ext_conf_present = true; + ucfg_mlme_get_twt_bcast_requestor(hdd_ctx->psoc, &twt_bcast_en); + if (twt_bcast_en) + twt_en_dis.oper = WMI_TWT_OPERATION_BROADCAST; + else + twt_en_dis.oper = WMI_TWT_OPERATION_INDIVIDUAL; + + wma_send_twt_enable_cmd(pdev_id, &twt_en_dis); + } + + /* If responder configured, send responder bcast/ucast config */ + if (is_responder_en) { + twt_en_dis.role = WMI_TWT_ROLE_RESPONDER; + twt_en_dis.ext_conf_present = true; + ucfg_mlme_get_twt_bcast_responder(hdd_ctx->psoc, &twt_bcast_en); + if (twt_bcast_en) + twt_en_dis.oper = WMI_TWT_OPERATION_BROADCAST; + else + twt_en_dis.oper = WMI_TWT_OPERATION_INDIVIDUAL; + + wma_send_twt_enable_cmd(pdev_id, &twt_en_dis); + } + + return; } QDF_STATUS hdd_send_twt_disable_cmd(struct hdd_context *hdd_ctx) { uint8_t pdev_id = hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id; + struct twt_enable_disable_conf twt_en_dis = {0}; + QDF_STATUS status; hdd_debug("TWT disable cmd :pdev:%d", pdev_id); - wma_send_twt_disable_cmd(pdev_id); + /* One disable should be fine, with extended configuration + * set to false, and extended arguments will be ignored by target + */ + hdd_ctx->twt_state = TWT_DISABLE_REQUESTED; + twt_en_dis.ext_conf_present = false; + wma_send_twt_disable_cmd(pdev_id, &twt_en_dis); - return qdf_wait_single_event(&hdd_ctx->twt_disable_comp_evt, - TWT_DISABLE_COMPLETE_TIMEOUT); + status = qdf_wait_single_event(&hdd_ctx->twt_disable_comp_evt, + TWT_DISABLE_COMPLETE_TIMEOUT); + + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_warn("TWT Responder disable timedout"); + + return status; } /** @@ -2103,8 +2187,12 @@ hdd_twt_disable_comp_cb(hdd_handle_t hdd_handle) hdd_err("TWT: Invalid HDD Context"); return; } + prev_state = hdd_ctx->twt_state; - hdd_ctx->twt_state = TWT_DISABLED; + /* Do not change the state for role specific disables */ + if (hdd_ctx->twt_state == TWT_DISABLE_REQUESTED) { + hdd_ctx->twt_state = TWT_DISABLED; + } hdd_debug("TWT: State transitioned from %d to %d", prev_state, hdd_ctx->twt_state); @@ -2114,6 +2202,52 @@ hdd_twt_disable_comp_cb(hdd_handle_t hdd_handle) hdd_err("Failed to set twt_disable_comp_evt"); } +void hdd_send_twt_role_disable_cmd(struct hdd_context *hdd_ctx, + enum twt_role role) +{ + uint8_t pdev_id = hdd_ctx->pdev->pdev_objmgr.wlan_pdev_id; + struct twt_enable_disable_conf twt_en_dis = {0}; + QDF_STATUS status; + + hdd_debug("TWT disable cmd :pdev:%d : %d", pdev_id, role); + + if ((role == TWT_REQUESTOR) || (role == TWT_REQUESTOR_INDV)) { + twt_en_dis.ext_conf_present = true; + twt_en_dis.role = WMI_TWT_ROLE_REQUESTOR; + twt_en_dis.oper = WMI_TWT_OPERATION_INDIVIDUAL; + wma_send_twt_disable_cmd(pdev_id, &twt_en_dis); + } + + if (role == TWT_REQUESTOR_BCAST) { + twt_en_dis.ext_conf_present = true; + twt_en_dis.role = WMI_TWT_ROLE_REQUESTOR; + twt_en_dis.oper = WMI_TWT_OPERATION_BROADCAST; + wma_send_twt_disable_cmd(pdev_id, &twt_en_dis); + } + + if ((role == TWT_RESPONDER) || (role == TWT_RESPONDER_INDV)) { + twt_en_dis.ext_conf_present = true; + twt_en_dis.role = WMI_TWT_ROLE_RESPONDER; + twt_en_dis.oper = WMI_TWT_OPERATION_INDIVIDUAL; + wma_send_twt_disable_cmd(pdev_id, &twt_en_dis); + } + + if (role == TWT_RESPONDER_BCAST) { + twt_en_dis.ext_conf_present = true; + twt_en_dis.role = WMI_TWT_ROLE_RESPONDER; + twt_en_dis.oper = WMI_TWT_OPERATION_BROADCAST; + wma_send_twt_disable_cmd(pdev_id, &twt_en_dis); + } + + status = qdf_wait_single_event(&hdd_ctx->twt_disable_comp_evt, + TWT_DISABLE_COMPLETE_TIMEOUT); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_warn("TWT request disable timedout"); + return; + } +} + void wlan_hdd_twt_init(struct hdd_context *hdd_ctx) { QDF_STATUS status; diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index 0548021d25..d9fd649c46 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -187,6 +187,8 @@ struct board_info { * @sar_version: Version of SAR supported by firmware * @bcast_twt_support: braodcast twt support * @restricted_80p80_bw_supp: Restricted 80+80MHz(165MHz BW) support + * @twt_bcast_req_support: twt bcast requestor support + * @twt_bcast_res_support: twt bcast responder support */ struct wma_tgt_cfg { uint32_t target_fw_version; @@ -230,5 +232,9 @@ struct wma_tgt_cfg { struct nan_tgt_caps nan_caps; bool bcast_twt_support; bool restricted_80p80_bw_supp; +#ifdef WLAN_SUPPORT_TWT + bool twt_bcast_req_support; + bool twt_bcast_res_support; +#endif }; #endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/inc/wma_twt.h b/core/wma/inc/wma_twt.h index 58efd09e37..5c274737de 100644 --- a/core/wma/inc/wma_twt.h +++ b/core/wma/inc/wma_twt.h @@ -22,7 +22,22 @@ #include "wma.h" #include "wmi_unified_twt_param.h" -#ifdef WLAN_SUPPORT_TWT +/** + * struct twt_enable_disable_conf - TWT enable/disable configuration/parameters + * @congestion_timeout: Congestion timer value in ms for firmware controlled TWT + * @bcast_en: If bcast TWT enabled + * @ext_conf_present: If extended config is present + * @role: The configuration is for WMI_TWT_ROLE + * @oper: The configuration is for WMI_TWT_OPERATION + */ +struct twt_enable_disable_conf { + uint32_t congestion_timeout; + bool bcast_en; + bool ext_conf_present; + enum WMI_TWT_ROLE role; + enum WMI_TWT_OPERATION oper; +}; + /** * struct twt_add_dialog_complete_event - TWT add dialog complete event * @params: Fixed parameters for TWT add dialog complete event @@ -36,17 +51,16 @@ struct twt_add_dialog_complete_event { struct wmi_twt_add_dialog_additional_params additional_params; }; +#ifdef WLAN_SUPPORT_TWT /** * wma_send_twt_enable_cmd() - Send TWT Enable command to firmware * @pdev_id: pdev id - * @congestion_timeout: Timeout value for the TWT congestion timer - * @bcast_val: broadcast twt support + * @conf: Pointer to twt_enable_disable_conf * * Return: None */ void wma_send_twt_enable_cmd(uint32_t pdev_id, - uint32_t congestion_timeout, - bool bcast_val); + struct twt_enable_disable_conf *conf); /** * wma_set_twt_peer_caps() - Fill the peer TWT capabilities @@ -61,10 +75,12 @@ void wma_set_twt_peer_caps(tpAddStaParams params, /** * wma_send_twt_disable_cmd() - Send TWT disable command to firmware * @pdev_id: pdev id + * @conf: Pointer to twt_enable_disable_conf * * Return: None */ -void wma_send_twt_disable_cmd(uint32_t pdev_id); +void wma_send_twt_disable_cmd(uint32_t pdev_id, + struct twt_enable_disable_conf *conf); /** * wma_twt_process_add_dialog() - Process twt add dialog command @@ -113,15 +129,37 @@ QDF_STATUS wma_twt_process_resume_dialog(t_wma_handle *wma_handle, struct wmi_twt_resume_dialog_cmd_param *params); +/** + * wma_update_bcast_twt_support() - update bcost twt support + * @wh: wma handle + * @tgt_cfg: target configuration to be updated + * + * Update braodcast twt support based on service bit. + * + * Return: None + */ +void wma_update_bcast_twt_support(tp_wma_handle wh, + struct wma_tgt_cfg *tgt_cfg); +/** + * wma_register_twt_events() - register for TWT wmi events + * @wma_handle : wma handle + * + * Registers the wmi event handlers for TWT. + * + * Return: None + */ +void wma_register_twt_events(tp_wma_handle wma_handle); #else -static inline void wma_send_twt_enable_cmd(uint32_t pdev_id, - uint32_t congestion_timeout, - bool bcast_val) +static inline void +wma_send_twt_enable_cmd(uint32_t pdev_id, + struct twt_enable_disable_conf *conf) { wma_debug("TWT not supported as WLAN_SUPPORT_TWT is disabled"); } -static inline void wma_send_twt_disable_cmd(uint32_t pdev_id) +static inline void +wma_send_twt_disable_cmd(uint32_t pdev_id, + struct twt_enable_disable_conf *conf) { } @@ -165,6 +203,15 @@ wma_twt_process_resume_dialog(t_wma_handle *wma_handle, return QDF_STATUS_E_INVAL; } + +static inline void wma_update_bcast_twt_support(tp_wma_handle wh, + struct wma_tgt_cfg *tgt_cfg) +{ +} + +static inline void wma_register_twt_events(tp_wma_handle wma_handle) +{ +} #endif #endif /* __WMA_HE_H */ diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 1de6a7d960..9d03cdb770 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3395,9 +3395,7 @@ QDF_STATUS wma_open(struct wlan_objmgr_psoc *psoc, wma_vdev_bss_color_collision_info_handler, WMA_RX_WORK_CTX); -#ifdef WLAN_SUPPORT_TWT wma_register_twt_events(wma_handle); -#endif wma_register_apf_events(wma_handle); wma_register_md_events(wma_handle); @@ -5171,25 +5169,6 @@ static void wma_update_obss_detection_support(tp_wma_handle wh, tgt_cfg->obss_detection_offloaded = false; } -/** - * wma_update_bcast_twt_support() - update bcost twt support - * @wh: wma handle - * @tgt_cfg: target configuration to be updated - * - * Update braodcast twt support based on service bit. - * - * Return: None - */ -static void wma_update_bcast_twt_support(tp_wma_handle wh, - struct wma_tgt_cfg *tgt_cfg) -{ - if (wmi_service_enabled(wh->wmi_handle, - wmi_service_bcast_twt_support)) - tgt_cfg->bcast_twt_support = true; - else - tgt_cfg->bcast_twt_support = false; -} - /** * wma_update_obss_color_collision_support() - update obss color collision * offload support diff --git a/core/wma/src/wma_twt.c b/core/wma/src/wma_twt.c index 2ceb0b142f..2d085cdb06 100644 --- a/core/wma/src/wma_twt.c +++ b/core/wma/src/wma_twt.c @@ -27,7 +27,7 @@ #include "wmi_unified_priv.h" void wma_send_twt_enable_cmd(uint32_t pdev_id, - uint32_t congestion_timeout, bool bcast_val) + struct twt_enable_disable_conf *conf) { t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA); struct wmi_twt_enable_param twt_enable_params = {0}; @@ -37,8 +37,11 @@ void wma_send_twt_enable_cmd(uint32_t pdev_id, return; twt_enable_params.pdev_id = pdev_id; - twt_enable_params.sta_cong_timer_ms = congestion_timeout; - twt_enable_params.b_twt_enable = bcast_val; + twt_enable_params.sta_cong_timer_ms = conf->congestion_timeout; + twt_enable_params.b_twt_enable = conf->bcast_en; + twt_enable_params.ext_conf_present = conf->ext_conf_present; + twt_enable_params.twt_role = conf->role; + twt_enable_params.twt_oper = conf->oper; ret = wmi_unified_twt_enable_cmd(wma->wmi_handle, &twt_enable_params); if (ret) @@ -87,7 +90,8 @@ int wma_twt_en_complete_event_handler(void *handle, return status; } -void wma_send_twt_disable_cmd(uint32_t pdev_id) +void wma_send_twt_disable_cmd(uint32_t pdev_id, + struct twt_enable_disable_conf *conf) { t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA); struct wmi_twt_disable_param twt_disable_params = {0}; @@ -97,6 +101,10 @@ void wma_send_twt_disable_cmd(uint32_t pdev_id) return; twt_disable_params.pdev_id = pdev_id; + twt_disable_params.ext_conf_present = conf->ext_conf_present; + twt_disable_params.twt_role = conf->role; + twt_disable_params.twt_oper = conf->oper; + ret = wmi_unified_twt_disable_cmd(wma->wmi_handle, &twt_disable_params); if (ret) @@ -433,6 +441,37 @@ int wma_twt_resume_dialog_complete_event_handler(void *handle, uint8_t *event, return status; } +/** + * wma_update_bcast_twt_support() - update bcost twt support + * @wh: wma handle + * @tgt_cfg: target configuration to be updated + * + * Update braodcast twt support based on service bit. + * + * Return: None + */ +void wma_update_bcast_twt_support(tp_wma_handle wh, + struct wma_tgt_cfg *tgt_cfg) +{ + if (wmi_service_enabled(wh->wmi_handle, + wmi_service_bcast_twt_support)) + tgt_cfg->bcast_twt_support = true; + else + tgt_cfg->bcast_twt_support = false; + + if (wmi_service_enabled(wh->wmi_handle, + wmi_service_twt_bcast_req_support)) + tgt_cfg->twt_bcast_req_support = true; + else + tgt_cfg->twt_bcast_req_support = false; + + if (wmi_service_enabled(wh->wmi_handle, + wmi_service_twt_bcast_resp_support)) + tgt_cfg->twt_bcast_res_support = true; + else + tgt_cfg->twt_bcast_res_support = false; +} + void wma_register_twt_events(tp_wma_handle wma_handle) { wmi_unified_register_event_handler(wma_handle->wmi_handle,