ソースを参照

Merge 1aa3a6c8e9f2e200fed6b18f9af8a21bf73fbbcd on remote branch

Change-Id: Ia9066539c2c26d9eff3feb5f3cd1d2aa281a4570
Linux Build Service Account 1 年間 前
コミット
19ebe47c52
45 ファイル変更1443 行追加414 行削除
  1. 5 0
      Kbuild
  2. 12 0
      Kconfig
  3. 13 0
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_ucfg.h
  4. 162 8
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
  5. 26 3
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
  6. 7 0
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_ucfg.c
  7. 2 0
      components/mlme/core/src/wlan_mlme_main.c
  8. 3 0
      components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c
  9. 27 0
      components/mlme/dispatcher/inc/cfg_mlme_sta.h
  10. 3 3
      components/mlme/dispatcher/inc/cfg_mlme_timeout.h
  11. 14 0
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  12. 2 0
      components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
  13. 10 0
      components/mlme/dispatcher/src/wlan_mlme_api.c
  14. 22 20
      components/tdls/core/src/wlan_tdls_ct.c
  15. 33 0
      components/tdls/core/src/wlan_tdls_main.c
  16. 2 0
      components/tdls/core/src/wlan_tdls_main.h
  17. 0 9
      components/tdls/core/src/wlan_tdls_peer.c
  18. 19 0
      components/tdls/dispatcher/inc/wlan_tdls_api.h
  19. 37 0
      components/tdls/dispatcher/src/wlan_tdls_api.c
  20. 41 18
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  21. 2 0
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  22. 2 0
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h
  23. 68 0
      components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h
  24. 158 9
      components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c
  25. 5 1
      components/wmi/src/wmi_unified_roam_tlv.c
  26. 12 0
      configs/config_to_feature.h
  27. 2 0
      configs/default_defconfig
  28. 2 0
      configs/pineapple_gki_kiwi-v2_defconfig
  29. 2 0
      configs/sun_gki_kiwi-v2_defconfig
  30. 12 1
      core/hdd/src/wlan_hdd_cfg80211.c
  31. 2 2
      core/mac/inc/qwlan_version.h
  32. 26 0
      core/mac/src/cfg/cfgUtil/dot11f.frms
  33. 20 2
      core/mac/src/include/dot11f.h
  34. 11 1
      core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
  35. 189 3
      core/mac/src/pe/lim/lim_process_sme_req_messages.c
  36. 48 9
      core/mac/src/pe/lim/lim_process_tdls.c
  37. 17 0
      core/mac/src/pe/lim/lim_utils.h
  38. 13 1
      core/mac/src/pe/sch/sch_beacon_process.c
  39. 316 246
      core/mac/src/sys/legacy/src/utils/src/dot11f.c
  40. 3 2
      core/mac/src/sys/legacy/src/utils/src/parser_api.c
  41. 28 45
      core/sme/src/common/sme_power_save.c
  42. 2 0
      core/wma/inc/wma.h
  43. 59 29
      core/wma/src/wma_data.c
  44. 1 2
      core/wma/src/wma_dev_if.c
  45. 3 0
      core/wma/src/wma_main.c

+ 5 - 0
Kbuild

@@ -4072,6 +4072,9 @@ ccflags-$(CONFIG_FEATURE_WLAN_AP_AP_ACS_OPTIMIZE) += -DFEATURE_WLAN_AP_AP_ACS_OP
 #Enable 4address scheme
 ccflags-$(CONFIG_FEATURE_WLAN_STA_4ADDR_SCHEME) += -DFEATURE_WLAN_STA_4ADDR_SCHEME
 
+#Optimize GC connection speed by skipping JOIN
+ccflags-$(CONFIG_FEATURE_WLAN_GC_SKIP_JOIN) += -DFEATURE_WLAN_GC_SKIP_JOIN
+
 #enable MDM/SDX special config
 ccflags-$(CONFIG_MDM_PLATFORM) += -DMDM_PLATFORM
 
@@ -4310,6 +4313,8 @@ ccflags-$(CONFIG_DP_WAR_VALIDATE_RX_ERR_MSDU_COOKIE) += -DDP_WAR_VALIDATE_RX_ERR
 ccflags-$(CONFIG_WLAN_DP_SRNG_USAGE_WM_TRACKING) += -DWLAN_DP_SRNG_USAGE_WM_TRACKING
 ccflags-$(CONFIG_WLAN_FEATURE_DP_CFG_EVENT_HISTORY) += -DWLAN_FEATURE_DP_CFG_EVENT_HISTORY
 ccflags-$(CONFIG_WLAN_DP_VDEV_NO_SELF_PEER) += -DWLAN_DP_VDEV_NO_SELF_PEER
+ccflags-$(CONFIG_DP_RX_MSDU_DONE_FAIL_HISTORY) += -DDP_RX_MSDU_DONE_FAIL_HISTORY
+ccflags-$(CONFIG_DP_RX_PEEK_MSDU_DONE_WAR) += -DDP_RX_PEEK_MSDU_DONE_WAR
 
 # Enable Low latency
 ccflags-$(CONFIG_WLAN_FEATURE_LL_MODE) += -DWLAN_FEATURE_LL_MODE

+ 12 - 0
Kconfig

@@ -1341,6 +1341,10 @@ config WLAN_FEATURE_SAP_ACS_OPTIMIZE
 	bool "Enable WLAN_FEATURE_SAP_ACS_OPTIMIZE"
 	default n
 
+config FEATURE_WLAN_GC_SKIP_JOIN
+	bool "enable CONFIG_FEATURE_WLAN_GC_SKIP_JOIN"
+	default n
+
 config WLAN_FEATURE_SARV1_TO_SARV2
 	bool "Enable conversion of SAR v1 to v2 feature"
 	default n
@@ -2041,5 +2045,13 @@ config DP_LEGACY_MODE_CSM_DEFAULT_DISABLE
 
 endif
 
+config DP_RX_MSDU_DONE_FAIL_HISTORY
+	bool "Enable DP_RX_MSDU_DONE_FAIL_HISTORY"
+	default n
+
+config DP_RX_PEEK_MSDU_DONE_WAR
+	bool "Enable DP_RX_PEEK_MSDU_DONE_WAR"
+	default n
+
 endmenu
 endif # QCA_CLD_WLAN

+ 13 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_ucfg.h

@@ -454,4 +454,17 @@ bool ucfg_policy_mgr_get_vdev_diff_freq_new_conn(struct wlan_objmgr_psoc *psoc,
 						 uint32_t new_freq,
 						 uint8_t *vdev_id);
 
+/**
+ * ucfg_policy_mgr_get_dbs_hw_modes() - to get the DBS HW modes
+ *
+ * @psoc: pointer to psoc
+ * @one_by_one_dbs: 1x1 DBS capability of HW
+ * @two_by_two_dbs: 2x2 DBS capability of HW
+ *
+ * Return: Failure in case of error otherwise success
+ */
+QDF_STATUS ucfg_policy_mgr_get_dbs_hw_modes(struct wlan_objmgr_psoc *psoc,
+					    bool *one_by_one_dbs,
+					    bool *two_by_two_dbs);
+
 #endif //__WLAN_POLICY_MGR_UCFG

+ 162 - 8
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -6941,6 +6941,13 @@ bool policy_mgr_is_mlo_in_mode_emlsr(struct wlan_objmgr_psoc *psoc,
 	uint8_t i, mlo_idx = 0;
 	struct wlan_objmgr_vdev *temp_vdev;
 	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return false;
+	}
 
 	mode_num = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
 							  vdev_id_list,
@@ -6967,6 +6974,27 @@ bool policy_mgr_is_mlo_in_mode_emlsr(struct wlan_objmgr_psoc *psoc,
 
 		wlan_objmgr_vdev_release_ref(temp_vdev, WLAN_POLICY_MGR_ID);
 	}
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (i = 0; i < MAX_NUMBER_OF_DISABLE_LINK; i++) {
+		if (!pm_disabled_ml_links[i].in_use)
+			continue;
+		if (pm_disabled_ml_links[i].mode != PM_STA_MODE)
+			continue;
+		temp_vdev =
+		wlan_objmgr_get_vdev_by_id_from_psoc(
+					psoc, pm_disabled_ml_links[i].vdev_id,
+					WLAN_POLICY_MGR_ID);
+		if (!temp_vdev) {
+			policy_mgr_err("invalid inactive vdev for id %d",
+				       pm_disabled_ml_links[i].vdev_id);
+			continue;
+		}
+		/* Check if existing vdev is eMLSR STA */
+		if (wlan_vdev_mlme_cap_get(temp_vdev, WLAN_VDEV_C_EMLSR_CAP))
+			emlsr_connection = true;
+		wlan_objmgr_vdev_release_ref(temp_vdev, WLAN_POLICY_MGR_ID);
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
 end:
 	if (num_mlo)
 		*num_mlo = mlo_idx;
@@ -8522,6 +8550,45 @@ policy_mgr_is_restart_sap_required_with_mlo_sta(struct wlan_objmgr_psoc *psoc,
 	return restart_required;
 }
 
+/**
+ * policy_mgr_is_new_force_allowed() - Check if the new force command is allowed
+ * @psoc: PSOC object information
+ * @active_link_bitmap: Active link bitmap
+ * @force_inactive_num_bitmap: Force inactive number bitmap
+ * @force_inactive_num: Number of links to be forced inactive
+ *
+ * If ML STA associates in 3-link (2.4 GHz + 5 GHz + 6 GHz), Host sends force
+ * inactive num command between 5 GHz and 6 GHz links to firmware as it's a DBS
+ * RD. This force has to be in effect at all times but any new force active num
+ * command request from the userspace (except for 5 GHz + 6 GHz links) should be
+ * honored. This API checks if the new force command can be allowed.
+ *
+ * Return: True if the new force command is allowed, else False
+ */
+static bool
+policy_mgr_is_new_force_allowed(struct wlan_objmgr_psoc *psoc,
+				uint32_t active_link_bitmap,
+				uint16_t force_inactive_num_bitmap,
+				uint8_t force_inactive_num)
+{
+	uint32_t link_bitmap = 0;
+	uint8_t link_num = 0;
+
+	link_bitmap = ~active_link_bitmap & force_inactive_num_bitmap;
+	if (force_inactive_num_bitmap) {
+		if (!link_bitmap) {
+			policy_mgr_err("New force bitmap not allowed");
+			return false;
+		}
+		link_num = convert_link_bitmap_to_link_ids(link_bitmap,
+							   0, NULL);
+		if (link_num < force_inactive_num)
+			return false;
+	}
+
+	return true;
+}
+
 void policy_mgr_activate_mlo_links_nlink(struct wlan_objmgr_psoc *psoc,
 					 uint8_t session_id, uint8_t num_links,
 					 struct qdf_mac_addr active_link_addr[2])
@@ -8604,10 +8671,17 @@ void policy_mgr_activate_mlo_links_nlink(struct wlan_objmgr_psoc *psoc,
 		}
 		ml_nlink_get_curr_force_state(psoc, vdev, &curr);
 		if (curr.force_inactive_num || curr.force_active_num) {
-			policy_mgr_debug("force num exists with act %d %d don't enter EMLSR mode",
-					 curr.force_active_num,
-					 curr.force_inactive_num);
-			goto done;
+			if (curr.force_inactive_num) {
+				if (!policy_mgr_is_new_force_allowed(
+						psoc, active_link_bitmap,
+						curr.force_inactive_num_bitmap,
+						curr.force_inactive_num)) {
+					policy_mgr_debug("force num exists with act %d %d don't enter EMLSR mode",
+							 curr.force_active_num,
+							 curr.force_inactive_num);
+				goto done;
+				}
+			}
 		}
 		/* If current force inactive bitmap exists, we have to remove
 		 * the new active bitmap from the existing inactive bitmap,
@@ -8643,6 +8717,15 @@ void policy_mgr_activate_mlo_links_nlink(struct wlan_objmgr_psoc *psoc,
 				     reason, mode, 0,
 				     active_link_bitmap, inactive_link_bitmap,
 				     link_ctrl_flags);
+	if (active_link_bitmap)
+		ml_nlink_vendor_command_set_link(
+			psoc, session_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
+
 done:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
 }
@@ -8659,6 +8742,8 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 	struct wlan_objmgr_vdev *vdev;
 	uint8_t *link_mac_addr;
 	bool active_vdev_present = false;
+	uint16_t active_link_bitmap = 0;
+	uint16_t inactive_link_bitmap = 0;
 
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, session_id,
 						    WLAN_POLICY_MGR_ID);
@@ -8692,6 +8777,8 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 					 QDF_MAC_ADDR_SIZE)) {
 				active_vdev_lst[active_vdev_cnt] =
 					wlan_vdev_get_id(tmp_vdev_lst[idx]);
+				active_link_bitmap |=
+				1 << wlan_vdev_get_link_id(tmp_vdev_lst[idx]);
 				active_vdev_cnt++;
 				active_vdev_present = true;
 				policy_mgr_debug("Link address match");
@@ -8700,6 +8787,9 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 		if (!active_vdev_present) {
 			inactive_vdev_lst[inactive_vdev_cnt] =
 					wlan_vdev_get_id(tmp_vdev_lst[idx]);
+			inactive_link_bitmap |=
+			1 << wlan_vdev_get_link_id(tmp_vdev_lst[idx]);
+
 			inactive_vdev_cnt++;
 			policy_mgr_err("No link address match");
 		}
@@ -8732,6 +8822,15 @@ void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 					    MLO_LINK_FORCE_REASON_DISCONNECT,
 					    MLO_LINK_FORCE_MODE_ACTIVE,
 					    active_vdev_cnt, active_vdev_lst);
+	if (active_link_bitmap)
+		ml_nlink_vendor_command_set_link(
+			psoc, session_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
+
 ref_release:
 	for (idx = 0; idx < ml_vdev_cnt; idx++)
 		mlo_release_vdev_ref(tmp_vdev_lst[idx]);
@@ -8758,6 +8857,9 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	uint32_t active_link_bitmap = 0;
+	uint32_t inactive_link_bitmap = 0;
+	bool update_vendor_cmd = false;
 
 	for (idx = 0; idx < num_links; idx++) {
 		if (config_state_list[idx] == 0)
@@ -8803,10 +8905,12 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 				if (config_state_list[link]) {
 					active_vdev_lst[active_vdev_cnt] =
 						wlan_vdev_get_id(vdev_lst[idx]);
+					active_link_bitmap |= 1 << link_id;
 					active_vdev_cnt++;
 				} else {
 					inactive_vdev_lst[inactive_vdev_cnt] =
 						wlan_vdev_get_id(vdev_lst[idx]);
+					inactive_link_bitmap |= 1 << link_id;
 					inactive_vdev_cnt++;
 				}
 			}
@@ -8865,6 +8969,10 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 					MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
 					active_vdev_cnt, active_vdev_lst,
 					inactive_vdev_cnt, inactive_vdev_lst);
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+
 			goto release_ml_vdev_ref;
 		}
 	} else {
@@ -8891,18 +8999,33 @@ policy_mgr_update_mlo_links_based_on_linkid(struct wlan_objmgr_psoc *psoc,
 		 * active vdev count, send single WMI for all active vdevs
 		 * with force mode MLO_LINK_FORCE_MODE_ACTIVE.
 		 */
-		if (active_vdev_cnt && inactive_vdev_cnt)
+		if (active_vdev_cnt && inactive_vdev_cnt) {
 			status = policy_mgr_mlo_sta_set_link_ext(psoc,
 					MLO_LINK_FORCE_REASON_CONNECT,
 					MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
 					active_vdev_cnt, active_vdev_lst,
 					inactive_vdev_cnt, inactive_vdev_lst);
-		else if (active_vdev_cnt && !inactive_vdev_cnt)
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+		} else if (active_vdev_cnt && !inactive_vdev_cnt) {
 			status = policy_mgr_mlo_sta_set_link(psoc,
 					MLO_LINK_FORCE_REASON_DISCONNECT,
 					MLO_LINK_FORCE_MODE_ACTIVE,
 					active_vdev_cnt, active_vdev_lst);
+			if (status == QDF_STATUS_E_PENDING ||
+			    status == QDF_STATUS_SUCCESS)
+				update_vendor_cmd = true;
+		}
 	}
