From 79e13b55ab4fed010baea74f16e39b4ba5b0c15c Mon Sep 17 00:00:00 2001 From: Madhvapathi Sriram Date: Thu, 9 Dec 2021 15:17:22 +0530 Subject: [PATCH] qcacld-3.0: User MCC quota setting Set the MCC quota for a given interface. Change-Id: I313cdf1673f8fc5f50a049d429c0d88fd213e66f CRs-Fixed: 3106146 --- Kbuild | 11 + components/mlme/core/src/wlan_mlme_main.c | 24 +- .../mlme/dispatcher/inc/wlan_mlme_api.h | 68 +++-- .../dispatcher/inc/wlan_mlme_public_struct.h | 15 ++ .../mlme/dispatcher/inc/wlan_mlme_ucfg_api.h | 51 +++- .../mlme/dispatcher/src/wlan_mlme_api.c | 130 ++++++++++ core/hdd/inc/wlan_hdd_main.h | 17 +- core/hdd/src/wlan_hdd_cfg80211.c | 2 + core/hdd/src/wlan_hdd_hostapd.c | 3 + core/hdd/src/wlan_hdd_main.c | 21 ++ core/hdd/src/wlan_hdd_mcc_quota.c | 241 ++++++++++++++++++ core/hdd/src/wlan_hdd_mcc_quota.h | 95 +++++++ core/sme/src/csr/csr_api_roam.c | 20 ++ 13 files changed, 675 insertions(+), 23 deletions(-) create mode 100644 core/hdd/src/wlan_hdd_mcc_quota.c create mode 100644 core/hdd/src/wlan_hdd_mcc_quota.h diff --git a/Kbuild b/Kbuild index b4729c84b5..98a2aa8d01 100644 --- a/Kbuild +++ b/Kbuild @@ -507,6 +507,10 @@ ifeq ($(CONFIG_QCACLD_WLAN_CONNECTIVITY_LOGGING), y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_connectivity_logging.o endif +ifeq ($(CONFIG_WLAN_FEATURE_MCC_QUOTA), y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_mcc_quota.o +endif + $(call add-wlan-objs,hdd,$(HDD_OBJS)) ###### OSIF_SYNC ######## @@ -4329,6 +4333,13 @@ endif cppflags-$(CONFIG_WLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET) += -DWLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET +ifeq ($(CONFIG_WLAN_FEATURE_MCC_QUOTA), y) +cppflags-y += -DWLAN_FEATURE_MCC_QUOTA +ifdef CONFIG_WLAN_MCC_MIN_CHANNEL_QUOTA +ccflags-y += -DWLAN_MCC_MIN_CHANNEL_QUOTA=$(CONFIG_WLAN_MCC_MIN_CHANNEL_QUOTA) +endif +endif + KBUILD_CPPFLAGS += $(cppflags-y) # Currently, for versions of gcc which support it, the kernel Makefile diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c index c16d07369e..2a83652230 100644 --- a/components/mlme/core/src/wlan_mlme_main.c +++ b/components/mlme/core/src/wlan_mlme_main.c @@ -2483,7 +2483,6 @@ mlme_init_dot11_mode_cfg(struct wlan_objmgr_psoc *psoc, /** * mlme_iot_parse_aggr_info - parse aggr related items in ini - * * @psoc: PSOC pointer * @iot: IOT related CFG items * @@ -2589,7 +2588,6 @@ end: /** * mlme_iot_parse_aggr_info - parse IOT related items in ini - * * @psoc: PSOC pointer * @iot: IOT related CFG items * @@ -2604,7 +2602,6 @@ mlme_init_iot_cfg(struct wlan_objmgr_psoc *psoc, /** * mlme_init_dual_sta_config - Initialize dual sta configuratons - * * @gen: Generic CFG config items * * Return: None @@ -2617,6 +2614,26 @@ mlme_init_dual_sta_config(struct wlan_mlme_generic *gen) QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED; } +#ifdef WLAN_FEATURE_MCC_QUOTA +/** + * mlme_init_user_mcc_quota_config - Initialize mcc quota + * @gen: Generic CFG config items + * + * Return: None + */ +static void +mlme_init_user_mcc_quota_config(struct wlan_mlme_generic *gen) +{ + gen->user_mcc_quota.quota = 0; + gen->user_mcc_quota.op_mode = QDF_MAX_NO_OF_MODE; + gen->user_mcc_quota.vdev_id = WLAN_UMAC_VDEV_ID_MAX; +} +#else +static void +mlme_init_user_mcc_quota_config(struct wlan_mlme_generic *gen) +{ +} +#endif QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) { struct wlan_mlme_psoc_ext_obj *mlme_obj; @@ -2672,6 +2689,7 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc) mlme_init_ratemask_cfg(psoc, &mlme_cfg->ratemask_cfg); mlme_init_iot_cfg(psoc, &mlme_cfg->iot); mlme_init_dual_sta_config(&mlme_cfg->gen); + mlme_init_user_mcc_quota_config(&mlme_cfg->gen); return status; } diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 89b9061a3c..343a573235 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -761,7 +761,6 @@ QDF_STATUS wlan_mlme_get_sap_chan_switch_rate_enabled(struct wlan_objmgr_psoc /** * wlan_mlme_get_sap_force_11n_for_11ac() - get the sap 11n for 11ac - * * @psoc: pointer to psoc object * @value: Value that needs to be set from the caller * @@ -772,7 +771,6 @@ QDF_STATUS wlan_mlme_get_sap_force_11n_for_11ac(struct wlan_objmgr_psoc /** * wlan_mlme_get_go_force_11n_for_11ac() - get the go 11n for 11ac - * * @psoc: pointer to psoc object * @value: Value that needs to be set from the caller * @@ -783,7 +781,6 @@ QDF_STATUS wlan_mlme_get_go_force_11n_for_11ac(struct wlan_objmgr_psoc /** * wlan_mlme_is_go_11ac_override() - Override 11ac bandwdith for P2P GO - * * @psoc: pointer to psoc object * @value: pointer to the value which will be filled for the caller * @@ -794,7 +791,6 @@ QDF_STATUS wlan_mlme_is_go_11ac_override(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_is_sap_11ac_override() - Override 11ac bandwdith for SAP - * * @psoc: pointer to psoc object * @value: pointer to the value which will be filled for the caller * @@ -805,7 +801,6 @@ QDF_STATUS wlan_mlme_is_sap_11ac_override(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_set_go_11ac_override() - set override 11ac bandwdith for P2P GO - * * @psoc: pointer to psoc object * @value: pointer to the value which will be filled for the caller * @@ -816,7 +811,6 @@ QDF_STATUS wlan_mlme_set_go_11ac_override(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_set_sap_11ac_override() - set override 11ac bandwdith for SAP - * * @psoc: pointer to psoc object * @value: pointer to the value which will be filled for the caller * @@ -946,7 +940,6 @@ QDF_STATUS wlan_mlme_cfg_get_enable_ul_ofdm(struct wlan_objmgr_psoc *psoc, /** * mlme_update_tgt_he_caps_in_cfg() - Update tgt he cap in mlme component - * * @psoc: pointer to psoc object * @cfg: pointer to config params from target * @@ -962,7 +955,6 @@ QDF_STATUS mlme_update_tgt_he_caps_in_cfg(struct wlan_objmgr_psoc *psoc, #ifdef WLAN_FEATURE_11BE /** * mlme_update_tgt_eht_caps_in_cfg() - Update tgt eht cap in mlme component - * * @psoc: pointer to psoc object * @cfg: pointer to config params from target * @@ -2262,7 +2254,6 @@ wlan_mlme_is_relaxed_6ghz_conn_policy_enabled(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_get_sta_miracast_mcc_rest_time() - Get STA/MIRACAST MCC rest time - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -2276,7 +2267,6 @@ wlan_mlme_get_sta_miracast_mcc_rest_time(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_get_scan_probe_unicast_ra() - Get scan probe unicast RA cfg - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -2290,7 +2280,6 @@ wlan_mlme_get_scan_probe_unicast_ra(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_set_scan_probe_unicast_ra() - Set scan probe unicast RA cfg - * * @psoc: pointer to psoc object * @value: set value * @@ -2304,7 +2293,6 @@ wlan_mlme_set_scan_probe_unicast_ra(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_get_sap_mcc_chnl_avoid() - Check if SAP MCC needs to be avoided - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -2318,7 +2306,6 @@ wlan_mlme_get_sap_mcc_chnl_avoid(struct wlan_objmgr_psoc *psoc, uint8_t *value); /** * wlan_mlme_get_mcc_bcast_prob_resp() - Get broadcast probe rsp in MCC - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -2333,7 +2320,6 @@ wlan_mlme_get_mcc_bcast_prob_resp(struct wlan_objmgr_psoc *psoc, uint8_t *value); /** * wlan_mlme_get_mcc_rts_cts_prot() - To get RTS-CTS protection in MCC. - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -2348,7 +2334,6 @@ wlan_mlme_get_mcc_rts_cts_prot(struct wlan_objmgr_psoc *psoc, uint8_t *value); /** * wlan_mlme_get_mcc_feature() - To find out to enable/disable MCC feature - * * @psoc: pointer to psoc object * @value: value which needs to filled by API * @@ -3396,7 +3381,6 @@ bool mlme_get_user_ps(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id); #ifdef WLAN_FEATURE_P2P_P2P_STA /** * wlan_mlme_get_p2p_p2p_conc_support() - Get p2p+p2p conc support - * * @psoc: pointer to psoc object * @val : value * @@ -3421,7 +3405,6 @@ enum phy_ch_width mlme_get_vht_ch_width(void); /** * wlan_mlme_get_mgmt_hw_tx_retry_count() - Get mgmt frame hw tx retry count - * * @psoc: pointer to psoc object * @frm_type: frame type of the query * @@ -3433,7 +3416,6 @@ wlan_mlme_get_mgmt_hw_tx_retry_count(struct wlan_objmgr_psoc *psoc, /** * wlan_mlme_get_tx_retry_multiplier() - Get the tx retry multiplier percentage - * * @psoc: pointer to psoc object * @tx_retry_multiplier: pointer to hold user config value of * tx_retry_multiplier @@ -3469,4 +3451,54 @@ QDF_STATUS wlan_mlme_update_ratemask_params(struct wlan_objmgr_vdev *vdev, uint8_t num_ratemask, struct config_ratemask_params *rate_params); +#ifdef WLAN_FEATURE_MCC_QUOTA +/** + * wlan_mlme_set_user_mcc_quota() - set the user mcc quota in mlme + * @psoc: pointer to psoc object + * @quota: pointer to user set mcc quota object + * + * Return: QDF Status + */ +QDF_STATUS wlan_mlme_set_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota); + +/** + * wlan_mlme_get_user_mcc_quota() - Get the user mcc quota from mlme + * @psoc: pointer to psoc object + * @quota: pointer to user set mcc quota object + * + * Return: QDF Status + */ +QDF_STATUS wlan_mlme_get_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota); + +/** + * wlan_mlme_get_user_mcc_duty_cycle_percentage() - Get user mcc duty cycle + * @psoc: pointer to psoc object + * + * Return: MCC duty cycle if MCC exists for the user MCC quota, else 0 + */ +uint32_t +wlan_mlme_get_user_mcc_duty_cycle_percentage(struct wlan_objmgr_psoc *psoc); +#else +static inline QDF_STATUS +wlan_mlme_set_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS +wlan_mlme_get_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) +{ + return QDF_STATUS_E_NOSUPPORT; +} + +static inline uint32_t +wlan_mlme_get_user_mcc_duty_cycle_percentage(struct wlan_objmgr_psoc *psoc) +{ + return 0; +} +#endif /* WLAN_FEATURE_MCC_QUOTA */ #endif /* _WLAN_MLME_API_H_ */ diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 2705061f77..cafc542965 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1290,6 +1290,18 @@ enum mlme_cfg_frame_type { #define MAX_MGMT_HW_TX_RETRY_COUNT 127 +/** + * struct wlan_user_mcc_quota - User MCC quota configuration + * @op_mode: Mode for which MCC quota needs to be applied + * @quota: User MCC quota value + * @vdev_id: Intended VDEV id for the quota + */ +struct wlan_user_mcc_quota { + enum QDF_OPMODE op_mode; + uint8_t quota; + uint8_t vdev_id; +}; + /* struct wlan_mlme_generic - Generic CFG config items * * @band_capability: HW Band Capability - Both or 2.4G only or 5G only @@ -1391,6 +1403,9 @@ struct wlan_mlme_generic { #ifdef CONFIG_BAND_6GHZ bool relaxed_6ghz_conn_policy; #endif +#ifdef WLAN_FEATURE_MCC_QUOTA + struct wlan_user_mcc_quota user_mcc_quota; +#endif }; /* diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index a3a5aff218..ad99a9c61e 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -4443,7 +4443,6 @@ bool ucfg_mlme_get_coex_unsafe_chan_reg_disable( * * Return: QDF_STATUS */ - static inline QDF_STATUS ucfg_set_ratemask_params(struct wlan_objmgr_vdev *vdev, uint8_t num_ratemask, @@ -4452,4 +4451,54 @@ ucfg_set_ratemask_params(struct wlan_objmgr_vdev *vdev, return wlan_mlme_update_ratemask_params(vdev, num_ratemask, rate_params); } + +/* + * ucfg_mlme_set_user_mcc_quota() - Set the user set mcc quota in mlme + * value + * @psoc: pointer to psoc object + * @quota: pointer to user mcc quota object + * + * Return: QDF Status + */ +static inline +QDF_STATUS ucfg_mlme_set_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) +{ + return wlan_mlme_set_user_mcc_quota(psoc, quota); +} + +/** + * ucfg_mlme_get_user_mcc_quota() - Get the user set mcc quota from mlme + * value + * @psoc: pointer to psoc object + * @quota: pointer to user mcc quota object + * + * Return: QDF Status + */ +static inline +QDF_STATUS ucfg_mlme_get_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) +{ + return wlan_mlme_get_user_mcc_quota(psoc, quota); +} + +/** + * ucfg_mlme_get_user_mcc_quota_percentage() - Get user mcc quota percentage + * duty-cycle for a i/f type or mode + * @psoc: pointer to psoc object + * + * MCC duty-cycle value in below format + * ****************************************************** + * |bit 31-24 | bit 23-16 | bits 15-8 |bits 7-0 | + * | Unused | Quota for | chan. # for |chan. # for| + * | | 1st chan | 1st chan. |2nd chan. | + * ***************************************************** + * + * Return: primary iface MCC duty-cycle value + */ +static inline +uint32_t ucfg_mlme_get_user_mcc_quota_percentage(struct wlan_objmgr_psoc *psoc) +{ + return wlan_mlme_get_user_mcc_duty_cycle_percentage(psoc); +} #endif /* _WLAN_MLME_UCFG_API_H_ */ diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index df9b2cabb7..702cfcbfec 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -5462,3 +5462,133 @@ wlan_mlme_update_ratemask_params(struct wlan_objmgr_vdev *vdev, } return QDF_STATUS_SUCCESS; } + +#ifdef WLAN_FEATURE_MCC_QUOTA +#define WLAN_MCC_MIN_QUOTA 10 /* in %age */ +#define WLAN_MCC_MAX_QUOTA 90 /* in %age */ +QDF_STATUS wlan_mlme_set_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) + +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + if (!quota) + return QDF_STATUS_E_NULL_VALUE; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_FAILURE; + + if (quota->quota < WLAN_MCC_MIN_QUOTA) + quota->quota = WLAN_MCC_MIN_QUOTA; + else if (quota->quota > WLAN_MCC_MAX_QUOTA) + quota->quota = WLAN_MCC_MAX_QUOTA; + + mlme_obj->cfg.gen.user_mcc_quota.quota = quota->quota; + mlme_obj->cfg.gen.user_mcc_quota.op_mode = quota->op_mode; + mlme_obj->cfg.gen.user_mcc_quota.vdev_id = quota->vdev_id; + + mlme_debug("quota : %u, op_mode : %d, vdev_id : %u", + quota->quota, quota->op_mode, quota->vdev_id); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS wlan_mlme_get_user_mcc_quota(struct wlan_objmgr_psoc *psoc, + struct wlan_user_mcc_quota *quota) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + if (!quota) + return QDF_STATUS_E_NULL_VALUE; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_FAILURE; + + quota->quota = mlme_obj->cfg.gen.user_mcc_quota.quota; + quota->op_mode = mlme_obj->cfg.gen.user_mcc_quota.op_mode; + quota->vdev_id = mlme_obj->cfg.gen.user_mcc_quota.vdev_id; + + return QDF_STATUS_SUCCESS; +} + +uint32_t +wlan_mlme_get_user_mcc_duty_cycle_percentage(struct wlan_objmgr_psoc *psoc) +{ + uint32_t mcc_freq, ch_freq, quota_value; + struct wlan_user_mcc_quota quota; + uint8_t operating_channel; + int status; + + quota.vdev_id = WLAN_UMAC_VDEV_ID_MAX; + quota.quota = 0; + if (QDF_IS_STATUS_ERROR(wlan_mlme_get_user_mcc_quota(psoc, "a))) { + mlme_debug("Error getting user quota set"); + return 0; + } + + if (quota.vdev_id == WLAN_UMAC_VDEV_ID_MAX || quota.quota == 0) { + mlme_debug("Invalid quota : vdev %u, quota %u", + quota.vdev_id, quota.quota); + return 0; + } + status = policy_mgr_get_chan_by_session_id(psoc, quota.vdev_id, + &ch_freq); + if (QDF_IS_STATUS_ERROR(status)) { + mlme_debug("Could not get vdev %u chan", quota.vdev_id); + return 0; + } + mcc_freq = policy_mgr_get_mcc_operating_channel(psoc, quota.vdev_id); + if (mcc_freq == INVALID_CHANNEL_ID) + return 0; + + operating_channel = wlan_freq_to_chan(ch_freq); + if (!operating_channel) { + mlme_debug("Primary op channel is invalid"); + return 0; + } + /* + * The channel numbers for both adapters and the time + * quota for the 1st adapter, i.e., one specified in cmd + * are formatted as a bit vector + * ****************************************************** + * |bit 31-24 | bit 23-16 | bits 15-8 |bits 7-0 | + * | Unused | Quota for | chan. # for |chan. # for| + * | | 1st chan | 1st chan. |2nd chan. | + * ****************************************************** + */ + mlme_debug("Opmode (%d) vdev (%u) channel %u and quota %u", + quota.op_mode, quota.vdev_id, + operating_channel, quota.quota); + quota_value = quota.quota; + /* Move the time quota for first channel to bits 15-8 */ + quota_value = quota_value << 8; + /* + * Store the channel number of 1st channel at bits 7-0 + * of the bit vector + */ + quota_value |= operating_channel; + + operating_channel = wlan_freq_to_chan(mcc_freq); + if (!operating_channel) { + mlme_debug("Secondary op channel is invalid"); + return 0; + } + + /* + * Now move the time quota and channel number of the + * 1st adapter to bits 23-16 and bits 15-8 of the bit + * vector, respectively. + */ + quota_value = quota_value << 8; + /* + * Set the channel number for 2nd MCC vdev at bits + * 7-0 of set_value + */ + quota_value |= operating_channel; + mlme_debug("quota value:%x", quota_value); + + return quota_value; +} +#endif /* WLAN_FEATURE_MCC_QUOTA */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 2dce7a1b55..7c91dbbe51 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -3747,7 +3747,22 @@ void hdd_indicate_mgmt_frame(tSirSmeMgmtFrameInd *frame_ind); * */ struct hdd_adapter *hdd_get_adapter_by_iface_name(struct hdd_context *hdd_ctx, - const char *iface_name); + const char *iface_name); + +/** + * hdd_get_adapter_by_ifindex() - Return adapter associated with an ifndex + * @hdd_ctx: hdd context. + * @if_index: netdev interface index + * + * This function is used to get the adapter associated with a netdev with the + * given interface index. + * + * Return: adapter pointer if found, NULL otherwise + * + */ +struct hdd_adapter *hdd_get_adapter_by_ifindex(struct hdd_context *hdd_ctx, + uint32_t if_index); + enum phy_ch_width hdd_map_nl_chan_width(enum nl80211_chan_width ch_width); /** diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index e0f346c55f..d2d524d887 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -178,6 +178,7 @@ #include "wlan_pkt_capture_ucfg_api.h" #include "os_if_pkt_capture.h" #include "wlan_hdd_son.h" +#include "wlan_hdd_mcc_quota.h" #define g_mode_rates_size (12) #define a_mode_rates_size (8) @@ -17639,6 +17640,7 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { QCA_WLAN_VENDOR_ATTR_ROAM_EVENTS_MAX) }, #endif + FEATURE_MCC_QUOTA_VENDOR_COMMANDS }; struct hdd_context *hdd_cfg80211_wiphy_alloc(void) diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 91c2b07961..c651e40cc8 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -107,6 +107,7 @@ #include #endif #include "wlan_hdd_son.h" +#include "wlan_hdd_mcc_quota.h" #define ACS_SCAN_EXPIRY_TIMEOUT_S 4 @@ -2154,6 +2155,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event, hdd_err("qdf_event_set failed! status: %d", qdf_status); goto stopbss; } + + wlan_hdd_apply_user_mcc_quota(adapter); break; /* Event will be sent after Switch-Case stmt */ case eSAP_STOP_BSS_EVENT: diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index c0378382ea..75e2d3246f 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -9375,6 +9375,27 @@ struct hdd_adapter *hdd_get_adapter_by_iface_name(struct hdd_context *hdd_ctx, return NULL; } +struct hdd_adapter *hdd_get_adapter_by_ifindex(struct hdd_context *hdd_ctx, + uint32_t if_index) +{ + struct hdd_adapter *adapter, *next_adapter = NULL; + wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_GET_ADAPTER; + + hdd_for_each_adapter_dev_held_safe(hdd_ctx, adapter, next_adapter, + dbgid) { + if (adapter->dev->ifindex == if_index) { + hdd_adapter_dev_put_debug(adapter, dbgid); + if (next_adapter) + hdd_adapter_dev_put_debug(next_adapter, + dbgid); + return adapter; + } + hdd_adapter_dev_put_debug(adapter, dbgid); + } + + return NULL; +} + /** * hdd_get_adapter() - to get adapter matching the mode * @hdd_ctx: hdd context diff --git a/core/hdd/src/wlan_hdd_mcc_quota.c b/core/hdd/src/wlan_hdd_mcc_quota.c new file mode 100644 index 0000000000..fad6fd5399 --- /dev/null +++ b/core/hdd/src/wlan_hdd_mcc_quota.c @@ -0,0 +1,241 @@ +/* + * 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_mcc_quota.c + * + * WLAN Host Device Driver MCC quota feature cfg80211 APIs implementation + * + */ + +#include +#include +#include +#include +#include +#include +#include "osif_sync.h" +#include +#include +#include "sme_api.h" +#include "wlan_hdd_cfg80211.h" +#include "wlan_hdd_hostapd.h" +#include "wlan_hdd_main.h" +#include "wlan_hdd_mcc_quota.h" +#include "wlan_hdd_trace.h" +#include "qdf_str.h" +#include "qdf_trace.h" +#include "qdf_types.h" +#include "wlan_policy_mgr_api.h" +#include +#include "wlan_utility.h" +#include "wlan_policy_mgr_ucfg.h" +#include "wlan_mlme_ucfg_api.h" +#include "wlan_mlme_public_struct.h" +#include "wlan_hdd_object_manager.h" +#include "sme_api.h" + +const struct nla_policy +set_mcc_quota_policy[QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE] = { .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES] = + VENDOR_NLA_POLICY_NESTED(set_mcc_quota_policy), + [QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_FREQ] = { + .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE] = { + .type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX] = { .type = NLA_U32 }, +}; + +int wlan_hdd_set_mcc_adaptive_sched(struct wlan_objmgr_psoc *psoc, bool enable) +{ + bool enable_mcc_adaptive_sch; + + hdd_debug("enable : %d", enable); + ucfg_policy_mgr_get_mcc_adaptive_sch(psoc, &enable_mcc_adaptive_sch); + if (enable_mcc_adaptive_sch) { + ucfg_policy_mgr_set_dynamic_mcc_adaptive_sch(psoc, enable); + if (QDF_IS_STATUS_ERROR(sme_set_mas(enable))) { + hdd_err("Fail to config mcc adaptive sched."); + return -EINVAL; + } + } + + return 0; +} + +int wlan_hdd_cfg80211_set_mcc_quota(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *attr, + int attr_len) +{ + struct hdd_adapter *if_adapter; + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX + 1]; + struct nlattr *quota_entries[QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX + 1]; + struct nlattr *curr_attr; + struct wlan_objmgr_psoc *psoc; + uint32_t duty_cycle, cmd_id, quota_type, rem_bytes, entries, if_idx; + struct wlan_user_mcc_quota mcc_quota; + int att_id, rc; + + hdd_enter(); + + if (wlan_hdd_validate_context(hdd_ctx)) + return -EINVAL; + + psoc = hdd_ctx->psoc; + if (!psoc) + return -EINVAL; + + if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX, + attr, attr_len, set_mcc_quota_policy)) { + hdd_err("Error parsing attributes"); + return -EINVAL; + } + + cmd_id = QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_TYPE; + if (!tb[cmd_id]) { + hdd_err("Quota type not specified"); + return -EINVAL; + } + quota_type = nla_get_u32(tb[cmd_id]); + if (quota_type != QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_FIXED && + quota_type != QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR) { + hdd_err("Quota type is not valid %u", quota_type); + return -EINVAL; + } + + if (quota_type == QCA_WLAN_VENDOR_MCC_QUOTA_TYPE_CLEAR) { + /* Remove quota, enable MCC adaptive scheduling */ + if (wlan_hdd_set_mcc_adaptive_sched(hdd_ctx->psoc, true)) + return -EAGAIN; + mcc_quota.op_mode = QDF_MAX_NO_OF_MODE; + mcc_quota.vdev_id = WLAN_UMAC_VDEV_ID_MAX; + ucfg_mlme_set_user_mcc_quota(psoc, &mcc_quota); + return 0; + } + + cmd_id = QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_ENTRIES; + if (!tb[cmd_id]) { + hdd_err("No entries present"); + return -EINVAL; + } + + entries = 0; + nla_for_each_nested(curr_attr, tb[cmd_id], rem_bytes) { + if (entries > 0) { + hdd_debug("Only one entry permitted"); + hdd_debug("Entry (%d) for (%u) is ignored", + entries, nla_type(curr_attr)); + entries++; + continue; + } + rc = wlan_cfg80211_nla_parse_nested(quota_entries, + QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX, + curr_attr, + set_mcc_quota_policy); + if (rc) { + hdd_err("Entry parse error %d", rc); + return -EINVAL; + } + + att_id = QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_IFINDEX; + if (!quota_entries[att_id]) { + hdd_err("if_index not specified"); + return -EINVAL; + } + + if_idx = nla_get_u32(quota_entries[att_id]); + if (if_idx == 0) { + hdd_debug("Invalid if_index"); + return -EINVAL; + } + if_adapter = hdd_get_adapter_by_ifindex(hdd_ctx, if_idx); + + if (!if_adapter) { + hdd_err("interface (%u) not found", if_idx); + return -EINVAL; + } + + if (wlan_hdd_validate_vdev_id(if_adapter->vdev_id)) + return -EINVAL; + + att_id = QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_CHAN_TIME_PERCENTAGE; + if (!quota_entries[att_id]) { + hdd_err("Quota not specified"); + return -EINVAL; + } + mcc_quota.quota = nla_get_u32(quota_entries[att_id]); + mcc_quota.vdev_id = if_adapter->vdev_id; + mcc_quota.op_mode = if_adapter->device_mode; + + entries++; + } + + if (entries == 0) { + hdd_err("No entries found"); + return -EINVAL; + } + + ucfg_mlme_set_user_mcc_quota(psoc, &mcc_quota); + + duty_cycle = ucfg_mlme_get_user_mcc_quota_percentage(psoc); + + if (duty_cycle == 0) { + hdd_debug("Quota will be configured when MCC scenario exists"); + return 0; + } + + if (wlan_hdd_set_mcc_adaptive_sched(hdd_ctx->psoc, false)) + return -EAGAIN; + + if (wlan_hdd_send_mcc_vdev_quota(if_adapter, duty_cycle)) + return -EINVAL; + + return 0; +} + +int wlan_hdd_apply_user_mcc_quota(struct hdd_adapter *adapter) +{ + struct hdd_context *hdd_ctx; + uint32_t quota_val; + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (!hdd_ctx) + return -EINVAL; + + quota_val = + ucfg_mlme_get_user_mcc_quota_percentage(hdd_ctx->psoc); + + if (quota_val == 0) { + hdd_debug("no mcc/quota for mode %d, vdev_id : %u", + adapter->device_mode, adapter->vdev_id); + return 0; + } + + if (wlan_hdd_set_mcc_adaptive_sched(hdd_ctx->psoc, false)) + return 0; + + if (wlan_hdd_send_mcc_vdev_quota(adapter, quota_val)) { + hdd_info("Could not send quota"); + wlan_hdd_set_mcc_adaptive_sched(hdd_ctx->psoc, true); + } + + return 0; +} diff --git a/core/hdd/src/wlan_hdd_mcc_quota.h b/core/hdd/src/wlan_hdd_mcc_quota.h new file mode 100644 index 0000000000..0c5972141c --- /dev/null +++ b/core/hdd/src/wlan_hdd_mcc_quota.h @@ -0,0 +1,95 @@ +/* + * 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 + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** + * DOC: wlan_hdd_mcc_quota.h + * + * WLAN Host Device Driver MCC quota feature interface definitions + * + */ +#ifndef WLAN_HDD_MCC_QUOTA_H +#define WLAN_HDD_MCC_QUOTA_H +#include "qdf_types.h" +#include "qdf_status.h" +#include "qca_vendor.h" +#include + +struct hdd_context; +struct hdd_adapter; +struct wlan_objmgr_psoc; + +#ifdef WLAN_FEATURE_MCC_QUOTA +extern const struct nla_policy +set_mcc_quota_policy[QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX + 1]; + +/** + * wlan_hdd_set_mcc_adaptive_sched: Enable or disable MCC adaptive scheduling + * @hdd_ctx: HDD context + * @enable: Enable (true) or disable (false) + * + * Return: 0 for success, Non zero failure code for errors + */ +int wlan_hdd_set_mcc_adaptive_sched(struct wlan_objmgr_psoc *psoc, + bool enable); + +/** + * wlan_hdd_cfg80211_set_mcc_quota() - Set user MCC quota to the target + * @wiphy: Wireless info object + * @wdev: Wireless dev object + * @attr: Command attributes + * @attr_len: Length of attributes + * + * Return: 0 on success, negative errno on failure + */ +int wlan_hdd_cfg80211_set_mcc_quota(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *attr, + int attr_len); + +#define FEATURE_MCC_QUOTA_VENDOR_COMMANDS \ +{ \ + .info.vendor_id = QCA_NL80211_VENDOR_ID, \ + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_MCC_QUOTA, \ + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,\ + .doit = wlan_hdd_cfg80211_set_mcc_quota, \ + vendor_command_policy(set_mcc_quota_policy, \ + QCA_WLAN_VENDOR_ATTR_MCC_QUOTA_MAX) \ +}, + +/** + * wlan_hdd_apply_user_mcc_quota() - Apply the user MCC quota to the target + * @adapter: pointer to HDD adapter object + * + * Return: 0 on succcess, errno for error + */ +int wlan_hdd_apply_user_mcc_quota(struct hdd_adapter *adapter); +#else /* WLAN_FEATURE_MCC_QUOTA */ +#define FEATURE_MCC_QUOTA_VENDOR_COMMANDS + +static inline int wlan_hdd_apply_user_mcc_quota(struct hdd_adapter *adapter) +{ + return 0; +} + +static inline int wlan_hdd_set_mcc_adaptive_sched(struct wlan_objmgr_psoc *psoc, + bool enable) +{ + return 0; +} +#endif /* WLAN_FEATURE_MCC_QUOTA */ +#endif /* WLAN_HDD_MCC_QUOTA_H */ diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index e749e9a87c..9dbaed644f 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -6650,6 +6650,26 @@ cm_csr_connect_done_ind(struct wlan_objmgr_vdev *vdev, return -EAGAIN; } } + } else { + QDF_STATUS status = QDF_STATUS_SUCCESS; + uint32_t quota_val; + + quota_val = + ucfg_mlme_get_user_mcc_quota_percentage(mac_ctx->psoc); + + if (quota_val) { + if (enable_mcc_adaptive_sch) { + policy_mgr_set_dynamic_mcc_adaptive_sch( + mac_ctx->psoc, false); + status = sme_set_mas(false); + } + if (status == QDF_STATUS_SUCCESS) + sme_cli_set_command(wlan_vdev_get_id(vdev), + WMA_VDEV_MCC_SET_TIME_QUOTA, + quota_val, VDEV_CMD); + } else { + sme_debug("no applicable user mcc/quota"); + } } /*