diff --git a/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h b/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h index d4cea7cee7..3f98c0f300 100644 --- a/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h +++ b/components/spatial_reuse/dispatcher/inc/spatial_reuse_api.h @@ -37,4 +37,30 @@ QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, uint8_t sr_ctrl, uint8_t non_srg_max_pd_offset); +/** + * wlan_spatial_reuse_he_siga_val15_allowed_set() - Set spatial reuse config + * he_siga_val15_allowed + * @vdev: objmgr manager vdev + * @he_siga_va15_allowed: enable/disable he_siga_val15_allowed + * + * Return: QDF_STATUS + */ +QDF_STATUS wlan_spatial_reuse_he_siga_val15_allowed_set( + struct wlan_objmgr_vdev *vdev, + bool he_siga_va15_allowed); + +/** + * wlan_sr_setup_req() - Enable SR with provided pd threshold + * + * @vdev: objmgr vdev + * @pdev: objmgr pdev + * @is_sr_enable: sr enable/disable + * @pd_threshold: pd threshold + * + * Return: QDF_STATUS + */ +QDF_STATUS +wlan_sr_setup_req(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_pdev *pdev, bool is_sr_enable, + int32_t pd_threshold); #endif diff --git a/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h b/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h index adcbcbe18d..04dba550b5 100644 --- a/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h +++ b/components/spatial_reuse/dispatcher/inc/spatial_reuse_ucfg_api.h @@ -20,9 +20,9 @@ #ifndef _SPATIAL_REUSE_UCFG_API_H_ #define _SPATIAL_REUSE_UCFG_API_H_ +#ifdef WLAN_FEATURE_SR #include #include - /** * ucfg_spatial_reuse_get_sr_config() - Spatial reuse config get * @@ -60,5 +60,43 @@ void ucfg_spatial_reuse_set_sr_config(struct wlan_objmgr_vdev *vdev, */ void ucfg_spatial_reuse_send_sr_config(struct wlan_objmgr_vdev *vdev, bool enable); -#endif +/** + * ucfg_spatial_reuse_set_sr_enable() - set enable/disable Spatial reuse + * + * @vdev: object manager vdev + * @enable: spatial reuse to be enabled or not + * + * Return: void + */ +void ucfg_spatial_reuse_set_sr_enable(struct wlan_objmgr_vdev *vdev, + bool enable); + +/** + * ucfg_spatial_reuse_send_sr_prohibit() - Send spatial reuse config to enable + * or disbale he_siga_val15_allowed + * + * @vdev: object manager vdev + * @enable_he_siga_val15_prohibit: enable/disable he_siga_val15_allowed + * + * Return: void + */ +void ucfg_spatial_reuse_send_sr_prohibit(struct wlan_objmgr_vdev *vdev, + bool enable_he_siga_val15_prohibit); + +/** + * ucfg_spatial_reuse_setup_req() - To enable/disable SR + * + * vdev: object manager vdev + * pdev: object manager pdev + * is_sr_enable: sr enable/disable + * pd_threshold: pd thresold + * + * Return: Success/Failure + */ +QDF_STATUS ucfg_spatial_reuse_setup_req(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_pdev *pdev, + bool is_sr_enable, + int32_t pd_threshold); +#endif +#endif diff --git a/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c b/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c index 8a22a75aed..ce7dd52f3c 100644 --- a/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c +++ b/components/spatial_reuse/dispatcher/src/spatial_reuse_api.c @@ -17,7 +17,6 @@ /** * DOC : contains interface prototypes for spatial_reuse api */ - #include QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, @@ -40,3 +39,41 @@ QDF_STATUS wlan_spatial_reuse_config_set(struct wlan_objmgr_vdev *vdev, return QDF_STATUS_E_NULL_VALUE; } + +QDF_STATUS wlan_spatial_reuse_he_siga_val15_allowed_set( + struct wlan_objmgr_vdev *vdev, + bool he_siga_va15_allowed) +{ + struct wlan_lmac_if_tx_ops *tx_ops; + struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev); + + if (!psoc) + return QDF_STATUS_E_NULL_VALUE; + + tx_ops = wlan_psoc_get_lmac_if_txops(psoc); + if (!tx_ops) + return QDF_STATUS_E_NULL_VALUE; + + if (tx_ops->spatial_reuse_tx_ops.send_sr_prohibit_cfg) + return tx_ops->spatial_reuse_tx_ops.send_sr_prohibit_cfg( + vdev, + he_siga_va15_allowed); + return QDF_STATUS_E_NULL_VALUE; +} + +QDF_STATUS +wlan_sr_setup_req(struct wlan_objmgr_vdev *vdev, struct wlan_objmgr_pdev *pdev, + bool is_sr_enable, int32_t pd_threshold) { + struct wlan_lmac_if_tx_ops *tx_ops; + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + tx_ops = wlan_psoc_get_lmac_if_txops(wlan_pdev_get_psoc(pdev)); + if (tx_ops && + tx_ops->spatial_reuse_tx_ops.target_if_set_sr_enable_disable) { + status = + tx_ops->spatial_reuse_tx_ops.target_if_set_sr_enable_disable( + vdev, pdev, is_sr_enable, pd_threshold); + return status; + } + return status; +} diff --git a/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c b/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c index 581af86b62..200dd5e29a 100644 --- a/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c +++ b/components/spatial_reuse/dispatcher/src/spatial_reuse_ucfg_api.c @@ -17,7 +17,6 @@ /** * DOC : contains interface prototypes for OS_IF layer */ - #include #include #include @@ -60,3 +59,27 @@ void ucfg_spatial_reuse_send_sr_config(struct wlan_objmgr_vdev *vdev, wlan_vdev_mlme_set_he_spr_enabled(vdev, false); } } + +void ucfg_spatial_reuse_set_sr_enable(struct wlan_objmgr_vdev *vdev, + bool enable) +{ + wlan_vdev_mlme_set_he_spr_enabled(vdev, enable); +} + +void ucfg_spatial_reuse_send_sr_prohibit(struct wlan_objmgr_vdev *vdev, + bool enable_he_siga_val15_prohibit) +{ + bool sr_enabled = wlan_vdev_mlme_get_he_spr_enabled(vdev); + + if (sr_enabled) + wlan_spatial_reuse_he_siga_val15_allowed_set( + vdev, enable_he_siga_val15_prohibit); +} + +QDF_STATUS +ucfg_spatial_reuse_setup_req(struct wlan_objmgr_vdev *vdev, + struct wlan_objmgr_pdev *pdev, + bool is_sr_enable, int32_t pd_threshold) +{ + return wlan_sr_setup_req(vdev, pdev, is_sr_enable, pd_threshold); +} diff --git a/core/hdd/inc/wlan_hdd_he.h b/core/hdd/inc/wlan_hdd_he.h index 05d7d06c43..7c4a2e5fce 100644 --- a/core/hdd/inc/wlan_hdd_he.h +++ b/core/hdd/inc/wlan_hdd_he.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. 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 @@ -66,6 +67,10 @@ enum qca_wlan_vendor_attr_get_he_capabilities { QCA_WLAN_VENDOR_ATTR_HE_CAPABILITIES_AFTER_LAST - 1, }; +/* QCA_NL80211_VENDOR_SUBCMD_SR policy*/ +extern const struct nla_policy +wlan_hdd_sr_policy[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1]; + /** * hdd_update_tgt_he_cap() - Update HE related capabilities * @hdd_ctx: HDD context @@ -116,6 +121,29 @@ int hdd_update_he_cap_in_cfg(struct hdd_context *hdd_ctx); int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); +#ifdef WLAN_FEATURE_SR +/** + * wlan_hdd_cfg80211_sr_operations() - Spatial Reuse Operations + * @wiphy: pointer to wireless wiphy structure. + * @wdev: pointer to wireless_dev structure. + * @data: Pointer to the data to be passed via vendor interface + * @data_len:Length of the data to be passed + * + * Return: Return the Success or Failure code. + */ +int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len); +#else +static inline +int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + return 0; +} +#endif + #define FEATURE_11AX_VENDOR_COMMANDS \ { \ .info.vendor_id = QCA_NL80211_VENDOR_ID, \ @@ -124,6 +152,16 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy, WIPHY_VENDOR_CMD_NEED_NETDEV, \ .doit = wlan_hdd_cfg80211_get_he_cap, \ vendor_command_policy(VENDOR_CMD_RAW_DATA, 0) \ +}, \ +{ \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_SR, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | \ + WIPHY_VENDOR_CMD_NEED_NETDEV | \ + WIPHY_VENDOR_CMD_NEED_RUNNING, \ + .doit = wlan_hdd_cfg80211_sr_operations, \ + vendor_command_policy(wlan_hdd_sr_policy, \ + QCA_WLAN_VENDOR_ATTR_SR_MAX) \ }, #else diff --git a/core/hdd/src/wlan_hdd_he.c b/core/hdd/src/wlan_hdd_he.c index c46a4bfc26..903d0dd202 100644 --- a/core/hdd/src/wlan_hdd_he.c +++ b/core/hdd/src/wlan_hdd_he.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. 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 @@ -30,6 +30,34 @@ #include "wma_he.h" #include "wlan_utility.h" #include "wlan_mlme_ucfg_api.h" +#include "spatial_reuse_ucfg_api.h" + +const struct nla_policy +wlan_hdd_sr_policy[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_SR_OPERATION] = {.type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS] = {.type = NLA_NESTED}, + [QCA_WLAN_VENDOR_ATTR_SR_STATS] = {.type = NLA_NESTED}, +}; + +static const struct nla_policy +qca_wlan_vendor_srp_param_policy[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE] = { + .type = NLA_FLAG}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_DISALLOW] = { + .type = NLA_FLAG}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MIN_OFFSET] = { + .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_OBSS_PD_MAX_OFFSET] = { + .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_OBSS_PD_MAX_OFFSET] = { + .type = NLA_U8}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD] = { + .type = NLA_S32}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD] = { + .type = NLA_S32}, + [QCA_WLAN_VENDOR_ATTR_SR_PARAMS_REASON_CODE] = {.type = NLA_U32}, + +}; void hdd_update_tgt_he_cap(struct hdd_context *hdd_ctx, struct wma_tgt_cfg *cfg) @@ -216,3 +244,166 @@ int wlan_hdd_cfg80211_get_he_cap(struct wiphy *wiphy, return errno; } + +/** + * __wlan_hdd_cfg80211_sr_operations: To handle SR operation + * + * @wiphy: wiphy structure + * @wdev: wireless dev + * @data: vendor command data + * @data_len: data len + * + * return: success/failure code + */ +#ifdef WLAN_FEATURE_SR +static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + QDF_STATUS status; + uint32_t id; + bool is_sr_enable = false; + int32_t pd_threshold = 0; + uint8_t sr_he_siga_val15_allowed = true; + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(wdev->netdev); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SR_MAX + 1]; + struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX + 1]; + enum qca_wlan_sr_operation sr_oper; + struct nlattr *sr_oper_attr; + struct nlattr *sr_param_attr; + uint8_t sr_ctrl, non_srg_max_pd_offset; + int ret = 0; + + hdd_enter_dev(wdev->netdev); + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam() || + QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) { + hdd_err("Command not allowed in FTM or Monitor mode"); + return -EPERM; + } + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + if (hdd_ctx->driver_status == DRIVER_MODULES_CLOSED) { + hdd_err("Driver Modules are closed"); + return -EINVAL; + } + if (!sme_is_feature_supported_by_fw(DOT11AX)) { + hdd_err("11AX is not supported"); + return -EINVAL; + } + if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_SR_MAX, data, + data_len, wlan_hdd_sr_policy)) { + hdd_err("invalid attr"); + return -EINVAL; + } + id = QCA_WLAN_VENDOR_ATTR_SR_OPERATION; + sr_oper_attr = tb[id]; + + if (!sr_oper_attr) { + hdd_err("SR operation not specified"); + return -EINVAL; + } + + sr_oper = nla_get_u8(sr_oper_attr); + hdd_debug("SR Operation 0x%x", sr_oper); + + ucfg_spatial_reuse_get_sr_config(adapter->vdev, &sr_ctrl, + &non_srg_max_pd_offset, &is_sr_enable); + + if (sr_oper != QCA_WLAN_SR_OPERATION_SR_ENABLE && !is_sr_enable) { + hdd_err("SR operation not allowed"); + return -EINVAL; + } + + id = QCA_WLAN_VENDOR_ATTR_SR_PARAMS; + sr_param_attr = tb[id]; + if (sr_param_attr) + ret = wlan_cfg80211_nla_parse_nested( + tb2, QCA_WLAN_VENDOR_ATTR_SR_PARAMS_MAX, + sr_param_attr, + qca_wlan_vendor_srp_param_policy); + switch (sr_oper) { + case QCA_WLAN_SR_OPERATION_SR_ENABLE: + case QCA_WLAN_SR_OPERATION_SR_DISABLE: + if (sr_oper == QCA_WLAN_SR_OPERATION_SR_ENABLE) + is_sr_enable = 1; + else + is_sr_enable = 0; + /** + * As per currenct implementation from userspace same + * PD threshold value is configured for both SRG and + * NON-SRG and fw will decide further based on BSS color + * So only SRG param is parsed and set as pd threshold + */ + if (is_sr_enable && + tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]) { + pd_threshold = + nla_get_s32( + tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]); + } + hdd_debug("setting sr enable %d with pd threshold %d", + is_sr_enable, pd_threshold); + /* Set the variables */ + ucfg_spatial_reuse_set_sr_enable(adapter->vdev, is_sr_enable); + status = ucfg_spatial_reuse_setup_req(adapter->vdev, + hdd_ctx->pdev, + is_sr_enable, + pd_threshold); + if (status != QDF_STATUS_SUCCESS) { + hdd_err("failed to enable Spatial Reuse feature"); + return -EINVAL; + } + + break; + case QCA_WLAN_SR_OPERATION_GET_STATS: + break; + case QCA_WLAN_SR_OPERATION_CLEAR_STATS: + break; + case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT: + if (tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE]) + sr_he_siga_val15_allowed = nla_get_u8( + tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE] + ); + if (!sr_he_siga_val15_allowed) { + hdd_err("invalid sr_he_siga_val15_enable param"); + return -EINVAL; + } + ucfg_spatial_reuse_send_sr_prohibit(adapter->vdev, + sr_he_siga_val15_allowed); + break; + case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW: + ucfg_spatial_reuse_send_sr_prohibit(adapter->vdev, false); + break; + case QCA_WLAN_SR_OPERATION_GET_PARAMS: + break; + default: + hdd_err("Invalid SR Operation"); + ret = -EINVAL; + break; + } + + hdd_exit(); + + return ret; +} + +int wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct osif_psoc_sync *psoc_sync; + int errno; + + errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_sr_operations(wiphy, wdev, data, data_len); + + osif_psoc_sync_op_stop(psoc_sync); + + return errno; +} +#endif diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 9265c1c067..8ce6c1b6ae 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -7369,7 +7369,7 @@ wlan_util_get_centre_freq(struct wireless_dev *wdev, unsigned int link_id) } #endif -#if defined WLAN_FEATURE_11AX +#ifdef WLAN_FEATURE_SR void hdd_update_he_obss_pd(struct hdd_adapter *adapter, struct cfg80211_ap_settings *params, bool iface_start) @@ -7412,7 +7412,6 @@ void hdd_update_he_obss_pd(struct hdd_adapter *adapter, WLAN_HDD_ID_OBJ_MGR); if (!conc_vdev) goto release_ref; - if (iface_start) { ucfg_spatial_reuse_send_sr_config(conc_vdev, false); hdd_debug("disable obss pd for vdev:%d", conc_vdev_id);