+	if (update_vendor_cmd)
+		ml_nlink_vendor_command_set_link(
+			psoc, vdev_id,
+			LINK_CONTROL_MODE_USER,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_INACTIVE,
+			0, active_link_bitmap,
+			inactive_link_bitmap);
 
 release_ml_vdev_ref:
 	for (idx = 0; idx < ml_vdev_cnt; idx++)
@@ -9032,13 +9155,15 @@ QDF_STATUS policy_mgr_update_active_mlo_num_links(struct wlan_objmgr_psoc *psoc,
 						  uint8_t vdev_id,
 						  uint8_t force_active_cnt)
 {
-	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_vdev *vdev, *tmp_vdev;
 	uint8_t num_ml_sta = 0, num_disabled_ml_sta = 0, num_non_ml = 0;
 	uint8_t num_enabled_ml_sta = 0, conn_count;
 	uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint16_t link_bitmap = 0;
+	uint8_t i;
 
 	if (policy_mgr_is_emlsr_sta_concurrency_present(psoc)) {
 		policy_mgr_debug("Concurrency exists, cannot enter EMLSR mode");
@@ -9174,8 +9299,33 @@ set_link:
 					     MLO_LINK_FORCE_MODE_ACTIVE_NUM,
 					     num_ml_sta, ml_sta_vdev_lst,
 					     force_active_cnt);
-	if (QDF_IS_STATUS_SUCCESS(status))
+	if (QDF_IS_STATUS_SUCCESS(status)) {
 		policy_mgr_debug("vdev %d: link enable allowed", vdev_id);
+		for (i = 0; i < num_ml_sta; i++) {
+			if (i >= force_active_cnt)
+				break;
+			tmp_vdev = wlan_objmgr_get_vdev_by_id_from_psoc(
+				psoc, ml_sta_vdev_lst[i],
+				WLAN_POLICY_MGR_ID);
+			if (!tmp_vdev) {
+				policy_mgr_err("vdev not found for vdev_id %d ",
+					       ml_sta_vdev_lst[i]);
+				continue;
+			}
+
+			link_bitmap |= 1 << wlan_vdev_get_link_id(tmp_vdev);
+			wlan_objmgr_vdev_release_ref(tmp_vdev,
+						     WLAN_POLICY_MGR_ID);
+		}
+		ml_nlink_vendor_command_set_link(
+			psoc, vdev_id,
+			LINK_CONTROL_MODE_MIXED,
+			MLO_LINK_FORCE_REASON_CONNECT,
+			MLO_LINK_FORCE_MODE_ACTIVE_NUM,
+			force_active_cnt,
+			link_bitmap,
+			0);
+	}
 
 release_vdev_ref:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
@@ -9219,6 +9369,10 @@ policy_mgr_clear_ml_links_settings_in_fw(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_err("vdev: %d Invalid Context", vdev_id);
 		goto release_vdev_ref;
 	}
+	/* Clear all user vendor command setting for switching to "default" */
+	ml_nlink_vendor_command_set_link(psoc, vdev_id,
+					 LINK_CONTROL_MODE_DEFAULT,
+					 0, 0, 0, 0, 0);
 
 	policy_mgr_get_ml_sta_info(pm_ctx, &num_ml_sta, &num_disabled_ml_sta,
 				   ml_sta_vdev_lst, ml_freq_lst, &num_non_ml,

+ 26 - 3
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -1039,8 +1039,11 @@ policy_mgr_modify_pcl_based_on_indoor(struct wlan_objmgr_psoc *psoc,
 
 	for (i = 0; i < *pcl_len_org; i++) {
 		if (wlan_reg_is_freq_indoor_in_secondary_list(pm_ctx->pdev,
-							      pcl_list_org[i]))
+							pcl_list_org[i])) {
+			policy_mgr_debug("Remove freq: %d from PCL as it's indoor",
+					 pcl_list_org[i]);
 			continue;
+		}
 		pcl_list[pcl_len] = pcl_list_org[i];
 		weight_list[pcl_len++] = weight_list_org[i];
 	}
@@ -4314,6 +4317,21 @@ policy_mgr_get_sap_mandatory_channel(struct wlan_objmgr_psoc *psoc,
 	}
 
 	sap_new_freq = pcl.pcl_list[0];
+	/*
+	 * pcl_list carries multiple channel in ML-STA case depending on
+	 * the no.of links connected. Check if intf_ch_freq is carrying
+	 * any frequency from the list and pick it. If intf_ch_freq is not
+	 * present in the list, the frequency present at pcl_list[0] can
+	 * be picked as caller doesn't have any preferred/chosen channel
+	 * as such.
+	 */
+	for (i = 0; i < pcl.pcl_len; i++) {
+		if (pcl.pcl_list[i] == *intf_ch_freq) {
+			sap_new_freq = pcl.pcl_list[i];
+			break;
+		}
+	}
+
 	user_config_freq = policy_mgr_get_user_config_sap_freq(psoc, vdev_id);
 
 	for (i = 0; i < pcl.pcl_len; i++) {
@@ -4672,8 +4690,13 @@ QDF_STATUS policy_mgr_filter_passive_ch(struct wlan_objmgr_pdev *pdev,
 	}
 
 	for (ch_index = 0; ch_index < *ch_cnt; ch_index++) {
-		if (!wlan_reg_is_passive_for_freq(pdev, ch_freq_list[ch_index]))
-			ch_freq_list[target_ch_cnt++] = ch_freq_list[ch_index];
+		if (wlan_reg_is_passive_for_freq(pdev,
+						 ch_freq_list[ch_index])) {
+			policy_mgr_debug("Remove freq: %d from list as it's passive",
+					 ch_freq_list[ch_index]);
+			continue;
+		}
+		ch_freq_list[target_ch_cnt++] = ch_freq_list[ch_index];
 	}
 
 	*ch_cnt = target_ch_cnt;

+ 7 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_ucfg.c

@@ -362,3 +362,10 @@ bool ucfg_policy_mgr_get_vdev_diff_freq_new_conn(struct wlan_objmgr_psoc *psoc,
 	return policy_mgr_get_vdev_diff_freq_new_conn(psoc, new_freq, vdev_id);
 }
 
+QDF_STATUS ucfg_policy_mgr_get_dbs_hw_modes(struct wlan_objmgr_psoc *psoc,
+					    bool *one_by_one_dbs,
+					    bool *two_by_two_dbs)
+{
+	return policy_mgr_get_dbs_hw_modes(psoc, one_by_one_dbs,
+					   two_by_two_dbs);
+}

+ 2 - 0
components/mlme/core/src/wlan_mlme_main.c

@@ -2564,6 +2564,8 @@ static void mlme_init_sta_mlo_cfg(struct wlan_objmgr_psoc *psoc,
 		cfg_get(psoc, CFG_MLO_PREFER_PERCENTAGE);
 	sta->mlo_same_link_mld_address =
 		cfg_default(CFG_MLO_SAME_LINK_MLD_ADDR);
+	sta->mlo_5gl_5gh_mlsr =
+		cfg_default(CFG_MLO_MLO_5GL_5GH_MLSR);
 }
 
 static bool

+ 3 - 0
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -46,6 +46,7 @@
 #endif
 #include <wlan_lmac_if_def.h>
 #include "target_if_mlme.h"
+#include "wlan_mlo_mgr_sta.h"
 
 static struct vdev_mlme_ops sta_mlme_ops;
 static struct vdev_mlme_ops ap_mlme_ops;
@@ -867,6 +868,8 @@ QDF_STATUS mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev,
 	}
 
 	mlme_priv->chan_switch_in_progress = val;
+	mlo_set_chan_switch_in_progress(vdev, val);
+
 	mlme_legacy_info("Set chan_switch_in_progress: %d vdev %d",
 			 val, wlan_vdev_get_id(vdev));
 

+ 27 - 0
components/mlme/dispatcher/inc/cfg_mlme_sta.h

@@ -744,6 +744,33 @@
 #define CFG_EHT_DISABLE_PUNCT_IN_US_LPI_CFG
 #endif
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/*
+ * <cfg>
+ * mlo_5gl_5gh_mlsr - enable/disable 5GL+5GH MLSR
+ * @Min: false
+ * @Max: true
+ * @Default: true
+ *
+ * Related: None
+ *
+ * Supported Feature: 5GL+5GH MLSR
+ *
+ * Usage: Internal
+ *
+ * </cfg>
+ */
+
+#define CFG_MLO_MLO_5GL_5GH_MLSR CFG_BOOL( \
+		"mlo_5gl_5gh_mlsr",\
+		0, \
+		"enable 5GL+5GH MLSR")
+
+#define CFG_MLO_MLO_5GL_5GH_MLSR_CFG CFG(CFG_MLO_MLO_5GL_5GH_MLSR)
+#else
+#define CFG_MLO_MLO_5GL_5GH_MLSR_CFG
+#endif
+
 #define CFG_STA_ALL \
 	CFG(CFG_INFRA_STA_KEEP_ALIVE_PERIOD) \
 	CFG(CFG_STA_BSS_MAX_IDLE_PERIOD) \

