diff --git a/components/mlme/dispatcher/inc/wlan_mlme_api.h b/components/mlme/dispatcher/inc/wlan_mlme_api.h index 5d6a58dbdc..371ec58a7b 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_api.h @@ -270,6 +270,16 @@ QDF_STATUS wlan_mlme_get_band_capability(struct wlan_objmgr_psoc *psoc, QDF_STATUS wlan_mlme_set_band_capability(struct wlan_objmgr_psoc *psoc, uint32_t band_capability); +/** + * wlan_mlme_set_dual_sta_policy() - Set the dual sta config + * @psoc: pointer to psoc object + * @dual_sta_config: Value to be set from the caller + * + * Return: QDF Status + */ +QDF_STATUS wlan_mlme_set_dual_sta_policy(struct wlan_objmgr_psoc *psoc, + uint8_t dual_sta_config); + /** * wlan_mlme_get_prevent_link_down() - Get the prevent link down config * @psoc: pointer to psoc object diff --git a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h index 30cbcbc23d..6578c6f3b9 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_public_struct.h @@ -1276,6 +1276,15 @@ struct wlan_mlme_ratemask { uint32_t higher32_2; }; +/** + * struct dual_sta_policy - Concurrent STA policy configuration + * @concurrent_sta_policy: Possible values are defined in enum + * qca_wlan_concurrent_sta_policy_config + */ +struct dual_sta_policy { + uint8_t concurrent_sta_policy; +}; + /* struct wlan_mlme_generic - Generic CFG config items * * @band_capability: HW Band Capability - Both or 2.4G only or 5G only @@ -1324,6 +1333,7 @@ struct wlan_mlme_ratemask { * @monitor_mode_concurrency: Monitor mode concurrency supported * @ocv_support: FW supports OCV or not * @wds_mode: wds mode supported + * @dual_sta_policy_cfg: Dual STA policies configuration */ struct wlan_mlme_generic { uint32_t band_capability; @@ -1369,6 +1379,7 @@ struct wlan_mlme_generic { enum monitor_mode_concurrency monitor_mode_concurrency; bool ocv_support; enum wlan_wds_mode wds_mode; + struct dual_sta_policy dual_sta_policy; }; /* diff --git a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h index 18b083f1ca..dba055ea38 100644 --- a/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h +++ b/components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h @@ -255,6 +255,21 @@ QDF_STATUS ucfg_mlme_set_band_capability(struct wlan_objmgr_psoc *psoc, return wlan_mlme_set_band_capability(psoc, band_capability); } +/** + * ucfg_mlme_set_dual_sta_policy() - Configures the Concurrent STA policy + * value + * @psoc: pointer to psoc object + * @dual_sta_config: Concurrent STA policy configuration value + * + * Return: QDF Status + */ +static inline +QDF_STATUS ucfg_mlme_set_dual_sta_policy(struct wlan_objmgr_psoc *psoc, + uint8_t dual_sta_config) +{ + return wlan_mlme_set_dual_sta_policy(psoc, dual_sta_config); +} + /** * ucfg_mlme_get_prevent_link_down() - Get the prevent link down config * @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 1fa7e06822..c0f6d95736 100644 --- a/components/mlme/dispatcher/src/wlan_mlme_api.c +++ b/components/mlme/dispatcher/src/wlan_mlme_api.c @@ -229,6 +229,22 @@ QDF_STATUS wlan_mlme_set_band_capability(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_SUCCESS; } +QDF_STATUS wlan_mlme_set_dual_sta_policy(struct wlan_objmgr_psoc *psoc, + uint8_t dual_sta_config) + +{ + struct wlan_mlme_psoc_ext_obj *mlme_obj; + + mlme_obj = mlme_get_psoc_ext_obj(psoc); + if (!mlme_obj) + return QDF_STATUS_E_FAILURE; + + mlme_obj->cfg.gen.dual_sta_policy.concurrent_sta_policy = + dual_sta_config; + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS wlan_mlme_get_prevent_link_down(struct wlan_objmgr_psoc *psoc, bool *prevent_link_down) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 654c6aba1e..414cb870a9 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -12268,8 +12268,8 @@ QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX + 1] = { */ static int __wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy, - struct wireless_dev *wdev, - const void *data, int data_len) + struct wireless_dev *wdev, + const void *data, int data_len) { struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -12342,9 +12342,10 @@ __wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy, * in Scanning. * Return: 0 on success; errno on failure */ -static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy, - struct wireless_dev *wdev, - const void *data, int data_len) +static int +wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, + int data_len) { int errno; struct osif_vdev_sync *vdev_sync; @@ -12361,6 +12362,100 @@ static int wlan_hdd_cfg80211_sta_roam_policy(struct wiphy *wiphy, return errno; } +const struct nla_policy +wlan_hdd_set_dual_sta_policy[ +QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX + 1] = { + [QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG] = {.type = NLA_U8 }, +}; + +/** + * __wlan_hdd_cfg80211_dual_sta_policy() - Wrapper to configure the concurrent + * session policies + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Configure the concurrent session policies when multiple STA ifaces are + * (getting) active. + * Return: 0 on success; errno on failure + */ +static int __wlan_hdd_cfg80211_dual_sta_policy(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + struct hdd_context *hdd_ctx = wiphy_priv(wiphy); + struct nlattr *tb[ + QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX + 1]; + QDF_STATUS status; + uint8_t dual_sta_config = + QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED; + + if (wlan_hdd_validate_context(hdd_ctx)) { + hdd_err("Invalid hdd context"); + return -EINVAL; + } + + if (wlan_cfg80211_nla_parse(tb, + QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX, + data, data_len, + wlan_hdd_set_dual_sta_policy)) { + hdd_err("nla_parse failed"); + return -EINVAL; + } + + if (!tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG]) { + hdd_err("sta policy config attribute not present"); + return -EINVAL; + } + + dual_sta_config = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_CONFIG]); + hdd_debug("Concurrent STA policy : %d", dual_sta_config); + + if (dual_sta_config > QCA_WLAN_CONCURRENT_STA_POLICY_UNBIASED) + return -EINVAL; + + status = ucfg_mlme_set_dual_sta_policy(hdd_ctx->psoc, dual_sta_config); + if (QDF_IS_STATUS_ERROR(status)) { + hdd_err("failed to set MLME dual sta config"); + return -EINVAL; + } + + return 0; +} + +/** + * wlan_hdd_cfg80211_dual_sta_policy() - Wrapper to configure the concurrent + * session policies + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Configure the concurrent session policies when multiple STA ifaces are + * (getting) active. + * Return: 0 on success; errno on failure + */ +static int wlan_hdd_cfg80211_dual_sta_policy(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int errno; + struct osif_vdev_sync *vdev_sync; + + errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync); + if (errno) + return errno; + + errno = __wlan_hdd_cfg80211_dual_sta_policy(wiphy, wdev, data, + data_len); + + osif_vdev_sync_op_stop(vdev_sync); + + return errno; +} + #ifdef FEATURE_WLAN_CH_AVOID /** * __wlan_hdd_cfg80211_avoid_freq() - ask driver to restart SAP if SAP @@ -15788,6 +15883,19 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { wlan_hdd_set_sta_roam_config_policy, QCA_WLAN_VENDOR_ATTR_STA_CONNECT_ROAM_POLICY_MAX) }, + + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = + QCA_NL80211_VENDOR_SUBCMD_CONCURRENT_MULTI_STA_POLICY, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wlan_hdd_cfg80211_dual_sta_policy, + vendor_command_policy( + wlan_hdd_set_dual_sta_policy, + QCA_WLAN_VENDOR_ATTR_CONCURRENT_STA_POLICY_MAX) + }, + #ifdef FEATURE_WLAN_CH_AVOID { .info.vendor_id = QCA_NL80211_VENDOR_ID,