diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 371ec58a7b..91b2386b12 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -1053,6 +1053,20 @@ QDF_STATUS wlan_mlme_get_fils_enabled_info(struct wlan_objmgr_psoc *psoc, QDF_STATUS wlan_mlme_set_fils_enabled_info(struct wlan_objmgr_psoc *psoc, bool value); +/** + * wlan_mlme_set_primary_interface() - Set the primary iface id for driver + * @psoc: pointer to psoc object + * @value: value that needs to be set from the caller + * + * When a vdev is set as primary then based on the dual sta policy + * "qca_wlan_concurrent_sta_policy_config" mcc preference and roaming has + * to be enabled on the primary vdev + * + * Return: QDF Status + */ +QDF_STATUS wlan_mlme_set_primary_interface(struct wlan_objmgr_psoc *psoc, + uint8_t value); + /** * wlan_mlme_get_tl_delayed_trgr_frm_int() - Get delay interval(in ms) * of UAPSD auto trigger diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 6578c6f3b9..4a80703ccd 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1280,9 +1280,12 @@ struct wlan_mlme_ratemask { * struct dual_sta_policy - Concurrent STA policy configuration * @concurrent_sta_policy: Possible values are defined in enum * qca_wlan_concurrent_sta_policy_config + * @primary_vdev_id: specified iface is the primary STA iface, say 0 means + * vdev 0 is acting as primary interface */ struct dual_sta_policy { uint8_t concurrent_sta_policy; + uint8_t primary_vdev_id; }; /* struct wlan_mlme_generic - Generic CFG config items diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index dba055ea38..3328ead3ca 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -1961,6 +1961,26 @@ QDF_STATUS ucfg_mlme_set_fils_enabled_info(struct wlan_objmgr_psoc *psoc, return wlan_mlme_set_fils_enabled_info(psoc, value); } +/** + * ucfg_mlme_set_primary_interface() - Set primary STA iface id + * + * @psoc: pointer to psoc object + * @value: value that needs to be set from the caller + * + * When a vdev is set as primary then based on the dual sta policy + * "qca_wlan_concurrent_sta_policy_config" mcc preference and roaming has + * to be enabled on the primary vdev + * + * Return: QDF_STATUS_SUCCESS or QDF_STATUS_FAILURE + */ +static inline +QDF_STATUS ucfg_mlme_set_primary_interface(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + return wlan_mlme_set_primary_interface(psoc, value); +} + + /** * ucfg_mlme_set_enable_bcast_probe_rsp() - Set enable bcast probe resp info * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/src/wlan_mlme_api.c b/components/mlme/dispatcher/src/wlan_mlme_api.c index c0f6d95736..34ca729a95 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -2411,6 +2411,18 @@ QDF_STATUS wlan_mlme_set_fils_enabled_info(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS wlan_mlme_set_primary_interface(struct wlan_objmgr_psoc *psoc, + uint8_t value) +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj = mlme_get_psoc_ext_obj(psoc); + + if (!mlme_obj) + return QDF_STATUS_E_FAILURE; + + mlme_obj->cfg.gen.dual_sta_policy.primary_vdev_id = value; + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wlan_mlme_set_enable_bcast_probe_rsp(struct wlan_objmgr_psoc *psoc, bool value) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 414cb870a9..19ddf75cee 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -7001,7 +7001,8 @@ const struct nla_policy wlan_hdd_wifi_config_policy[ [QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL] = {.type = NLA_S32 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS] = {.type = NLA_U8 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS] = {.type = NLA_U8 }, - + [QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY] = { + .type = NLA_U8 }, }; static const struct nla_policy @@ -8623,6 +8624,33 @@ static int hdd_config_disable_fils(struct hdd_adapter *adapter, return qdf_status_to_os_return(status); } +static int hdd_set_primary_interface(struct hdd_adapter *adapter, + const struct nlattr *attr) +{ + struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + bool is_set_primary_iface; + QDF_STATUS status; + uint8_t primary_vdev_id; + + /* ignore unless in STA mode */ + if (adapter->device_mode != QDF_STA_MODE) + return 0; + + is_set_primary_iface = nla_get_u8(attr); + + primary_vdev_id = is_set_primary_iface ? adapter->vdev_id : WLAN_UMAC_VDEV_ID_MAX; + hdd_debug("Primary interface: %d", primary_vdev_id); + + status = ucfg_mlme_set_primary_interface(hdd_ctx->psoc, + primary_vdev_id); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("could not set primary interface, %d", status); + return -EINVAL; + } + + return 0; +} + static int hdd_config_rsn_ie(struct hdd_adapter *adapter, const struct nlattr *attr) { @@ -8976,6 +9004,8 @@ static const struct independent_setters independent_setters[] = { hdd_config_power}, {QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE, hdd_config_udp_qos_upgrade_threshold}, + {QCA_WLAN_VENDOR_ATTR_CONFIG_CONCURRENT_STA_PRIMARY, + hdd_set_primary_interface}, }; #ifdef WLAN_FEATURE_ELNA