+ 3 - 3
components/mlme/dispatcher/inc/cfg_mlme_timeout.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2019, 2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 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
@@ -271,7 +271,7 @@
 /*
  * <ini>
  * sae_auth_failure_timeout - SAE Auth failure timeout value in msec
- * @Min: 500
+ * @Min: 100
  * @Max: 1000
  * @Default: 1000
  *
@@ -283,7 +283,7 @@
  */
 #define CFG_SAE_AUTH_FAILURE_TIMEOUT CFG_INI_UINT( \
 		"sae_auth_failure_timeout", \
-		500, \
+		100, \
 		1000, \
 		1000, \
 		CFG_VALUE_OR_DEFAULT, \

+ 14 - 0
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -4297,6 +4297,14 @@ wlan_mlme_get_bt_profile_con(struct wlan_objmgr_psoc *psoc);
  */
 uint8_t wlan_mlme_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * wlan_mlme_is_5gl_5gh_mlsr_supported() - check 5GH_5GL MLSR supported
+ * @psoc: pointer to psoc object
+ *
+ * Return: true if 5GH_5GL MLSR supported otherwise false
+ */
+bool wlan_mlme_is_5gl_5gh_mlsr_supported(struct wlan_objmgr_psoc *psoc);
+
 /**
  * wlan_mlme_set_sta_mlo_conn_max_num() - set max number of links that sta mlo
  *                                        connection can support
@@ -4448,6 +4456,12 @@ wlan_mlme_get_sta_mlo_conn_max_num(struct wlan_objmgr_psoc *psoc)
 	return 0;
 }
 
+static inline bool
+wlan_mlme_is_5gl_5gh_mlsr_supported(struct wlan_objmgr_psoc *psoc)
+{
+	return 0;
+}
+
 static inline QDF_STATUS
 wlan_mlme_set_sta_mlo_simultaneous_links(struct wlan_objmgr_psoc *psoc,
 					 uint8_t value)

+ 2 - 0
components/mlme/dispatcher/inc/wlan_mlme_public_struct.h

@@ -1820,6 +1820,7 @@ enum station_prefer_bw {
  * @mlo_support_link_band:          band bitmap that sta mlo supports
  * @mlo_max_simultaneous_links:     number of simultaneous links
  * @mlo_prefer_percentage:          percentage to boost/reduce mlo scoring
+ * @mlo_5gl_5gh_mlsr:               enable/disable 5GL+5GH MLSR
  * @epcs_capability:                epcs capability enable or disable flag
  * @usr_disable_eht:                user disable the eht for STA
  * @eht_disable_punct_in_us_lpi:    Disable eht puncture in us lpi mode
@@ -1857,6 +1858,7 @@ struct wlan_mlme_sta_cfg {
 	uint8_t mlo_support_link_band;
 	uint8_t mlo_max_simultaneous_links;
 	int8_t mlo_prefer_percentage;
+	bool mlo_5gl_5gh_mlsr;
 #endif
 #ifdef WLAN_FEATURE_11BE
 	bool epcs_capability;

+ 10 - 0
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -1715,6 +1715,16 @@ QDF_STATUS wlan_mlme_set_sta_mlo_conn_band_bmp(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+bool wlan_mlme_is_5gl_5gh_mlsr_supported(struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return 0;
+	return mlme_obj->cfg.sta.mlo_5gl_5gh_mlsr;
+}
+
 void
 wlan_mlme_get_mlo_prefer_percentage(struct wlan_objmgr_psoc *psoc,
 				    int8_t *mlo_prefer_percentage)

+ 22 - 20
components/tdls/core/src/wlan_tdls_ct.c

@@ -818,8 +818,8 @@ void tdls_ct_idle_handler(void *user_data)
  */
 static void
 tdls_ct_process_idle_and_discovery(struct tdls_peer *curr_peer,
-				struct tdls_vdev_priv_obj *tdls_vdev_obj,
-				struct tdls_soc_priv_obj *tdls_soc_obj)
+				   struct tdls_vdev_priv_obj *tdls_vdev_obj,
+				   struct tdls_soc_priv_obj *tdls_soc_obj)
 {
 	uint16_t valid_peers;
 
@@ -944,10 +944,10 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer,
 					struct tdls_vdev_priv_obj *tdls_vdev,
 					struct tdls_soc_priv_obj *tdls_soc)
 {
-	if (TDLS_IS_EXTERNAL_CONTROL_ENABLED(
-			tdls_soc->tdls_configs.tdls_feature_flags) &&
-			(!curr_peer->is_forced_peer))
-			return;
+	if (!curr_peer->is_forced_peer &&
+	    TDLS_IS_EXTERNAL_CONTROL_ENABLED(
+				tdls_soc->tdls_configs.tdls_feature_flags))
+		return;
 
 	if (curr_peer->rx_pkt || curr_peer->tx_pkt)
 		tdls_debug(QDF_MAC_ADDR_FMT "link_status %d tdls_support %d tx %d rx %d vdev %d",
@@ -956,29 +956,31 @@ static void tdls_ct_process_cap_unknown(struct tdls_peer *curr_peer,
 			   curr_peer->tx_pkt, curr_peer->rx_pkt,
 			   wlan_vdev_get_id(tdls_vdev->vdev));
 
-	if (!TDLS_IS_LINK_CONNECTED(curr_peer) &&
-	    ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
-	    tdls_vdev->threshold_config.tx_packet_n)) {
-		/* Ignore discovery attempt if External Control is enabled, that
+	if (TDLS_IS_LINK_CONNECTED(curr_peer))
+		return;
+
+	if ((curr_peer->tx_pkt + curr_peer->rx_pkt) >=
+	     tdls_vdev->threshold_config.tx_packet_n) {
+		/*
+		 * Ignore discovery attempt if External Control is enabled, that
 		 * is, peer is forced. In that case, continue discovery attempt
 		 * regardless attempt count
 		 */
 		tdls_debug("TDLS UNKNOWN pre discover ");
 		if (curr_peer->is_forced_peer ||
-			curr_peer->discovery_attempt++ <
+		    curr_peer->discovery_attempt <
 		    tdls_vdev->threshold_config.discovery_tries_n) {
 			tdls_debug("TDLS UNKNOWN discover ");
 			tdls_vdev->curr_candidate = curr_peer;
 			tdls_implicit_send_discovery_request(tdls_vdev);
-		} else {
-			if (curr_peer->link_status != TDLS_LINK_CONNECTING) {
-				curr_peer->tdls_support =
-						TDLS_CAP_NOT_SUPPORTED;
-				tdls_set_peer_link_status(
-						curr_peer,
-						TDLS_LINK_IDLE,
-						TDLS_LINK_NOT_SUPPORTED);
-			}
+
+			return;
+		}
+
+		if (curr_peer->link_status != TDLS_LINK_CONNECTING) {
+			curr_peer->tdls_support = TDLS_CAP_NOT_SUPPORTED;
+			tdls_set_peer_link_status(curr_peer, TDLS_LINK_IDLE,
+						  TDLS_LINK_NOT_SUPPORTED);
 		}
 	}
 }

+ 33 - 0
components/tdls/core/src/wlan_tdls_main.c

@@ -1557,6 +1557,37 @@ tdls_process_sta_connect(struct tdls_sta_notify_params *notify)
 	return QDF_STATUS_SUCCESS;
 }
 
+static void
+tdls_update_discovery_tries(struct wlan_objmgr_vdev *vdev)
+{
+	struct tdls_soc_priv_obj *soc_obj;
+	struct tdls_vdev_priv_obj *vdev_obj;
+	struct tdls_user_config *tdls_config;
+	struct tdls_config_params *vdev_config;
+	QDF_STATUS status;
+
+	status = tdls_get_vdev_objects(vdev, &vdev_obj, &soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("can't get vdev_obj & soc_obj");
+		return;
+	}
+
+	vdev_config = &vdev_obj->threshold_config;
+	tdls_config = &soc_obj->tdls_configs;
+
+	vdev_config->discovery_tries_n =
+			tdls_config->tdls_max_discovery_attempt;
+
+	/*
+	 * For MLO peer discovery will happen on 2 links and the best link
+	 * will be chosen based on score for TDLS. So factor that into the
+	 * number of discovery attempts to increase the discoverability
+	 * window for the peer.
+	 */
+	if (wlan_vdev_mlme_is_mlo_vdev(vdev))
+		vdev_config->discovery_tries_n *= 2;
+}
+
 QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
 {
 	QDF_STATUS status;
@@ -1573,6 +1604,8 @@ QDF_STATUS tdls_notify_sta_connect(struct tdls_sta_notify_params *notify)
 	}
 
 	status = tdls_process_sta_connect(notify);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		tdls_update_discovery_tries(notify->vdev);
 
 	wlan_objmgr_vdev_release_ref(notify->vdev, WLAN_TDLS_NB_ID);
 	qdf_mem_free(notify);

+ 2 - 0
components/tdls/core/src/wlan_tdls_main.h

@@ -473,6 +473,8 @@ wlan_vdev_get_tdls_vdev_obj(struct wlan_objmgr_vdev *vdev)
  * @mac: mac address of tdls peer
  * @link_state: tdls link state
  * @link_reason: reason
+ *
+ * Return: None
  */
 void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev,
 			  const uint8_t *mac,

+ 0 - 9
components/tdls/core/src/wlan_tdls_peer.c

@@ -821,15 +821,6 @@ static void tdls_update_pmo_status(struct tdls_vdev_priv_obj *tdls_vdev,
 }
 #endif
 
-/**
- * tdls_set_link_status() - set link statue for TDLS peer
- * @vdev_obj: TDLS vdev object
- * @mac: MAC address of current TDLS peer
- * @link_status: link status
- * @link_reason: reason with link status
- *
- * Return: None.
- */
 void tdls_set_link_status(struct tdls_vdev_priv_obj *vdev_obj,
 			  const uint8_t *mac,
 			  enum tdls_link_state link_status,

+ 19 - 0
components/tdls/dispatcher/inc/wlan_tdls_api.h

@@ -193,6 +193,19 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc,
 					 struct wlan_objmgr_vdev *vdev)
 {}
 #endif /* WLAN_FEATURE_TDLS_CONCURRENCIES */
+
+/**
+ * wlan_tdls_increment_discovery_attempts() - Increment TDLS peer discovery
+ * attempts
+ * @psoc: Pointer to PSOC object
+ * @vdev_id: Vdev id
+ * @peer_addr: Peer mac address
+ *
+ * Return: None
+ */
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr);
 #else
 
 #ifdef FEATURE_SET
@@ -267,5 +280,11 @@ void wlan_tdls_handle_p2p_client_connect(struct wlan_objmgr_psoc *psoc,
 static inline
 void wlan_tdls_notify_start_bss_failure(struct wlan_objmgr_psoc *psoc)
 {}
+
+static inline
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr)
+{}
 #endif
 #endif

+ 37 - 0
components/tdls/dispatcher/src/wlan_tdls_api.c

@@ -26,6 +26,7 @@
 #include "../../core/src/wlan_tdls_main.h"
 #include "../../core/src/wlan_tdls_ct.h"
 #include "../../core/src/wlan_tdls_mgmt.h"
+#include "wlan_tdls_peer.h"
 #include <wlan_objmgr_global_obj.h>
 #include <wlan_objmgr_cmn.h>
 #include "wlan_tdls_cfg_api.h"
