diff --git a/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h b/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h
index d5f29894fc67..b7c5c063edc3 100644
--- a/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h
+++ b/components/action_oui/dispatcher/inc/wlan_action_oui_public_struct.h
@@ -89,7 +89,8 @@
* @ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN: connect in 1x1 & disable diversity gain
* @ACTION_OUI_DISABLE_AGGRESSIVE_TX: disable aggressive TX in firmware
* @ACTION_OUI_FORCE_MAX_NSS: Force Max NSS connection with few IOT APs
- * @ACTION_OUI_MAXIMUM_ID: maximun number of action oui types
+ * @ACTION_OUI_DISABLE_AGGRESSIVE_EDCA: disable aggressive EDCA with the ap
+ * @ACTION_OUI_MAXIMUM_ID: maximum number of action oui types
*/
enum action_oui_id {
ACTION_OUI_CONNECT_1X1 = 0,
@@ -100,6 +101,7 @@ enum action_oui_id {
ACTION_OUI_CONNECT_1X1_WITH_1_CHAIN = 5,
ACTION_OUI_DISABLE_AGGRESSIVE_TX = 6,
ACTION_OUI_FORCE_MAX_NSS = 7,
+ ACTION_OUI_DISABLE_AGGRESSIVE_EDCA = 8,
ACTION_OUI_MAXIMUM_ID
};
diff --git a/components/mlme/core/inc/wlan_mlme_main.h b/components/mlme/core/inc/wlan_mlme_main.h
index c91664273e8e..16fe2aae7216 100644
--- a/components/mlme/core/inc/wlan_mlme_main.h
+++ b/components/mlme/core/inc/wlan_mlme_main.h
@@ -118,6 +118,7 @@ struct wlan_mlme_roam {
* @vdev_start_failed: flag to indicate that vdev start failed.
* @connection_fail: flag to indicate connection failed
* @cac_required_for_new_channel: if CAC is required for new channel
+ * @follow_ap_edca: if true, it is forced to follow the AP's edca.
* @assoc_type: vdev associate/reassociate type
* @dynamic_cfg: current configuration of nss, chains for vdev.
* @ini_cfg: Max configuration of nss, chains supported for vdev.
@@ -136,6 +137,7 @@ struct mlme_legacy_priv {
bool vdev_start_failed;
bool connection_fail;
bool cac_required_for_new_channel;
+ bool follow_ap_edca;
enum vdev_assoc_type assoc_type;
struct wlan_mlme_nss_chains dynamic_cfg;
struct wlan_mlme_nss_chains ini_cfg;
@@ -371,6 +373,23 @@ void mlme_set_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev,
*/
void mlme_free_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev);
+/**
+ * mlme_set_follow_ap_edca_flag() - Set follow ap's edca flag
+ * @vdev: vdev pointer
+ * @flag: carries if following ap's edca is true or not.
+ *
+ * Return: None
+ */
+void mlme_set_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev, bool flag);
+
+/**
+ * mlme_get_follow_ap_edca_flag() - Get follow ap's edca flag
+ * @vdev: vdev pointer
+ *
+ * Return: value of follow_ap_edca
+ */
+bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev);
+
/**
* mlme_get_peer_disconnect_ies() - Get diconnect IEs from vdev object
* @vdev: vdev pointer
diff --git a/components/mlme/core/src/wlan_mlme_main.c b/components/mlme/core/src/wlan_mlme_main.c
index 26d907ddf05e..c60995d2a97e 100644
--- a/components/mlme/core/src/wlan_mlme_main.c
+++ b/components/mlme/core/src/wlan_mlme_main.c
@@ -2587,6 +2587,32 @@ struct wlan_ies *mlme_get_peer_disconnect_ies(struct wlan_objmgr_vdev *vdev)
return &mlme_priv->peer_disconnect_ies;
}
+void mlme_set_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev, bool flag)
+{
+ struct mlme_legacy_priv *mlme_priv;
+
+ mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+ if (!mlme_priv) {
+ mlme_legacy_err("vdev legacy private object is NULL");
+ return;
+ }
+
+ mlme_priv->follow_ap_edca = flag;
+}
+
+bool mlme_get_follow_ap_edca_flag(struct wlan_objmgr_vdev *vdev)
+{
+ struct mlme_legacy_priv *mlme_priv;
+
+ mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+ if (!mlme_priv) {
+ mlme_legacy_err("vdev legacy private object is NULL");
+ return false;
+ }
+
+ return mlme_priv->follow_ap_edca;
+}
+
void mlme_set_peer_pmf_status(struct wlan_objmgr_peer *peer,
bool is_pmf_enabled)
{
diff --git a/core/hdd/inc/hdd_config.h b/core/hdd/inc/hdd_config.h
index 8c9cbd483f75..2fd6465c4d54 100644
--- a/core/hdd/inc/hdd_config.h
+++ b/core/hdd/inc/hdd_config.h
@@ -1169,7 +1169,42 @@ struct dhcp_server {
"FFFFFF 00 2A F85971000000 E0 50 FFFFFF 00 2A 14ABC5000000 E0 50", \
"Used to specify action OUIs to disable aggressive TX")
- /* End of action oui inis */
+/*
+ *
+ * gActionOUIDisableAggressiveEDCA - Used to specify action OUIs to control
+ * EDCA configuration when join the candidate AP
+ *
+ * @Default: NULL
+ * Note: User should strictly add new action OUIs at the end of this
+ * default value.
+ *
+ * This ini is used to specify AP OUIs. The station's EDCA should follow the
+ * APs' when connecting to those AP, even if the gEnableEdcaParams is set.
+ * For example, it follows the AP's EDCA whose OUI is 0050F2 with the
+ * following setting:
+ * gActionOUIDisableAggressiveEDCA=0050F2 00 01
+ * Explain: 0050F2: OUI
+ * 00: data length is 0
+ * 01: info mask, only OUI present in Info mask
+ * Refer to gEnableActionOUI for more detail about the format.
+ *
+ * Related: gEnableEdcaParams, gEnableActionOUI
+ *
+ * Supported Feature: Action OUIs
+ *
+ * Usage: External
+ *
+ *
+ */
+#define CFG_ACTION_OUI_DISABLE_AGGRESSIVE_EDCA CFG_INI_STRING( \
+ "gActionOUIDisableAggressiveEDCA", \
+ 0, \
+ ACTION_OUI_MAX_STR_LEN, \
+ "", \
+ "Used to specify action OUIs to control edca configuration")
+
+/* End of action oui inis */
+
#ifdef ENABLE_MTRACE_LOG
/*
*
@@ -1451,6 +1486,7 @@ enum host_log_level {
CFG(CFG_ACTION_OUI_ITO_EXTENSION) \
CFG(CFG_ACTION_OUI_DISABLE_AGGRESSIVE_TX) \
CFG(CFG_ACTION_OUI_FORCE_MAX_NSS) \
+ CFG(CFG_ACTION_OUI_DISABLE_AGGRESSIVE_EDCA) \
CFG(CFG_ACTION_OUI_SWITCH_TO_11N_MODE) \
CFG(CFG_ADVERTISE_CONCURRENT_OPERATION) \
CFG(CFG_BUG_ON_REINIT_FAILURE) \
diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c
index f71c21fcc25b..0c0e39f57051 100644
--- a/core/hdd/src/wlan_hdd_main.c
+++ b/core/hdd/src/wlan_hdd_main.c
@@ -10185,7 +10185,12 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx)
ACTION_OUI_MAX_STR_LEN);
qdf_str_lcopy(config->action_oui_str[ACTION_OUI_FORCE_MAX_NSS],
cfg_get(psoc, CFG_ACTION_OUI_FORCE_MAX_NSS),
- ACTION_OUI_MAX_STR_LEN);
+ ACTION_OUI_MAX_STR_LEN);
+ qdf_str_lcopy(config->action_oui_str
+ [ACTION_OUI_DISABLE_AGGRESSIVE_EDCA],
+ cfg_get(psoc,
+ CFG_ACTION_OUI_DISABLE_AGGRESSIVE_EDCA),
+ ACTION_OUI_MAX_STR_LEN);
config->enable_rtt_support = cfg_get(psoc, CFG_ENABLE_RTT_SUPPORT);
config->is_unit_test_framework_enabled =
cfg_get(psoc, CFG_ENABLE_UNIT_TEST_FRAMEWORK);
diff --git a/core/mac/src/pe/sch/sch_beacon_process.c b/core/mac/src/pe/sch/sch_beacon_process.c
index 70713603a597..ced80cf7fc53 100644
--- a/core/mac/src/pe/sch/sch_beacon_process.c
+++ b/core/mac/src/pe/sch/sch_beacon_process.c
@@ -1185,6 +1185,7 @@ sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca,
struct pe_session *session)
{
uint8_t i;
+ bool follow_ap_edca;
#ifdef FEATURE_WLAN_DIAG_SUPPORT
host_log_qos_edca_pkt_type *log_ptr = NULL;
#endif /* FEATURE_WLAN_DIAG_SUPPORT */
@@ -1194,6 +1195,8 @@ sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca,
return QDF_STATUS_E_FAILURE;
}
+ follow_ap_edca = mlme_get_follow_ap_edca_flag(session->vdev);
+
pe_debug("Updating parameter set count: Old %d ---> new %d",
session->gLimEdcaParamSetCount, edca->qosInfo.count);
@@ -1203,7 +1206,7 @@ sch_beacon_edca_process(struct mac_context *mac, tSirMacEdcaParamSetIE *edca,
session->gLimEdcaParams[QCA_WLAN_AC_VI] = edca->acvi;
session->gLimEdcaParams[QCA_WLAN_AC_VO] = edca->acvo;
- if (mac->mlme_cfg->edca_params.enable_edca_params) {
+ if (mac->mlme_cfg->edca_params.enable_edca_params && !follow_ap_edca) {
session->gLimEdcaParams[QCA_WLAN_AC_VO].aci.aifsn =
mac->mlme_cfg->edca_params.edca_ac_vo.vo_aifs;
session->gLimEdcaParams[QCA_WLAN_AC_VI].aci.aifsn =
diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c
index c518b4af9adb..217963815468 100644
--- a/core/sme/src/csr/csr_api_roam.c
+++ b/core/sme/src/csr/csr_api_roam.c
@@ -15531,6 +15531,8 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId,
enum csr_akm_type akm;
bool force_max_nss;
uint8_t ap_nss;
+ struct wlan_objmgr_vdev *vdev;
+ bool follow_ap_edca;
if (!pSession) {
sme_err("session %d not found", sessionId);
@@ -15691,6 +15693,18 @@ QDF_STATUS csr_send_join_req_msg(struct mac_context *mac, uint32_t sessionId,
if (pSession->nss == 1)
pSession->supported_nss_1x1 = true;
+ follow_ap_edca = ucfg_action_oui_search(mac->psoc,
+ &vendor_ap_search_attr,
+ ACTION_OUI_DISABLE_AGGRESSIVE_EDCA);
+
+ vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
+ sessionId,
+ WLAN_LEGACY_MAC_ID);
+ if (vdev) {
+ mlme_set_follow_ap_edca_flag(vdev, follow_ap_edca);
+ wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+ }
+
is_vendor_ap_present =
ucfg_action_oui_search(mac->psoc,
&vendor_ap_search_attr,