@@ -470,3 +471,39 @@ void wlan_tdls_update_rx_pkt_cnt(struct wlan_objmgr_vdev *vdev,
 {
 	tdls_update_rx_pkt_cnt(vdev, mac_addr, dest_mac_addr);
 }
+
+void wlan_tdls_increment_discovery_attempts(struct wlan_objmgr_psoc *psoc,
+					    uint8_t vdev_id,
+					    uint8_t *peer_addr)
+{
+	struct tdls_soc_priv_obj *tdls_soc_obj;
+	struct tdls_vdev_priv_obj *tdls_vdev_obj;
+	struct tdls_peer *peer;
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_TDLS_NB_ID);
+	if (!vdev)
+		return;
+
+	status = tdls_get_vdev_objects(vdev, &tdls_vdev_obj, &tdls_soc_obj);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		tdls_err("Failed to get TDLS objects");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+		return;
+	}
+
+	peer = tdls_get_peer(tdls_vdev_obj, peer_addr);
+	if (!peer) {
+		tdls_err("tdls_peer is NULL");
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+		return;
+	}
+
+	peer->discovery_attempt++;
+	tdls_debug("vdev:%d peer discovery attempts:%d", vdev_id,
+		   peer->discovery_attempt);
+
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_TDLS_NB_ID);
+}

+ 41 - 18
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -3085,6 +3085,8 @@ cm_roam_mlo_config(struct wlan_objmgr_psoc *psoc,
 		wlan_mlme_get_sta_mlo_conn_max_num(psoc);
 	roam_mlo_params->support_link_band =
 		wlan_mlme_get_sta_mlo_conn_band_bmp(psoc);
+	roam_mlo_params->mlo_5gl_5gh_mlsr =
+		wlan_mlme_is_5gl_5gh_mlsr_supported(psoc);
 
 	/*
 	 * Update the supported link band based on roam_band_bitmap
@@ -6049,20 +6051,29 @@ send_evt:
 #if (defined(CONNECTIVITY_DIAG_EVENT) || \
 	defined(WLAN_FEATURE_CONNECTIVITY_LOGGING)) && \
 	defined(WLAN_FEATURE_ROAM_OFFLOAD)
-static
-bool wlan_is_valid_frequency(uint32_t freq, uint32_t band_capability,
-			     uint32_t band_mask)
-{
-	if ((band_capability == BIT(REG_BAND_5G) ||
-	     band_mask == BIT(REG_BAND_5G) ||
-	     band_capability == BIT(REG_BAND_6G) ||
-	     band_mask == BIT(REG_BAND_6G)) &&
-	     WLAN_REG_IS_24GHZ_CH_FREQ(freq))
+static bool wlan_is_valid_frequency(uint32_t freq, uint32_t band_capability,
+				    uint32_t band_mask)
+{
+	bool is_2g_band, is_5g_band, is_6g_band;
+
+	if (band_capability == REG_BAND_MASK_ALL &&
+	    band_mask == REG_BAND_MASK_ALL)
+		return true;
+
+	is_2g_band = (band_capability & BIT(REG_BAND_2G)) &&
+		     (band_mask & BIT(REG_BAND_2G));
+	is_5g_band = (band_capability & BIT(REG_BAND_5G)) &&
+		     (band_mask & BIT(REG_BAND_5G));
+	is_6g_band = (band_capability & BIT(REG_BAND_6G)) &&
+		     (band_mask & BIT(REG_BAND_6G));
+
+	if (!is_6g_band && WLAN_REG_IS_6GHZ_CHAN_FREQ(freq))
 		return false;
 
-	if ((band_capability == BIT(REG_BAND_2G) ||
-	     band_mask == BIT(REG_BAND_2G)) &&
-	     !WLAN_REG_IS_24GHZ_CH_FREQ(freq))
+	if (!is_5g_band && WLAN_REG_IS_5GHZ_CH_FREQ(freq))
+		return false;
+
+	if (!is_2g_band && WLAN_REG_IS_24GHZ_CH_FREQ(freq))
 		return false;
 
 	return true;
@@ -6218,7 +6229,7 @@ void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
 	struct wmi_roam_candidate_info *ap = scan->ap;
 	uint32_t *chan_freq = NULL;
 	uint8_t count = 0, status, num_chan;
-	uint32_t band_capability = 0, band_mask = 0;
+	uint32_t band_capability = 0, band_mask = 0, scan_band_mask = 0;
 	struct wlan_diag_roam_scan_done *wlan_diag_event = NULL;
 
 	wlan_diag_event = qdf_mem_malloc(sizeof(*wlan_diag_event));
@@ -6247,7 +6258,10 @@ void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
 	if (scan->num_ap)
 		wlan_diag_event->cand_ap_count = scan->num_ap - 1;
 
-	if (scan->type == ROAM_STATS_SCAN_TYPE_FULL && scan->present) {
+	if (scan->present &&
+	    (scan->type == ROAM_STATS_SCAN_TYPE_FULL ||
+	     scan->type == ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ ||
+	     scan->type == ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ)) {
 		status = mlme_get_fw_scan_channels(psoc, chan_freq, &num_chan);
 		if (QDF_IS_STATUS_ERROR(status))
 			goto out;
@@ -6260,12 +6274,21 @@ void cm_roam_scan_info_event(struct wlan_objmgr_psoc *psoc,
 		if (QDF_IS_STATUS_ERROR(status))
 			goto out;
 
-		band_mask =
-			policy_mgr_get_connected_roaming_vdev_band_mask(psoc,
-									vdev_id);
-
 		num_chan = QDF_MIN(WLAN_MAX_LOGGING_FREQ, NUM_CHANNELS);
 
+		band_mask = policy_mgr_get_connected_roaming_vdev_band_mask(
+							psoc, vdev_id);
+
+		mlme_debug("mask:%d, capability:%d, scan_type:%d, num_chan:%d",
+			   band_mask, band_capability, scan->type, num_chan);
+		if (scan->type == ROAM_STATS_SCAN_TYPE_HIGHER_BAND_6GHZ)
+			scan_band_mask = BIT(REG_BAND_6G);
+		else if (scan->type ==
+			 ROAM_STATS_SCAN_TYPE_HIGHER_BAND_5GHZ_6GHZ)
+			scan_band_mask = BIT(REG_BAND_5G) | BIT(REG_BAND_6G);
+
+		band_mask &= scan_band_mask;
+
 		for (i = 0; i < num_chan; i++) {
 			if (!wlan_is_valid_frequency(chan_freq[i],
 						     band_capability,

+ 2 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1704,6 +1704,7 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 		return;
 	}
 
+	wlan_crypto_aquire_lock();
 	for (i = 0; i < max_key_index; i++) {
 		crypto_key = wlan_crypto_get_key(vdev, i);
 		if (!crypto_key)
@@ -1716,6 +1717,7 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 				       crypto_key->cipher_type);
 		key_present = true;
 	}
+	wlan_crypto_release_lock();
 
 	if (!key_present && mlo_mgr_is_link_switch_in_progress(vdev)) {
 		mlme_err("No key found for link_id %d", link_id);

+ 2 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h

@@ -1986,12 +1986,14 @@ enum roam_rt_stats_params {
  *  Invalid value or 0 will use max supported value by fw.
  * @support_link_band: Configure the band bitmap of mlo connection supports
  * The bits of the bitmap are defined by the enum reg_wifi_band
+ * @mlo_5gl_5gh_mlsr: 5GL+5GH MLSR support
  */
 struct wlan_roam_mlo_config {
 	uint8_t vdev_id;
 	struct qdf_mac_addr partner_link_addr;
 	uint32_t support_link_num;
 	uint32_t support_link_band;
+	uint32_t mlo_5gl_5gh_mlsr;
 };
 
 /**

+ 68 - 0
components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h

@@ -38,6 +38,7 @@
  * @ml_nlink_ap_stopped_evt: SAP/GO bss stopped
  * @ml_nlink_connection_updated_evt: connection home channel changed
  * @ml_nlink_tdls_request_evt: tdls request link enable/disable
+ * @ml_nlink_vendor_cmd_request_evt: vendor command request
  */
 enum ml_nlink_change_event_type {
 	ml_nlink_link_switch_start_evt,
@@ -52,6 +53,26 @@ enum ml_nlink_change_event_type {
 	ml_nlink_ap_stopped_evt,
 	ml_nlink_connection_updated_evt,
 	ml_nlink_tdls_request_evt,
+	ml_nlink_vendor_cmd_request_evt,
+};
+
+/**
+ * enum link_control_modes - the types of MLO links state
+ * control modes. This enum is internal mapping of
+ * qca_wlan_vendor_link_state_control_modes.
+ * @LINK_CONTROL_MODE_DEFAULT: MLO links state controlled
+ * by the driver.
+ * @LINK_CONTROL_MODE_USER: MLO links state controlled by
+ * user space.
+ * @LINK_CONTROL_MODE_MIXED: User space provides the
+ * desired number of MLO links to operate in active state at any given time.
+ * The driver will choose which MLO links should operate in the active state.
+ * See enum qca_wlan_vendor_link_state for active state definition.
+ */
+enum link_control_modes {
+	LINK_CONTROL_MODE_DEFAULT = 0,
+	LINK_CONTROL_MODE_USER = 1,
+	LINK_CONTROL_MODE_MIXED = 2,
 };
 
 /**
@@ -59,6 +80,7 @@ enum ml_nlink_change_event_type {
  * @evt: event parameters
  * @link_switch: link switch start parameters
  * @tdls: tdls parameters
+ * @vendor: vendor command set link parameters
  */
 struct ml_nlink_change_event {
 	union {
@@ -75,6 +97,14 @@ struct ml_nlink_change_event {
 			enum mlo_link_force_mode mode;
 			enum mlo_link_force_reason reason;
 		} tdls;
+		struct {
+			enum link_control_modes link_ctrl_mode;
+			uint8_t link_num;
+			uint32_t link_bitmap;
+			uint32_t link_bitmap2;
+			enum mlo_link_force_mode mode;
+			enum mlo_link_force_reason reason;
+		} vendor;
 	} evt;
 };
 
@@ -119,6 +149,7 @@ static inline const char *link_evt_to_string(uint32_t evt)
 	CASE_RETURN_STRING(ml_nlink_ap_stopped_evt);
 	CASE_RETURN_STRING(ml_nlink_connection_updated_evt);
 	CASE_RETURN_STRING(ml_nlink_tdls_request_evt);
+	CASE_RETURN_STRING(ml_nlink_vendor_cmd_request_evt);
 	default:
 		return "Unknown";
 	}
@@ -190,6 +221,19 @@ ml_nlink_convert_vdev_bitmap_to_linkid_bitmap(
 				uint32_t *link_bitmap,
 				uint32_t *associated_bitmap);
 
+/**
+ * convert_link_bitmap_to_link_ids() - Convert link bitmap to link ids
+ * @link_bitmap: PSOC object information
+ * @link_id_sz: link_ids array size
+ * @link_ids: link id array
+ *
+ * Return: num of link id in link_ids array converted from link bitmap
+ */
+uint32_t
+convert_link_bitmap_to_link_ids(uint32_t link_bitmap,
+				uint8_t link_id_sz,
+				uint8_t *link_ids);
+
 /**
  * ml_nlink_convert_link_bitmap_to_ids() - convert link bitmap
  * to link ids
@@ -339,6 +383,30 @@ void
 ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc,
 			 struct wlan_objmgr_vdev *vdev);
 
+/**
+ * ml_nlink_vendor_command_set_link() - Update vendor command
+ * set link parameters
+ * @psoc: psoc object
+ * @vdev_id: vdev id
+ * @link_control_mode: link control mode: default, user, mix
+ * @reason: reason to set
+ * @mode: mode to set
+ * @link_num: number of link, valid for mode:
+ * @link_bitmap: link bitmap, valid for mode:
+ * @link_bitmap2: inactive link bitmap, only valid for mode
+ *
+ * Return: void
+ */
+void
+ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id,
+				 enum link_control_modes link_control_mode,
+				 enum mlo_link_force_reason reason,
+				 enum mlo_link_force_mode mode,
+				 uint8_t link_num,
+				 uint16_t link_bitmap,
+				 uint16_t link_bitmap2);
+
 /**
  * ml_is_nlink_service_supported() - support nlink or not
  * @psoc: psoc object

+ 158 - 9
components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c

@@ -216,6 +216,8 @@ ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc,
 	force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state;
 	qdf_mem_zero(force_state, sizeof(*force_state));
 	ml_nlink_dump_force_state(force_state, "");
+	qdf_mem_zero(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs,
+		     sizeof(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs));
 	mlo_dev_lock_release(mlo_dev_ctx);
 }
 
@@ -358,6 +360,78 @@ ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
 	mlo_dev_lock_release(mlo_dev_ctx);
 }
 
+static void
+ml_nlink_update_force_link_request(struct wlan_objmgr_psoc *psoc,
+				   struct wlan_objmgr_vdev *vdev,
+				   struct set_link_req *req,
+				   enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *old;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	*old = *req;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+static void
+ml_nlink_get_force_link_request(struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				struct set_link_req *req,
+				enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *old;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	*req = *old;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+static void
+ml_nlink_clr_force_link_request(struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				enum set_link_source source)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *req;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	if (source >= SET_LINK_SOURCE_MAX || source < 0) {
+		mlo_err("invalid source %d", source);
+		return;
+	}
+
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	req = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source];
+	qdf_mem_zero(req, sizeof(*req));
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
 void
 ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
 				    struct wlan_objmgr_vdev *vdev,
@@ -669,15 +743,7 @@ static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc,
 	*ml_link_bitmap = link_bitmap;
 }
 
-/**
- * convert_link_bitmap_to_link_ids() - Convert link bitmap to link ids
- * @link_bitmap: PSOC object information
- * @link_id_sz: link_ids array size
- * @link_ids: link id array
- *
- * Return: num of link id in link_ids array converted from link bitmap
- */
-static uint32_t
+uint32_t
 convert_link_bitmap_to_link_ids(uint32_t link_bitmap,
 				uint8_t link_id_sz,
 				uint8_t *link_ids)
@@ -1984,6 +2050,7 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	struct ml_link_force_state curr_force_state = {0};
 	QDF_STATUS status;
+	struct set_link_req vendor_req = {0};
 
 	ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state);
 
@@ -2023,6 +2090,15 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 				  curr_force_state.force_active_bitmap);
 			return QDF_STATUS_SUCCESS;
 		}
+		ml_nlink_get_force_link_request(psoc, vdev, &vendor_req,
+						SET_LINK_FROM_VENDOR_CMD);
+		if (data->evt.tdls.link_bitmap &
+		    vendor_req.force_active_bitmap) {
+			mlo_debug("link_bitmap 0x%x active hold by vendor cmd, 0x%x",
+				  data->evt.tdls.link_bitmap,
+				  vendor_req.force_active_bitmap);
+			return QDF_STATUS_SUCCESS;
+		}
 		break;
 	default:
 		mlo_err("unhandled for tdls force mode %d",
@@ -2050,6 +2126,50 @@ ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc,
 	return status;
 }
 
+static QDF_STATUS
+ml_nlink_vendor_cmd_handler(struct wlan_objmgr_psoc *psoc,
+			    struct wlan_objmgr_vdev *vdev,
+			    enum ml_nlink_change_event_type evt,
+			    struct ml_nlink_change_event *data)
+{
+	struct set_link_req req = {0};
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	mlo_debug("link ctrl %d mode %d reason %d num %d 0x%x 0x%x",
+		  data->evt.vendor.link_ctrl_mode,
+		  data->evt.vendor.mode,
+		  data->evt.vendor.reason,
+		  data->evt.vendor.link_num,
+		  data->evt.vendor.link_bitmap,
+		  data->evt.vendor.link_bitmap2);
+	switch (data->evt.vendor.link_ctrl_mode) {
+	case LINK_CONTROL_MODE_DEFAULT:
+		ml_nlink_clr_force_link_request(psoc, vdev,
+						SET_LINK_FROM_VENDOR_CMD);
+		break;
+	case LINK_CONTROL_MODE_USER:
+		req.mode = data->evt.vendor.mode;
+		req.reason = data->evt.vendor.reason;
+		req.force_active_bitmap = data->evt.vendor.link_bitmap;
+		req.force_inactive_bitmap = data->evt.vendor.link_bitmap2;
+		ml_nlink_update_force_link_request(psoc, vdev, &req,
+						   SET_LINK_FROM_VENDOR_CMD);
+		break;
+	case LINK_CONTROL_MODE_MIXED:
+		req.mode = data->evt.vendor.mode;
+		req.reason = data->evt.vendor.reason;
+		req.force_active_num = data->evt.vendor.link_num;
+		req.force_active_num_bitmap = data->evt.vendor.link_bitmap;
+		ml_nlink_update_force_link_request(psoc, vdev, &req,
+						   SET_LINK_FROM_VENDOR_CMD);
+		break;
+	default:
+		status = QDF_STATUS_E_INVAL;
+	}
+
+	return status;
+}
+
 static QDF_STATUS
 ml_nlink_swtich_dynamic_inactive_link(struct wlan_objmgr_psoc *psoc,
 				      struct wlan_objmgr_vdev *vdev)
@@ -2223,6 +2343,10 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 		status = ml_nlink_tdls_event_handler(
 			psoc, vdev, evt, data);
 		break;
+	case ml_nlink_vendor_cmd_request_evt:
+		status = ml_nlink_vendor_cmd_handler(
+			psoc, vdev, evt, data);
+		break;
 	default:
 		break;
 	}
@@ -2232,3 +2356,28 @@ ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc,
 
 	return status;
 }
+
+void
+ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc *psoc,
+				 uint8_t vdev_id,
+				 enum link_control_modes link_control_mode,
+				 enum mlo_link_force_reason reason,
+				 enum mlo_link_force_mode mode,
+				 uint8_t link_num,
+				 uint16_t link_bitmap,
+				 uint16_t link_bitmap2)
+{
+	struct ml_nlink_change_event data;
+
+	qdf_mem_zero(&data, sizeof(data));
+	data.evt.vendor.link_ctrl_mode = link_control_mode;
+	data.evt.vendor.mode = mode;
+	data.evt.vendor.reason = reason;
+	data.evt.vendor.link_num = link_num;
+	data.evt.vendor.link_bitmap = link_bitmap;
+	data.evt.vendor.link_bitmap2 = link_bitmap2;
+
+	ml_nlink_conn_change_notify(
+			psoc, vdev_id,
+			ml_nlink_vendor_cmd_request_evt, &data);
+}

+ 5 - 1
components/wmi/src/wmi_unified_roam_tlv.c

@@ -5079,12 +5079,16 @@ send_roam_mlo_config_tlv(wmi_unified_t wmi_handle,
 	cmd->support_link_num = req->support_link_num;
 	cmd->support_link_band = convert_support_link_band_to_wmi(
 						req->support_link_band);
+	if (!req->mlo_5gl_5gh_mlsr)
+		cmd->disallow_connect_modes |= WMI_ROAM_MLO_CONNECTION_MODE_5GL_5GH_MLSR;
+
 	WMI_CHAR_ARRAY_TO_MAC_ADDR(req->partner_link_addr.bytes,
 				   &cmd->partner_link_addr);
 
-	wmi_debug("RSO_CFG MLO: vdev_id:%d support_link_num:%d support_link_band:0x%0x link addr:"QDF_MAC_ADDR_FMT,
+	wmi_debug("RSO_CFG MLO: vdev_id:%d support_link_num:%d support_link_band:0x%0x disallow_connect_mode %d link addr:"QDF_MAC_ADDR_FMT,
 		  cmd->vdev_id, cmd->support_link_num,
 		  cmd->support_link_band,
+		  cmd->disallow_connect_modes,
 		  QDF_MAC_ADDR_REF(req->partner_link_addr.bytes));
 
 	wmi_mtrace(WMI_ROAM_MLO_CONFIG_CMDID, cmd->vdev_id, 0);

+ 12 - 0
configs/config_to_feature.h

@@ -1243,6 +1243,10 @@
 #define FEATURE_WLAN_STA_4ADDR_SCHEME (1)
 #endif
 
+#ifdef CONFIG_FEATURE_WLAN_GC_SKIP_JOIN
+#define FEATURE_WLAN_GC_SKIP_JOIN (1)
+#endif
+
 #ifdef CONFIG_MDM_PLATFORM
 #define MDM_PLATFORM (1)
 #endif
@@ -2953,4 +2957,12 @@
 #endif
 #endif
 
+#ifdef CONFIG_DP_RX_MSDU_DONE_FAIL_HISTORY
+#define DP_RX_MSDU_DONE_FAIL_HISTORY (1)
+#endif
+
+#ifdef CONFIG_DP_RX_PEEK_MSDU_DONE_WAR
+#define DP_RX_PEEK_MSDU_DONE_WAR (1)
+#endif
+
 #endif /* CONFIG_TO_FEATURE_H */

+ 2 - 0
configs/default_defconfig

@@ -165,6 +165,8 @@ endif
 	CONFIG_WLAN_DP_VDEV_NO_SELF_PEER := y
 	CONFIG_WLAN_DP_FEATURE_DEFERRED_REO_QDESC_DESTROY := y
 	CONFIG_WLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET := y
+	CONFIG_DP_RX_MSDU_DONE_FAIL_HISTORY := y
+	CONFIG_DP_RX_PEEK_MSDU_DONE_WAR := y
 endif
 
 ifeq (y,$(findstring y,$(CONFIG_LITHIUM) $(CONFIG_BERYLLIUM)))

+ 2 - 0
configs/pineapple_gki_kiwi-v2_defconfig

@@ -396,3 +396,5 @@ CONFIG_BCN_RATECODE_ENABLE=y
 CONFIG_WLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET=y
 CONFIG_WLAN_MULTI_CHIP_SUPPORT=y
 CONFIG_WLAN_FEATURE_LL_LT_SAP=y
+CONFIG_DP_RX_MSDU_DONE_FAIL_HISTORY=y
+CONFIG_DP_RX_PEEK_MSDU_DONE_WAR=y

+ 2 - 0
configs/sun_gki_kiwi-v2_defconfig

@@ -395,3 +395,5 @@ CONFIG_RPS=y
 CONFIG_BCN_RATECODE_ENABLE=y
 CONFIG_WLAN_FEATURE_MARK_FIRST_WAKEUP_PACKET=y
 CONFIG_WLAN_MULTI_CHIP_SUPPORT=y
+CONFIG_DP_RX_MSDU_DONE_FAIL_HISTORY=y
+CONFIG_DP_RX_PEEK_MSDU_DONE_WAR=y

+ 12 - 1
core/hdd/src/wlan_hdd_cfg80211.c

@@ -21945,6 +21945,7 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
 	bool is_bigtk_supported;
 	bool is_ocv_supported;
 	uint8_t iface_num;
+	bool dbs_one_by_one, dbs_two_by_two;
 
 	if (!wiphy) {
 		hdd_err("Invalid wiphy");
@@ -22013,7 +22014,17 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
 			}
 		}
 
-		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc)) {
+		status = ucfg_policy_mgr_get_dbs_hw_modes(hdd_ctx->psoc,
+							  &dbs_one_by_one,
+							  &dbs_two_by_two);
+
+		if (QDF_IS_STATUS_ERROR(status)) {
+			hdd_err("HW mode failure");
+			return;
+		}
+
+		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc) ||
+		    (dbs_one_by_one && !dbs_two_by_two)) {
 			wiphy->iface_combinations =
 						wlan_hdd_derived_combination;
 			iface_num = ARRAY_SIZE(wlan_hdd_derived_combination);

+ 2 - 2
core/mac/inc/qwlan_version.h

@@ -32,9 +32,9 @@
 #define QWLAN_VERSION_MAJOR            5
 #define QWLAN_VERSION_MINOR            2
 #define QWLAN_VERSION_PATCH            1
-#define QWLAN_VERSION_EXTRA            "A"
+#define QWLAN_VERSION_EXTRA            "J"
 #define QWLAN_VERSION_BUILD            84
 
-#define QWLAN_VERSIONSTR               "5.2.1.84A"
+#define QWLAN_VERSIONSTR               "5.2.1.84J"
 
 #endif /* QWLAN_VERSION_H */

+ 26 - 0
core/mac/src/cfg/cfgUtil/dot11f.frms

@@ -2586,6 +2586,32 @@ IE transmit_power_env (EID_TRANSMIT_POWER_ENVELOPE)
         max_tx_pwr_category:          2;
     }
     tx_power[1..8];
+    OPTIONAL UNION ext_max_tx_power (DISCRIMINATOR max_tx_pwr_interpret)
+    {
+       ext_max_tx_power_local_eirp (max_tx_pwr_interpret IS 0) {
+               max_tx_power_for_320, 1;
+       }
+       ext_max_tx_power_local_psd (max_tx_pwr_interpret IS 1) {
+               //ext_transmit_psd_info, 1;
+               {
+                       ext_count: 4;
+                       reserved: 4;
+               }
+               max_tx_psd_power[8];
+       }
+       ext_max_tx_power_reg_eirp (max_tx_pwr_interpret IS 2) {
+               max_tx_power_for_320, 1;
+       }
+       ext_max_tx_power_reg_psd (max_tx_pwr_interpret IS 3) {
+               //ext_transmit_psd_info, 1;
+               {
+                       ext_count: 4;
+                       reserved: 4;
+               }
+               max_tx_psd_power[8];
+       }
+
+    };
 }
 
 IE bw_ind_element (EID_EXTN_ID_ELEMENT) OUI (0x87)

+ 20 - 2
core/mac/src/include/dot11f.h

@@ -4947,6 +4947,24 @@ typedef struct sDot11fIEtransmit_power_env {
 	uint8_t  max_tx_pwr_category:2;
 	uint8_t             num_tx_power;
 	uint8_t             tx_power[8];
+	union {
+		struct {
+			uint8_t max_tx_power_for_320;
+		} ext_max_tx_power_local_eirp; /* max_tx_pwr_interpret = 0 */
+		struct {
+			uint8_t  ext_count:4;
+			uint8_t   reserved:4;
+			uint8_t max_tx_psd_power[8];
+		} ext_max_tx_power_local_psd; /* max_tx_pwr_interpret = 1 */
+		struct {
+			uint8_t max_tx_power_for_320;
+		} ext_max_tx_power_reg_eirp; /* max_tx_pwr_interpret = 2 */
+		struct {
+			uint8_t  ext_count:4;
+			uint8_t   reserved:4;
+			uint8_t max_tx_psd_power[8];
+		} ext_max_tx_power_reg_psd; /* max_tx_pwr_interpret = 3 */
+	} ext_max_tx_power;
 } tDot11fIEtransmit_power_env;
 
 #define DOT11F_EID_TRANSMIT_POWER_ENV (195)
@@ -4954,7 +4972,7 @@ typedef struct sDot11fIEtransmit_power_env {
 /* N.B. These #defines do *not* include the EID & length */
 #define DOT11F_IE_TRANSMIT_POWER_ENV_MIN_LEN (2)
 
-#define DOT11F_IE_TRANSMIT_POWER_ENV_MAX_LEN (9)
+#define DOT11F_IE_TRANSMIT_POWER_ENV_MAX_LEN (18)
 
 #ifdef __cplusplus
 extern "C" {
@@ -5198,7 +5216,7 @@ typedef struct sDot11fIEChannelSwitchWrapper {
 /* N.B. These #defines do *not* include the EID & length */
 #define DOT11F_IE_CHANNELSWITCHWRAPPER_MIN_LEN (0)
 
-#define DOT11F_IE_CHANNELSWITCHWRAPPER_MAX_LEN (24)
+#define DOT11F_IE_CHANNELSWITCHWRAPPER_MAX_LEN (33)
 
 #ifdef __cplusplus
 extern "C" {

+ 11 - 1
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -3005,7 +3005,7 @@ lim_update_mlo_mgr_ap_link_info_mbssid_connect(struct pe_session *session)
 {
 	struct mlo_partner_info *partner_info;
 	struct mlo_link_info *partner_link_info;
-	struct wlan_channel channel;
+	struct wlan_channel channel = {0};
 	struct mlo_link_switch_context *link_ctx;
 	uint8_t i = 0;
 
@@ -3094,6 +3094,16 @@ static void lim_process_switch_channel_join_req(
 		goto error;
 	}
 
+	if (lim_connect_skip_join_for_gc(session_entry)) {
+		join_cnf.resultCode = eSIR_SME_SUCCESS;
+		join_cnf.protStatusCode = STATUS_SUCCESS;
+		join_cnf.sessionId = session_entry->peSessionId;
+		lim_post_sme_message(mac_ctx,
+				     LIM_MLM_JOIN_CNF,
+				     (uint32_t *)&join_cnf.resultCode);
+		return;
+	}
+
 	bss = &session_entry->lim_join_req->bssDescription;
 	nontx_bss_id = bss->mbssid_info.profile_num;
 

+ 189 - 3
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -78,6 +78,14 @@
 #include <wlan_mlo_mgr_peer.h>
 #endif
 
+/*
+ * As per spec valid range is range –64 dBm to 63 dBm.
+ * Powers in range of 64 - 191 will be invalid.
+ */
+#define INVALID_TPE_POWER 100
+#define MAX_TX_PWR_COUNT_FOR_160MHZ 3
+#define MAX_NUM_TX_POWER_FOR_320MHZ 5
+
 /* SME REQ processing function templates */
 static bool __lim_process_sme_sys_ready_ind(struct mac_context *, uint32_t *);
 static bool __lim_process_sme_start_bss_req(struct mac_context *,
@@ -4708,6 +4716,17 @@ lim_cm_handle_join_req(struct cm_vdev_join_req *req)
 	lim_dump_he_info(mac_ctx, pe_session);
 	lim_dump_eht_info(pe_session);
 
+	if (lim_connect_skip_join_for_gc(pe_session)) {
+		pe_session->beacon =
+			qdf_mem_malloc(util_scan_entry_frame_len(req->entry));
+		if (!pe_session->beacon)
+			goto fail;
+		pe_session->bcnLen = util_scan_entry_frame_len(req->entry);
+		qdf_mem_copy(pe_session->beacon,
+			     util_scan_entry_frame_ptr(req->entry),
+			     pe_session->bcnLen);
+	}
+
 	status = lim_send_connect_req_to_mlm(pe_session);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		pe_err("Failed to send mlm req vdev id %d",
@@ -5593,6 +5612,143 @@ QDF_STATUS cm_process_preauth_req(struct scheduler_msg *msg)
 }
 #endif
 
+/**
+ * lim_get_eirp_320_power_from_tpe_ie() - To get eirp power for 320 MHZ
+ * @tpe: transmit power env Ie advertised by AP
+ *
+ * Return: eirp power
+ */
+static uint8_t
+lim_get_eirp_320_power_from_tpe_ie(tDot11fIEtransmit_power_env *tpe)
+{
+	uint8_t eirp_power_320_Mhz = 0;
+
+	/*
+	 * Don't consider 320 MHz EIRP power until AP advertises EIRP
+	 * powers till 160 MHz.
+	 */
+	if (tpe->max_tx_pwr_count < MAX_TX_PWR_COUNT_FOR_160MHZ) {
+		pe_debug("tx power count advertised by ap %d less than %d",
+			 tpe->max_tx_pwr_count, MAX_TX_PWR_COUNT_FOR_160MHZ);
+		return INVALID_TPE_POWER;
+	}
+
+	if (tpe->num_tx_power < MAX_NUM_TX_POWER_FOR_320MHZ)
+		return INVALID_TPE_POWER;
+
+	if (tpe->max_tx_pwr_interpret == LOCAL_EIRP)
+		eirp_power_320_Mhz =
+			tpe->ext_max_tx_power.ext_max_tx_power_local_eirp.max_tx_power_for_320;
+	else
+		eirp_power_320_Mhz =
+			tpe->ext_max_tx_power.ext_max_tx_power_reg_eirp.max_tx_power_for_320;
+
+	return eirp_power_320_Mhz;
+}
+
+/**
+ * lim_update_ext_tpe_power() - To update ext max transmit power element
+ * @mac: mac context
+ * @session: pe session
+ * @tpe: transmit power env Ie
+ * @curr_freq: current freq
+ * @tpe_updated: tpe power changed or not
+ * @existing_pwr_count: no of existing pwr updated
+ * @is_psd: is psd or not
+ *
+ * Return: no. of power updated
+ */
+static uint8_t
+lim_update_ext_tpe_power(struct mac_context *mac, struct pe_session *session,
+			 tDot11fIEtransmit_power_env *tpe, qdf_freq_t curr_freq,
+			 bool *tpe_updated, uint8_t existing_pwr_count,
+			 bool is_psd)
+{
+	struct vdev_mlme_obj *vdev_mlme;
+	struct ch_params ch_params = {0};
+	qdf_freq_t curr_op_freq;
+	uint8_t total_psd_power = 0;
+	uint8_t ext_power_updated = 0;
+	uint8_t i, j;
+	uint8_t eirp_pwr = 0;
+	uint8_t ext_psd_count = 0;
+
+	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
+	if (!vdev_mlme)
+		return 0;
+
+	ch_params.ch_width = CH_WIDTH_320MHZ;
+	curr_op_freq = session->curr_op_freq;
+	if (is_psd) {
+		if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD)
+			ext_psd_count =
+			tpe->ext_max_tx_power.ext_max_tx_power_local_psd.ext_count;
+		else
+			ext_psd_count =
+			tpe->ext_max_tx_power.ext_max_tx_power_reg_psd.ext_count;
+
+		if (existing_pwr_count >= MAX_NUM_PWR_LEVEL) {
+			pe_debug("already updated %d psd powers",
+				 existing_pwr_count);
+			return 0;
+		}
+
+		if (!ext_psd_count)  {
+			pe_debug("Ext psd count is 0");
+			return 0;
+		}
+
+		total_psd_power = existing_pwr_count + ext_psd_count;
+
+		i = existing_pwr_count;
+		for (j = 0; j < ext_psd_count && i < total_psd_power; j++)
+		{
+			if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD) {
+				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
+				    tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j] ||
+				    vdev_mlme->reg_tpc_obj.frequency[i] != curr_freq)
+					*tpe_updated = true;
+			} else {
+				if (vdev_mlme->reg_tpc_obj.tpe[i] !=
+				    tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j] ||
+				    vdev_mlme->reg_tpc_obj.frequency[i] != curr_freq)
+					*tpe_updated = true;
+			}
+
+			vdev_mlme->reg_tpc_obj.frequency[i] = curr_freq;
+			curr_freq += 20;
+			if (tpe->max_tx_pwr_interpret == LOCAL_EIRP_PSD)
+				vdev_mlme->reg_tpc_obj.tpe[i] =
+				tpe->ext_max_tx_power.ext_max_tx_power_local_psd.max_tx_psd_power[j];
+			else
+				vdev_mlme->reg_tpc_obj.tpe[i] =
+					tpe->ext_max_tx_power.ext_max_tx_power_reg_psd.max_tx_psd_power[j];
+			i++;
+		}
+		ext_power_updated = i;
+
+	} else {
+		eirp_pwr = lim_get_eirp_320_power_from_tpe_ie(tpe);
+		if (eirp_pwr == INVALID_TPE_POWER)
+			return 0;
+		i = lim_get_num_pwr_levels(false, CH_WIDTH_320MHZ) - 1;
+
+		wlan_reg_set_channel_params_for_pwrmode(
+				mac->pdev, curr_op_freq, 0,
+				&ch_params, REG_CURRENT_PWR_MODE);
+
+		if (vdev_mlme->reg_tpc_obj.tpe[i] != eirp_pwr ||
+		    vdev_mlme->reg_tpc_obj.frequency[i] !=
+							ch_params.mhz_freq_seg0)
+			*tpe_updated = true;
+
+		vdev_mlme->reg_tpc_obj.frequency[i] = ch_params.mhz_freq_seg0;
+		vdev_mlme->reg_tpc_obj.tpe[i] = eirp_pwr;
+		ext_power_updated = 1;
+	}
+	return ext_power_updated;
+}
+
 static uint8_t lim_get_num_tpe_octets(uint8_t max_transmit_power_count)
 {
 	if (!max_transmit_power_count)
@@ -5610,7 +5766,7 @@ void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
 	uint8_t psd_index = 0, non_psd_index = 0;
 	uint8_t bw_num;
 	uint16_t bw_val, ch_width;
-	qdf_freq_t curr_op_freq, curr_freq;
+	qdf_freq_t curr_op_freq, curr_freq = 0;
 	enum reg_6g_client_type client_mobility_type;
 	struct ch_params ch_params = {0};
 	tDot11fIEtransmit_power_env single_tpe, local_tpe, reg_tpe;
@@ -5625,6 +5781,7 @@ void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
 	uint8_t local_eirp_idx = 0, local_psd_idx = 0;
 	uint8_t reg_eirp_idx = 0, reg_psd_idx = 0;
 	uint8_t min_count = 0;
+	uint8_t ext_power_updated = 0, eirp_power = 0;
 
 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(session->vdev);
 	if (!vdev_mlme)
@@ -5709,9 +5866,12 @@ void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
 					single_tpe.max_tx_pwr_count + 1;
 
 		ch_params.ch_width = CH_WIDTH_20MHZ;
-
+		/*
+		 * Update tpe power till 160 MHZ, 320 MHZ power will be
+		 * advertised via ext_max_tx_power param of TPE IE.
+		 */
 		for (i = 0; i < single_tpe.max_tx_pwr_count + 1 &&
-		     (ch_params.ch_width != CH_WIDTH_INVALID); i++) {
+		     (ch_params.ch_width != CH_WIDTH_320MHZ); i++) {
 			wlan_reg_set_channel_params_for_pwrmode(
 							mac->pdev,
 							curr_op_freq, 0,
@@ -5729,6 +5889,16 @@ void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
 				ch_params.ch_width =
 					get_next_higher_bw[ch_params.ch_width];
 		}
+
+		if (ch_params.ch_width == CH_WIDTH_320MHZ) {
+			ext_power_updated =
+				lim_update_ext_tpe_power(
+						mac, session, &single_tpe,
+						curr_freq, has_tpe_updated,
+						0, false);
+			vdev_mlme->reg_tpc_obj.num_pwr_levels +=
+							ext_power_updated;
+		}
 	}
 
 	if (psd_set) {
@@ -5780,12 +5950,28 @@ void lim_parse_tpe_ie(struct mac_context *mac, struct pe_session *session,
 							single_tpe.tx_power[i];
 			}
 		}
+			ext_power_updated =
+			lim_update_ext_tpe_power(mac, session, &single_tpe,
+						 curr_freq, has_tpe_updated,
+						 num_octets, true);
+			vdev_mlme->reg_tpc_obj.num_pwr_levels =
+							ext_power_updated;
 	}
 
 	if (non_psd_set) {
 		single_tpe = tpe_ies[non_psd_index];
 		vdev_mlme->reg_tpc_obj.eirp_power =
 			single_tpe.tx_power[single_tpe.max_tx_pwr_count];
+		/*
+		 * If a valid eirp power is received in 320 MHZ via ext element
+		 * then update eirp power with received eirp.
+		 */
+		if (session->ch_width == CH_WIDTH_320MHZ) {
+			eirp_power =
+				lim_get_eirp_320_power_from_tpe_ie(&single_tpe);
+			if (eirp_power != INVALID_TPE_POWER)
+				vdev_mlme->reg_tpc_obj.eirp_power = eirp_power;
+		}
 		vdev_mlme->reg_tpc_obj.is_psd_power = false;
 	}
 

+ 48 - 9
core/mac/src/pe/lim/lim_process_tdls.c

@@ -98,6 +98,21 @@ static const uint8_t eth_890d_header[] = {
 	0x00, 0x00, 0x89, 0x0d,
 };
 
+#define ETH_ADDR_LEN 6 /* bytes */
+
+struct tdls_ethernet_hdr {
+	uint8_t dest_addr[ETH_ADDR_LEN];
+	uint8_t src_addr[ETH_ADDR_LEN];
+} qdf_packed;
+
+#define eth_890d_hdr_len 2 /* bytes */
+
+static const uint8_t eth_890d_tdls_discvory_frm_hdr[] = {
+	0x89, 0x0d, 0x02, 0x0c, 0x0a,
+};
+
+#define TDLS_ETHR_HDR_LEN (sizeof(struct tdls_ethernet_hdr))
+
 /*
  * type of links used in TDLS
  */
@@ -547,21 +562,45 @@ static uint32_t lim_prepare_tdls_frame_header(struct mac_context *mac, uint8_t *
  * @tx_complete: indicates tx success/failure
  * @params: tx completion params
  *
- * function will be invoked on receiving tx completion indication
+ * Function will be invoked on receiving tx completion indication
  *
- * return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE
+ * Return: success: eHAL_STATUS_SUCCESS failure: eHAL_STATUS_FAILURE
  */
-static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context,
-					    qdf_nbuf_t buf,
-					    uint32_t tx_complete,
-					    void *params)
+static QDF_STATUS lim_mgmt_tdls_tx_complete(void *context, qdf_nbuf_t buf,
+					    uint32_t tx_complete, void *params)
 {
 	struct mac_context *mac_ctx = (struct mac_context *)context;
+	struct tdls_ethernet_hdr *ethernet_hdr;
+	tpSirMacActionFrameHdr action_hdr;
+	bool is_tdls_discvory_frm;
 
 	pe_debug("tdls_frm_session_id: %x tx_complete: %x",
-		mac_ctx->lim.tdls_frm_session_id, tx_complete);
+		 mac_ctx->lim.tdls_frm_session_id, tx_complete);
 
 	if (NO_SESSION != mac_ctx->lim.tdls_frm_session_id) {
+		if (buf &&
+		    (qdf_nbuf_len(buf) >= (TDLS_ETHR_HDR_LEN +
+					  eth_890d_hdr_len +
+					  PAYLOAD_TYPE_TDLS_SIZE +
+					  sizeof(*action_hdr)))) {
+			ethernet_hdr =
+				(struct tdls_ethernet_hdr *)qdf_nbuf_data(buf);
+			is_tdls_discvory_frm =
+				!qdf_mem_cmp(((uint8_t *)qdf_nbuf_data(buf) +
+				TDLS_ETHR_HDR_LEN),
+				eth_890d_tdls_discvory_frm_hdr,
+				sizeof(eth_890d_tdls_discvory_frm_hdr));
+
+			pe_debug("is_tdls_discvory_frm: %d",
+				 is_tdls_discvory_frm);
+			if (is_tdls_discvory_frm &&
+			    tx_complete == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
+				wlan_tdls_increment_discovery_attempts(
+					mac_ctx->psoc,
+					mac_ctx->lim.tdls_frm_session_id,
+					ethernet_hdr->dest_addr);
+		}
+
 		lim_send_sme_mgmt_tx_completion(mac_ctx,
 				mac_ctx->lim.tdls_frm_session_id,
 				tx_complete);
@@ -3886,8 +3925,8 @@ lim_send_tdls_comp_mgmt_rsp(struct mac_context *mac_ctx, uint16_t msg_type,
 	struct tdls_send_mgmt_rsp *sme_rsp;
 	QDF_STATUS status;
 
-	pe_debug("Sending message %s with reasonCode %s",
-		lim_msg_str(msg_type), lim_result_code_str(result_code));
+	pe_debug("vdev:%d Sending message %s with reasonCode %s", vdev_id,
+		 lim_msg_str(msg_type), lim_result_code_str(result_code));
 
 	sme_rsp = qdf_mem_malloc(sizeof(*sme_rsp));
 	if (!sme_rsp)

+ 17 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -3272,6 +3272,23 @@ lim_skip_tpc_update_for_sta(struct mac_context *mac,
 			    struct pe_session *sta_session,
 			    struct pe_session *sap_session);
 
+#ifdef FEATURE_WLAN_GC_SKIP_JOIN
+static inline bool
+lim_connect_skip_join_for_gc(struct pe_session *pe_session)
+{
+	if (pe_session->opmode == QDF_P2P_CLIENT_MODE)
+		return true;
+	else
+		return false;
+}
+#else
+static inline bool
+lim_connect_skip_join_for_gc(struct pe_session *pe_session)
+{
+	return false;
+}
+#endif
+
 /**
  * lim_get_concurrent_session() - Function to get the concurrent session pointer
  *

+ 13 - 1
core/mac/src/pe/sch/sch_beacon_process.c

@@ -52,6 +52,7 @@
 #include "wlan_reg_services_api.h"
 #include "wlan_mlo_mgr_sta.h"
 #include "wlan_mlme_main.h"
+#include <wlan_mlo_mgr_link_switch.h>
 
 static void
 ap_beacon_process_5_ghz(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
@@ -1028,8 +1029,19 @@ sch_beacon_process(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
 	if (!session)
 		return;
 
+	/*
+	 * Drop the beacon/probe response from current connected AP in
+	 * below cases to avoid responding to the changes in beacon(e.g. doing
+	 * VDEV_RESTART to update to the latest capabilities),
+	 * 1. vdev is not in connected state: vdev might be transitioning
+	 * 2. Link switch is in progress: Current link or one of the partner
+	 *                                links are getting replaced.
+	 *
+	 * New beacons/probe rsps can be considered once post these operations.
+	 */
 	if (LIM_IS_STA_ROLE(session) &&
-	    !wlan_cm_is_vdev_connected(session->vdev)) {
+	    (!wlan_cm_is_vdev_connected(session->vdev) ||
+	     mlo_mgr_is_link_switch_in_progress(session->vdev))) {
 		pe_debug_rl("vdev %d, drop beacon", session->vdev_id);
 		return;
 	}

ファイルの差分が大きいため隠しています
+ 316 - 246
core/mac/src/sys/legacy/src/utils/src/dot11f.c


+ 3 - 2
core/mac/src/sys/legacy/src/utils/src/parser_api.c

@@ -4264,7 +4264,7 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
 						 session_entry, ar, pAssocRsp);
 	sir_convert_assoc_resp_frame2_t2lm_struct(mac, frame, frame_len,
 						  session_entry, ar, pAssocRsp);
-	pe_debug("ht %d vht %d vendor vht: cap %d op %d, he %d he 6ghband %d eht %d eht320 %d, max idle: present %d val %d, he mu edca %d wmm %d qos %d",
+	pe_debug("ht %d vht %d vendor vht: cap %d op %d, he %d he 6ghband %d eht %d eht320 %d, max idle: present %d val %d, he mu edca %d wmm %d qos %d mlo %d",
 		 ar->HTCaps.present, ar->VHTCaps.present,
 		 ar->vendor_vht_ie.VHTCaps.present,
 		 ar->vendor_vht_ie.VHTOperation.present, ar->he_cap.present,
@@ -4273,7 +4273,8 @@ sir_convert_assoc_resp_frame2_struct(struct mac_context *mac,
 		 ar->bss_max_idle_period.present,
 		 pAssocRsp->bss_max_idle_period.max_idle_period,
 		 ar->mu_edca_param_set.present, ar->WMMParams.present,
-		 ar->QosMapSet.present);
+		 ar->QosMapSet.present,
+		 ar->mlo_ie.present);
 
 	if (ar->WMMParams.present)
 		__print_wmm_params(mac, &ar->WMMParams);

+ 28 - 45
core/sme/src/common/sme_power_save.c

@@ -313,27 +313,6 @@ QDF_STATUS sme_ps_process_command(struct mac_context *mac_ctx, uint32_t session_
 	return status;
 }
 
-#ifdef QCA_WIFI_EMULATION
-static QDF_STATUS sme_ps_enable_user_check(bool usr_cfg_ps_enable,
-					   enum sme_ps_cmd command,
-					   uint32_t session_id)
-{
-	return QDF_STATUS_SUCCESS;
-}
-#else
-static QDF_STATUS sme_ps_enable_user_check(bool usr_cfg_ps_enable,
-					   enum sme_ps_cmd command,
-					   uint32_t session_id)
-{
-	if (command == SME_PS_ENABLE && !usr_cfg_ps_enable) {
-		sme_debug("vdev:%d Cannot initiate PS. PS is disabled by usr(ioctl)",
-			  session_id);
-		return QDF_STATUS_E_FAILURE;
-	}
-	return QDF_STATUS_SUCCESS;
-}
-#endif
-
 /**
  * sme_enable_sta_ps_check(): Checks if it is ok to enable power save or not.
  * @mac_ctx: global mac context
@@ -346,33 +325,37 @@ static QDF_STATUS sme_ps_enable_user_check(bool usr_cfg_ps_enable,
  * Return: QDF_STATUS
  */
 QDF_STATUS sme_enable_sta_ps_check(struct mac_context *mac_ctx,
-				   uint32_t session_id, enum sme_ps_cmd command)
+				   uint32_t vdev_id, enum sme_ps_cmd command)
 {
-	struct wlan_mlme_powersave *powersave_params;
 	bool usr_cfg_ps_enable;
 
-	QDF_BUG(session_id < WLAN_MAX_VDEVS);
-	if (session_id >= WLAN_MAX_VDEVS)
+	QDF_BUG(vdev_id < WLAN_MAX_VDEVS);
+	if (vdev_id >= WLAN_MAX_VDEVS)
 		return QDF_STATUS_E_INVAL;
 
-	/* Check if Sta Ps is enabled. */
-	powersave_params = &mac_ctx->mlme_cfg->ps_params;
-	if (!powersave_params->is_bmps_enabled) {
-		sme_debug("Cannot initiate PS. PS is disabled in ini");
+	if (!mac_ctx->mlme_cfg->ps_params.is_bmps_enabled) {
+		sme_debug("vdev:%d power save mode is disabled via ini", vdev_id);
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	usr_cfg_ps_enable = mlme_get_user_ps(mac_ctx->psoc, session_id);
-
-	if (sme_ps_enable_user_check(usr_cfg_ps_enable, command, session_id)
-	    != QDF_STATUS_SUCCESS)
+	usr_cfg_ps_enable = mlme_get_user_ps(mac_ctx->psoc, vdev_id);
+	if (command == SME_PS_ENABLE && !usr_cfg_ps_enable) {
+		sme_debug("vdev:%d power save mode is disabled by usr(ioctl)",
+			  vdev_id);
 		return QDF_STATUS_E_FAILURE;
+	}
+
+	/*
+	 * If command is power save disable there is not need to check for
+	 * connected or roaming state as firmware can handle this
+	 */
+	if (command == SME_PS_DISABLE)
+		return QDF_STATUS_SUCCESS;
 
-	/* Check whether the given session is Infra and in Connected State
-	 * also if command is power save disable  there is not need to check
-	 * for connected state as firmware can handle this
+	/* If command is power save enable, check whether the given session is
+	 * in connected or roaming state or not
 	 */
-	if (!cm_is_vdevid_connected(mac_ctx->pdev, session_id))
+	if (!cm_is_vdevid_active(mac_ctx->pdev, vdev_id))
 		return QDF_STATUS_E_FAILURE;
 
 	return QDF_STATUS_SUCCESS;
@@ -381,12 +364,12 @@ QDF_STATUS sme_enable_sta_ps_check(struct mac_context *mac_ctx,
 /**
  * sme_ps_enable_disable(): function to enable/disable PS.
  * @mac_handle: Opaque handle to the global MAC context
- * @session_id: session id
+ * @vdev_id: session id
  * sme_ps_cmd: power save message
  *
  * Return: QDF_STATUS
  */
-QDF_STATUS sme_ps_enable_disable(mac_handle_t mac_handle, uint32_t session_id,
+QDF_STATUS sme_ps_enable_disable(mac_handle_t mac_handle, uint32_t vdev_id,
 				 enum sme_ps_cmd command)
 {
 	QDF_STATUS status;
@@ -398,19 +381,19 @@ QDF_STATUS sme_ps_enable_disable(mac_handle_t mac_handle, uint32_t session_id,
 		return status;
 	}
 
-	status =  sme_enable_sta_ps_check(mac_ctx, session_id, command);
-	if (status != QDF_STATUS_SUCCESS) {
+	status =  sme_enable_sta_ps_check(mac_ctx, vdev_id, command);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		/*
 		 * In non associated state driver won't handle the power save
-		 * But kernel expects return status success even
-		 * in the disconnected state.
+		 * But kernel expects return status success even in the
+		 * disconnected state.
 		 */
-		if (!cm_is_vdevid_connected(mac_ctx->pdev, session_id))
+		if (!cm_is_vdevid_active(mac_ctx->pdev, vdev_id))
 			status = QDF_STATUS_SUCCESS;
 		sme_release_global_lock(&mac_ctx->sme);
 		return status;
 	}
-	status = sme_ps_process_command(mac_ctx, session_id, command);
+	status = sme_ps_process_command(mac_ctx, vdev_id, command);
 	sme_release_global_lock(&mac_ctx->sme);
 
 	return status;

+ 2 - 0
core/wma/inc/wma.h

@@ -1124,12 +1124,14 @@ enum frame_index {
  * @sub_type: sub type
  * @status: status
  * @ack_cmp_work: work structure
+ * @frame: frame nbuf
  */
 struct wma_tx_ack_work_ctx {
 	tp_wma_handle wma_handle;
 	uint16_t sub_type;
 	int32_t status;
 	qdf_work_t ack_cmp_work;
+	qdf_nbuf_t frame;
 };
 
 /**

+ 59 - 29
core/wma/src/wma_data.c

@@ -963,23 +963,27 @@ static void wma_data_tx_ack_work_handler(void *ack_work)
 	wma_handle = work->wma_handle;
 	if (!wma_handle || cds_is_load_or_unload_in_progress()) {
 		wma_err("Driver load/unload in progress");
-		goto end;
+		goto free_frame;
 	}
+
+	wma_debug("Data Tx Ack Cb Status %d", work->status);
 	ack_cb = wma_handle->umac_data_ota_ack_cb;
+	if (!ack_cb) {
+		wma_err("Data Tx Ack Cb is NULL");
+		goto free_frame;
+	}
 
-	if (work->status)
-		wma_debug("Data Tx Ack Cb Status %d", work->status);
-	else
-		wma_debug("Data Tx Ack Cb Status %d", work->status);
+	ack_cb(wma_handle->mac_context, work->frame, work->status,
+	       NULL);
+	goto end;
 
-	/* Call the Ack Cb registered by UMAC */
-	if (ack_cb)
-		ack_cb(wma_handle->mac_context, NULL, work->status, NULL);
-	else
-		wma_err("Data Tx Ack Cb is NULL");
+free_frame:
+	if (work->frame)
+		qdf_nbuf_free(work->frame);
 
 end:
 	qdf_mem_free(work);
+
 	if (wma_handle) {
 		wma_handle->umac_data_ota_ack_cb = NULL;
 		wma_handle->last_umac_data_nbuf = NULL;
@@ -1002,38 +1006,59 @@ void
 wma_data_tx_ack_comp_hdlr(void *wma_context, qdf_nbuf_t netbuf, int32_t status)
 {
 	tp_wma_handle wma_handle = (tp_wma_handle) wma_context;
+	struct wma_tx_ack_work_ctx *ack_work;
+	QDF_STATUS qdf_status;
 
 	if (wma_validate_handle(wma_handle))
 		return;
 
+	if (!netbuf) {
+		wma_debug("netbuf is NULL");
+		return;
+	}
+
 	/*
 	 * if netBuf does not match with pending nbuf then just free the
 	 * netbuf and do not call ack cb
 	 */
 	if (wma_handle->last_umac_data_nbuf != netbuf) {
-		if (wma_handle->umac_data_ota_ack_cb) {
-			wma_err("nbuf does not match but umac_data_ota_ack_cb is not null");
-		} else {
-			wma_err("nbuf does not match and umac_data_ota_ack_cb is also null");
-		}
+		wma_err("nbuf does not match but umac_data_ota_ack_cb is %s null",
+			wma_handle->umac_data_ota_ack_cb ? "not" : "");
 		goto free_nbuf;
 	}
 
-	if (wma_handle->umac_data_ota_ack_cb) {
-		struct wma_tx_ack_work_ctx *ack_work;
+	if (!wma_handle->umac_data_ota_ack_cb) {
+		wma_err_rl("ota_ack cb not registered");
+		goto free_nbuf;
+	}
 
-		ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx));
+	ack_work = qdf_mem_malloc(sizeof(struct wma_tx_ack_work_ctx));
+	if (ack_work) {
 		wma_handle->ack_work_ctx = ack_work;
-		if (ack_work) {
-			ack_work->wma_handle = wma_handle;
-			ack_work->sub_type = 0;
-			ack_work->status = status;
-
-			qdf_create_work(0, &ack_work->ack_cmp_work,
-					wma_data_tx_ack_work_handler,
-					ack_work);
-			qdf_sched_work(0, &ack_work->ack_cmp_work);
+
+		ack_work->wma_handle = wma_handle;
+		ack_work->sub_type = 0;
+		ack_work->status = status;
+		ack_work->frame = netbuf;
+
+		/*
+		 * free of the netbuf will be done by the scheduled work so
+		 * just do unmap here
+		 */
+		qdf_nbuf_unmap_single(wma_handle->qdf_dev, netbuf,
+				      QDF_DMA_TO_DEVICE);
+
+		qdf_status = qdf_create_work(0, &ack_work->ack_cmp_work,
+					     wma_data_tx_ack_work_handler,
+					     ack_work);
+		if (QDF_IS_STATUS_ERROR(qdf_status)) {
+			qdf_nbuf_free(netbuf);
+			wma_err("Failed to create TX ack work");
+			return;
 		}
+
+		qdf_sched_work(0, &ack_work->ack_cmp_work);
+		return;
 	}
 
 free_nbuf:
@@ -2314,6 +2339,11 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (vdev_id >= wma_handle->max_bssid) {
+		wma_err("tx packet with invalid vdev_id :%d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	iface = &wma_handle->interfaces[vdev_id];
 
 	if (!soc) {
@@ -2345,7 +2375,7 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 		return QDF_STATUS_E_FAILURE;
 	}
 
-	if ((iface && (iface->rmfEnabled || tx_flag & HAL_USE_PMF)) &&
+	if (((iface->rmfEnabled || tx_flag & HAL_USE_PMF)) &&
 	    (frmType == TXRX_FRM_802_11_MGMT) &&
 	    (pFc->subType == SIR_MAC_MGMT_DISASSOC ||
 	     pFc->subType == SIR_MAC_MGMT_DEAUTH ||
@@ -2692,7 +2722,7 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 	mgmt_param.use_6mbps = use_6mbps;
 	mgmt_param.tx_type = tx_frm_index;
 	mgmt_param.peer_rssi = peer_rssi;
-	if (iface && wlan_vdev_mlme_get_opmode(iface->vdev) == QDF_STA_MODE &&
+	if (wlan_vdev_mlme_get_opmode(iface->vdev) == QDF_STA_MODE &&
 	    wlan_vdev_mlme_is_mlo_vdev(iface->vdev) &&
 	    (wlan_vdev_mlme_is_active(iface->vdev) == QDF_STATUS_SUCCESS) &&
 	    frmType == TXRX_FRM_802_11_MGMT &&

+ 1 - 2
core/wma/src/wma_dev_if.c

@@ -412,7 +412,7 @@ QDF_STATUS wma_vdev_detach_callback(struct vdev_delete_response *rsp)
 		return QDF_STATUS_E_FAILURE;
 
 	/* Sanitize the vdev id*/
-	if (rsp->vdev_id > wma->max_bssid) {
+	if (rsp->vdev_id >= wma->max_bssid) {
 		wma_err("vdev delete response with invalid vdev_id :%d",
 			rsp->vdev_id);
 		QDF_BUG(0);
@@ -729,7 +729,6 @@ QDF_STATUS wma_vdev_detach(struct del_vdev_params *pdel_vdev_req_param)
 	iface = &wma_handle->interfaces[vdev_id];
 	if (!iface->vdev) {
 		wma_err("vdev %d is NULL", vdev_id);
-		mlme_vdev_self_peer_delete_resp(pdel_vdev_req_param);
 		return status;
 	}
 

+ 3 - 0
core/wma/src/wma_main.c

@@ -4813,6 +4813,9 @@ QDF_STATUS wma_stop(void)
 
 	if (wma_handle->ack_work_ctx) {
 		cds_flush_work(&wma_handle->ack_work_ctx->ack_cmp_work);
+		if (wma_handle->ack_work_ctx->frame)
+			qdf_nbuf_free(wma_handle->ack_work_ctx->frame);
+
 		qdf_mem_free(wma_handle->ack_work_ctx);
 		wma_handle->ack_work_ctx = NULL;
 	}

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません