Sfoglia il codice sorgente

Merge 20b5a974e588dec0851d13e7f9ef04c44c02b7f4 on remote branch

Change-Id: Ie6b745f9955589fc2b42c4c4349bdfe5bfa1738d
Linux Build Service Account 1 anno fa
parent
commit
ff9aae7889
82 ha cambiato i file con 2404 aggiunte e 725 eliminazioni
  1. 4 0
      Android.mk
  2. 11 0
      Kbuild
  3. 10 0
      Kconfig
  4. 1 1
      components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c
  5. 67 8
      components/cmn_services/logging/inc/wlan_connectivity_logging.h
  6. 25 0
      components/cmn_services/logging/src/wlan_connectivity_logging.c
  7. 6 0
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
  8. 3 2
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
  9. 131 6
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
  10. 10 23
      components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
  11. 1 1
      components/dp/core/src/wlan_dp_fisa_rx.h
  12. 4 4
      components/fw_offload/dispatcher/inc/cfg_coex.h
  13. 26 0
      components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h
  14. 3 1
      components/mlme/core/src/wlan_mlme_main.c
  15. 53 14
      components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c
  16. 3 2
      components/mlme/dispatcher/inc/cfg_mlme_fe_rrm.h
  17. 1 1
      components/mlme/dispatcher/inc/cfg_mlme_generic.h
  18. 2 2
      components/mlme/dispatcher/inc/cfg_mlme_he_caps.h
  19. 57 0
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  20. 3 0
      components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
  21. 54 0
      components/mlme/dispatcher/src/wlan_mlme_api.c
  22. 3 2
      components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
  23. 4 0
      components/pkt_capture/core/inc/wlan_pkt_capture_priv.h
  24. 13 0
      components/pkt_capture/core/src/wlan_pkt_capture_main.c
  25. 1 1
      components/target_if/cp_stats/src/target_if_mc_cp_stats.c
  26. 3 0
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c
  27. 15 3
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  28. 27 3
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c
  29. 26 8
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  30. 39 0
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h
  31. 5 0
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h
  32. 54 1
      components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c
  33. 8 6
      components/umac/mlme/mlo_mgr/src/wlan_epcs_api.c
  34. 46 0
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.c
  35. 15 1
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.h
  36. 7 4
      components/wmi/src/wmi_unified_roam_tlv.c
  37. 10 0
      configs/config_to_feature.h
  38. 15 0
      configs/default_defconfig
  39. 4 0
      configs/kiwi_v2_defconfig
  40. 2 0
      configs/peach_defconfig
  41. 3 0
      configs/pineapple_gki_kiwi-v2_defconfig
  42. 2 0
      configs/wcn6450_defconfig
  43. 32 2
      core/hdd/inc/wlan_hdd_assoc.h
  44. 22 1
      core/hdd/inc/wlan_hdd_ipa.h
  45. 120 3
      core/hdd/src/wlan_hdd_assoc.c
  46. 137 27
      core/hdd/src/wlan_hdd_cfg80211.c
  47. 10 0
      core/hdd/src/wlan_hdd_cfg80211.h
  48. 18 3
      core/hdd/src/wlan_hdd_cm_connect.c
  49. 21 44
      core/hdd/src/wlan_hdd_he.c
  50. 19 2
      core/hdd/src/wlan_hdd_hostapd.c
  51. 49 10
      core/hdd/src/wlan_hdd_ioctl.c
  52. 150 1
      core/hdd/src/wlan_hdd_ipa.c
  53. 41 14
      core/hdd/src/wlan_hdd_main.c
  54. 6 1
      core/hdd/src/wlan_hdd_sar_limits.c
  55. 39 0
      core/hdd/src/wlan_hdd_station_info.c
  56. 32 48
      core/hdd/src/wlan_hdd_stats.c
  57. 3 0
      core/hdd/src/wlan_hdd_sysfs.c
  58. 158 0
      core/hdd/src/wlan_hdd_sysfs_rf_test_mode.c
  59. 61 0
      core/hdd/src/wlan_hdd_sysfs_rf_test_mode.h
  60. 2 2
      core/mac/inc/qwlan_version.h
  61. 0 20
      core/mac/src/pe/include/lim_api.h
  62. 9 208
      core/mac/src/pe/lim/lim_api.c
  63. 4 3
      core/mac/src/pe/lim/lim_mlo.c
  64. 39 17
      core/mac/src/pe/lim/lim_process_beacon_frame.c
  65. 10 6
      core/mac/src/pe/lim/lim_send_management_frames.c
  66. 30 0
      core/mac/src/pe/lim/lim_send_sme_rsp_messages.c
  67. 57 34
      core/mac/src/pe/lim/lim_utils.c
  68. 7 7
      core/mac/src/pe/lim/lim_utils.h
  69. 114 68
      core/mac/src/pe/rrm/rrm_api.c
  70. 15 20
      core/mac/src/pe/sch/sch_beacon_process.c
  71. 14 10
      core/mac/src/sys/legacy/src/utils/src/parser_api.c
  72. 25 4
      core/sap/inc/sap_api.h
  73. 16 11
      core/sap/src/sap_ch_select.c
  74. 17 0
      core/sap/src/sap_internal.h
  75. 54 3
      core/sap/src/sap_module.c
  76. 22 0
      core/sme/src/common/sme_api.c
  77. 10 0
      core/sme/src/csr/csr_util.c
  78. 6 3
      core/sme/src/rrm/sme_rrm.c
  79. 12 8
      core/wma/src/wma_dev_if.c
  80. 231 44
      core/wma/src/wma_features.c
  81. 5 2
      core/wma/src/wma_sar_public_structs.h
  82. 10 5
      wlan_qcacld3_modules.bzl

+ 4 - 0
Android.mk

@@ -16,6 +16,10 @@ endef
 LOCAL_MODULE_DDK_BUILD := false
 LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := false
 
+ifeq ($(TARGET_BOARD_PLATFORM), sun)
+LOCAL_MODULE_DDK_BUILD := true
+LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := true
+endif
 ifeq ($(TARGET_BOARD_PLATFORM), pineapple)
 LOCAL_MODULE_DDK_BUILD := true
 LOCAL_MODULE_DDK_ALLOW_UNSAFE_HEADERS := true

+ 11 - 0
Kbuild

@@ -476,6 +476,10 @@ ifeq ($(CONFIG_WLAN_SYSFS_ROAM_TRIGGER_BITMAP), y)
 HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_roam_trigger_bitmap.o
 endif
 
+ifeq ($(CONFIG_WLAN_SYSFS_RF_TEST_MODE), y)
+HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_sysfs_rf_test_mode.o
+endif
+
 endif # CONFIG_WLAN_SYSFS
 
 ifeq ($(CONFIG_QCACLD_FEATURE_FW_STATE), y)
@@ -3661,6 +3665,7 @@ ccflags-$(CONFIG_WLAN_SYSFS_DFSNOL) += -DCONFIG_WLAN_SYSFS_DFSNOL
 ccflags-$(CONFIG_WLAN_SYSFS_WDS_MODE) += -DFEATURE_SYSFS_WDS_MODE
 ccflags-$(CONFIG_WLAN_SYSFS_ROAM_TRIGGER_BITMAP) += -DFEATURE_SYSFS_ROAM_TRIGGER_BITMAP
 cppflags-$(CONFIG_BCN_RATECODE_ENABLE) += -DWLAN_BCN_RATECODE_ENABLE
+ccflags-$(CONFIG_WLAN_SYSFS_RF_TEST_MODE) += -DFEATURE_SYSFS_RF_TEST_MODE
 
 ifeq ($(CONFIG_LEAK_DETECTION), y)
 ccflags-y += \
@@ -4798,6 +4803,12 @@ endif
 ifdef CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES
 ccflags-y += -DDP_RX_BUFFER_POOL_ALLOC_THRES=$(CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES)
 endif
+ifdef CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE
+ccflags-y += -DDP_RX_REFILL_BUFF_POOL_SIZE=$(CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE)
+endif
+ifdef CONFIG_DP_RX_REFILL_THRD_THRESHOLD
+ccflags-y += -DDP_RX_REFILL_THRD_THRESHOLD=$(CONFIG_DP_RX_REFILL_THRD_THRESHOLD)
+endif
 endif
 
 ccflags-$(CONFIG_DP_FT_LOCK_HISTORY) += -DDP_FT_LOCK_HISTORY

+ 10 - 0
Kconfig

@@ -225,6 +225,12 @@ config DP_RX_BUFFER_POOL_ALLOC_THRES
 config DP_RX_BUFFER_POOL_SIZE
 	int "Enable DP_RX_BUFFER_POOL_SIZE"
 
+config DP_RX_REFILL_BUFF_POOL_SIZE
+	int "Enable DP_RX_REFILL_BUFF_POOL_SIZE"
+
+config DP_RX_REFILL_THRD_THRESHOLD
+	int "Enable DP_RX_REFILL_THRD_THRESHOLD"
+
 config DP_RX_DROP_RAW_FRM
 	bool "Enable DP_RX_DROP_RAW_FRM"
 	default n
@@ -1895,4 +1901,8 @@ config QCA_WIFI_PEACH
 config BCN_RATECODE_ENABLE
 	bool "enable CONFIG_BCN_RATECODE_ENABLE"
 	default n
+
+config WLAN_SYSFS_RF_TEST_MODE
+	bool "enable CONFIG_WLAN_SYSFS_RF_TEST_MODE"
+	default n
 endif # QCA_CLD_WLAN

+ 1 - 1
components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c

@@ -66,7 +66,7 @@ if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev *pdev,
 			     struct wlan_objmgr_vdev *vdev,
 			     uint8_t cur_vdev_id)
 {
-	return true;
+	return false;
 }
 #endif
 

+ 67 - 8
components/cmn_services/logging/inc/wlan_connectivity_logging.h

@@ -26,6 +26,7 @@
 
 #include "wlan_logging_sock_svc.h"
 #include "wlan_cm_roam_public_struct.h"
+#include "wlan_mlo_mgr_public_structs.h"
 
 #define WLAN_MAX_LOGGING_FREQ 120
 
@@ -1205,7 +1206,24 @@ wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
  * Return: None
  */
 void wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev);
+#else
+static inline void
+wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev)
+{
+}
+#endif
 
+/**
+ * wlan_populate_vsie() - Populate VSIE field for logging
+ * @vdev: vdev pointer
+ * @data: Diag packet info data
+ * @is_tx: flag to indicate whether packet transmitted or received
+ *
+ * Return: None
+ */
+void
+wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
+		   struct wlan_diag_packet_info *data, bool is_tx);
 /**
  * wlan_convert_freq_to_diag_band() - API to convert frequency to band value
  * mentioned in enum wlan_diag_wifi_band
@@ -1216,12 +1234,6 @@ void wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev);
 enum wlan_diag_wifi_band
 wlan_convert_freq_to_diag_band(uint16_t ch_freq);
 
-#else
-static inline
-void wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev)
-{
-}
-#endif
 static inline void wlan_connectivity_logging_stop(void)
 {}
 
@@ -1234,6 +1246,7 @@ void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
 				 uint8_t vdev_id);
 
+
 #elif defined(WLAN_FEATURE_CONNECTIVITY_LOGGING)
 /**
  * wlan_connectivity_logging_start()  - Initialize the connectivity/roaming
@@ -1323,6 +1336,28 @@ wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
 void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
 				 uint8_t vdev_id);
+
+/**
+ * wlan_convert_freq_to_diag_band() - API to convert frequency to band value
+ * mentioned in enum wlan_diag_wifi_band
+ * @ch_freq: Frequency(in MHz)
+ *
+ * Return: Band specified in enum wlan_diag_wifi_band
+ */
+enum wlan_diag_wifi_band
+wlan_convert_freq_to_diag_band(uint16_t ch_freq);
+
+/**
+ * wlan_populate_vsie() - Populate VSIE field for logging
+ * @vdev: vdev pointer
+ * @data: Diag packet info data
+ * @is_tx: flag to indicate whether packet transmitted or received
+ *
+ * Return: None
+ */
+void
+wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
+		   struct wlan_diag_packet_info *data, bool is_tx);
 #else
 static inline
 void wlan_connectivity_logging_start(struct wlan_objmgr_psoc *psoc,
@@ -1361,10 +1396,34 @@ wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
 {
 }
 
+static inline enum wlan_diag_wifi_band
+wlan_convert_freq_to_diag_band(uint16_t ch_freq)
+{
+	return WLAN_INVALID_BAND;
+}
+
 static inline void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
 				 uint8_t vdev_id)
-{
-}
+{}
 #endif
+
+#if defined(CONNECTIVITY_DIAG_EVENT) && defined(WLAN_FEATURE_11BE_MLO)
+/**
+ * wlan_connectivity_mld_link_status_event() - Send connectivity logging
+ * ML Link Status event
+ * @psoc: Pointer to global PSOC object
+ * @src: Src parameters to be sent
+ *
+ * Return: None
+ */
+void
+wlan_connectivity_mld_link_status_event(struct wlan_objmgr_psoc *psoc,
+					struct mlo_link_switch_params *src);
+#else
+static inline
+void wlan_connectivity_mld_link_status_event(struct wlan_objmgr_psoc *psoc,
+					     struct mlo_link_switch_params *src)
+{}
+#endif /* CONNECTIVITY_DIAG_EVENT && WLAN_FEATURE_11BE_MLO */
 #endif /* _WLAN_CONNECTIVITY_LOGGING_H_ */

+ 25 - 0
components/cmn_services/logging/src/wlan_connectivity_logging.c

@@ -647,4 +647,29 @@ out:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
 
 }
+
+#ifdef WLAN_FEATURE_11BE_MLO
+void wlan_connectivity_mld_link_status_event(struct wlan_objmgr_psoc *psoc,
+					     struct mlo_link_switch_params *src)
+{
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event,
+				 struct wlan_diag_mlo_link_status);
+
+	qdf_mem_zero(&wlan_diag_event,
+
+		     sizeof(struct wlan_diag_mlo_link_status));
+
+	wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
+	wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get());
+	wlan_diag_event.version = DIAG_MLO_LINK_STATUS_VERSION;
+
+	wlan_diag_event.active_link = src->active_link_bitmap;
+	wlan_diag_event.prev_active_link = src->prev_link_bitmap;
+	wlan_diag_event.reason = src->reason_code;
+	wlan_diag_event.diag_cmn.fw_timestamp = src->fw_timestamp;
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event,
+				    EVENT_WLAN_MLO_LINK_STATUS);
+}
+#endif
 #endif

+ 6 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h

@@ -5153,6 +5153,12 @@ QDF_STATUS policy_mgr_update_active_mlo_num_links(struct wlan_objmgr_psoc *psoc,
 						  uint8_t vdev_id,
 						  uint8_t num_links);
 #else
+static inline bool
+policy_mgr_vdev_is_force_inactive(struct wlan_objmgr_psoc *psoc,
+				  uint8_t vdev_id)
+{
+	return false;
+}
 
 static inline bool policy_mgr_is_mlo_sap_concurrency_allowed(
 			struct wlan_objmgr_psoc *psoc,

+ 3 - 2
components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c

@@ -2835,8 +2835,9 @@ static bool policy_mgr_valid_sta_channel_check(struct wlan_objmgr_psoc *psoc,
 	    wlan_reg_is_passive_or_disable_for_pwrmode(
 	    pm_ctx->pdev, sta_ch_freq, REG_CURRENT_PWR_MODE) ||
 	    (wlan_reg_is_freq_indoor(pm_ctx->pdev, sta_ch_freq) &&
-	    !sta_sap_scc_on_indoor_channel) ||
-	    !policy_mgr_is_safe_channel(psoc, sta_ch_freq)) {
+	     !sta_sap_scc_on_indoor_channel) ||
+	    (!policy_mgr_sta_sap_scc_on_lte_coex_chan(psoc) &&
+	     !policy_mgr_is_safe_channel(psoc, sta_ch_freq))) {
 		if (policy_mgr_is_hw_dbs_capable(psoc))
 			return true;
 		else

+ 131 - 6
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -1163,6 +1163,117 @@ add_freq:
 	return QDF_STATUS_SUCCESS;
 }
 
+/**
+ * policy_mgr_channel_mcc_with_non_sap() - Helper function to check if channel
+ * is MCC with exist non-movable connections.
+ * @psoc: pointer to SOC
+ * @chan_freq: channel frequency to check
+ *
+ * Return: true if is MCC with exist non-movable connections, otherwise false.
+ */
+static bool policy_mgr_channel_mcc_with_non_sap(struct wlan_objmgr_psoc *psoc,
+						qdf_freq_t chan_freq)
+{
+	uint32_t i, connection_of_2ghz = 0;
+	qdf_freq_t conc_freq;
+	bool is_mcc = false, check_only_dbs = false;
+	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;
+	}
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
+		if (pm_conc_connection_list[i].in_use &&
+		    WLAN_REG_IS_24GHZ_CH_FREQ(pm_conc_connection_list[i].freq))
+			connection_of_2ghz++;
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	if (connection_of_2ghz >= 2)
+		check_only_dbs = true;
+
+	qdf_mutex_acquire(&pm_ctx->qdf_conc_list_lock);
+	for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) {
+		if (pm_conc_connection_list[i].in_use &&
+		    (pm_conc_connection_list[i].mode == PM_STA_MODE ||
+		     pm_conc_connection_list[i].mode == PM_P2P_CLIENT_MODE ||
+		     pm_conc_connection_list[i].mode == PM_P2P_GO_MODE)) {
+			conc_freq = pm_conc_connection_list[i].freq;
+			if (conc_freq != chan_freq &&
+			    ((check_only_dbs &&
+			      policy_mgr_2_freq_same_mac_in_dbs(pm_ctx,
+								chan_freq,
+								conc_freq)) ||
+			     policy_mgr_2_freq_always_on_same_mac(psoc,
+								  chan_freq,
+								  conc_freq))) {
+				is_mcc = true;
+				break;
+			}
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	return is_mcc;
+}
+
+/**
+ * policy_mgr_modify_sap_pcl_filter_mcc() - API to filter out MCC channel with
+ * existing non-SAP connection frequency from SAP PCL list.
+ * @psoc: pointer to SOC
+ * @pcl_list_org: channel list to filter out
+ * @weight_list_org: weight of channel list
+ * @pcl_len_org: length of channel list
+ * @mode: Policy manager connection mode
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+policy_mgr_modify_sap_pcl_filter_mcc(struct wlan_objmgr_psoc *psoc,
+				     uint32_t *pcl_list_org,
+				     uint8_t *weight_list_org,
+				     uint32_t *pcl_len_org,
+				     enum policy_mgr_con_mode mode)
+{
+	uint32_t i, pcl_len = 0;
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+
+	if (mode == PM_LL_LT_SAP_MODE)
+		return QDF_STATUS_SUCCESS;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid Context");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (*pcl_len_org > NUM_CHANNELS) {
+		policy_mgr_err("Invalid PCL List Length %d", *pcl_len_org);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (!policy_mgr_is_force_scc(psoc)) {
+		policy_mgr_debug("force SCC is not prefer, skip!");
+		return QDF_STATUS_SUCCESS;
+	}
+
+	for (i = 0; i < *pcl_len_org; i++) {
+		if (policy_mgr_channel_mcc_with_non_sap(psoc, pcl_list_org[i]))
+			continue;
+
+		pcl_list_org[pcl_len] = pcl_list_org[i];
+		weight_list_org[pcl_len++] = weight_list_org[i];
+	}
+
+	*pcl_len_org = pcl_len;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /**
  * policy_mgr_modify_sap_go_4th_conc_disallow() - filter out channel that
  * is not allowed for 4th sap/go connection
@@ -1217,7 +1328,8 @@ end:
 static QDF_STATUS policy_mgr_pcl_modification_for_sap(
 			struct wlan_objmgr_psoc *psoc,
 			uint32_t *pcl_channels, uint8_t *pcl_weight,
-			uint32_t *len, uint32_t weight_len)
+			uint32_t *len, uint32_t weight_len,
+			enum policy_mgr_con_mode mode)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 	struct policy_mgr_psoc_priv_obj *pm_ctx;
@@ -1227,6 +1339,7 @@ static QDF_STATUS policy_mgr_pcl_modification_for_sap(
 	bool indoor_modified_pcl = false;
 	bool passive_modified_pcl = false;
 	bool band_6ghz_modified_pcl = false;
+	bool fourth_conc_modified_pcl = false;
 	bool modified_final_pcl = false;
 	bool srd_chan_enabled;
 
@@ -1309,16 +1422,27 @@ static QDF_STATUS policy_mgr_pcl_modification_for_sap(
 		policy_mgr_err("failed to modify pcl for 4th sap channels");
 		return status;
 	}
+	fourth_conc_modified_pcl = true;
+
+	status = policy_mgr_modify_sap_pcl_filter_mcc(psoc,
+						      pcl_channels,
+						      pcl_weight, len,
+						      mode);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		policy_mgr_err("failed to modify pcl for filter mcc");
+		return status;
+	}
 
 	modified_final_pcl = true;
-	policy_mgr_debug("%d %d %d %d %d %d %d",
+	policy_mgr_debug("%d %d %d %d %d %d %d %d",
 			 mandatory_modified_pcl,
 			 nol_modified_pcl,
 			 dfs_modified_pcl,
 			 indoor_modified_pcl,
 			 passive_modified_pcl,
-			 modified_final_pcl,
-			 band_6ghz_modified_pcl);
+			 band_6ghz_modified_pcl,
+			 fourth_conc_modified_pcl,
+			 modified_final_pcl);
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1453,7 +1577,8 @@ static QDF_STATUS policy_mgr_pcl_modification_for_ll_lt_sap(
 
 	is_dynamic_sbs_enabled = policy_mgr_is_dynamic_sbs_enabled(psoc);
 	policy_mgr_pcl_modification_for_sap(
-		psoc, pcl_channels, pcl_weight, len, weight_len);
+		psoc, pcl_channels, pcl_weight, len, weight_len,
+		PM_LL_LT_SAP_MODE);
 
 	for (i = 0; i < *len; i++) {
 		/* Remove passive/dfs/6G invalid channel for LL_LT_SAP */
@@ -1514,7 +1639,7 @@ static QDF_STATUS policy_mgr_mode_specific_modification_on_pcl(
 	switch (mode) {
 	case PM_SAP_MODE:
 		status = policy_mgr_pcl_modification_for_sap(
-			psoc, pcl_channels, pcl_weight, len, weight_len);
+			psoc, pcl_channels, pcl_weight, len, weight_len, mode);
 		break;
 	case PM_P2P_GO_MODE:
 		status = policy_mgr_pcl_modification_for_p2p_go(

+ 10 - 23
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -760,38 +760,26 @@ tgt_mc_cp_stats_extract_congestion_stats(struct wlan_objmgr_psoc *psoc,
 
 #ifdef WLAN_FEATURE_11BE_MLO
 static void
-update_ml_vdev_id_from_stats_event(struct wlan_objmgr_psoc *psoc,
-				   struct request_info *req,
+update_ml_vdev_id_from_stats_event(struct request_info *req,
 				   uint8_t *vdev_id)
 {
-	uint8_t j, t_vdev_id;
-
-	if ((!wlan_vdev_mlme_get_is_mlo_vdev(psoc, req->vdev_id) &&
-	    !wlan_vdev_mlme_get_is_mlo_link(psoc, req->vdev_id)) ||
-	    !req->ml_vdev_info.ml_vdev_count) {
+	if (!req->ml_vdev_info.ml_vdev_count) {
 		*vdev_id = req->vdev_id;
 		return;
 	}
 
-	t_vdev_id = *vdev_id;
-	for (j = 0; j < req->ml_vdev_info.ml_vdev_count; j++) {
-		if (t_vdev_id == req->ml_vdev_info.ml_vdev_id[j]) {
-			*vdev_id = req->ml_vdev_info.ml_vdev_id[j];
-			return;
-		}
-	}
-
-	if (j == req->ml_vdev_info.ml_vdev_count) {
-		cp_stats_err("vdev[%u] not found", t_vdev_id);
+	if (*vdev_id == WLAN_UMAC_VDEV_ID_MAX ||
+	    *vdev_id >= WLAN_MAX_VDEVS) {
+		cp_stats_err("Invalid vdev[%u] sent by firmware", *vdev_id);
 		*vdev_id = WLAN_UMAC_VDEV_ID_MAX;
 	}
 }
 #else
-static void
-update_ml_vdev_id_from_stats_event(struct wlan_objmgr_psoc *psoc,
-				   struct request_info *req,
+static inline void
+update_ml_vdev_id_from_stats_event(struct request_info *req,
 				   uint8_t *vdev_id)
 {
+	*vdev_id = req->vdev_id;
 }
 #endif
 
@@ -895,10 +883,9 @@ static void tgt_mc_cp_stats_extract_vdev_summary_stats(
 		return;
 	}
 
-	vdev_id = last_req.vdev_id;
 	for (i = 0; i < ev->num_summary_stats; i++) {
 		vdev_id = ev->vdev_summary_stats[i].vdev_id;
-		update_ml_vdev_id_from_stats_event(psoc, &last_req, &vdev_id);
+		update_ml_vdev_id_from_stats_event(&last_req, &vdev_id);
 		if (ev->vdev_summary_stats[i].vdev_id == vdev_id)
 			break;
 	}
@@ -978,7 +965,7 @@ static void tgt_mc_cp_stats_extract_vdev_chain_rssi_stats(
 
 	for (i = 0; i < ev->num_chain_rssi_stats; i++) {
 		vdev_id = ev->vdev_chain_rssi[i].vdev_id;
-		update_ml_vdev_id_from_stats_event(psoc, &last_req, &vdev_id);
+		update_ml_vdev_id_from_stats_event(&last_req, &vdev_id);
 		if (ev->vdev_chain_rssi[i].vdev_id != vdev_id)
 			continue;
 

+ 1 - 1
components/dp/core/src/wlan_dp_fisa_rx.h

@@ -53,7 +53,7 @@
 	(FISA_MAX_SINGLE_CUMULATIVE_IP_LEN * FISA_FLOW_MAX_AGGR_COUNT)
 
 /* minimal pure UDP data length required for FISA */
-#define FISA_MIN_UDP_DATA_LEN 16
+#define FISA_MIN_UDP_DATA_LEN 64
 /* minimal length without L2/L3 header required for FISA */
 #define FISA_MIN_L4_AND_DATA_LEN \
 	(FISA_UDP_HDR_LEN + FISA_MIN_UDP_DATA_LEN)

+ 4 - 4
components/fw_offload/dispatcher/inc/cfg_coex.h

@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2012 - 2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2012-2021 The Linux Foundation. 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
@@ -109,7 +109,7 @@
  * gSetBtLowRssiThreshold - Set BT low RSSI threshold for BTC mode switching
  * @Min: -100
  * @Max: 0
- * @Default: -80
+ * @Default: -65
  *
  * Usage: External
  *
@@ -119,7 +119,7 @@
 			"gSetBtLowRssiThreshold", \
 			-100, \
 			0, \
-			-80, \
+			-65, \
 			CFG_VALUE_OR_DEFAULT, \
 			"BT Low RSSI Threshold")
 

+ 26 - 0
components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h

@@ -573,4 +573,30 @@ wlan_handle_emlsr_sta_concurrency(struct wlan_objmgr_psoc *psoc,
 {
 }
 #endif
+
+#ifdef WLAN_FEATURE_LL_LT_SAP
+/**
+ * wlan_ll_sap_sort_channel_list() - Sort channel list
+ * @vdev_id: Vdev Id
+ * @list: Pointer to list
+ * @ch_info: Pointer to ch_info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_ll_sap_sort_channel_list(uint8_t vdev_id, qdf_list_t *list,
+			      struct sap_sel_ch_info *ch_info);
+#endif
+
+/**
+ * wlan_sap_get_user_config_acs_ch_list: Get user configured channel list
+ * @vdev_id: Vdev Id
+ * @filter: Filter to apply to get scan result
+ *
+ * Return: None
+ *
+ */
+void
+wlan_sap_get_user_config_acs_ch_list(uint8_t vdev_id,
+				     struct scan_filter *filter);
 #endif

+ 3 - 1
components/mlme/core/src/wlan_mlme_main.c

@@ -1261,7 +1261,8 @@ static void mlme_init_emlsr_mode(struct wlan_objmgr_psoc *psoc,
 static void mlme_init_tl2m_negotiation_support(struct wlan_objmgr_psoc *psoc,
 						 struct wlan_mlme_generic *gen)
 {
-	gen->t2lm_negotiation_support = cfg_default(CFG_T2LM_NEGOTIATION_SUPPORT);
+	gen->t2lm_negotiation_support = cfg_get(psoc,
+						CFG_T2LM_NEGOTIATION_SUPPORT);
 }
 #else
 static void mlme_init_emlsr_mode(struct wlan_objmgr_psoc *psoc,
@@ -3437,6 +3438,7 @@ static void mlme_init_btm_cfg(struct wlan_objmgr_psoc *psoc,
 	btm->abridge_flag = cfg_get(psoc, CFG_ENABLE_BTM_ABRIDGE);
 	if (btm->abridge_flag)
 		MLME_SET_BIT(btm->btm_offload_config, BTM_OFFLOAD_CONFIG_BIT_7);
+	wlan_mlme_set_btm_abridge_flag(psoc, btm->abridge_flag);
 
 	btm->btm_solicited_timeout = cfg_get(psoc, CFG_BTM_SOLICITED_TIMEOUT);
 	btm->btm_max_attempt_cnt = cfg_get(psoc, CFG_BTM_MAX_ATTEMPT_CNT);

+ 53 - 14
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c

@@ -89,12 +89,24 @@ QDF_STATUS mlme_register_mlme_ext_ops(void)
 #ifdef WLAN_FEATURE_11BE_MLO
 QDF_STATUS mlme_register_mlo_ext_ops(void)
 {
+	QDF_STATUS status;
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 
-	if (mlo_ctx)
-		mlo_reg_mlme_ext_cb(mlo_ctx, &mlo_ext_ops);
+	if (!mlo_ctx)
+		return QDF_STATUS_E_FAILURE;
 
-	return QDF_STATUS_SUCCESS;
+	mlo_reg_mlme_ext_cb(mlo_ctx, &mlo_ext_ops);
+
+	status = mlo_mgr_register_link_switch_notifier(WLAN_UMAC_COMP_MLME,
+						       wlan_cm_link_switch_notif_cb);
+	if (status == QDF_STATUS_E_NOSUPPORT) {
+		status = QDF_STATUS_SUCCESS;
+		mlme_debug("Link switch not supported");
+	} else if (QDF_IS_STATUS_ERROR(status)) {
+		mlme_err("Failed to register link switch notifier for mlme!");
+	}
+
+	return status;
 }
 
 QDF_STATUS mlme_unregister_mlo_ext_ops(void)
@@ -256,8 +268,7 @@ int mlme_sr_is_enable(struct wlan_objmgr_vdev *vdev)
 	uint8_t sr_ctrl;
 
 	sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev);
-	return ((!(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
-		 (sr_ctrl & NON_SRG_OFFSET_PRESENT)) ||
+	return (!sr_ctrl || !(sr_ctrl & NON_SRG_PD_SR_DISALLOWED) ||
 		(sr_ctrl & SRG_INFO_PRESENT));
 }
 
@@ -279,6 +290,7 @@ mlme_sr_handle_conc(struct wlan_objmgr_vdev *vdev,
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_lmac_if_tx_ops *tx_ops;
+	struct wlan_lmac_if_spatial_reuse_tx_ops *sr_tx_ops;
 	uint8_t conc_vdev_id = wlan_vdev_get_id(conc_vdev);
 
 	pdev = wlan_vdev_get_pdev(vdev);
@@ -289,7 +301,12 @@ mlme_sr_handle_conc(struct wlan_objmgr_vdev *vdev,
 
 	psoc = wlan_vdev_get_psoc(vdev);
 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
+	if (!tx_ops) {
+		mlme_err("tx_ops is NULL");
+		return;
+	}
 
+	sr_tx_ops = &tx_ops->spatial_reuse_tx_ops;
 	if (en_sr_curr_vdev) {
 		wlan_vdev_mlme_set_sr_disable_due_conc(vdev, true);
 		wlan_vdev_mlme_set_sr_disable_due_conc(conc_vdev, true);
@@ -297,24 +314,27 @@ mlme_sr_handle_conc(struct wlan_objmgr_vdev *vdev,
 		if (!wlan_vdev_mlme_get_he_spr_enabled(conc_vdev))
 			return;
 
-		if (tx_ops && tx_ops->spatial_reuse_tx_ops.target_if_sr_update)
-			tx_ops->spatial_reuse_tx_ops.target_if_sr_update
-						     (pdev, conc_vdev_id, val);
+		if (mlme_sr_is_enable(conc_vdev)) {
+			if (sr_tx_ops->target_if_sr_update)
+				sr_tx_ops->target_if_sr_update
+						(pdev, conc_vdev_id, val);
 
-		wlan_spatial_reuse_osif_event(conc_vdev, SR_OPERATION_SUSPEND,
-					      SR_REASON_CODE_CONCURRENCY);
+			wlan_spatial_reuse_osif_event(conc_vdev,
+						      SR_OPERATION_SUSPEND,
+						   SR_REASON_CODE_CONCURRENCY);
+		}
 	} else if (wlan_vdev_mlme_is_sr_disable_due_conc(conc_vdev)) {
 		wlan_vdev_mlme_set_sr_disable_due_conc(conc_vdev, false);
 
 		if (!wlan_vdev_mlme_get_he_spr_enabled(conc_vdev))
 			return;
 
-		if (mlme_sr_is_enable(vdev)) {
+		if (mlme_sr_is_enable(conc_vdev)) {
 			wlan_mlme_update_sr_data(conc_vdev, &val, 0, 0, true);
 
-			if (tx_ops && tx_ops->spatial_reuse_tx_ops.target_if_sr_update)
-				tx_ops->spatial_reuse_tx_ops.target_if_sr_update
-						      (pdev, conc_vdev_id, val);
+			if (sr_tx_ops->target_if_sr_update)
+				sr_tx_ops->target_if_sr_update
+						(pdev, conc_vdev_id, val);
 
 			wlan_spatial_reuse_osif_event(conc_vdev,
 						      SR_OPERATION_RESUME,
@@ -388,6 +408,7 @@ void mlme_sr_update(struct wlan_objmgr_vdev *vdev, bool enable)
 			wlan_mlme_update_sr_data(vdev, &val, 0, 0, true);
 		} else {
 			/* VDEV down, disable SR */
+			wlan_vdev_mlme_set_he_spr_enabled(vdev, false);
 			wlan_vdev_mlme_set_sr_ctrl(vdev, 0);
 			wlan_vdev_mlme_set_non_srg_pd_offset(vdev, 0);
 		}
@@ -845,6 +866,8 @@ QDF_STATUS mlme_set_chan_switch_in_progress(struct wlan_objmgr_vdev *vdev,
 	}
 
 	mlme_priv->chan_switch_in_progress = val;
+	mlme_legacy_info("Set chan_switch_in_progress: %d vdev %d",
+			 val, wlan_vdev_get_id(vdev));
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -2251,6 +2274,22 @@ static QDF_STATUS ap_mlme_vdev_csa_complete(struct vdev_mlme_obj *vdev_mlme)
 	return QDF_STATUS_SUCCESS;
 }
 
+#ifdef WLAN_FEATURE_LL_LT_SAP
+QDF_STATUS
+wlan_ll_sap_sort_channel_list(uint8_t vdev_id, qdf_list_t *list,
+			      struct sap_sel_ch_info *ch_info)
+{
+	return wlansap_sort_channel_list(vdev_id, list, ch_info);
+}
+#endif
+
+void
+wlan_sap_get_user_config_acs_ch_list(uint8_t vdev_id,
+				     struct scan_filter *filter)
+{
+	wlansap_get_user_config_acs_ch_list(vdev_id, filter);
+}
+
 static struct vdev_mlme_ops sta_mlme_ops = {
 	.mlme_vdev_start_send = sta_mlme_vdev_start_send,
 	.mlme_vdev_restart_send = sta_mlme_vdev_restart_send,

+ 3 - 2
components/mlme/dispatcher/inc/cfg_mlme_fe_rrm.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 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
@@ -96,7 +97,7 @@
 /*
  * <ini>
  * rm_capability - Configure RM enabled capabilities IE
- * @Default: 0x73,0x10,0x91,0x00,0x04
+ * @Default: 0x73,0x1A,0x91,0x00,0x04
  *
  * This ini is used to configure RM enabled capabilities IE.
  * Using this INI, we can set/unset any of the bits in 5 bytes
@@ -117,7 +118,7 @@
 #define CFG_RM_CAPABILITY CFG_INI_STRING("rm_capability", \
 					 24, \
 					 40, \
-					 "0x73,0x10,0x91,0x00,0x04", \
+					 "0x73,0x1A,0x91,0x00,0x04", \
 					 "RM enabled capabilities IE")
 
 #define CFG_FE_RRM_ALL \

+ 1 - 1
components/mlme/dispatcher/inc/cfg_mlme_generic.h

@@ -1195,7 +1195,7 @@ enum wlan_epcs_frame {
  *
  * Supported Feature: STA
  */
-#define CFG_T2LM_NEGOTIATION_SUPPORT CFG_UINT( \
+#define CFG_T2LM_NEGOTIATION_SUPPORT CFG_INI_UINT( \
 					"t2lm_negotiation_supported", \
 					T2LM_NEGOTIATION_DISABLED, \
 					T2LM_NEGOTIATION_DISJOINT_MAPPING, \

+ 2 - 2
components/mlme/dispatcher/inc/cfg_mlme_he_caps.h

@@ -117,11 +117,11 @@
 				0, \
 				"HE Ofdma Ra")
 
-#define CFG_HE_MAX_AMPDU_LEN CFG_UINT( \
+#define CFG_HE_MAX_AMPDU_LEN CFG_INI_UINT( \
 				"he_max_ampdu_len", \
 				0, \
 				3, \
-				0, \
+				3, \
 				CFG_VALUE_OR_DEFAULT, \
 				"HE Max Ampdu Len")
 

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

@@ -2821,6 +2821,26 @@ QDF_STATUS
 wlan_mlme_set_t2lm_negotiation_supported(struct wlan_objmgr_psoc *psoc,
 					 uint8_t value);
 
+/**
+ * wlan_mlme_get_eht_mld_id() - Get the MLD ID of the requested BSS
+ * @psoc: psoc context
+ *
+ * Return: MLD ID of the requested BSS
+ */
+uint8_t
+wlan_mlme_get_eht_mld_id(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_mlme_set_eht_mld_id() - Set MLD ID of the requested BSS information
+ * within the ML probe request.
+ * @psoc: psoc context
+ * @value: MLD ID
+ *
+ * Return: qdf status
+ */
+QDF_STATUS
+wlan_mlme_set_eht_mld_id(struct wlan_objmgr_psoc *psoc, uint8_t value);
+
 /*
  * wlan_mlme_get_mlo_prefer_percentage() - get MLO preference percentage
  * @psoc: pointer to psoc object
@@ -2888,6 +2908,18 @@ wlan_mlme_set_t2lm_negotiation_supported(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_E_NOSUPPORT;
 }
 
+static inline uint8_t
+wlan_mlme_get_eht_mld_id(struct wlan_objmgr_psoc *psoc)
+{
+	return 0;
+}
+
+static inline QDF_STATUS
+wlan_mlme_set_eht_mld_id(struct wlan_objmgr_psoc *psoc, uint8_t value)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
 static inline void
 wlan_mlme_get_mlo_prefer_percentage(
 				struct wlan_objmgr_psoc *psoc,
@@ -2895,6 +2927,31 @@ wlan_mlme_get_mlo_prefer_percentage(
 {}
 #endif
 
+/**
+ * wlan_mlme_set_btm_abridge_flag() - Set BTM abridge flag
+ * @psoc: psoc context
+ * @value: abridge flag
+ *
+ * Return: qdf status
+ *
+ * BTM abridge flag indicates whether to select candidates
+ * for BTM roam based on score.
+ */
+QDF_STATUS
+wlan_mlme_set_btm_abridge_flag(struct wlan_objmgr_psoc *psoc, bool value);
+
+/**
+ * wlan_mlme_get_btm_abridge_flag() - Get BTM abridge flag
+ * @psoc: psoc context
+ *
+ * Return: abridge flag
+ *
+ * BTM abridge flag indicates whether to select candidates
+ * for BTM roam based on score.
+ */
+bool
+wlan_mlme_get_btm_abridge_flag(struct wlan_objmgr_psoc *psoc);
+
 /**
  * wlan_mlme_get_sta_miracast_mcc_rest_time() - Get STA/MIRACAST MCC rest time
  * @psoc: pointer to psoc object

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

@@ -1458,6 +1458,7 @@ struct wlan_mlme_aux_dev_caps {
  * @eht_mode: EHT mode of operation
  * @t2lm_negotiation_support: T2LM negotiation supported enum value
  * @enable_emlsr_mode: 11BE eMLSR mode support
+ * @mld_id: MLD ID of requested BSS within ML probe request frame
  * @safe_mode_enable: safe mode to bypass some strict 6 GHz checks for
  * connection, bypass strict power levels
  * @sr_enable_modes: modes for which SR(Spatial Reuse) is enabled
@@ -1518,6 +1519,7 @@ struct wlan_mlme_generic {
 	enum wlan_eht_mode eht_mode;
 	bool enable_emlsr_mode;
 	enum t2lm_negotiation_support t2lm_negotiation_support;
+	uint8_t mld_id;
 #endif
 #ifdef WLAN_FEATURE_MCC_QUOTA
 	struct wlan_user_mcc_quota user_mcc_quota;
@@ -2568,6 +2570,7 @@ struct wlan_mlme_wifi_pos_cfg {
 };
 
 #define MLME_SET_BIT(value, bit_offset) ((value) |= (1 << (bit_offset)))
+#define MLME_CLEAR_BIT(value, bit_offset) ((value) &= ~(1 << (bit_offset)))
 
 /* Mask to check if BTM offload is enabled/disabled*/
 #define BTM_OFFLOAD_ENABLED_MASK    0x01

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

@@ -3905,8 +3905,62 @@ wlan_mlme_set_t2lm_negotiation_supported(struct wlan_objmgr_psoc *psoc,
 
 	return QDF_STATUS_SUCCESS;
 }
+
+uint8_t
+wlan_mlme_get_eht_mld_id(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.gen.mld_id;
+}
+
+QDF_STATUS
+wlan_mlme_set_eht_mld_id(struct wlan_objmgr_psoc *psoc,
+			 uint8_t value)
+{
+	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.mld_id = value;
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
+QDF_STATUS
+wlan_mlme_set_btm_abridge_flag(struct wlan_objmgr_psoc *psoc,
+			       bool value)
+{
+	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.btm.abridge_flag = value;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+bool
+wlan_mlme_get_btm_abridge_flag(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 false;
+
+	return mlme_obj->cfg.btm.abridge_flag;
+}
+
 QDF_STATUS
 wlan_mlme_cfg_set_vht_chan_width(struct wlan_objmgr_psoc *psoc, uint8_t value)
 {

+ 3 - 2
components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c

@@ -435,7 +435,8 @@ ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
 	}
 
 	if (wlan_vdev_mlme_is_mlo_vdev(vdev) && link_id != 0xFF) {
-		link_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
+		link_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
+						    WLAN_MLME_OBJMGR_ID);
 		if (!link_vdev) {
 			mlme_legacy_debug("vdev is null for the link id:%u",
 					  link_id);
@@ -452,7 +453,7 @@ ucfg_mlme_send_ch_width_update_with_notify(struct wlan_objmgr_psoc *psoc,
 							    link_vdev_id,
 							    ch_width);
 	if (is_mlo_link)
-		mlo_release_vdev_ref(link_vdev);
+		wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLME_OBJMGR_ID);
 
 release:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);

+ 4 - 0
components/pkt_capture/core/inc/wlan_pkt_capture_priv.h

@@ -65,6 +65,8 @@ struct pkt_capture_cb_context {
  * @last_freq: Last connected freq
  * @curr_freq: current connected freq
  * @rx_vht_sgi: guard interval of vht rx packet
+ * @wake_lock: wake lock for packet capture
+ * @runtime_lock: runtime lock for packet capture
  */
 struct pkt_capture_vdev_priv {
 	struct wlan_objmgr_vdev *vdev;
@@ -78,6 +80,8 @@ struct pkt_capture_vdev_priv {
 	qdf_freq_t last_freq;
 	qdf_freq_t curr_freq;
 	uint8_t rx_vht_sgi;
+	qdf_wake_lock_t wake_lock;
+	qdf_runtime_lock_t runtime_lock;
 };
 
 /**

+ 13 - 0
components/pkt_capture/core/src/wlan_pkt_capture_main.c

@@ -775,6 +775,10 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev,
 		goto send_mode_fail;
 	}
 
+	qdf_wake_lock_acquire(&vdev_priv->wake_lock,
+			      WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
+	qdf_runtime_pm_prevent_suspend(&vdev_priv->runtime_lock);
+
 	return QDF_STATUS_SUCCESS;
 
 send_mode_fail:
@@ -845,6 +849,10 @@ QDF_STATUS pkt_capture_deregister_callbacks(struct wlan_objmgr_vdev *vdev)
 	vdev_priv->cb_ctx->mon_cb = NULL;
 	vdev_priv->cb_ctx->mon_ctx = NULL;
 
+	qdf_wake_lock_release(&vdev_priv->wake_lock,
+			      WIFI_POWER_EVENT_WAKELOCK_MONITOR_MODE);
+	qdf_runtime_pm_allow_suspend(&vdev_priv->runtime_lock);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -1097,6 +1105,8 @@ pkt_capture_vdev_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	}
 	qdf_spinlock_create(&vdev_priv->lock_q);
 	qdf_list_create(&vdev_priv->ppdu_stats_q, PPDU_STATS_Q_MAX_SIZE);
+	qdf_wake_lock_create(&vdev_priv->wake_lock, "pkt_capture_mode");
+	qdf_runtime_lock_init(&vdev_priv->runtime_lock);
 
 	return status;
 
@@ -1133,6 +1143,9 @@ pkt_capture_vdev_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	qdf_runtime_lock_deinit(&vdev_priv->runtime_lock);
+	qdf_wake_lock_destroy(&vdev_priv->wake_lock);
+
 	while (qdf_list_remove_front(&vdev_priv->ppdu_stats_q, &node)
 	       == QDF_STATUS_SUCCESS) {
 		stats_node = qdf_container_of(

+ 1 - 1
components/target_if/cp_stats/src/target_if_mc_cp_stats.c

@@ -874,7 +874,7 @@ target_if_cp_stats_extract_vdev_extd_stats(struct wmi_unified *wmi_hdl,
 	if (!ev->num_vdev_extd_stats)
 		return QDF_STATUS_SUCCESS;
 
-	if (ev->num_vdev_extd_stats > WLAN_MAX_MLD) {
+	if (ev->num_vdev_extd_stats > WLAN_MAX_VDEVS) {
 		cp_stats_err("num_vdev_extd_stats is invalid: %u",
 			     ev->num_vdev_extd_stats);
 		return QDF_STATUS_E_INVAL;

+ 3 - 0
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -954,6 +954,9 @@ cm_update_scan_db_on_roam_success(struct wlan_objmgr_vdev *vdev,
 
 	cm_update_scan_mlme_on_roam(vdev, &resp->bssid,
 				    SCAN_ENTRY_CON_STATE_ASSOC);
+
+	cm_standby_link_update_mlme_by_bssid(vdev, SCAN_ENTRY_CON_STATE_ASSOC,
+					     resp->ssid);
 }
 
 #ifdef WLAN_FEATURE_11BE_MLO

+ 15 - 3
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -527,7 +527,8 @@ cm_roam_scan_offload_fill_lfr3_config(struct wlan_objmgr_vdev *vdev,
 	 * Instead of making another infra, send the RSN-CAPS in MSB of
 	 * beacon Caps.
 	 */
-	rsn_caps = rso_cfg->orig_sec_info.rsn_caps;
+	/* RSN caps with global user MFP which can be used for cross-AKM roam */
+	rsn_caps = rso_cfg->rso_rsn_caps;
 
 	/* Fill LFR3 specific self capabilities for roam scan mode TLV */
 	self_caps.ess = 1;
@@ -2913,6 +2914,7 @@ cm_update_btm_offload_config(struct wlan_objmgr_psoc *psoc,
 	bool is_hs_20_ap, is_pmf_enabled, is_open_connection = false;
 	uint8_t vdev_id;
 	uint32_t mbo_oce_enabled_ap;
+	bool abridge_flag;
 
 	mlme_obj = mlme_get_psoc_ext_obj(psoc);
 	if (!mlme_obj)
@@ -2967,6 +2969,14 @@ cm_update_btm_offload_config(struct wlan_objmgr_psoc *psoc,
 
 	wlan_cm_roam_cfg_get_value(psoc, vdev_id, MBO_OCE_ENABLED_AP, &temp);
 	mbo_oce_enabled_ap = temp.uint_value;
+
+	abridge_flag = wlan_mlme_get_btm_abridge_flag(psoc);
+	if (!abridge_flag)
+		MLME_CLEAR_BIT(*btm_offload_config,
+			       BTM_OFFLOAD_CONFIG_BIT_7);
+	mlme_debug("Abridge flag: %d, btm offload: %u", abridge_flag,
+		   *btm_offload_config);
+
 	/*
 	 * If peer does not support PMF in case of OCE/MBO
 	 * Connection, Disable BTM offload to firmware.
@@ -6681,8 +6691,9 @@ cm_roam_neigh_rpt_req_event(struct wmi_neighbor_report_data *neigh_rpt,
 			  (uint64_t)neigh_rpt->timestamp, NULL);
 
 	wlan_diag_event.subtype = WLAN_CONN_DIAG_NBR_RPT_REQ_EVENT;
-	wlan_diag_event.version = DIAG_NBR_RPT_VERSION;
+	wlan_diag_event.version = DIAG_NBR_RPT_VERSION_2;
 	wlan_diag_event.token = neigh_rpt->req_token;
+	wlan_diag_event.band = neigh_rpt->band;
 
 	wlan_vdev_mlme_get_ssid(vdev, wlan_diag_event.ssid,
 				(uint8_t *)&wlan_diag_event.ssid_len);
@@ -6704,7 +6715,7 @@ cm_roam_neigh_rpt_resp_event(struct wmi_neighbor_report_data *neigh_rpt,
 			  (uint64_t)neigh_rpt->timestamp, NULL);
 
 	wlan_diag_event.subtype = WLAN_CONN_DIAG_NBR_RPT_RESP_EVENT;
-	wlan_diag_event.version = DIAG_NBR_RPT_VERSION;
+	wlan_diag_event.version = DIAG_NBR_RPT_VERSION_2;
 	wlan_diag_event.token = neigh_rpt->resp_token;
 	wlan_diag_event.num_freq = neigh_rpt->num_freq;
 
@@ -6712,6 +6723,7 @@ cm_roam_neigh_rpt_resp_event(struct wmi_neighbor_report_data *neigh_rpt,
 		wlan_diag_event.freq[i] = neigh_rpt->freq[i];
 
 	wlan_diag_event.num_rpt = neigh_rpt->num_rpt;
+	wlan_diag_event.band = neigh_rpt->band;
 
 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_NBR_RPT);
 }

+ 27 - 3
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c

@@ -393,6 +393,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 	struct rso_config *rso_cfg;
 	struct roam_synch_frame_ind *sync_frame_ind = frame_ind;
 	struct roam_synch_frame_ind *roam_synch_frame_ind;
+	struct roam_scan_candidate_frame roam_candidate = {0};
 	uint8_t vdev_id;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
@@ -411,7 +412,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 	rso_cfg = wlan_cm_get_rso_config(vdev);
 	if (!rso_cfg) {
 		status = QDF_STATUS_E_FAILURE;
-		goto err;
+		goto complete;
 	}
 
 	roam_synch_frame_ind = &rso_cfg->roam_sync_frame_ind;
@@ -420,7 +421,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 		mlme_err("Ignoring this event as it is unexpected");
 		wlan_cm_free_roam_synch_frame_ind(rso_cfg);
 		status = QDF_STATUS_E_FAILURE;
-		goto err;
+		goto complete;
 	}
 
 	if (sync_frame_ind->bcn_probe_rsp_len) {
@@ -463,7 +464,30 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 			sync_frame_ind->reassoc_rsp;
 	}
 
-err:
+	if (!sync_frame_ind->bcn_probe_rsp_len &&
+	    !sync_frame_ind->link_bcn_probe_rsp_len)
+		goto complete;
+
+	roam_candidate.vdev_id = vdev_id;
+
+	if (sync_frame_ind->bcn_probe_rsp_len) {
+		roam_candidate.frame_length = sync_frame_ind->bcn_probe_rsp_len;
+		roam_candidate.frame = sync_frame_ind->bcn_probe_rsp;
+		roam_candidate.roam_offload_candidate_frm = false;
+		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
+							  &roam_candidate);
+	}
+
+	if (sync_frame_ind->link_bcn_probe_rsp_len) {
+		roam_candidate.frame_length =
+					sync_frame_ind->link_bcn_probe_rsp_len;
+		roam_candidate.frame = sync_frame_ind->link_bcn_probe_rsp;
+		roam_candidate.roam_offload_candidate_frm = false;
+		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
+							  &roam_candidate);
+	}
+
+complete:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 	return status;
 }

+ 26 - 8
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1038,6 +1038,8 @@ void cm_get_sta_cxn_info(struct wlan_objmgr_vdev *vdev,
 #endif
 #endif
 
+#define MGMT_FRAME_FULL_PROTECTION (RSN_CAP_MFP_REQUIRED | RSN_CAP_MFP_CAPABLE)
+
 QDF_STATUS cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 				struct wlan_cm_connect_req *req)
 {
@@ -1062,6 +1064,8 @@ QDF_STATUS cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 
 	rso_cfg = wlan_cm_get_rso_config(vdev);
 	if (rso_cfg) {
+		uint8_t rso_user_mfp;
+
 		rso_cfg->orig_sec_info.rsn_caps = req->crypto.rsn_caps;
 		rso_cfg->orig_sec_info.authmodeset = req->crypto.auth_type;
 		rso_cfg->orig_sec_info.ucastcipherset =
@@ -1075,6 +1079,19 @@ QDF_STATUS cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 		 * wlan_cm_send_connect_rsp
 		 */
 		rso_cfg->tried_candidate_freq_list.num_chan = 0;
+
+		/*
+		 * This user configure MFP capability is global and is for
+		 * multiple profiles which can be used by firmware for cross-AKM
+		 * roaming. When user configures MFP required then we should
+		 * set both MFPC and MFPR in RSN caps.
+		 */
+		rso_user_mfp = req->crypto.user_mfp;
+		if (rso_user_mfp == RSN_CAP_MFP_REQUIRED)
+			rso_user_mfp = MGMT_FRAME_FULL_PROTECTION;
+		rso_cfg->rso_rsn_caps = (req->crypto.rsn_caps) &
+					(~MGMT_FRAME_FULL_PROTECTION);
+		rso_cfg->rso_rsn_caps = (rso_cfg->rso_rsn_caps) | rso_user_mfp;
 	}
 
 	if (wlan_get_vendor_ie_ptr_from_oui(HS20_OUI_TYPE,
@@ -1655,12 +1672,12 @@ cm_update_tid_mapping(struct wlan_objmgr_vdev *vdev)
 static void
 cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_objmgr_peer *peer;
 	struct wlan_crypto_key *crypto_key;
 	enum QDF_OPMODE op_mode;
 	uint16_t i;
 	bool pairwise;
 	uint8_t vdev_id;
+	uint8_t link_id;
 	uint16_t max_key_index = WLAN_CRYPTO_MAXKEYIDX +
 				 WLAN_CRYPTO_MAXIGTKKEYIDX +
 				 WLAN_CRYPTO_MAXBIGTKKEYIDX;
@@ -1674,9 +1691,11 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev))
 		return;
 
-	peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLME_CM_ID);
-	if (!peer) {
-		mlo_err("Peer is null return");
+	link_id = wlan_vdev_get_link_id(vdev);
+
+	if (!mlo_is_set_key_defered(vdev, link_id) &&
+	    !mlo_mgr_is_link_switch_in_progress(vdev)) {
+		mlme_debug("keys are not deferred for link_id %d", link_id);
 		return;
 	}
 
@@ -1686,13 +1705,12 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 			continue;
 
 		pairwise = crypto_key->key_type ? WLAN_CRYPTO_KEY_TYPE_UNICAST : WLAN_CRYPTO_KEY_TYPE_GROUP;
-		mlo_debug("MLO:send keys for vdev_id %d, key_idx %d, pairwise %d",
-			  vdev_id, i, pairwise);
+		mlo_debug("MLO:send keys for vdev_id %d link_id %d , key_idx %d, pairwise %d",
+			  vdev_id, link_id, i, pairwise);
 		mlme_cm_osif_send_keys(vdev, i, pairwise,
 				       crypto_key->cipher_type);
 	}
-
-	wlan_objmgr_peer_release_ref(peer, WLAN_MLME_CM_ID);
+	mlo_defer_set_keys(vdev, link_id, false);
 }
 
 QDF_STATUS

+ 39 - 0
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h

@@ -1351,6 +1351,18 @@ wlan_cm_update_offload_ssid_from_candidate(struct wlan_objmgr_pdev *pdev,
 QDF_STATUS
 wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 			     struct roam_scan_candidate_frame *frame);
+
+/**
+ * wlan_cm_add_all_link_probe_rsp_to_scan_db() - Parse and generate
+ * probe responses for each of the per-sta profile
+ *
+ * @psoc: psoc objmgr ptr
+ * @candidate: roam scan candidate info
+ */
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate);
+
 #else
 static inline
 void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc,
@@ -1606,6 +1618,13 @@ wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
@@ -2107,6 +2126,18 @@ wlan_cm_roaming_get_peer_link_addr(struct wlan_objmgr_vdev *vdev);
  */
 bool
 wlan_cm_roam_is_mlo_ap(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_cm_link_switch_notif_cb() - MLME CM link switch notifier callback
+ * @vdev: object manager vdev
+ * @req: Link switch request
+ * @notify_reason: Notify reason
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_cm_link_switch_notif_cb(struct wlan_objmgr_vdev *vdev,
+					struct wlan_mlo_link_switch_req *req,
+					enum wlan_mlo_link_switch_notify_reason notify_reason);
 #else
 static inline void
 wlan_cm_store_mlo_roam_peer_address(struct wlan_objmgr_pdev *pdev,
@@ -2131,6 +2162,14 @@ wlan_cm_roam_is_mlo_ap(struct wlan_objmgr_vdev *vdev)
 {
 	return false;
 }
+
+static inline
+QDF_STATUS wlan_cm_link_switch_notif_cb(struct wlan_objmgr_vdev *vdev,
+					struct wlan_mlo_link_switch_req *req,
+					enum wlan_mlo_link_switch_notify_reason notify_reason)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif /* WLAN_FEATURE_11BE_MLO && WLAN_FEATURE_ROAM_OFFLOAD */
 
 /**

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

@@ -572,6 +572,8 @@ struct sae_roam_auth_map {
  * @roam_invoke_bssid: mac address used for roam invoke
  * @is_forced_roaming: bool value indicating if its forced roaming
  * @tried_candidate_freq_list: freq list on which connection tried
+ * @rso_rsn_caps: rsn caps with global user MFP which can be used for
+ *                cross-AKM roaming
  */
 struct rso_config {
 #ifdef WLAN_FEATURE_HOST_ROAM
@@ -625,6 +627,7 @@ struct rso_config {
 	struct qdf_mac_addr roam_invoke_bssid;
 	bool is_forced_roaming;
 	struct wlan_chan_list tried_candidate_freq_list;
+	uint16_t rso_rsn_caps;
 };
 
 /**
@@ -2871,12 +2874,14 @@ struct roam_offload_synch_ind {
  * @frame_length : Length of the beacon/probe rsp frame
  * @frame : Pointer to the frame
  * @rssi: RSSI of the received frame, 0 if not available
+ * @roam_offload_candidate_frm: Is a roam offload candidate frame
  */
 struct roam_scan_candidate_frame {
 	uint8_t vdev_id;
 	uint32_t frame_length;
 	uint8_t *frame;
 	int32_t rssi;
+	bool roam_offload_candidate_frm;
 };
 
 /**

+ 54 - 1
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -4997,7 +4997,14 @@ wlan_cm_add_frame_to_scan_db(struct wlan_objmgr_psoc *psoc,
 
 	extracted_ie = (uint8_t *)wlan_get_ie_ptr_from_eid(WLAN_ELEMID_SSID,
 							   ie_ptr, ie_len);
-	if (extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) {
+	/*
+	 * Roam offload ssid/bssid needs to be set only for SAE roam offload
+	 * candidate frames for supporting cross-ssid roaming.
+	 * This update is not needed for probe/beacons received from the
+	 * roam sync frame event.
+	 */
+	if (frame->roam_offload_candidate_frm &&
+	    extracted_ie && extracted_ie[0] == WLAN_ELEMID_SSID) {
 		wh = (struct wlan_frame_hdr *)frame->frame;
 		WLAN_ADDR_COPY(&bssid.bytes[0], wh->i_addr2);
 
@@ -5208,6 +5215,14 @@ cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
 }
+
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return mlo_add_all_link_probe_rsp_to_scan_db(psoc, candidate);
+}
+
 #elif defined(WLAN_FEATURE_ROAM_OFFLOAD) /* end WLAN_FEATURE_11BE_MLO */
 QDF_STATUS
 cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
@@ -5215,4 +5230,42 @@ cm_roam_candidate_event_handler(struct wlan_objmgr_psoc *psoc,
 {
 	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
 }
+
+QDF_STATUS
+wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
+				struct roam_scan_candidate_frame *candidate)
+{
+	return wlan_cm_add_frame_to_scan_db(psoc, candidate);
+}
+
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
+
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
+QDF_STATUS wlan_cm_link_switch_notif_cb(struct wlan_objmgr_vdev *vdev,
+					struct wlan_mlo_link_switch_req *req,
+					enum wlan_mlo_link_switch_notify_reason notify_reason)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (notify_reason != MLO_LINK_SWITCH_NOTIFY_REASON_PRE_START_PRE_SER)
+		return status;
+
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return status;
+
+	/* Only send RSO stop for assoc vdev */
+	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev))
+		return status;
+
+	status = cm_roam_state_change(wlan_vdev_get_pdev(vdev),
+				      wlan_vdev_get_id(vdev),
+				      WLAN_ROAM_RSO_STOPPED,
+				      REASON_DISCONNECTED, NULL, false);
+	if (QDF_IS_STATUS_ERROR(status))
+		mlme_err("vdev:%d switch to RSO Stop failed",
+			 wlan_vdev_get_id(vdev));
+
+	return status;
+}
+#endif
+

+ 8 - 6
components/umac/mlme/mlo_mgr/src/wlan_epcs_api.c

@@ -338,7 +338,8 @@ static QDF_STATUS epcs_handle_rx_req(struct wlan_objmgr_vdev *vdev,
 	edca_info = &epcs_req.pa_info;
 	for (i = 0; i < edca_info->num_links; i++) {
 		link = &edca_info->link_info[i];
-		link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id);
+		link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id,
+						    WLAN_MLO_MGR_ID);
 		if (!link_vdev)
 			continue;
 
@@ -353,7 +354,7 @@ static QDF_STATUS epcs_handle_rx_req(struct wlan_objmgr_vdev *vdev,
 		if (link->muedca_ie_present)
 			epcs_update_mu_edca_param(link_vdev, &link->muedca);
 
-		mlo_release_vdev_ref(link_vdev);
+		wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLO_MGR_ID);
 	}
 
 	args.category = ACTION_CATEGORY_PROTECTED_EHT;
@@ -389,11 +390,11 @@ static QDF_STATUS epcs_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 	QDF_STATUS status;
 
 	if (!vdev || !peer)
-		return QDF_STATUS_E_INVAL;
+		return QDF_STATUS_E_NULL_VALUE;
 
 	ml_peer = peer->mlo_peer_ctx;
 	if (!ml_peer)
-		return QDF_STATUS_E_FAILURE;
+		return QDF_STATUS_E_NULL_VALUE;
 
 	epcs_info = &ml_peer->epcs_info;
 	if (epcs_info->state == EPCS_ENABLE) {
@@ -421,7 +422,8 @@ static QDF_STATUS epcs_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 	edca_info = &epcs_rsp.pa_info;
 	for (i = 0; i < edca_info->num_links; i++) {
 		link = &edca_info->link_info[i];
-		link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id);
+		link_vdev = mlo_get_vdev_by_link_id(vdev, link->link_id,
+						    WLAN_MLO_MGR_ID);
 		if (!link_vdev)
 			continue;
 
@@ -436,7 +438,7 @@ static QDF_STATUS epcs_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 		if (link->muedca_ie_present)
 			epcs_update_mu_edca_param(link_vdev, &link->muedca);
 
-		mlo_release_vdev_ref(link_vdev);
+		wlan_objmgr_vdev_release_ref(link_vdev, WLAN_MLO_MGR_ID);
 	}
 
 	epcs_info->state = EPCS_ENABLE;

+ 46 - 0
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.c

@@ -15,6 +15,8 @@
  */
 
 #include "wlan_ll_lt_sap_main.h"
+#include "wlan_scan_ucfg_api.h"
+#include "wlan_mlme_vdev_mgr_interface.h"
 
 bool ll_lt_sap_is_supported(void)
 {
@@ -23,3 +25,47 @@ bool ll_lt_sap_is_supported(void)
 	 */
 	return true;
 }
+
+QDF_STATUS
+ll_lt_sap_get_sorted_user_config_acs_ch_list(struct wlan_objmgr_psoc *psoc,
+					     uint8_t vdev_id,
+					     struct sap_sel_ch_info *ch_info)
+{
+	struct scan_filter *filter;
+	qdf_list_t *list = NULL;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_LL_SAP_ID);
+
+	if (!vdev) {
+		ll_sap_err("Invalid vdev for vdev_id %d", vdev_id);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+
+	filter = qdf_mem_malloc(sizeof(*filter));
+	if (!filter)
+		goto rel_ref;
+
+	wlan_sap_get_user_config_acs_ch_list(vdev_id, filter);
+
+	list = wlan_scan_get_result(pdev, filter);
+
+	qdf_mem_free(filter);
+
+	if (!list)
+		goto rel_ref;
+
+	status = wlan_ll_sap_sort_channel_list(vdev_id, list, ch_info);
+
+	wlan_scan_purge_results(list);
+
+rel_ref:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_LL_SAP_ID);
+
+	return status;
+}

+ 15 - 1
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.h

@@ -21,7 +21,8 @@
 #ifndef _WLAN_LL_LT_SAP_MAIN_H_
 #define _WLAN_LL_LT_SAP_MAIN_H_
 
-#include <i_qdf_types.h>
+#include "wlan_ll_sap_main.h"
+#include "wlan_mlme_public_struct.h"
 
 /**
  * ll_lt_sap_is_supported() - Check if ll_lt_sap is supported or not
@@ -30,4 +31,17 @@
  */
 bool ll_lt_sap_is_supported(void);
 
+/**
+ * ll_lt_sap_get_sorted_user_config_acs_ch_list() - API to get sorted user
+ * configured channel list
+ * @psoc: Pointer to psoc object
+ * @vdev_id: Vdev Id
+ * @ch_info: Pointer to ch_info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ll_lt_sap_get_sorted_user_config_acs_ch_list(
+					struct wlan_objmgr_psoc *psoc,
+					uint8_t vdev_id,
+					struct sap_sel_ch_info *ch_info);
 #endif /* _WLAN_LL_SAP_MAIN_H_ */

+ 7 - 4
components/wmi/src/wmi_unified_roam_tlv.c

@@ -3013,10 +3013,13 @@ extract_roam_stats_with_single_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf,
 {
 	QDF_STATUS status;
 	uint8_t vdev_id = stats_info->vdev_id;
-	uint8_t band = stats_info->scan[0].band;
+	uint8_t band;
+
+	band = stats_info->scan[0].band;
 
 	status = wmi_unified_extract_roam_11kv_stats(
-			wmi_handle, evt_buf, &stats_info->data_11kv[0], 0, 0, band);
+			wmi_handle, evt_buf, &stats_info->data_11kv[0], 0, 0,
+			band);
 	if (QDF_IS_STATUS_ERROR(status))
 		wmi_debug("Roam 11kv stats extract failed vdev %d", vdev_id);
 
@@ -3059,10 +3062,9 @@ extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf,
 	struct roam_msg_info *roam_msg_info = NULL;
 	uint8_t vdev_id, i, num_btm = 0, num_frames = 0;
 	uint8_t num_tlv = 0, num_chan = 0, num_ap = 0, num_rpt = 0;
-	uint8_t num_trigger_reason = 0;
+	uint8_t num_trigger_reason = 0, band;
 	uint32_t rem_len;
 	QDF_STATUS status;
-	uint8_t band;
 
 	param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf;
 	if (!param_buf) {
@@ -3489,6 +3491,7 @@ extract_roam_candidate_frame_tlv(wmi_unified_t wmi_handle, uint8_t *event,
 	data->vdev_id = frame_params->vdev_id;
 	data->frame_length = frame_params->frame_length;
 	data->frame = (uint8_t *)param_buf->frame;
+	data->roam_offload_candidate_frm = true;
 	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG,
 			   data->frame, data->frame_length);
 

+ 10 - 0
configs/config_to_feature.h

@@ -924,6 +924,10 @@
 #define FEATURE_SYSFS_ROAM_TRIGGER_BITMAP (1)
 #endif
 
+#ifdef CONFIG_WLAN_SYSFS_RF_TEST_MODE
+#define FEATURE_SYSFS_RF_TEST_MODE (1)
+#endif
+
 #ifdef CONFIG_RX_PERFORMANCE
 #define RX_PERFORMANCE (1)
 #endif
@@ -2659,6 +2663,12 @@
 #ifdef CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES
 #define DP_RX_BUFFER_POOL_ALLOC_THRES (CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES)
 #endif
+#ifdef CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE
+#define DP_RX_REFILL_BUFF_POOL_SIZE (CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE)
+#endif
+#ifdef CONFIG_DP_RX_REFILL_THRD_THRESHOLD
+#define DP_RX_REFILL_THRD_THRESHOLD (CONFIG_DP_RX_REFILL_THRD_THRESHOLD)
+#endif
 #endif
 #ifdef CONFIG_DP_FT_LOCK_HISTORY
 #define DP_FT_LOCK_HISTORY (1)

+ 15 - 0
configs/default_defconfig

@@ -149,6 +149,8 @@ ifeq (y,$(findstring y,$(CONFIG_CNSS_KIWI) $(CONFIG_CNSS_KIWI_V2)))
 	CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 	CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 	CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+	CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+	CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 	CONFIG_NO_RX_PKT_HDR_TLV := y
 ifeq ($(CONFIG_DP_CON_MON_MSI_ENABLED), y)
 	CONFIG_DP_CON_MON_MSI_SKIP_SET := y
@@ -413,6 +415,7 @@ endif
 	CONFIG_WLAN_SYSFS_DFSNOL := y
 	CONFIG_WLAN_SYSFS_WDS_MODE := y
 	CONFIG_WLAN_SYSFS_ROAM_TRIGGER_BITMAP := y
+	CONFIG_WLAN_SYSFS_RF_TEST_MODE := y
 endif
 CONFIG_WLAN_PDEV_VDEV_SEND_MULTI_PARAM := y
 CONFIG_WLAN_POWER_DEBUG := y
@@ -480,6 +483,8 @@ CONFIG_WBM_IDLE_LSB_WR_CNF_WAR := y
 CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 ifeq ($(CONFIG_WDI3_STATS_UPDATE), y)
 CONFIG_WDI3_STATS_BW_MONITOR := y
 endif
@@ -1061,6 +1066,12 @@ CONFIG_ENABLE_SMMU_S1_TRANSLATION := y
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_SA515M), y)
+ifeq ($(CONFIG_IPA_OFFLOAD), y)
+CONFIG_IPA_P2P_SUPPORT := y
+endif
+endif
+
 ifeq ($(CONFIG_ARCH_SM8150), y)
 ifeq ($(CONFIG_IPA_OFFLOAD), y)
 ifneq (y,$(filter y,$(CONFIG_LITHIUM) $(CONFIG_BERYLLIUM)))
@@ -1565,6 +1576,8 @@ ifeq ($(CONFIG_CNSS_QCA6750), y)
 CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 CONFIG_DP_SWLM := y
 CONFIG_WLAN_FEATURE_CE_RX_BUFFER_REUSE := y
 endif
@@ -1577,6 +1590,8 @@ ifeq (y,$(filter y,$(CONFIG_ARCH_SDXLEMUR) $(CONFIG_ARCH_SDXBAAGHA)))
 CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 CONFIG_BEACON_TX_OFFLOAD_MAX_VDEV := 4
 CONFIG_NUM_IPA_IFACE := 4
 CONFIG_MAX_CLIENTS_ALLOWED := 64

+ 4 - 0
configs/kiwi_v2_defconfig

@@ -103,6 +103,10 @@ endif # IPA_OFFLOAD
 
 CONFIG_WLAN_SYSFS_RANGE_EXT := n
 
+CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 256
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 128
+
 endif # ARCH_SDXPINN
 
 ifeq ($(CONFIG_ARCH_PINEAPPLE), y)

+ 2 - 0
configs/peach_defconfig

@@ -97,6 +97,8 @@ CONFIG_DP_PKT_STATS_PER_LMAC := y
 CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 CONFIG_NO_RX_PKT_HDR_TLV := y
 ifeq ($(CONFIG_DP_CON_MON_MSI_ENABLED), y)
 	CONFIG_DP_CON_MON_MSI_SKIP_SET := y

+ 3 - 0
configs/pineapple_gki_kiwi-v2_defconfig

@@ -45,6 +45,8 @@ CONFIG_DP_PKT_ADD_TIMESTAMP=y
 CONFIG_DP_PKT_STATS_PER_LMAC=y
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES=5
 CONFIG_DP_RX_BUFFER_POOL_SIZE=128
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE=2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD=512
 CONFIG_DP_RX_DROP_RAW_FRM=y
 CONFIG_DP_RX_PKT_NO_PEER_DELIVER=y
 CONFIG_DP_RX_SPECIAL_FRAME_NEED=y
@@ -328,6 +330,7 @@ CONFIG_WLAN_SYSFS_TEMPERATURE=y
 CONFIG_WLAN_SYSFS_TX_STBC=y
 CONFIG_WLAN_SYSFS_WLAN_DBG=y
 CONFIG_WLAN_SYSFS_BITRATES=y
+CONFIG_WLAN_SYSFS_RF_TEST_MODE=y
 CONFIG_WLAN_THERMAL_CFG=y
 CONFIG_WLAN_THERMAL_MULTI_CLIENT_SUPPORT=y
 CONFIG_WLAN_TRACEPOINTS=y

+ 2 - 0
configs/wcn6450_defconfig

@@ -764,6 +764,8 @@ CONFIG_FEATURE_VDEV_OPS_WAKELOCK := y
 CONFIG_WLAN_FEATURE_RX_BUFFER_POOL := y
 CONFIG_DP_RX_BUFFER_POOL_SIZE := 128
 CONFIG_DP_RX_BUFFER_POOL_ALLOC_THRES := 5
+CONFIG_DP_RX_REFILL_BUFF_POOL_SIZE := 2048
+CONFIG_DP_RX_REFILL_THRD_THRESHOLD := 512
 CONFIG_DP_SWLM := y
 
 #Enable Hang Event

+ 32 - 2
core/hdd/inc/wlan_hdd_assoc.h

@@ -70,7 +70,7 @@ enum peer_status {
  * @ht_op_present: ht operation present or not
  * @vht_op_present: vht operation present or not
  * @he_present: he operation present or not
- * @reserved: reserved spare bits
+ * @eht_op_present: eht operation present or not
  */
 struct hdd_conn_flag {
 	uint8_t ht_present:1;
@@ -80,7 +80,7 @@ struct hdd_conn_flag {
 	uint8_t ht_op_present:1;
 	uint8_t vht_op_present:1;
 	uint8_t he_present:1;
-	uint8_t reserved:1;
+	uint8_t eht_op_present:1;
 };
 
 /*defines for tx_BF_cap_info */
@@ -158,6 +158,8 @@ struct hdd_conn_flag {
  * to which currently sta is connected.
  * @prev_ap_bcn_ie: ap beacon IE information to which sta is currently connected
  * @ieee_link_id: AP Link Id valid for MLO connection
+ * @eht_operation: EHT operation info
+ * @eht_oper_len: length of @eht_operation
  */
 struct hdd_connection_info {
 	eConnectionState conn_state;
@@ -201,6 +203,10 @@ struct hdd_connection_info {
 #ifdef WLAN_FEATURE_11BE_MLO
 	int32_t ieee_link_id;
 #endif
+#ifdef WLAN_FEATURE_11BE
+	struct ieee80211_eht_operation eht_operation;
+	uint32_t eht_oper_len;
+#endif
 };
 
 /* Forward declarations */
@@ -534,6 +540,30 @@ void hdd_copy_ht_operation(struct hdd_station_ctx *hdd_sta_ctx,
 void hdd_copy_vht_operation(struct hdd_station_ctx *hdd_sta_ctx,
 			    tDot11fIEVHTOperation *vht_ops);
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+/**
+ * hdd_copy_eht_operation()- copy EHT operations element to
+ * hdd station context.
+ * @hdd_sta_ctx: pointer to hdd station context
+ * @eht_ops: pointer to eht operation
+ *
+ * Return: None
+ */
+void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+			    tDot11fIEeht_op *eht_ops);
+
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+			    tDot11fIEeht_op *eht_ops);
+#else
+static inline void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+					  tDot11fIEeht_op *eht_ops)
+{
+}
+#endif
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) && \
      defined(WLAN_FEATURE_11AX)
 /**

+ 22 - 1
core/hdd/inc/wlan_hdd_ipa.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2019 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
@@ -52,6 +52,20 @@ void hdd_ipa_send_nbuf_to_network(qdf_nbuf_t nbuf, qdf_netdev_t dev);
  */
 void hdd_ipa_set_mcc_mode(bool mcc_mode);
 
+/**
+ * hdd_ipa_get_tx_pipe() - Get tx pipe for the new connection
+ * @hdd_ctx: pointer to hdd_context
+ * @link: pointer to struct wlan_hdd_link_info
+ * @tx_pipe: boolean output param to store which pipe to use for @link.
+ *	     false is the primary tx pipe and true is the alternate tx pipe.
+ *
+ * Return: QDF_STATUS_SUCCESS for success, and otherwise for failure scenarios.
+ *
+ */
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe);
+
 #else
 static inline
 void hdd_ipa_send_nbuf_to_network(qdf_nbuf_t skb, qdf_netdev_t dev)
@@ -62,5 +76,12 @@ static inline void hdd_ipa_set_mcc_mode(bool mcc_mode)
 {
 }
 
+static inline QDF_STATUS
+hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+		    struct wlan_hdd_link_info *link,
+		    bool *tx_pipe)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 #endif /* HDD_IPA_H__ */

+ 120 - 3
core/hdd/src/wlan_hdd_assoc.c

@@ -226,6 +226,18 @@ static const int beacon_filter_extn_table[] = {
 #define HE_OPERATION_BSS_COL_DISABLED_POS 31
 #endif
 
+/* EHT operation BIT positins */
+#if defined(WLAN_FEATURE_11BE)
+#define EHT_OPER_BASIC_RX_NSS_MCS_0_TO_7_POS 0
+#define EHT_OPER_BASIC_TX_NSS_MCS_0_TO_7_POS 4
+#define EHT_OPER_BASIC_RX_NSS_MCS_8_AND_9_POS 8
+#define EHT_OPER_BASIC_TX_NSS_MCS_8_AND_9_POS 12
+#define EHT_OPER_BASIC_RX_NSS_MCS_10_AND_11_POS 16
+#define EHT_OPER_BASIC_TX_NSS_MCS_10_AND_11_POS 20
+#define EHT_OPER_BASIC_RX_NSS_MCS_12_AND_13_POS 24
+#define EHT_OPER_BASIC_TX_NSS_MCS_12_AND_13_POS 28
+#endif
+
 #if defined(WLAN_FEATURE_SAE) && \
 		(defined(CFG80211_EXTERNAL_AUTH_SUPPORT) || \
 		LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
@@ -1112,6 +1124,99 @@ void hdd_copy_vht_operation(struct hdd_station_ctx *hdd_sta_ctx,
 	hdd_vht_ops->basic_mcs_set = vht_ops->basicMCSSet;
 }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+			    tDot11fIEeht_op *eht_ops)
+{
+	struct ieee80211_eht_operation *hdd_eht_ops =
+		&hdd_sta_ctx->conn_info.eht_operation;
+	uint32_t mcs_param = 0, filled = 0, len = 0;
+
+	qdf_mem_zero(hdd_eht_ops, sizeof(struct ieee80211_eht_operation));
+
+	if (!eht_ops->eht_op_information_present)
+		return;
+
+	/* Min length if op_info_present */
+	len += 3;
+
+	hdd_eht_ops->params |= IEEE80211_EHT_OPER_INFO_PRESENT;
+
+	if (eht_ops->eht_default_pe_duration)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_EHT_DEF_PE_DURATION;
+	if (eht_ops->group_addr_bu_indication_limit)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_LIMIT;
+	if (eht_ops->group_addr_bu_indication_exponent)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_EXP_MASK;
+
+	mcs_param |= eht_ops->basic_rx_max_nss_for_mcs_0_to_7 <<
+				EHT_OPER_BASIC_RX_NSS_MCS_0_TO_7_POS;
+	mcs_param |= eht_ops->basic_tx_max_nss_for_mcs_0_to_7 <<
+				EHT_OPER_BASIC_TX_NSS_MCS_0_TO_7_POS;
+	mcs_param |= eht_ops->basic_rx_max_nss_for_mcs_8_and_9 <<
+				EHT_OPER_BASIC_RX_NSS_MCS_8_AND_9_POS;
+	mcs_param |= eht_ops->basic_tx_max_nss_for_mcs_8_and_9 <<
+				EHT_OPER_BASIC_TX_NSS_MCS_8_AND_9_POS;
+	mcs_param |= eht_ops->basic_rx_max_nss_for_mcs_10_and_11 <<
+				EHT_OPER_BASIC_RX_NSS_MCS_10_AND_11_POS;
+	mcs_param |= eht_ops->basic_tx_max_nss_for_mcs_10_and_11 <<
+				EHT_OPER_BASIC_TX_NSS_MCS_10_AND_11_POS;
+	mcs_param |= eht_ops->basic_rx_max_nss_for_mcs_12_and_13 <<
+				EHT_OPER_BASIC_RX_NSS_MCS_12_AND_13_POS;
+	mcs_param |= eht_ops->basic_tx_max_nss_for_mcs_12_and_13 <<
+				EHT_OPER_BASIC_TX_NSS_MCS_12_AND_13_POS;
+
+	hdd_eht_ops->basic_mcs_nss = mcs_param;
+	hdd_eht_ops->optional[filled++] = eht_ops->channel_width;
+	hdd_eht_ops->optional[filled++] = eht_ops->ccfs0;
+	hdd_eht_ops->optional[filled++] = eht_ops->ccfs1;
+
+	if (eht_ops->disabled_sub_chan_bitmap_present) {
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT;
+		len += 2;
+		hdd_eht_ops->optional[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][0];
+		hdd_eht_ops->optional[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][1];
+	}
+	hdd_sta_ctx->conn_info.eht_oper_len =
+				sizeof(struct ieee80211_eht_operation) + len;
+}
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+			    tDot11fIEeht_op *eht_ops)
+{
+	struct ieee80211_eht_operation *hdd_eht_ops =
+		&hdd_sta_ctx->conn_info.eht_operation;
+	uint32_t filled = 0, len = 0;
+
+	qdf_mem_zero(hdd_eht_ops, sizeof(struct ieee80211_eht_operation));
+
+	if (!eht_ops->eht_op_information_present)
+		return;
+
+	hdd_eht_ops->chan_width = eht_ops->channel_width;
+	hdd_eht_ops->ccfs = eht_ops->ccfs0;
+	hdd_eht_ops->present_bm = eht_ops->disabled_sub_chan_bitmap_present;
+
+	if (eht_ops->disabled_sub_chan_bitmap_present) {
+		hdd_eht_ops->disable_subchannel_bitmap[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][0];
+		hdd_eht_ops->disable_subchannel_bitmap[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][1];
+		len += 2;
+	}
+	hdd_sta_ctx->conn_info.eht_oper_len =
+				sizeof(struct ieee80211_eht_operation) + len;
+}
+#endif
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0)) && \
      defined(WLAN_FEATURE_11AX)
 void hdd_copy_he_operation(struct hdd_station_ctx *hdd_sta_ctx,
@@ -1473,6 +1578,9 @@ hdd_change_sta_state_authenticated(struct wlan_hdd_link_info *link_info,
 	uint8_t *mac_addr;
 	struct hdd_station_ctx *sta_ctx;
 	struct hdd_adapter *adapter = link_info->adapter;
+	struct hdd_context *hdd_ctx;
+	QDF_STATUS status;
+	bool alt_pipe;
 
 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 
@@ -1482,13 +1590,22 @@ hdd_change_sta_state_authenticated(struct wlan_hdd_link_info *link_info,
 	    adapter->device_mode == QDF_STA_MODE &&
 	    sta_ctx->conn_info.auth_type != eCSR_AUTH_TYPE_NONE &&
 	    sta_ctx->conn_info.auth_type != eCSR_AUTH_TYPE_OPEN_SYSTEM &&
-	    sta_ctx->conn_info.auth_type != eCSR_AUTH_TYPE_SHARED_KEY)
+	    sta_ctx->conn_info.auth_type != eCSR_AUTH_TYPE_SHARED_KEY) {
+
+		hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+		status = hdd_ipa_get_tx_pipe(hdd_ctx, link_info, &alt_pipe);
+		if (!QDF_IS_STATUS_SUCCESS(status)) {
+			hdd_debug("Failed to get alternate pipe for vdev %d",
+				  link_info->vdev_id);
+			alt_pipe = false;
+		}
+
 		ucfg_ipa_wlan_evt(adapter->hdd_ctx->pdev, adapter->dev,
 				  adapter->device_mode,
 				  link_info->vdev_id,
 				  WLAN_IPA_STA_CONNECT, mac_addr,
-				  WLAN_REG_IS_24GHZ_CH_FREQ(
-					sta_ctx->conn_info.chan_freq));
+				  alt_pipe);
+	}
 
 	hdd_cm_set_peer_authenticate(link_info,
 				     &sta_ctx->conn_info.bssid, false);

+ 137 - 27
core/hdd/src/wlan_hdd_cfg80211.c

@@ -805,6 +805,25 @@ wlan_hdd_p2p_p2p_iface_limit[] = {
 	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
 	},
 };
+#elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
+/* STA + AP + P2P combination */
+static const struct ieee80211_iface_limit
+wlan_hdd_sta_ap_p2p_iface_limit[] = {
+	{
+	   .max = 1,
+	   .types = BIT(NL80211_IFTYPE_STATION)
+	},
+	{
+	   .max = 1,
+	   .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT)
+	},
+#ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
+	{
+	   .max = 1,
+	   .types = BIT(NL80211_IFTYPE_AP)
+	},
+#endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
+};
 #endif
 
 #ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
@@ -951,7 +970,23 @@ static struct ieee80211_iface_combination
 		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
 		.beacon_int_infra_match = true,
 	},
-#endif
+#elif defined(WLAN_FEATURE_STA_SAP_P2P_CONCURRENCY)
+	/* STA + P2P + SAP */
+	{
+		.limits = wlan_hdd_sta_ap_p2p_iface_limit,
+		/* we can allow 3 channels for three different persona
+		 * but due to firmware limitation, allow max 2 concrnt channels.
+		 */
+		.num_different_channels = 2,
+#ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
+		.max_interfaces = 3,
+#else
+		.max_interfaces = 2,
+#endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
+		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_p2p_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+#endif /* WLAN_FEATURE_NO_P2P_CONCURRENCY */
 	/* STA + P2P */
 	{
 		.limits = wlan_hdd_sta_p2p_iface_limit,
@@ -3824,7 +3859,7 @@ hdd_remove_passive_dfs_acs_channel_for_ll_sap(struct sap_config *sap_config,
 #endif
 
 /* Stored ACS Frequency timeout in msec */
-#define STORED_ACS_FREQ_TIMEOUT 500
+#define STORED_ACS_FREQ_TIMEOUT 5000
 static bool
 wlan_hdd_is_prev_acs_freq_present_in_acs_config(struct sap_config *sap_cfg)
 {
@@ -8617,6 +8652,8 @@ wlan_hdd_wifi_test_config_policy[
 			.type = NLA_U8},
 		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_EHT_MLO_STR_TX] = {
 			.type = NLA_U8},
+		[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ] = {
+			.type = NLA_U8},
 };
 
 /**
@@ -12268,6 +12305,7 @@ static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
 	struct wlan_objmgr_vdev *vdev, *link_vdev;
 	struct wlan_channel *bss_chan;
 	uint8_t nl80211_chwidth;
+	int8_t ret = 0;
 
 	chwidth = wma_cli_get_command(link_info->vdev_id,
 				      wmi_vdev_param_chwidth, VDEV_CMD);
@@ -12283,47 +12321,50 @@ static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
 	if (wlan_vdev_mlme_is_mlo_vdev(vdev)) {
 		mlo_bd_info = nla_nest_start(skb, CONFIG_MLO_LINKS);
 		for (link_id = 0; link_id < WLAN_MAX_LINK_ID; link_id++) {
-			link_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
+			link_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
+							    WLAN_OSIF_ID);
 			if (!link_vdev)
 				continue;
 
 			mlo_bd = nla_nest_start(skb, i);
 			if (!mlo_bd) {
-				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
-				mlo_release_vdev_ref(link_vdev);
 				hdd_err("nla_nest_start fail");
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 			bss_chan = wlan_vdev_mlme_get_bss_chan(link_vdev);
 			if (!bss_chan) {
-				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
-				mlo_release_vdev_ref(link_vdev);
 				hdd_err("fail to get bss_chan info");
-				return QDF_STATUS_E_FAILURE;
+				ret = -EINVAL;
+				goto end;
 			}
 			if (nla_put_u8(skb, CONFIG_MLO_LINK_ID, link_id)) {
-				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
-				mlo_release_vdev_ref(link_vdev);
 				hdd_err("nla_put failure");
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 
 			nl80211_chwidth = hdd_phy_chwidth_to_nl80211_chwidth(bss_chan->ch_width);
 			if (nla_put_u8(skb, CONFIG_CHANNEL_WIDTH,
 				       nl80211_chwidth)) {
-				hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
-				mlo_release_vdev_ref(link_vdev);
 				hdd_err("nla_put failure");
-				return -EINVAL;
+				ret = -EINVAL;
+				goto end;
 			}
 			nla_nest_end(skb, mlo_bd);
 			i++;
-			mlo_release_vdev_ref(link_vdev);
+			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
 		}
 		nla_nest_end(skb, mlo_bd_info);
 	}
+
+end:
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
-	return 0;
+
+	if (ret)
+		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
+
+	return ret;
 }
 
 /**
@@ -13233,11 +13274,11 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 			QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_SEND_ADDBA_REQ]);
 		if (cfg_val) {
 			/*Auto BA mode*/
-			set_val = 0;
+			set_val = HDD_BA_MODE_AUTO;
 			hdd_debug("BA operating mode is set to auto");
 		} else {
 			/*Manual BA mode*/
-			set_val = 1;
+			set_val = HDD_BA_MODE_MANUAL;
 			hdd_debug("BA operating mode is set to Manual");
 		}
 
@@ -13305,6 +13346,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 			goto send_err;
 		}
 	} else if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]) {
+		uint32_t arg[2];
 		buff_size = nla_get_u16(tb[
 		QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ADDBA_BUFF_SIZE]);
 		hdd_debug("set buff size to %d for all tids", buff_size);
@@ -13332,6 +13374,16 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 		ret_val = wma_cli_set_command(link_info->vdev_id,
 					      GEN_VDEV_PARAM_AMPDU,
 					      buff_size, GEN_CMD);
+
+		if (set_val == HDD_BA_MODE_512) {
+			arg[0] = 703;
+			arg[1] = 0;
+			ret_val = sme_send_unit_test_cmd(
+						adapter->deflink->vdev_id,
+						0x48, 2, arg);
+			if (ret_val)
+				hdd_err("Failed to set Full state BA support");
+		}
 	}
 
 	if (tb[QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_ENABLE_NO_ACK]) {
@@ -14234,7 +14286,7 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 							mac_handle,
 							vdev_id, cfg_val);
 				if (ret_val)
-					sme_err("Failed to send vdev pause");
+					hdd_err("Failed to send vdev pause");
 			}
 		}
 	}
@@ -14251,7 +14303,16 @@ __wlan_hdd_cfg80211_set_wifi_test_config(struct wiphy *wiphy,
 						 0x48, 2, arg);
 
 		if (ret_val)
-			sme_err("Failed to send STR TX indication");
+			hdd_err("Failed to send STR TX indication");
+	}
+
+	cmd_id = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MLD_ID_ML_PROBE_REQ;
+	if (tb[cmd_id]) {
+		cfg_val = nla_get_u8(tb[cmd_id]);
+		hdd_debug("MLD ID in ML probe request: %d", cfg_val);
+		ret_val = wlan_mlme_set_eht_mld_id(hdd_ctx->psoc, cfg_val);
+		if (ret_val)
+			hdd_err("Failed to set MLD ID");
 	}
 
 	if (update_sme_cfg)
@@ -21458,6 +21519,17 @@ static void wlan_hdd_set_vlan_offload(struct hdd_context *hdd_ctx)
 }
 #endif
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
+{
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MFP_OPTIONAL);
+}
+#else
+static void wlan_hdd_set_mfp_optional(struct wiphy *wiphy)
+{
+}
+#endif
+
 /*
  * In this function, wiphy structure is updated after QDF
  * initialization. In wlan_hdd_cfg80211_init, only the
@@ -21565,6 +21637,7 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
 	wlan_hdd_set_32bytes_kck_support(wiphy);
 	wlan_hdd_set_nan_secure_mode(wiphy);
 	wlan_hdd_set_vlan_offload(hdd_ctx);
+	wlan_hdd_set_mfp_optional(wiphy);
 }
 
 /**
@@ -22739,7 +22812,7 @@ struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
 		return vdev;
 
-	link_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
+	link_vdev = mlo_get_vdev_by_link_id(vdev, link_id, id);
 	hdd_objmgr_put_vdev_by_user(vdev, id);
 
 	return link_vdev;
@@ -22753,7 +22826,7 @@ void wlan_key_put_link_vdev(struct wlan_objmgr_vdev *link_vdev,
 		return;
 	}
 
-	mlo_release_vdev_ref(link_vdev);
+	wlan_objmgr_vdev_release_ref(link_vdev, id);
 }
 #else
 struct wlan_objmgr_vdev *wlan_key_get_link_vdev(struct hdd_adapter *adapter,
@@ -23069,18 +23142,23 @@ wlan_hdd_mlo_defer_set_keys(struct hdd_adapter *adapter,
 			    struct wlan_objmgr_vdev *vdev,
 			    struct qdf_mac_addr *mac_address)
 {
+	uint8_t link_id;
+
 	if (!adapter)
 		return false;
 
-	if (!vdev)
+	if (!vdev || !vdev->mlo_dev_ctx)
 		return false;
 
+	link_id = wlan_vdev_get_link_id(vdev);
+
 	if ((adapter->device_mode == QDF_STA_MODE) &&
 	    ((!wlan_cm_is_vdev_connected(vdev)) ||
 	    (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
 	     mlo_roam_is_auth_status_connected(adapter->hdd_ctx->psoc,
 					       wlan_vdev_get_id(vdev))))) {
-		hdd_debug("MLO:Defer set keys for vdev %d", wlan_vdev_get_id(vdev));
+		hdd_debug("MLO:Defer set keys for link_id %d", link_id);
+		mlo_defer_set_keys(vdev, link_id, true);
 		return true;
 	}
 
@@ -23145,14 +23223,14 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
 		} else if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) &&
 			   adapter->device_mode == QDF_STA_MODE) {
 			status = wlan_objmgr_vdev_try_get_ref(vdev,
-							      WLAN_MLO_MGR_ID);
+							      WLAN_OSIF_ID);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				hdd_err("Failed to get vdev ref");
 				return qdf_status_to_os_return(status);
 			}
 			status = wlan_hdd_mlo_copy_partner_addr_from_mlie(
 							vdev, &mac_address);
-			mlo_release_vdev_ref(vdev);
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				hdd_err("Failed to get peer address from ML IEs");
 				return qdf_status_to_os_return(status);
@@ -23498,6 +23576,8 @@ static int wlan_add_key_standby_link(struct hdd_adapter *adapter,
 			params,
 			&mlo_link_info->link_addr,
 			link_id);
+	hdd_debug("ml defer set key link id %d", link_id);
+	mlo_defer_set_keys(vdev, link_id, true);
 	return errno;
 }
 
@@ -27918,6 +27998,36 @@ hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode)
 	}
 }
 
+enum qca_wlan_802_11_mode
+hdd_convert_phymode_to_80211mode(eCsrPhyMode mode)
+{
+	switch (mode) {
+	case eCSR_DOT11_MODE_11a:
+		return QCA_WLAN_802_11_MODE_11A;
+	case eCSR_DOT11_MODE_11b:
+		return QCA_WLAN_802_11_MODE_11B;
+	case eCSR_DOT11_MODE_11g:
+	case eCSR_DOT11_MODE_11g_ONLY:
+		return QCA_WLAN_802_11_MODE_11G;
+	case eCSR_DOT11_MODE_11n:
+	case eCSR_DOT11_MODE_11n_ONLY:
+		return QCA_WLAN_802_11_MODE_11N;
+	case eCSR_DOT11_MODE_11ac:
+	case eCSR_DOT11_MODE_11ac_ONLY:
+		return QCA_WLAN_802_11_MODE_11AC;
+	case eCSR_DOT11_MODE_11ax:
+	case eCSR_DOT11_MODE_11ax_ONLY:
+		return QCA_WLAN_802_11_MODE_11AX;
+	case eCSR_DOT11_MODE_11be:
+	case eCSR_DOT11_MODE_11be_ONLY:
+		return QCA_WLAN_802_11_MODE_11BE;
+	case eCSR_DOT11_MODE_abg:
+	case eCSR_DOT11_MODE_AUTO:
+	default:
+		return QCA_WLAN_802_11_MODE_INVALID;
+	}
+}
+
 bool hdd_is_legacy_connection(struct wlan_hdd_link_info *link_info)
 {
 	struct hdd_station_ctx *sta_ctx;

+ 10 - 0
core/hdd/src/wlan_hdd_cfg80211.h

@@ -927,6 +927,16 @@ hdd_latency_level_event_handler_cb(const void *event_data,
 enum qca_wlan_802_11_mode
 hdd_convert_cfgdot11mode_to_80211mode(enum csr_cfgdot11mode mode);
 
+/**
+ * hdd_convert_phymode_to_80211mode() - Function to convert eCsrPhyMode
+ *					to 80211 mode
+ * @mode: eCsrPhyMode
+ *
+ * Return: 80211 mode
+ */
+enum qca_wlan_802_11_mode
+hdd_convert_phymode_to_80211mode(eCsrPhyMode mode);
+
 /**
  * hdd_send_update_owe_info_event - Send update OWE info event
  * @adapter: Pointer to adapter

+ 18 - 3
core/hdd/src/wlan_hdd_cm_connect.c

@@ -1151,6 +1151,11 @@ static void hdd_cm_save_bss_info(struct wlan_hdd_link_info *link_info,
 	else
 		hdd_sta_ctx->conn_info.conn_flag.eht_present = false;
 
+	if (assoc_resp->eht_op.present)
+		hdd_sta_ctx->conn_info.conn_flag.eht_op_present = true;
+	else
+		hdd_sta_ctx->conn_info.conn_flag.eht_op_present = false;
+
 	/*
 	 * Cache connection info only in case of station
 	 */
@@ -1158,6 +1163,7 @@ static void hdd_cm_save_bss_info(struct wlan_hdd_link_info *link_info,
 		/* Cleanup already existing he info */
 		hdd_cleanup_conn_info(link_info);
 
+		hdd_copy_eht_operation(hdd_sta_ctx, &assoc_resp->eht_op);
 		/* Cache last connection info */
 		qdf_mem_copy(&hdd_sta_ctx->cache_conn_info,
 			     &hdd_sta_ctx->conn_info,
@@ -1533,6 +1539,8 @@ hdd_cm_connect_success_pre_user_update(struct wlan_objmgr_vdev *vdev,
 	struct hdd_adapter *assoc_link_adapter;
 	bool is_immediate_power_save;
 	struct wlan_hdd_link_info *link_info;
+	QDF_STATUS status;
+	bool alt_pipe;
 
 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	if (!hdd_ctx) {
@@ -1695,14 +1703,21 @@ hdd_cm_connect_success_pre_user_update(struct wlan_objmgr_vdev *vdev,
 			adapter->device_mode);
 	}
 
-	if (ucfg_ipa_is_enabled() && !is_auth_required)
+	if (ucfg_ipa_is_enabled() && !is_auth_required) {
+		status = hdd_ipa_get_tx_pipe(hdd_ctx, link_info, &alt_pipe);
+		if (!QDF_IS_STATUS_SUCCESS(status)) {
+			hdd_debug("Failed to get alternate pipe for vdev %d",
+				  link_info->vdev_id);
+			alt_pipe = false;
+		}
+
 		ucfg_ipa_wlan_evt(hdd_ctx->pdev, adapter->dev,
 				  adapter->device_mode,
 				  link_info->vdev_id,
 				  WLAN_IPA_STA_CONNECT,
 				  rsp->bssid.bytes,
-				  WLAN_REG_IS_24GHZ_CH_FREQ(
-					sta_ctx->conn_info.chan_freq));
+				  alt_pipe);
+	}
 
 	if (adapter->device_mode == QDF_STA_MODE)
 		cdp_reset_rx_hw_ext_stats(soc);

+ 21 - 44
core/hdd/src/wlan_hdd_he.c

@@ -663,7 +663,7 @@ static bool hdd_check_mode_support_for_sr(struct hdd_adapter *adapter,
 					  uint8_t sr_ctrl)
 {
 	if ((adapter->device_mode == QDF_STA_MODE) &&
-	    (!hdd_cm_is_vdev_connected(adapter->deflink) || !sr_ctrl ||
+	    (!hdd_cm_is_vdev_connected(adapter->deflink) ||
 	    ((sr_ctrl & NON_SRG_PD_SR_DISALLOWED) &&
 	    !(sr_ctrl & SRG_INFO_PRESENT)))) {
 		hdd_err("mode %d doesn't supports SR", adapter->device_mode);
@@ -707,7 +707,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 	struct sk_buff *skb;
 	struct cdp_pdev_obss_pd_stats_tlv stats;
 	uint8_t sr_device_modes;
-	bool is_pd_threshold_present = false;
 
 	hdd_enter_dev(wdev->netdev);
 
@@ -727,7 +726,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 		hdd_err("Null VDEV");
 		return -EINVAL;
 	}
-	sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(vdev);
 	/**
 	 * Reject command if SR concurrency is not allowed and
 	 * only STA mode is set in ini to enable SR.
@@ -776,6 +774,15 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 
 	ucfg_spatial_reuse_get_sr_config(vdev, &sr_ctrl, &non_srg_max_pd_offset,
 					 &is_sr_enable);
+
+	if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl) &&
+	    (sr_oper != QCA_WLAN_SR_OPERATION_GET_PARAMS)) {
+		hdd_err("SR operation not allowed, sr_ctrl = %x, mode = %d",
+			sr_ctrl, adapter->device_mode);
+		ret = -EINVAL;
+		goto exit;
+	}
+
 	if (sr_oper != QCA_WLAN_SR_OPERATION_SR_ENABLE && !is_sr_enable) {
 		hdd_err("SR operation not allowed");
 		ret = -EINVAL;
@@ -818,9 +825,7 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 			srg_pd_threshold =
 			nla_get_s32(
 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_SRG_PD_THRESHOLD]);
-			is_pd_threshold_present = true;
-			wlan_vdev_mlme_set_pd_threshold_present(
-						vdev, is_pd_threshold_present);
+			wlan_vdev_mlme_set_pd_threshold_present(vdev, true);
 		}
 
 		if (is_sr_enable &&
@@ -829,37 +834,25 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 			nla_get_s32(
 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_NON_SRG_PD_THRESHOLD]
 			);
-			is_pd_threshold_present = true;
-			wlan_vdev_mlme_set_pd_threshold_present(
-						vdev, is_pd_threshold_present);
-		}
-		if (is_pd_threshold_present) {
-			if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-				ret = -EINVAL;
-				goto exit;
-			}
+			wlan_vdev_mlme_set_pd_threshold_present(vdev, true);
 		}
+
 		hdd_debug("setting sr enable %d with pd threshold srg: %d non srg: %d",
 			  is_sr_enable, srg_pd_threshold, non_srg_pd_threshold);
 		/* Set the variables */
 		ucfg_spatial_reuse_set_sr_enable(vdev, is_sr_enable);
-		if (hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			status = ucfg_spatial_reuse_setup_req(
-				vdev, hdd_ctx->pdev, is_sr_enable,
-				srg_pd_threshold, non_srg_pd_threshold);
-			if (status != QDF_STATUS_SUCCESS) {
-				hdd_err("failed to enable Spatial Reuse feature");
-				ret = -EINVAL;
-				goto exit;
-			}
+		status = ucfg_spatial_reuse_setup_req(vdev, hdd_ctx->pdev,
+						      is_sr_enable,
+						      srg_pd_threshold,
+						      non_srg_pd_threshold);
+		if (status != QDF_STATUS_SUCCESS) {
+			hdd_err("failed to enable Spatial Reuse feature");
+			ret = -EINVAL;
+			goto exit;
 		}
 
 		break;
 	case QCA_WLAN_SR_OPERATION_GET_STATS:
-		if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			ret = -EINVAL;
-			goto exit;
-		}
 		status = policy_mgr_get_mac_id_by_session_id(
 						hdd_ctx->psoc,
 						adapter->deflink->vdev_id,
@@ -892,10 +885,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 		ret = wlan_cfg80211_vendor_cmd_reply(skb);
 		break;
 	case QCA_WLAN_SR_OPERATION_CLEAR_STATS:
-		if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			ret = -EINVAL;
-			goto exit;
-		}
 		status = policy_mgr_get_mac_id_by_session_id(
 						hdd_ctx->psoc,
 						adapter->deflink->vdev_id,
@@ -912,10 +901,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 		}
 		break;
 	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_PROHIBIT:
-		if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			ret = -EINVAL;
-			goto exit;
-		}
 		if (tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE])
 			sr_he_siga_val15_allowed = nla_get_u8(
 			tb2[QCA_WLAN_VENDOR_ATTR_SR_PARAMS_HESIGA_VAL15_ENABLE]
@@ -933,10 +918,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 		}
 		break;
 	case QCA_WLAN_SR_OPERATION_PSR_AND_NON_SRG_OBSS_PD_ALLOW:
-		if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			ret = -EINVAL;
-			goto exit;
-		}
 		if (!QDF_IS_STATUS_SUCCESS(ucfg_spatial_reuse_send_sr_prohibit(
 					   vdev, false))) {
 			hdd_debug("Prohibit command can not be sent");
@@ -945,10 +926,6 @@ static int __wlan_hdd_cfg80211_sr_operations(struct wiphy *wiphy,
 		}
 		break;
 	case QCA_WLAN_SR_OPERATION_GET_PARAMS:
-		if (!hdd_check_mode_support_for_sr(adapter, sr_ctrl)) {
-			ret = -EINVAL;
-			goto exit;
-		}
 		wlan_vdev_mlme_get_srg_pd_offset(vdev, &srg_max_pd_offset,
 						 &srg_min_pd_offset);
 		non_srg_max_pd_offset =

+ 19 - 2
core/hdd/src/wlan_hdd_hostapd.c

@@ -2088,6 +2088,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 	struct qdf_mac_addr sta_addr = {0};
 	qdf_freq_t dfs_freq;
 	struct wlan_hdd_link_info *link_info;
+	bool alt_pipe;
 
 	dev = context;
 	if (!dev) {
@@ -2252,6 +2253,14 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 		}
 
 		if (ucfg_ipa_is_enabled()) {
+			status = hdd_ipa_get_tx_pipe(hdd_ctx, link_info,
+						     &alt_pipe);
+			if (!QDF_IS_STATUS_SUCCESS(status)) {
+				hdd_debug("Failed to get alt pipe for vdev %d",
+					  link_info->vdev_id);
+				alt_pipe = false;
+			}
+
 			status = ucfg_ipa_wlan_evt(
 					hdd_ctx->pdev,
 					adapter->dev,
@@ -2259,8 +2268,7 @@ QDF_STATUS hdd_hostapd_sap_event_cb(struct sap_event *sap_event,
 					link_info->vdev_id,
 					WLAN_IPA_AP_CONNECT,
 					adapter->dev->dev_addr,
-					WLAN_REG_IS_24GHZ_CH_FREQ(
-						ap_ctx->operating_chan_freq));
+					alt_pipe);
 			if (status)
 				hdd_err("WLAN_AP_CONNECT event failed");
 		}
@@ -7665,6 +7673,15 @@ static void hdd_update_he_obss_pd(struct wlan_hdd_link_info *link_info,
 {
 	struct wlan_objmgr_vdev *vdev;
 	struct ieee80211_he_obss_pd *obss_pd;
+	uint8_t sr_device_modes;
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(link_info->adapter);
+
+	ucfg_mlme_get_sr_enable_modes(hdd_ctx->psoc, &sr_device_modes);
+	if (!(sr_device_modes & (1 << link_info->adapter->device_mode))) {
+		hdd_debug("SR operation not allowed for mode %d",
+			  link_info->adapter->device_mode);
+		return;
+	}
 
 	if (!params || !params->he_obss_pd.enable)
 		return;

+ 49 - 10
core/hdd/src/wlan_hdd_ioctl.c

@@ -6396,6 +6396,11 @@ static int drv_cmd_set_channel_switch(struct wlan_hdd_link_info *link_info,
 		return -EINVAL;
 	}
 
+	if (!qdf_atomic_test_bit(SOFTAP_BSS_STARTED, &link_info->link_flags)) {
+		hdd_err("SAP not started");
+		return -EINVAL;
+	}
+
 	status = hdd_parse_set_channel_switch_command(value,
 							&chan_number, &chan_bw);
 	if (status) {
@@ -6554,20 +6559,52 @@ next_adapter:
 	}
 }
 
+/**
+ * hdd_check_chan_and_fill_freq() - to validate chan and convert into freq
+ * @pdev: The physical dev to cache the channels for
+ * @in_chan: input as channel number or freq
+ * @freq: frequency for input in_chan (output parameter)
+ *
+ * This function checks input "in_chan" is channel number, if yes then fills
+ * appropriate frequency into "freq" out param. If the "in_param" is greater
+ * than MAX_5GHZ_CHANNEL then gets the valid frequencies for legacy channels
+ * else get the valid channel for 6Ghz frequency.
+ *
+ * Return: true if "in_chan" is valid channel/frequency; false otherwise
+ */
+static bool hdd_check_chan_and_fill_freq(struct wlan_objmgr_pdev *pdev,
+					 uint32_t *in_chan, qdf_freq_t *freq)
+{
+	if (IS_CHANNEL_VALID(*in_chan)) {
+		*freq = wlan_reg_legacy_chan_to_freq(pdev, *in_chan);
+	} else if (WLAN_REG_IS_24GHZ_CH_FREQ(*in_chan) ||
+		   WLAN_REG_IS_5GHZ_CH_FREQ(*in_chan) ||
+		   WLAN_REG_IS_6GHZ_CHAN_FREQ(*in_chan)) {
+		*freq = *in_chan;
+		*in_chan = wlan_reg_freq_to_chan(pdev, *in_chan);
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
 /**
  * hdd_parse_disable_chan_cmd() - Parse the channel list received
  * in command.
  * @adapter: pointer to hdd adapter
  * @ptr: Pointer to the command string
  *
- * This function parses the channel list received in the command.
+ * This function parses the channel list/frequency received in the command.
  * command should be a string having format
  * SET_DISABLE_CHANNEL_LIST <num of channels>
- * <channels separated by spaces>.
- * If the command comes multiple times than this function will compare
- * the channels received in the command with the channels cached in the
- * first command, if the channel list matches with the cached channels,
- * it returns success otherwise returns failure.
+ * <channels separated by spaces>/<frequency separated by spaces>.
+ * If this command has frequency as input, this function first converts into
+ * equivalent channel.
+ * If the command comes multiple times then the channels received in the
+ * command or channels converted from frequency will be compared with the
+ * channels cached in the first command, if the channel list matches with
+ * the cached channels, it returns success otherwise returns failure.
  *
  * Return: 0 on success, Error code on failure
  */
@@ -6579,6 +6616,7 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr)
 	int j, i, temp_int, ret = 0, num_channels;
 	qdf_freq_t *chan_freq_list = NULL;
 	bool is_command_repeated = false;
+	qdf_freq_t freq = 0;
 
 	if (!hdd_ctx) {
 		hdd_err("HDD Context is NULL");
@@ -6678,15 +6716,16 @@ static int hdd_parse_disable_chan_cmd(struct hdd_adapter *adapter, uint8_t *ptr)
 			goto parse_failed;
 		}
 
-		if (!IS_CHANNEL_VALID(temp_int)) {
+		if (!hdd_check_chan_and_fill_freq(hdd_ctx->pdev, &temp_int,
+						  &freq)) {
 			hdd_err("Invalid channel number received");
 			ret = -EINVAL;
 			goto parse_failed;
 		}
 
-		hdd_debug("channel[%d] = %d", j, temp_int);
-		chan_freq_list[j] = wlan_reg_legacy_chan_to_freq(hdd_ctx->pdev,
-								 temp_int);
+		hdd_debug("channel[%d] = %d Frequency[%d] = %d", j, temp_int,
+			  j, freq);
+		chan_freq_list[j] = freq;
 	}
 
 	/*extra arguments check*/

+ 150 - 1
core/hdd/src/wlan_hdd_ipa.c

@@ -26,7 +26,7 @@
 /* Include Files */
 #include <wlan_hdd_includes.h>
 #include <wlan_hdd_ipa.h>
-#include "wlan_policy_mgr_api.h"
+#include "wlan_policy_mgr_ucfg.h"
 #include "wlan_ipa_ucfg_api.h"
 #include <wlan_hdd_softap_tx_rx.h>
 #include <linux/inetdevice.h>
@@ -40,6 +40,21 @@
 #include "wlan_dp_ucfg_api.h"
 
 #ifdef IPA_OFFLOAD
+
+/**
+ * struct hdd_ipa_connection_info - connectio info for IPA component
+ * @vdev_id: vdev id
+ * @ch_freq: channel frequency
+ * @ch_width: channel width
+ * @wlan_80211_mode: enum qca_wlan_802_11_mode
+ */
+struct hdd_ipa_connection_info {
+	uint8_t vdev_id;
+	qdf_freq_t ch_freq;
+	enum phy_ch_width ch_width;
+	enum qca_wlan_802_11_mode wlan_80211_mode;
+};
+
 #if (defined(QCA_CONFIG_SMP) && defined(PF_WAKE_UP_IDLE)) ||\
 	IS_ENABLED(CONFIG_SCHED_WALT)
 /**
@@ -287,4 +302,138 @@ void hdd_ipa_set_mcc_mode(bool mcc_mode)
 
 	ucfg_ipa_set_mcc_mode(hdd_ctx->pdev, mcc_mode);
 }
+
+#ifdef IPA_WDI3_TX_TWO_PIPES
+static void
+hdd_ipa_fill_sta_connection_info(struct wlan_hdd_link_info *link,
+				 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_station_ctx *ctx = WLAN_HDD_GET_STATION_CTX_PTR(link);
+
+	conn->ch_freq = ctx->conn_info.chan_freq;
+	conn->ch_width = ctx->conn_info.ch_width;
+	conn->wlan_80211_mode = hdd_convert_cfgdot11mode_to_80211mode(
+			ctx->conn_info.dot11mode);
+}
+
+static void
+hdd_ipa_fill_sap_connection_info(struct wlan_hdd_link_info *link,
+				 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_ap_ctx *ctx = WLAN_HDD_GET_AP_CTX_PTR(link);
+
+	conn->ch_freq = ctx->operating_chan_freq;
+	conn->ch_width = ctx->sap_config.ch_params.ch_width;
+	conn->wlan_80211_mode = hdd_convert_phymode_to_80211mode(
+			ctx->sap_config.SapHw_mode);
+}
+
+static void hdd_ipa_fill_connection_info(struct wlan_hdd_link_info *link,
+					 struct hdd_ipa_connection_info *conn)
+{
+	struct hdd_adapter *adapter = link->adapter;
+
+	conn->vdev_id = link->vdev_id;
+
+	if (adapter->device_mode == QDF_STA_MODE)
+		hdd_ipa_fill_sta_connection_info(link, conn);
+	else if (adapter->device_mode == QDF_SAP_MODE)
+		hdd_ipa_fill_sap_connection_info(link, conn);
+}
+
+static QDF_STATUS
+hdd_ipa_get_tx_pipe_multi_conn(struct hdd_context *hdd_ctx,
+			       struct hdd_ipa_connection_info *conn,
+			       bool *tx_pipe)
+{
+	uint32_t new_freq = conn->ch_freq;
+	QDF_STATUS status;
+	uint8_t vdev_id;
+	bool pipe;
+
+	if (ucfg_policy_mgr_get_vdev_same_freq_new_conn(hdd_ctx->psoc,
+							new_freq,
+							&vdev_id)) {
+		/* Inherit the pipe selection of the connection that has
+		 * same freq.
+		 */
+		return ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id, tx_pipe);
+	} else {
+		if (ucfg_policy_mgr_get_vdev_diff_freq_new_conn(hdd_ctx->psoc,
+								new_freq,
+								&vdev_id)) {
+			status = ucfg_ipa_get_alt_pipe(hdd_ctx->pdev, vdev_id,
+						       &pipe);
+			if (QDF_IS_STATUS_ERROR(status))
+				return QDF_STATUS_E_INVAL;
+
+			/* Inverse the pipe selection of the connection that
+			 * has different channel frequency.
+			 */
+			*tx_pipe = !pipe;
+			return QDF_STATUS_SUCCESS;
+		} else {
+			return QDF_STATUS_E_INVAL;
+		}
+	}
+}
+
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe)
+{
+	struct hdd_ipa_connection_info conn;
+	uint32_t count;
+
+	if (qdf_unlikely(!hdd_ctx || !link || !tx_pipe)) {
+		hdd_debug("Invalid parameters");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* If SBS not capable, use legacy DBS selection */
+	if (!ucfg_policy_mgr_is_hw_sbs_capable(hdd_ctx->psoc)) {
+		hdd_debug("firmware is not sbs capable");
+		*tx_pipe = WLAN_REG_IS_24GHZ_CH_FREQ(conn.ch_freq);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	hdd_ipa_fill_connection_info(link, &conn);
+
+	/* Always select the primary pipe for connection that is EHT160 or
+	 * EHT320 due to higher tput requiements.
+	 */
+	if (conn.wlan_80211_mode == QCA_WLAN_802_11_MODE_11BE &&
+	    (conn.ch_width == CH_WIDTH_160MHZ ||
+	     conn.ch_width == CH_WIDTH_320MHZ)) {
+		*tx_pipe = false;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	count = ucfg_policy_mgr_get_connection_count(hdd_ctx->psoc);
+	if (!count) {
+		/* For first connection that is below EHT160, select the
+		 * alternate pipe so as to reserve the primary pipe for
+		 * potential connections that are above EHT160.
+		 */
+		*tx_pipe = true;
+		return QDF_STATUS_SUCCESS;
+	}
+
+	return hdd_ipa_get_tx_pipe_multi_conn(hdd_ctx, &conn, tx_pipe);
+}
+#else /* !IPA_WDI3_TX_TWO_PIPES */
+QDF_STATUS hdd_ipa_get_tx_pipe(struct hdd_context *hdd_ctx,
+			       struct wlan_hdd_link_info *link,
+			       bool *tx_pipe)
+{
+	if (qdf_unlikely(!tx_pipe))
+		return QDF_STATUS_E_INVAL;
+
+	/* For IPA_WDI3_TX_TWO_PIPES=n, only one tx pipe is available */
+	*tx_pipe = false;
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* IPA_WDI3_TX_TWO_PIPES */
+
 #endif

+ 41 - 14
core/hdd/src/wlan_hdd_main.c

@@ -550,6 +550,7 @@ static void
 wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx)
 {
 	struct hdd_adapter *adapter;
+	struct osif_vdev_sync *vdev_sync;
 	void *soc;
 	bool running;
 
@@ -574,9 +575,17 @@ wlan_hdd_lpc_del_monitor_interface(struct hdd_context *hdd_ctx)
 	}
 
 	hdd_debug("lpc: Delete monitor interface");
+	vdev_sync = osif_vdev_sync_unregister(adapter->dev);
+	if (vdev_sync)
+		osif_vdev_sync_wait_for_ops(vdev_sync);
+
 	wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes);
 	hdd_stop_adapter(hdd_ctx, adapter);
+	hdd_deinit_adapter(hdd_ctx, adapter, true);
 	hdd_close_adapter(hdd_ctx, adapter, true);
+
+	if (vdev_sync)
+		osif_vdev_sync_destroy(vdev_sync);
 }
 #else
 static inline
@@ -7305,6 +7314,31 @@ hdd_set_vdev_mlo_external_sae_auth_conversion(struct wlan_objmgr_vdev *vdev,
 }
 #endif
 
+static void
+hdd_vdev_configure_rtscts_enable(struct hdd_context *hdd_ctx,
+				 struct wlan_objmgr_vdev *vdev)
+{
+	int ret;
+	QDF_STATUS status;
+	uint16_t rts_profile = 0;
+
+	if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE)
+		return;
+
+	status = ucfg_fwol_get_rts_profile(hdd_ctx->psoc, &rts_profile);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("FAILED TO GET RTSCTS Profile status:%d", status);
+		return;
+	}
+
+	ret = sme_cli_set_command(wlan_vdev_get_id(vdev),
+				  wmi_vdev_param_enable_rtscts,
+				  rts_profile,
+				  VDEV_CMD);
+	if (ret)
+		hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
+}
+
 static void
 hdd_vdev_configure_opmode_params(struct hdd_context *hdd_ctx,
 				 struct wlan_objmgr_vdev *vdev)
@@ -7330,6 +7364,7 @@ hdd_vdev_configure_opmode_params(struct hdd_context *hdd_ctx,
 	ucfg_fwol_configure_vdev_params(psoc, vdev);
 	hdd_set_vdev_mlo_external_sae_auth_conversion(vdev, opmode);
 	hdd_store_nss_chains_cfg_in_vdev(hdd_ctx, vdev);
+	hdd_vdev_configure_rtscts_enable(hdd_ctx, vdev);
 }
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC) && \
@@ -8101,7 +8136,7 @@ err:
 int hdd_set_fw_params(struct hdd_adapter *adapter)
 {
 	int ret;
-	uint16_t upper_brssi_thresh, lower_brssi_thresh, rts_profile;
+	uint16_t upper_brssi_thresh, lower_brssi_thresh;
 	bool enable_dtim_1chrx;
 	QDF_STATUS status;
 	struct hdd_context *hdd_ctx;
@@ -8282,19 +8317,6 @@ int hdd_set_fw_params(struct hdd_adapter *adapter)
 		goto error;
 	}
 
-	status = ucfg_fwol_get_rts_profile(hdd_ctx->psoc, &rts_profile);
-	if (QDF_IS_STATUS_ERROR(status))
-		return -EINVAL;
-
-	ret = sme_cli_set_command(adapter->deflink->vdev_id,
-				  wmi_vdev_param_enable_rtscts,
-				  rts_profile,
-				  VDEV_CMD);
-	if (ret) {
-		hdd_err("FAILED TO SET RTSCTS Profile ret:%d", ret);
-		goto error;
-	}
-
 	if (!hdd_ctx->is_fw_dbg_log_levels_configured) {
 		hdd_set_fw_log_params(hdd_ctx, adapter->deflink->vdev_id);
 		hdd_ctx->is_fw_dbg_log_levels_configured = true;
@@ -18302,6 +18324,11 @@ static void __hdd_inform_wifi_off(void)
 		return;
 
 	ucfg_dlm_wifi_off(hdd_ctx->pdev);
+
+	if (rtnl_trylock()) {
+		wlan_hdd_lpc_del_monitor_interface(hdd_ctx);
+		rtnl_unlock();
+	}
 }
 
 static void hdd_inform_wifi_off(void)

+ 6 - 1
core/hdd/src/wlan_hdd_sar_limits.c

@@ -324,6 +324,10 @@ static u32 hdd_to_nl_sar_version(enum sar_version hdd_sar_version)
 		return QCA_WLAN_VENDOR_SAR_VERSION_2;
 	case (SAR_VERSION_3):
 		return QCA_WLAN_VENDOR_SAR_VERSION_3;
+	case (SAR_VERSION_4):
+	case (SAR_VERSION_5):
+	case (SAR_VERSION_6):
+		return QCA_WLAN_VENDOR_SAR_VERSION_1;
 	default:
 		hdd_err("Unexpected SAR version received :%u, sending default to userspace",
 			hdd_sar_version);
@@ -350,7 +354,8 @@ static int hdd_sar_fill_capability_response(struct sk_buff *skb,
 	attr = QCA_WLAN_VENDOR_ATTR_SAR_CAPABILITY_VERSION;
 	value = hdd_to_nl_sar_version(hdd_ctx->sar_version);
 
-	hdd_debug("Sending SAR Version = %u to userspace", value);
+	hdd_debug("Sending SAR Version = %u to userspace, fw_sar_version: %d",
+		  value, hdd_ctx->sar_version);
 
 	errno = nla_put_u32(skb, attr, value);
 

+ 39 - 0
core/hdd/src/wlan_hdd_station_info.c

@@ -141,6 +141,8 @@
 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_ASSOC_REQ_IES
 #define REMOTE_CH_WIDTH_V2\
 	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_REMOTE_CH_WIDTH_V2
+#define EHT_OPERATION \
+	QCA_WLAN_VENDOR_ATTR_GET_STATION_INFO_EHT_OPERATION
 
 /*
  * MSB of rx_mc_bc_cnt indicates whether FW supports rx_mc_bc_cnt
@@ -767,6 +769,39 @@ static uint32_t hdd_get_he_op_len(struct hdd_station_ctx *hdd_sta_ctx)
 }
 #endif
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+static int32_t hdd_add_eht_oper_info(struct sk_buff *skb,
+				     struct hdd_station_ctx *hdd_sta_ctx)
+{
+	int32_t ret = 0;
+	struct hdd_connection_info *conn_info;
+
+	conn_info = &hdd_sta_ctx->cache_conn_info;
+	if (!conn_info->eht_oper_len)
+		return -EINVAL;
+
+	if (nla_put(skb, EHT_OPERATION, conn_info->eht_oper_len,
+		    &conn_info->eht_operation)) {
+		ret = -EINVAL;
+	} else {
+		hdd_nofl_debug("STA EHT operation:");
+		qdf_trace_hex_dump(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
+				   (uint8_t *)&conn_info->eht_operation,
+				   conn_info->eht_oper_len);
+	}
+
+	return ret;
+}
+#else
+static inline int32_t hdd_add_eht_oper_info(
+					struct sk_buff *skb,
+					struct hdd_station_ctx *hdd_sta_ctx)
+{
+	return 0;
+}
+#endif
+
 static uint32_t hdd_get_prev_connected_bss_ies_len(
 					struct hdd_station_ctx *hdd_sta_ctx)
 {
@@ -919,6 +954,10 @@ hdd_populate_station_info_skb(struct sk_buff *skb,
 		hdd_err("he operation info put fail");
 		return QDF_STATUS_E_FAILURE;
 	}
+	if (hdd_add_eht_oper_info(skb, hdd_sta_ctx)) {
+		hdd_err("eht operation info put fail");
+		return QDF_STATUS_E_FAILURE;
+	}
 
 	if (hdd_sta_ctx->cache_conn_info.conn_flag.hs20_present) {
 		tmp_hs20 =

+ 32 - 48
core/hdd/src/wlan_hdd_stats.c

@@ -509,7 +509,7 @@ hdd_get_link_info_by_bssid(struct hdd_context *hdd_ctx, const uint8_t *bssid)
 	return NULL;
 }
 
-#if defined(WLAN_FEATURE_11BE_MLO)
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
 #define WLAN_INVALID_RSSI_VALUE -128
 /**
  * wlan_hdd_is_per_link_stats_supported - Check if FW supports per link stats
@@ -1416,6 +1416,8 @@ wlan_hdd_update_iface_stats_info(struct wlan_hdd_link_info *link_info,
 	stats->avg_rx_frms_leaked = hdd_stats->avg_rx_frms_leaked;
 	stats->rx_leak_window = hdd_stats->rx_leak_window;
 	stats->nf_cal_val = hdd_stats->nf_cal_val;
+	stats->num_peers = hdd_stats->num_peers;
+	stats->num_ac = hdd_stats->num_ac;
 
 	if_stat->rts_succ_cnt = link_info->ll_iface_stats.rts_succ_cnt;
 	if_stat->rts_fail_cnt = link_info->ll_iface_stats.rts_fail_cnt;
@@ -1643,16 +1645,16 @@ wlan_hdd_send_mlo_ll_peer_stats_to_user(struct hdd_adapter *adapter)
 	}
 
 	hdd_adapter_for_each_link_info(adapter, link_info) {
+		wlan_hdd_get_connected_link_info(link_info, &info);
+		if (info.link_id == WLAN_INVALID_LINK_ID)
+			continue;
+
 		peers = nla_nest_start(skb, i);
 		if (!peers) {
 			hdd_err("nla_nest_start failed");
 			goto exit;
 		}
 
-		wlan_hdd_get_connected_link_info(link_info, &info);
-		if (info.link_id == WLAN_INVALID_LINK_ID)
-			continue;
-
 		if (!wlan_hdd_put_mlo_peer_info(link_info, skb)) {
 			hdd_err("put_wifi_peer_info fail");
 			goto exit;
@@ -1890,7 +1892,7 @@ wlan_hdd_send_mlo_ll_iface_stats_to_user(struct hdd_adapter *adapter)
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	u32 num_links, per_link_peers;
 	uint8_t i = 0;
-	int8_t rssi = WLAN_INVALID_PER_CHAIN_RSSI;
+	int8_t rssi = WLAN_INVALID_RSSI_VALUE;
 	struct wifi_interface_stats cumulative_if_stat = {0};
 	struct wlan_hdd_mlo_iface_stats_info info = {0};
 	struct wifi_interface_stats *stats;
@@ -1930,6 +1932,12 @@ wlan_hdd_send_mlo_ll_iface_stats_to_user(struct hdd_adapter *adapter)
 		if ((link_info->rssi != 0) && (rssi <= link_info->rssi)) {
 			rssi = link_info->rssi;
 			update_stats = true;
+			if (!hdd_get_interface_info(link_info,
+						    &cumulative_if_stat.info)) {
+				hdd_err("failed to get iface info for link %u",
+					info.link_id);
+				goto err;
+			}
 		} else {
 			update_stats = false;
 		}
@@ -1966,16 +1974,16 @@ wlan_hdd_send_mlo_ll_iface_stats_to_user(struct hdd_adapter *adapter)
 	}
 
 	hdd_adapter_for_each_link_info(adapter, link_info) {
+		wlan_hdd_get_connected_link_info(link_info, &info);
+		if (info.link_id == WLAN_INVALID_LINK_ID)
+			continue;
+
 		ml_iface_links = nla_nest_start(skb, i);
 		if (!ml_iface_links) {
 			hdd_err("per link mlo iface stats failed");
 			goto err;
 		}
 
-		wlan_hdd_get_connected_link_info(link_info, &info);
-		if (info.link_id == WLAN_INVALID_LINK_ID)
-			continue;
-
 		stats = &link_info->ll_iface_stats;
 		per_link_peers = stats->link_stats.num_peers;
 
@@ -7296,24 +7304,14 @@ wlan_hdd_refill_os_rateflags(struct rate_info *os_rate, uint8_t preamble)
  * @sinfo: kernel station_info struct to populate
  * @link_info: pointer to link_info struct in adapter,
  *             where hdd_stats is located in this struct
- * @mac_handle: opaque handle to MAC context
- * @rate_flags: indicating phy mode and bandwidth
- * @fw_mcs_index: MCS from parsing rate_flags and fw_raw_rate
- * @fw_rate: raw_rate from fw
- * @nss_max: max nss
  *
- * When rates info reported is provided by driver, this function
- * will take effect to replace the bandwidth calculated from fw.
+ * This function is to replace RX rates which was previously filled by fw.
  *
  * Return: None
  */
 static void
 wlan_hdd_refill_actual_rate(struct station_info *sinfo,
-			    struct wlan_hdd_link_info *link_info,
-			    mac_handle_t mac_handle,
-			    enum tx_rate_info rate_flags,
-			    uint8_t fw_mcs_index,
-			    uint16_t fw_rate, uint8_t nss_max)
+			    struct wlan_hdd_link_info *link_info)
 {
 	uint8_t preamble = link_info->hdd_stats.class_a_stat.rx_preamble;
 
@@ -7326,16 +7324,10 @@ wlan_hdd_refill_actual_rate(struct station_info *sinfo,
 	} else if (qdf_unlikely(preamble == INVALID_PREAMBLE)) {
 		/*
 		 * If preamble is invalid, it means that DP has not received
-		 * a data frame since assoc or roaming so there is no rates
-		 * info. In this case, we report max rate with FW rates info.
+		 * a data frame since assoc or roaming so there is no rates.
+		 * In this case, using FW rates which was set previously.
 		 */
-		hdd_report_max_rate(link_info, mac_handle,
-				    &sinfo->rxrate,
-				    sinfo->signal,
-				    rate_flags,
-				    fw_mcs_index,
-				    fw_rate,
-				    nss_max);
+		hdd_debug("Driver failed to get rate, reporting FW rate");
 		return;
 	}
 
@@ -7363,11 +7355,7 @@ wlan_hdd_refill_actual_rate(struct station_info *sinfo,
 #else
 static inline void
 wlan_hdd_refill_actual_rate(struct station_info *sinfo,
-			    struct wlan_hdd_link_info *link_info,
-			    mac_handle_t mac_handle,
-			    enum tx_rate_info rate_flags,
-			    uint8_t fw_mcs_index,
-			    uint16_t fw_rate, uint8_t nss_max)
+			    struct wlan_hdd_link_info *link_info)
 {
 }
 #endif
@@ -7583,8 +7571,6 @@ static int wlan_hdd_update_rate_info(struct wlan_hdd_link_info *link_info,
 					       rx_nss, rx_dcm, rx_gi);
 		}
 	} else {
-		uint8_t rx_nss_max = wlan_vdev_mlme_get_nss(vdev);
-
 		/* Fill TX stats */
 		hdd_report_actual_rate(tx_rate_flags, my_tx_rate,
 				       &sinfo->txrate, tx_mcs_index,
@@ -7596,9 +7582,7 @@ static int wlan_hdd_update_rate_info(struct wlan_hdd_link_info *link_info,
 				       rx_nss, rx_dcm, rx_gi);
 
 		/* Using driver RX rate to replace the FW RX rate */
-		wlan_hdd_refill_actual_rate(sinfo, link_info, mac_handle,
-					    rx_rate_flags, rx_mcs_index,
-					    my_rx_rate, rx_nss_max);
+		wlan_hdd_refill_actual_rate(sinfo, link_info);
 	}
 
 	wlan_hdd_fill_summary_stats(&hdd_stats->summary_stat,
@@ -7774,15 +7758,13 @@ wlan_hdd_update_mlo_sinfo(struct wlan_hdd_link_info *link_info,
 
 	sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
 
-	if (!link_info->is_mlo_vdev_active) {
+	if (!link_info->is_mlo_vdev_active)
 		hdd_nofl_debug("vdev_id[%d] is inactive", link_info->vdev_id);
-		return;
-	}
 
 	/* Update the rate info for link with best RSSI */
 	if (sinfo->signal > hdd_sinfo->signal) {
-		hdd_nofl_debug("Updating rates for link_id %d",
-			       sta_ctx->conn_info.ieee_link_id);
+		hdd_debug_rl("Updating rates for link_id %d",
+			     sta_ctx->conn_info.ieee_link_id);
 		wlan_hdd_update_mlo_rate_info(hdd_sinfo, sinfo);
 	}
 
@@ -9114,8 +9096,10 @@ void wlan_hdd_get_peer_rx_rate_stats(struct wlan_hdd_link_info *link_info)
 		return;
 
 	peer_stats = qdf_mem_malloc(sizeof(*peer_stats));
-	if (!peer_stats)
+	if (!peer_stats) {
+		hdd_err("Failed to malloc peer_stats");
 		return;
+	}
 
 	/*
 	 * If failed to get RX rates info, assign an invalid value to the
@@ -9126,7 +9110,7 @@ void wlan_hdd_get_peer_rx_rate_stats(struct wlan_hdd_link_info *link_info)
 	status = wlan_hdd_get_per_peer_stats(link_info, peer_stats);
 	if (qdf_unlikely(QDF_IS_STATUS_ERROR(status)) ||
 	    qdf_unlikely(peer_stats->rx.last_rx_rate == 0)) {
-		hdd_debug("No rates, reporting max rate, rx mcs=%d, status=%d",
+		hdd_debug("Driver failed to get rx rates, rx mcs=%d, status=%d",
 			  hdd_stats->class_a_stat.rx_mcs_index, status);
 		hdd_stats->class_a_stat.rx_preamble = INVALID_PREAMBLE;
 		if (hdd_stats->class_a_stat.rx_mcs_index == INVALID_MCS_IDX) {

+ 3 - 0
core/hdd/src/wlan_hdd_sysfs.c

@@ -95,6 +95,7 @@
 #include <wlan_hdd_sysfs_wds_mode.h>
 #include <wlan_hdd_sysfs_roam_trigger_bitmap.h>
 #include <wlan_hdd_sysfs_bitrates.h>
+#include <wlan_hdd_sysfs_rf_test_mode.h>
 
 #define MAX_PSOC_ID_SIZE 10
 
@@ -966,12 +967,14 @@ void hdd_create_sysfs_files(struct hdd_context *hdd_ctx)
 		hdd_sysfs_log_buffer_create(driver_kobject);
 		hdd_sysfs_wds_mode_create(driver_kobject);
 		hdd_sysfs_roam_trigger_bitmap_create(driver_kobject);
+		hdd_sysfs_rf_test_mode_create(driver_kobject);
 	}
 }
 
 void hdd_destroy_sysfs_files(void)
 {
 	if  (QDF_GLOBAL_MISSION_MODE == hdd_get_conparam()) {
+		hdd_sysfs_rf_test_mode_destroy(driver_kobject);
 		hdd_sysfs_roam_trigger_bitmap_destroy(driver_kobject);
 		hdd_sysfs_wds_mode_destroy(driver_kobject);
 		hdd_sysfs_log_buffer_destroy(driver_kobject);

+ 158 - 0
core/hdd/src/wlan_hdd_sysfs_rf_test_mode.c

@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <wlan_hdd_includes.h>
+#include "osif_psoc_sync.h"
+#include <wlan_hdd_sysfs.h>
+#include <wlan_hdd_sysfs_rf_test_mode.h>
+
+#define RF_TEST_MODE_ENABLE 1
+
+static ssize_t __hdd_sysfs_rf_test_mode_show(struct hdd_context *hdd_ctx,
+					     struct kobj_attribute *attr,
+					     char *buf)
+{
+	int ret = 0;
+	bool value;
+
+	if (!hdd_ctx || !hdd_ctx->psoc) {
+		hdd_err_rl("invalid input");
+		return ret;
+	}
+
+	ret = scnprintf(buf, PAGE_SIZE, "0x%x",
+			ucfg_mlme_is_rf_test_mode_enabled(hdd_ctx->psoc,
+							  &value));
+
+	return ret;
+}
+
+static ssize_t hdd_sysfs_rf_test_mode_show(struct kobject *kobj,
+					   struct kobj_attribute *attr,
+					   char *buf)
+{
+	struct osif_psoc_sync *psoc_sync;
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	ssize_t errno_size;
+
+	errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
+					     &psoc_sync);
+	if (errno_size)
+		return errno_size;
+
+	errno_size = __hdd_sysfs_rf_test_mode_show(hdd_ctx, attr, buf);
+
+	osif_psoc_sync_op_stop(psoc_sync);
+
+	return errno_size;
+}
+
+static ssize_t
+__hdd_sysfs_rf_test_mode_store(struct hdd_context *hdd_ctx,
+			       struct kobj_attribute *attr,
+			       const char *buf, size_t count)
+{
+	char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
+	char *sptr, *token;
+	uint32_t value;
+	int ret = 0;
+
+	if (!hdd_ctx || !hdd_ctx->psoc) {
+		hdd_err_rl("invalid hdd ctx");
+		return ret;
+	}
+
+	ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
+					      buf, count);
+
+	if (ret) {
+		hdd_err_rl("invalid input");
+		return ret;
+	}
+
+	sptr = buf_local;
+	token = strsep(&sptr, " ");
+	if (!token)
+		return -EINVAL;
+	if (kstrtou32(token, 0, &value))
+		return -EINVAL;
+
+	hdd_debug("rf_test_mode: 0x%x", value);
+
+	/*
+	 * To enable rf_test_mode if value set is greater than one
+	 * adjust this value as one by default
+	 */
+	if (value > RF_TEST_MODE_ENABLE)
+		value = RF_TEST_MODE_ENABLE;
+
+	ucfg_mlme_set_rf_test_mode_enabled(hdd_ctx->psoc, value);
+
+	return count;
+}
+
+static ssize_t
+hdd_sysfs_rf_test_mode_store(struct kobject *kobj,
+			     struct kobj_attribute *attr,
+			     char const *buf, size_t count)
+{
+	struct osif_psoc_sync *psoc_sync;
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	ssize_t errno_size;
+
+	errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
+					     &psoc_sync);
+	if (errno_size)
+		return errno_size;
+
+	errno_size = __hdd_sysfs_rf_test_mode_store(hdd_ctx, attr, buf,
+						    count);
+
+	osif_psoc_sync_op_stop(psoc_sync);
+
+	return errno_size;
+}
+
+static struct kobj_attribute rf_test_mode_attribute =
+	__ATTR(rf_test_mode, 0664, hdd_sysfs_rf_test_mode_show,
+	       hdd_sysfs_rf_test_mode_store);
+
+int hdd_sysfs_rf_test_mode_create(struct kobject *driver_kobject)
+{
+	int error;
+
+	if (!driver_kobject) {
+		hdd_err("could not get driver kobject!");
+		return -EINVAL;
+	}
+
+	error = sysfs_create_file(driver_kobject,
+				  &rf_test_mode_attribute.attr);
+	if (error)
+		hdd_err("could not create rf_test_mode sysfs file");
+
+	return error;
+}
+
+void
+hdd_sysfs_rf_test_mode_destroy(struct kobject *driver_kobject)
+{
+	if (!driver_kobject) {
+		hdd_err("could not get driver kobject!");
+		return;
+	}
+	sysfs_remove_file(driver_kobject, &rf_test_mode_attribute.attr);
+}

+ 61 - 0
core/hdd/src/wlan_hdd_sysfs_rf_test_mode.h

@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _WLAN_HDD_SYSFS_RF_TEST_MODE_H
+#define _WLAN_HDD_SYSFS_RF_TEST_MODE_H
+
+#if defined(WLAN_SYSFS) && defined(FEATURE_SYSFS_RF_TEST_MODE)
+
+/**
+ * hdd_sysfs_rf_test_mode_create() - API to create rf_test_mode sysfs file
+ *
+ * @driver_kobject: sysfs driver kobject
+ *
+ * file path: /sys/kernel/<chip name>/rf_test_mode
+ *
+ * usage:
+ *      echo [arg_0] > rf_test_mode
+ *
+ * Return: 0 on success and errno on failure
+ */
+int hdd_sysfs_rf_test_mode_create(struct kobject *driver_kobject);
+
+/**
+ * hdd_sysfs_rf_test_mode_destroy() - destroy hdd rf_test_mode sysfs node
+ *
+ * @driver_kobject: pointer to driver kobject
+ *
+ * Return: void
+ *
+ */
+void
+hdd_sysfs_rf_test_mode_destroy(struct kobject *driver_kobject);
+
+#else
+
+static inline int
+hdd_sysfs_rf_test_mode_create(struct kobject *driver_kobject)
+{
+	return 0;
+}
+
+static inline void
+hdd_sysfs_rf_test_mode_destroy(struct kobject *driver_kobject)
+{
+}
+#endif
+#endif
+

+ 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            "B"
+#define QWLAN_VERSION_EXTRA            "S"
 #define QWLAN_VERSION_BUILD            79
 
-#define QWLAN_VERSIONSTR               "5.2.1.79B"
+#define QWLAN_VERSIONSTR               "5.2.1.79S"
 
 #endif /* QWLAN_VERSION_H */

+ 0 - 20
core/mac/src/pe/include/lim_api.h

@@ -684,18 +684,6 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     uint8_t *probe_rsp,
 			     uint32_t probe_rsp_len);
 
-/**
- * lim_gen_link_probe_rsp_roam() - Generate link prb rsp from assoc link prb rsp
- * @mac_ctx: Pointer to mac context
- * @session_entry: pe session
- * @roam_sync_ind_ptr: Roam synch parameters
- *
- * Return qdf status
- */
-QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session_entry,
-			    struct roam_offload_synch_ind *roam_sync_ind);
 #else
 static inline QDF_STATUS
 lim_update_mlo_mgr_info(struct mac_context *mac_ctx,
@@ -723,14 +711,6 @@ lim_check_for_ml_probe_req(struct pe_session *session)
 	return QDF_STATUS_E_NOSUPPORT;
 }
 
-static inline QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session_entry,
-			    struct roam_offload_synch_ind *roam_sync_ind)
-{
-	return QDF_STATUS_E_NOSUPPORT;
-}
-
 static inline QDF_STATUS
 lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     struct pe_session *session,

+ 9 - 208
core/mac/src/pe/lim/lim_api.c

@@ -2195,15 +2195,6 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 				roam_synch_ind->link_beacon_probe_resp_length;
 			}
 		} else {
-			/*
-			 * This indicates that firmware hasn't sent link beacon,
-			 * which means assoc probe rsp is an ML probe rsp.
-			 * Extract the link probe rsp also from that.
-			 */
-			status = lim_gen_link_probe_rsp_roam(mac,
-						session, roam_synch_ind);
-			if (QDF_IS_STATUS_ERROR(status))
-				return status;
 			mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind,
 						  &bssid);
 			status = wlan_scan_get_entry_by_mac_addr(mac->pdev,
@@ -4251,188 +4242,6 @@ end:
 	return status;
 }
 
-QDF_STATUS
-lim_gen_link_probe_rsp_roam(struct mac_context *mac_ctx,
-			    struct pe_session *session,
-			    struct roam_offload_synch_ind *roam_sync_ind)
-{
-	struct element_info rcvd_probe_rsp, gen_probe_rsp = {0, NULL}, frame;
-	struct qdf_mac_addr sta_link_addr;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	tSirProbeRespBeacon *probe_rsp;
-	uint8_t *src_addr;
-	struct wlan_frame_hdr *hdr;
-	uint16_t gen_frame_len;
-	uint32_t idx, link_id, ml_probe_link_id;
-	struct roam_scan_candidate_frame rcvd_frame;
-	qdf_freq_t freq;
-
-	if (!session || !roam_sync_ind)
-		return QDF_STATUS_E_NULL_VALUE;
-
-	if (!roam_sync_ind->num_setup_links)
-		return status;
-
-	if (roam_sync_ind->link_beacon_probe_resp_length) {
-		pe_debug("Firmware sent link beacon also. No need to generate a new one from assoc bcn/prb rsp");
-		return QDF_STATUS_SUCCESS;
-	}
-
-	frame.ptr = (uint8_t *)roam_sync_ind +
-				roam_sync_ind->beacon_probe_resp_offset;
-	frame.len = roam_sync_ind->beacon_probe_resp_length;
-
-	QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_DEBUG,
-			   frame.ptr, frame.len);
-
-	/* Strip the header */
-	rcvd_probe_rsp.ptr = frame.ptr + sizeof(*hdr);
-	rcvd_probe_rsp.len = frame.len - sizeof(*hdr);
-
-
-	probe_rsp = qdf_mem_malloc(sizeof(tSirProbeRespBeacon));
-	if (!probe_rsp)
-		return QDF_STATUS_E_NOMEM;
-
-	probe_rsp->ssId.length = 0;
-	probe_rsp->wpa.length = 0;
-	/* Enforce Mandatory IEs */
-	status = sir_convert_probe_frame2_struct(mac_ctx, rcvd_probe_rsp.ptr,
-						 rcvd_probe_rsp.len, probe_rsp);
-	if (status == QDF_STATUS_E_FAILURE ||
-	    !probe_rsp->ssidPresent) {
-		pe_err("Parse error ProbeResponse, length=%d",
-		       rcvd_probe_rsp.len);
-		qdf_mem_free(probe_rsp);
-		return QDF_STATUS_E_INVAL;
-	}
-
-	if (!probe_rsp->mlo_ie.mlo_ie_present)
-		goto err1;
-
-	/* Add received ml bcn/probe rsp to scan db */
-	src_addr = wlan_mlme_get_src_addr_from_frame(&frame);
-	if (!src_addr) {
-		pe_err("MLO: Failed to fetch src address");
-		status = QDF_STATUS_E_FAILURE;
-		goto err1;
-	}
-	freq = mlo_roam_get_link_freq_from_mac_addr(roam_sync_ind,
-						    src_addr);
-	/*
-	 * Frequency corresponds to a link mac address might not be
-	 * present in the ml roam info if firmware hadn't roamed to
-	 * the link where ML probe response is received. It might have
-	 * roamed to other links. This happens frequently when roamed
-	 * to a 3-link(2+5+6) AP. As STA can do only 2-link association,
-	 * it chooses best two links(5+6) due to scoring but it might
-	 * have got ML probe response from 2ghz link.
-	 */
-	if (!freq) {
-		pe_debug("MLO: Failed to fetch freq");
-		status = QDF_STATUS_E_FAILURE;
-		goto err1;
-	}
-	lim_add_bcn_probe(session->vdev, frame.ptr, frame.len,
-			  freq, roam_sync_ind->rssi);
-	/*
-	 * When STA roams to an MLO AP, non-assoc link might be superior
-	 * in features compared to  assoc link and the per-STA profile
-	 * info may carry corresponding IEs. These IEs are extracted
-	 * and added to IE list of link probe response while generating
-	 * it. So, the link probe response generated from assoc link
-	 * probe response might be of more size than assoc link probe
-	 * rsp. Allocate buffer for the bss descriptor to accommodate
-	 * all of the IEs got generated as part of link probe rsp
-	 * generation. Allocate MAX_MGMT_MPDU_LEN bytes for IEs as the
-	 * max frame size that can be received from AP is
-	 * MAX_MGMT_MPDU_LEN bytes.
-	 */
-	gen_frame_len = MAX_MGMT_MPDU_LEN;
-
-	gen_probe_rsp.ptr = qdf_mem_malloc(gen_frame_len);
-	if (!gen_probe_rsp.ptr) {
-		status = QDF_STATUS_E_NOMEM;
-		goto err1;
-	}
-
-	/*
-	 * It's ok to keep assoc vdev mac address as DA as link vdev
-	 * is just cleanedup and it may not be an ML vdev till the
-	 * flags are set again
-	 */
-	qdf_mem_copy(&sta_link_addr, session->self_mac_addr,
-		     QDF_MAC_ADDR_SIZE);
-
-	gen_probe_rsp.len = gen_frame_len;
-	src_addr = wlan_mlme_get_src_addr_from_frame(&frame);
-	status = mlo_roam_get_link_id_from_mac_addr(roam_sync_ind,
-						    src_addr,
-						    &ml_probe_link_id);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		pe_debug("Invalid link id for mac_addr: " QDF_MAC_ADDR_FMT,
-			 QDF_MAC_ADDR_REF(src_addr));
-		goto done;
-	}
-	for (idx = 0; idx < roam_sync_ind->num_setup_links; idx++) {
-		link_id =  roam_sync_ind->ml_link[idx].link_id;
-		if (link_id == ml_probe_link_id)
-			continue;
-		status = util_gen_link_probe_rsp(rcvd_probe_rsp.ptr,
-					rcvd_probe_rsp.len,
-					link_id,
-					sta_link_addr,
-					gen_probe_rsp.ptr,
-					gen_frame_len,
-					(qdf_size_t *)&gen_probe_rsp.len);
-		if (QDF_IS_STATUS_ERROR(status)) {
-			pe_err("MLO: Link %d probe resp gen failed %d",
-			       link_id, status);
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		pe_debug("MLO: link probe rsp size:%u orig probe rsp :%u",
-			 gen_probe_rsp.len, rcvd_probe_rsp.len);
-
-		src_addr = wlan_mlme_get_src_addr_from_frame(
-						&gen_probe_rsp);
-		if (!src_addr) {
-			pe_err("MLO: Failed to fetch src address");
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		if (gen_probe_rsp.len > gen_frame_len) {
-			pe_err("MLO: gen probe rsp len %u larger than buffer size: %u",
-			       gen_probe_rsp.len, gen_frame_len);
-			status = QDF_STATUS_E_FAILURE;
-			goto done;
-		}
-
-		lim_add_bcn_probe(session->vdev, gen_probe_rsp.ptr,
-				  gen_probe_rsp.len,
-				  mlo_roam_get_link_freq_from_mac_addr(
-					       roam_sync_ind, src_addr),
-				  roam_sync_ind->rssi);
-	}
-
-done:
-	qdf_mem_free(gen_probe_rsp.ptr);
-err1:
-	qdf_mem_free(probe_rsp);
-
-	if (QDF_IS_STATUS_ERROR(status)) {
-		rcvd_frame.vdev_id = roam_sync_ind->roamed_vdev_id;
-		rcvd_frame.frame = frame.ptr;
-		rcvd_frame.frame_length = frame.len;
-		rcvd_frame.rssi = roam_sync_ind->rssi;
-		status = mlo_add_all_link_probe_rsp_to_scan_db(mac_ctx->psoc,
-							       &rcvd_frame);
-	}
-	return status;
-}
-
 QDF_STATUS
 lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     struct pe_session *session,
@@ -4492,7 +4301,8 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 
 	for (i = 0; i < partner_info.num_partner_links; i++) {
 		link_id = partner_info.partner_link_info[i].link_id;
-		partner_vdev = mlo_get_vdev_by_link_id(vdev, link_id);
+		partner_vdev = mlo_get_vdev_by_link_id(vdev, link_id,
+						       WLAN_LEGACY_MAC_ID);
 		if (!partner_vdev) {
 			pe_debug("No partner vdev for link id %d", link_id);
 			continue;
@@ -4501,26 +4311,19 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 		status = lim_cu_info_from_rnr_per_link_id(rnr, link_id,
 							  &bpcc, &aui);
 		if (QDF_IS_STATUS_ERROR(status)) {
-			wlan_objmgr_vdev_release_ref(partner_vdev,
-						     WLAN_MLO_MGR_ID);
 			pe_debug("no cu info in rnr for link id %d", link_id);
-			continue;
+			goto ref_rel;
 		}
 
 		cu_flag = lim_check_cu_happens(partner_vdev, bpcc);
-		if (!cu_flag) {
-			wlan_objmgr_vdev_release_ref(partner_vdev,
-						     WLAN_MLO_MGR_ID);
-			continue;
-		}
+		if (!cu_flag)
+			goto ref_rel;
 
 		vdev_id = wlan_vdev_get_id(partner_vdev);
 		session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
 		if (!session) {
-			wlan_objmgr_vdev_release_ref(partner_vdev,
-						     WLAN_MLO_MGR_ID);
 			pe_debug("session is null for vdev id %d", vdev_id);
-			continue;
+			goto ref_rel;
 		}
 
 		qdf_mem_copy(&sta_link_addr, session->self_mac_addr,
@@ -4540,17 +4343,15 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 		if (QDF_IS_STATUS_ERROR(status)) {
 			pe_err("MLO: Link probe response generation failed %d",
 			       status);
-			wlan_objmgr_vdev_release_ref(partner_vdev,
-						     WLAN_MLO_MGR_ID);
-			continue;
+			goto ref_rel;
 		}
 
 		lim_process_gen_probe_rsp_frame(mac_ctx, session,
 						link_probe_rsp.ptr,
 						link_probe_rsp.len);
 
-		wlan_objmgr_vdev_release_ref(partner_vdev,
-					     WLAN_MLO_MGR_ID);
+ref_rel:
+		wlan_objmgr_vdev_release_ref(partner_vdev, WLAN_LEGACY_MAC_ID);
 	}
 
 	qdf_mem_free(link_probe_rsp.ptr);

+ 4 - 3
core/mac/src/pe/lim/lim_mlo.c

@@ -191,7 +191,7 @@ QDF_STATUS lim_partner_link_info_change(struct wlan_objmgr_vdev *vdev)
 
 void lim_mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev)
 {
-	mlo_release_vdev_ref(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID);
 }
 
 struct pe_session *pe_find_partner_session_by_link_id(
@@ -212,7 +212,8 @@ struct pe_session *pe_find_partner_session_by_link_id(
 		return NULL;
 	}
 
-	vdev = mlo_get_vdev_by_link_id(session->vdev, link_id);
+	vdev = mlo_get_vdev_by_link_id(session->vdev, link_id,
+				       WLAN_LEGACY_MAC_ID);
 
 	if (!vdev) {
 		pe_err("vdev is null");
@@ -223,7 +224,7 @@ struct pe_session *pe_find_partner_session_by_link_id(
 			mac, vdev->vdev_objmgr.vdev_id);
 
 	if (!partner_session)
-		lim_mlo_release_vdev_ref(vdev);
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
 
 	return partner_session;
 }

+ 39 - 17
core/mac/src/pe/lim/lim_process_beacon_frame.c

@@ -52,6 +52,7 @@
 #include "wlan_t2lm_api.h"
 
 #ifdef WLAN_FEATURE_11BE_MLO
+
 void lim_process_bcn_prb_rsp_t2lm(struct mac_context *mac_ctx,
 				  struct pe_session *session,
 				  tpSirProbeRespBeacon bcn_ptr)
@@ -98,6 +99,9 @@ void lim_process_beacon_mlo(struct mac_context *mac_ctx,
 	struct wlan_objmgr_vdev *vdev;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_mlo_dev_context *mlo_ctx;
+	uint8_t is_sta_csa_synced;
+	struct mlo_link_info *link_info;
+	uint8_t sta_info_len = 0;
 
 	if (!session || !bcn_ptr || !mac_ctx) {
 		pe_err("invalid input parameters");
@@ -128,34 +132,48 @@ void lim_process_beacon_mlo(struct mac_context *mac_ctx,
 		xcsa_ie = NULL;
 		qdf_mem_zero(&csa_param, sizeof(csa_param));
 		per_sta_pro = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].data;
-		per_sta_pro_len =
-			bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].num_data;
-		stacontrol = *(uint16_t *)per_sta_pro;
-		/* IE ID + LEN + STA control */
-		sta_pro = per_sta_pro + MIN_IE_LEN + 2;
-		sta_pro_len = per_sta_pro_len - MIN_IE_LEN - 2;
+		/* Append one byte to get the element length  */
+		per_sta_pro_len = bcn_ptr->mlo_ie.mlo_ie.sta_profile[i].num_data;
+		stacontrol = *(uint16_t *)(per_sta_pro + sizeof(struct subelem_header));
+		sta_info_len = *(uint8_t *)(per_sta_pro +
+				sizeof(struct subelem_header) + WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE);
+		/* IE ID + LEN + STA control STA info len*/
+		sta_pro = per_sta_pro + sizeof(struct subelem_header) +
+			WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE + sta_info_len;
+		sta_pro_len = per_sta_pro_len - sizeof(struct subelem_header) -
+				WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE - sta_info_len;
 		link_id = QDF_GET_BITS(
 			    stacontrol,
 			    WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_IDX,
 			    WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_LINKID_BITS);
 
-		if (!mlo_is_sta_csa_synced(mlo_ctx, link_id)) {
-			csa_ie = (struct ieee80211_channelswitch_ie *)
-					wlan_get_ie_ptr_from_eid(
-						DOT11F_EID_CHANSWITCHANN,
-						sta_pro, sta_pro_len);
-			xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
-					wlan_get_ie_ptr_from_eid(
-						DOT11F_EID_EXT_CHAN_SWITCH_ANN,
-						sta_pro, sta_pro_len);
+		csa_ie = (struct ieee80211_channelswitch_ie *)
+				wlan_get_ie_ptr_from_eid(
+					DOT11F_EID_CHANSWITCHANN,
+					sta_pro, sta_pro_len);
+		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
+				wlan_get_ie_ptr_from_eid(
+					DOT11F_EID_EXT_CHAN_SWITCH_ANN,
+					sta_pro, sta_pro_len);
+		is_sta_csa_synced = mlo_is_sta_csa_synced(mlo_ctx, link_id);
+		link_info = mlo_mgr_get_ap_link_by_link_id(mlo_ctx, link_id);
+		if (!link_info) {
+			mlo_err("link info null");
+			return;
 		}
+
 		if (csa_ie) {
 			csa_param.channel = csa_ie->newchannel;
 			csa_param.csa_chan_freq = wlan_reg_legacy_chan_to_freq(
 						pdev, csa_ie->newchannel);
 			csa_param.switch_mode = csa_ie->switchmode;
 			csa_param.ies_present_flag |= MLME_CSA_IE_PRESENT;
-			mlo_sta_csa_save_params(mlo_ctx, link_id, &csa_param);
+			mlo_sta_handle_csa_standby_link(mlo_ctx, link_id,
+							&csa_param, vdev);
+
+			if (!is_sta_csa_synced)
+				mlo_sta_csa_save_params(mlo_ctx, link_id,
+							&csa_param);
 		} else if (xcsa_ie) {
 			csa_param.channel = xcsa_ie->newchannel;
 			csa_param.switch_mode = xcsa_ie->switchmode;
@@ -170,7 +188,11 @@ void lim_process_beacon_mlo(struct mac_context *mac_ctx,
 					wlan_reg_legacy_chan_to_freq(
 						pdev, xcsa_ie->newchannel);
 			csa_param.ies_present_flag |= MLME_XCSA_IE_PRESENT;
-			mlo_sta_csa_save_params(mlo_ctx, link_id, &csa_param);
+			mlo_sta_handle_csa_standby_link(mlo_ctx, link_id,
+							&csa_param, vdev);
+			if (!is_sta_csa_synced)
+				mlo_sta_csa_save_params(mlo_ctx, link_id,
+							&csa_param);
 		}
 	}
 }

+ 10 - 6
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -5598,31 +5598,35 @@ returnAfterError:
  * event
  * @token: Dialog token
  * @num_rpt: Number of Report element
- * @vdev_id: vdev Id
+ * @pe_session: pe session pointer
  */
 static void
 lim_beacon_report_response_event(uint8_t token, uint8_t num_rpt,
-				 uint8_t vdev_id)
+				 struct pe_session *pe_session)
 {
 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
 
 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
 
-	wlan_diag_event.diag_cmn.vdev_id = vdev_id;
+	wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev);
 	wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
 	wlan_diag_event.diag_cmn.ktime_us =  qdf_ktime_to_us(qdf_ktime_get());
 
-	wlan_diag_event.version = DIAG_BCN_RPT_VERSION;
+	wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2;
 	wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_RESP_EVENT;
 	wlan_diag_event.meas_token = token;
 	wlan_diag_event.num_rpt = num_rpt;
 
+	if (mlo_is_mld_sta(pe_session->vdev))
+		wlan_diag_event.band =
+			wlan_convert_freq_to_diag_band(pe_session->curr_op_freq);
+
 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_BCN_RPT);
 }
 #else
 static void
 lim_beacon_report_response_event(uint8_t token, uint8_t num_rpt,
-				 uint8_t vdev_id)
+				 struct pe_session *pe_session)
 {
 }
 #endif
@@ -5787,7 +5791,7 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
 	if (frm->MeasurementReport[0].type == SIR_MAC_RRM_BEACON_TYPE) {
 		lim_beacon_report_response_event(frm->MeasurementReport[0].token,
 						 num_report,
-						 wlan_vdev_get_id(pe_session->vdev));
+						 pe_session);
 	}
 
 	pe_nofl_info("TX: type:%d seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report:%d peer:"QDF_MAC_ADDR_FMT,

+ 30 - 0
core/mac/src/pe/lim/lim_send_sme_rsp_messages.c

@@ -1899,6 +1899,18 @@ static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch,
 	return lim_ch_switch->puncture_bitmap == session->puncture_bitmap;
 }
 
+static void update_csa_link_info(struct wlan_objmgr_vdev *vdev,
+				 uint8_t link_id,
+				 struct csa_offload_params *csa_params)
+{
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+
+	mlo_mgr_update_csa_link_info(vdev->mlo_dev_ctx,
+				     csa_params, link_id);
+	pe_debug("vdev_id: %d link id %d mlo csa sta param updated ",
+		 vdev_id, link_id);
+}
+
 #else
 static void lim_set_csa_chan_param_11be(struct pe_session *session,
 					struct csa_offload_params *csa_param,
@@ -1920,6 +1932,13 @@ static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch,
 {
 	return true;
 }
+
+static void update_csa_link_info(struct wlan_objmgr_vdev *vdev,
+				 uint8_t link_id,
+				 struct csa_offload_params *csa_params)
+{
+}
+
 #endif
 
 void lim_handle_sta_csa_param(struct mac_context *mac_ctx,
@@ -1935,6 +1954,7 @@ void lim_handle_sta_csa_param(struct mac_context *mac_ctx,
 	uint8_t country_code[CDS_COUNTRY_CODE_LEN + 1];
 	tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL;
 	tLimChannelSwitchInfo *lim_ch_switch = NULL;
+	uint8_t link_id;
 
 	if (!csa_params) {
 		pe_err("limMsgQ body ptr is NULL");
@@ -2227,6 +2247,16 @@ void lim_handle_sta_csa_param(struct mac_context *mac_ctx,
 		goto err;
 	}
 
+	if (!wlan_cm_is_vdev_connected(session_entry->vdev)) {
+		pe_info_rl("Ignore CSA, vdev is in not in conncted state");
+		goto err;
+	}
+
+	if (wlan_vdev_mlme_is_mlo_vdev(session_entry->vdev)) {
+		link_id = wlan_vdev_get_link_id(session_entry->vdev);
+		update_csa_link_info(session_entry->vdev, link_id, csa_params);
+	}
+
 	if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) &&
 	    session_entry->dot11mode == MLME_DOT11_MODE_11A)
 		session_entry->dot11mode = MLME_DOT11_MODE_11G;

+ 57 - 34
core/mac/src/pe/lim/lim_utils.c

@@ -1841,34 +1841,37 @@ lim_decide_sta_protection(struct mac_context *mac_ctx,
  *
  ***NOTE:
  * @param  pe_session           - Pointer to pe session
- * @return None
+ *
+ * @return qdf_status
  */
-static void __lim_process_channel_switch_timeout(struct pe_session *pe_session)
+static QDF_STATUS
+__lim_process_channel_switch_timeout(struct pe_session *pe_session)
 {
 	struct mac_context *mac;
 	uint32_t channel_freq;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	if (!pe_session) {
 		pe_err("Invalid pe session");
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 	mac = pe_session->mac_ctx;
 	if (!mac) {
 		pe_err("Invalid mac context");
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 
 	if (!LIM_IS_STA_ROLE(pe_session)) {
 		pe_warn("Channel switch can be done only in STA role, Current Role: %d",
 			       GET_LIM_SYSTEM_ROLE(pe_session));
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 
 	if (pe_session->gLimSpecMgmt.dot11hChanSwState !=
 	   eLIM_11H_CHANSW_RUNNING) {
 		pe_warn("Channel switch timer should not have been running in state: %d",
 			pe_session->gLimSpecMgmt.dot11hChanSwState);
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 
 	channel_freq = pe_session->gLimChannelSwitch.sw_target_freq;
@@ -1887,7 +1890,7 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session)
 		if (lim_restore_pre_channel_switch_state(mac, pe_session) !=
 		    QDF_STATUS_SUCCESS) {
 			pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system");
-			return;
+			return QDF_STATUS_E_INVAL;
 		}
 
 		/*
@@ -1900,20 +1903,19 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session)
 		 */
 		pe_err("Invalid channel freq %u Ignore CSA request",
 		       channel_freq);
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 	switch (pe_session->gLimChannelSwitch.state) {
 	case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY:
-		lim_switch_primary_channel(mac,
-					   pe_session->gLimChannelSwitch.
-					   sw_target_freq, pe_session);
+		status = lim_switch_primary_channel(mac,
+				pe_session->gLimChannelSwitch.sw_target_freq,
+				pe_session);
 		pe_session->gLimChannelSwitch.state =
 			eLIM_CHANNEL_SWITCH_IDLE;
 		break;
 	case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY:
-		lim_switch_primary_secondary_channel(mac, pe_session);
-		pe_session->gLimChannelSwitch.state =
-			eLIM_CHANNEL_SWITCH_IDLE;
+		status = lim_switch_primary_secondary_channel(mac, pe_session);
+		pe_session->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE;
 		break;
 
 	case eLIM_CHANNEL_SWITCH_IDLE:
@@ -1922,9 +1924,13 @@ static void __lim_process_channel_switch_timeout(struct pe_session *pe_session)
 		if (lim_restore_pre_channel_switch_state(mac, pe_session) !=
 		    QDF_STATUS_SUCCESS) {
 			pe_err("Could not restore pre-channelSwitch (11h) state, resetting the system");
+			status = QDF_STATUS_E_FAILURE;
 		}
-		return; /* Please note, this is 'return' and not 'break' */
+		/* Please note, this is 'return' and not 'break' */
+		return status;
 	}
+
+	return status;
 }
 
 void lim_disconnect_complete(struct pe_session *session, bool del_bss)
@@ -2140,9 +2146,9 @@ void lim_switch_channel_cback(struct mac_context *mac, QDF_STATUS status,
 	lim_switch_channel_vdev_started(pe_session);
 }
 
-void lim_switch_primary_channel(struct mac_context *mac,
-				uint32_t new_channel_freq,
-				struct pe_session *pe_session)
+QDF_STATUS lim_switch_primary_channel(struct mac_context *mac,
+				      uint32_t new_channel_freq,
+				      struct pe_session *pe_session)
 {
 	pe_debug("freq: %d --> freq: %d", pe_session->curr_op_freq,
 		 new_channel_freq);
@@ -2159,8 +2165,7 @@ void lim_switch_primary_channel(struct mac_context *mac,
 	mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
 	mac->lim.gpchangeChannelData = NULL;
 
-	lim_send_switch_chnl_params(mac, pe_session);
-	return;
+	return lim_send_switch_chnl_params(mac, pe_session);
 }
 
 #ifdef WLAN_FEATURE_11BE
@@ -2184,8 +2189,8 @@ lim_set_puncture_from_chan_switch_to_session(struct pe_session *pe_session)
 }
 #endif
 
-void lim_switch_primary_secondary_channel(struct mac_context *mac,
-					  struct pe_session *pe_session)
+QDF_STATUS lim_switch_primary_secondary_channel(struct mac_context *mac,
+						struct pe_session *pe_session)
 {
 	uint32_t new_channel_freq;
 	uint8_t ch_center_freq_seg0;
@@ -2236,9 +2241,7 @@ void lim_switch_primary_secondary_channel(struct mac_context *mac,
 	pe_session->ch_width = ch_width;
 	lim_set_puncture_from_chan_switch_to_session(pe_session);
 
-	lim_send_switch_chnl_params(mac, pe_session);
-
-	return;
+	return lim_send_switch_chnl_params(mac, pe_session);
 }
 
 /**
@@ -3734,7 +3737,8 @@ QDF_STATUS lim_tx_complete(void *context, qdf_nbuf_t buf, bool free)
 	return QDF_STATUS_SUCCESS;
 }
 
-static void lim_ht_switch_chnl_params(struct pe_session *pe_session)
+static QDF_STATUS
+lim_ht_switch_chnl_params(struct pe_session *pe_session)
 {
 	uint8_t center_freq = 0;
 	enum phy_ch_width ch_width = CH_WIDTH_20MHZ;
@@ -3744,7 +3748,7 @@ static void lim_ht_switch_chnl_params(struct pe_session *pe_session)
 	mac = pe_session->mac_ctx;
 	if (!mac) {
 		pe_err("Invalid mac_ctx");
-		return;
+		return QDF_STATUS_E_INVAL;
 	}
 
 	primary_channel = wlan_reg_freq_to_chan(mac->pdev,
@@ -3782,7 +3786,7 @@ static void lim_ht_switch_chnl_params(struct pe_session *pe_session)
 	mac->lim.gpchangeChannelCallback = lim_switch_channel_cback;
 	mac->lim.gpchangeChannelData = NULL;
 
-	lim_send_switch_chnl_params(mac, pe_session);
+	return lim_send_switch_chnl_params(mac, pe_session);
 }
 
 static void lim_ht_switch_chnl_req(struct pe_session *session)
@@ -7424,6 +7428,15 @@ lim_revise_req_he_cap_per_band(struct mlme_legacy_priv *mlme_priv,
 {
 	struct mac_context *mac = session->mac_ctx;
 	tDot11fIEhe_cap *he_config;
+	struct wlan_objmgr_psoc *psoc;
+	uint32_t max_ampdu_len_exp;
+
+	psoc = wlan_vdev_get_psoc(session->vdev);
+	if (!psoc) {
+		pe_err("Failed to get psoc");
+		return;
+	}
+	max_ampdu_len_exp = cfg_get(psoc, CFG_HE_MAX_AMPDU_LEN);
 
 	he_config = &mlme_priv->he_config;
 	if (wlan_reg_is_24ghz_ch_freq(session->curr_op_freq)) {
@@ -7434,7 +7447,8 @@ lim_revise_req_he_cap_per_band(struct mlme_legacy_priv *mlme_priv,
 		he_config->rx_he_mcs_map_lt_80 =
 			mac->he_cap_2g.rx_he_mcs_map_lt_80;
 		he_config->max_ampdu_len_exp_ext =
-			mac->he_cap_2g.max_ampdu_len_exp_ext;
+			QDF_MIN(max_ampdu_len_exp,
+				mac->he_cap_2g.max_ampdu_len_exp_ext);
 		he_config->ul_2x996_tone_ru_supp = 0;
 		he_config->num_sounding_gt_80 = 0;
 		he_config->bfee_sts_gt_80 = 0;
@@ -7453,7 +7467,8 @@ lim_revise_req_he_cap_per_band(struct mlme_legacy_priv *mlme_priv,
 		he_config->num_sounding_lt_80 =
 			mac->he_cap_5g.num_sounding_lt_80;
 		he_config->max_ampdu_len_exp_ext =
-			mac->he_cap_5g.max_ampdu_len_exp_ext;
+			QDF_MIN(max_ampdu_len_exp,
+				mac->he_cap_5g.max_ampdu_len_exp_ext);
 		if (he_config->chan_width_2 ||
 		    he_config->chan_width_3) {
 			he_config->bfee_sts_gt_80 =
@@ -10094,6 +10109,7 @@ QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
 					  uint16_t data_len, void *data)
 {
 	struct pe_session *session;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	session = (struct pe_session *)data;
 	if (!session) {
@@ -10111,19 +10127,26 @@ QDF_STATUS lim_sta_mlme_vdev_restart_send(struct vdev_mlme_obj *vdev_mlme,
 	if (mlme_is_chan_switch_in_progress(vdev_mlme->vdev)) {
 		switch (session->channelChangeReasonCode) {
 		case LIM_SWITCH_CHANNEL_OPERATION:
-			__lim_process_channel_switch_timeout(session);
+			status = __lim_process_channel_switch_timeout(session);
 			break;
 		case LIM_SWITCH_CHANNEL_HT_WIDTH:
-			lim_ht_switch_chnl_params(session);
+			status = lim_ht_switch_chnl_params(session);
 			break;
 		case LIM_SWITCH_CHANNEL_REASSOC:
-			lim_send_switch_chnl_params(session->mac_ctx, session);
+			status = lim_send_switch_chnl_params(session->mac_ctx,
+							     session);
 			break;
 		default:
 			break;
 		}
 	}
-	return QDF_STATUS_SUCCESS;
+	if (QDF_IS_STATUS_ERROR(status)) {
+		pe_err_rl("Failed to send VDEV_RESTART for chan switch vdev %d",
+			  wlan_vdev_get_id(vdev_mlme->vdev));
+		mlme_set_chan_switch_in_progress(vdev_mlme->vdev, false);
+	}
+
+	return status;
 }
 
 QDF_STATUS lim_sta_mlme_vdev_stop_send(struct vdev_mlme_obj *vdev_mlme,

+ 7 - 7
core/mac/src/pe/lim/lim_utils.h

@@ -528,11 +528,11 @@ void lim_process_channel_switch(struct mac_context *mac, uint8_t vdev_id);
  *
  * This function changes the current operating channel frequency.
  *
- * return NONE
+ * return qdf_status
  */
-void lim_switch_primary_channel(struct mac_context *mac,
-				uint32_t new_channel_freq,
-				struct pe_session *pe_session);
+QDF_STATUS lim_switch_primary_channel(struct mac_context *mac,
+				      uint32_t new_channel_freq,
+				      struct pe_session *pe_session);
 
 /**
  * lim_switch_primary_secondary_channel() - switch primary and secondary
@@ -546,10 +546,10 @@ void lim_switch_primary_channel(struct mac_context *mac,
  *  then we must set this new channel in session context and
  *  assign notify LIM of such change.
  *
- * @return NONE
+ * @return qdf_status
  */
-void lim_switch_primary_secondary_channel(struct mac_context *mac,
-					  struct pe_session *pe_session);
+QDF_STATUS lim_switch_primary_secondary_channel(struct mac_context *mac,
+						struct pe_session *pe_session);
 
 void lim_update_sta_run_time_ht_capability(struct mac_context *mac,
 		tDot11fIEHTCaps *pHTCaps);

+ 114 - 68
core/mac/src/pe/rrm/rrm_api.c

@@ -50,11 +50,13 @@
 #include "../../core/src/wlan_cp_stats_defs.h"
 #include "cdp_txrx_host_stats.h"
 #include "utils_mlo.h"
+#include "wlan_mlo_mgr_sta.h"
 
 #define MAX_CTRL_STAT_VDEV_ENTRIES 1
 #define MAX_CTRL_STAT_MAC_ADDR_ENTRIES 1
 #define MAX_RMM_STA_STATS_REQUESTED 2
-#define MAX_MEAS_DURATION_FOR_STA_STATS 10
+#define MIN_MEAS_DURATION_FOR_STA_STATS 10
+
 /* Max passive scan dwell for wide band rrm scan, in milliseconds */
 #define RRM_SCAN_MAX_DWELL_TIME 110
 
@@ -581,24 +583,28 @@ void rrm_get_country_code_from_connected_profile(struct mac_context *mac,
  * @chan: channel number
  * @req_mode: Request mode
  * @duration: The duration over which the Beacon report was measured
- * @vdev_id: vdev Id
+ * @pe_session: pe session pointer
  */
 static void
 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
 				   uint8_t op_class, uint8_t chan,
 				   uint8_t req_mode, uint32_t duration,
-				   uint8_t vdev_id)
+				   struct pe_session *pe_session)
 {
 	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_bcn_rpt);
 
 	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
 
-	wlan_diag_event.diag_cmn.vdev_id = vdev_id;
+	wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(pe_session->vdev);
 	wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();
 	wlan_diag_event.diag_cmn.ktime_us =  qdf_ktime_to_us(qdf_ktime_get());
 
 	wlan_diag_event.subtype = WLAN_CONN_DIAG_BCN_RPT_REQ_EVENT;
-	wlan_diag_event.version = DIAG_BCN_RPT_VERSION;
+	wlan_diag_event.version = DIAG_BCN_RPT_VERSION_2;
+
+	if (mlo_is_mld_sta(pe_session->vdev))
+		wlan_diag_event.band =
+			wlan_convert_freq_to_diag_band(pe_session->curr_op_freq);
 
 	wlan_diag_event.meas_token = token;
 	wlan_diag_event.mode = mode;
@@ -614,7 +620,7 @@ static void
 wlan_diag_log_beacon_rpt_req_event(uint8_t token, uint8_t mode,
 				   uint8_t op_class, uint8_t chan,
 				   uint8_t req_mode, uint32_t duration,
-				   uint8_t vdev_id)
+				   struct pe_session *pe_session)
 {
 }
 #endif
@@ -889,6 +895,48 @@ get_stats_fail:
 }
 #endif
 
+/* -------------------------------------------------------------------- */
+/**
+ * rrm_get_max_meas_duration() - calculate max measurement duration for a
+ * rrm req
+ * @mac: global mac context
+ * @pe_session: per vdev pe context
+ *
+ * Return: max measurement duration
+ */
+static uint16_t rrm_get_max_meas_duration(struct mac_context *mac,
+					  struct pe_session *pe_session)
+{
+	int8_t max_dur;
+	uint16_t max_meas_dur, sign;
+
+	/*
+	 * The logic here is to check the measurement duration passed in the
+	 * beacon request. Following are the cases handled.
+	 * Case 1: If measurement duration received in the beacon request is
+	 * greater than the max measurement duration advertised in the RRM
+	 * capabilities(Assoc Req), and Duration Mandatory bit is set to 1,
+	 * REFUSE the beacon request.
+	 * Case 2: If measurement duration received in the beacon request is
+	 * greater than the max measurement duration advertised in the RRM
+	 * capabilities(Assoc Req), and Duration Mandatory bit is set to 0,
+	 * perform measurement for the duration advertised in the
+	 * RRM capabilities
+	 * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
+	 */
+	max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
+	sign = (max_dur < 0) ? 1 : 0;
+	max_dur = (1L << ABS(max_dur));
+	if (!sign)
+		max_meas_dur =
+			max_dur * pe_session->beaconParams.beaconInterval;
+	else
+		max_meas_dur =
+			pe_session->beaconParams.beaconInterval / max_dur;
+
+	return max_meas_dur;
+}
+
 /**
  * rrm_process_sta_stats_report_req: Process RRM sta stats request
  * @mac: mac context
@@ -905,16 +953,31 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
 				 struct pe_session *pe_session)
 {
 	QDF_STATUS status;
-	uint8_t meas_duration = 1;
+	uint16_t meas_duration = MIN_MEAS_DURATION_FOR_STA_STATS;
+	uint8_t max_meas_duration;
 	struct rrm_sta_stats *rrm_sta_statistics;
 
+	max_meas_duration = rrm_get_max_meas_duration(mac, pe_session);
+
+	/*
+	 * Keep timer value atleast of 10 ms even if measurement duration
+	 * provided in meas request is < 10 ms because FW takes some time to
+	 * calculate and respond stats.
+	 * Start timer of 10 ms even if meas duration is 0.
+	 * To get stats from FW.
+	 */
 	if (sta_stats_req->measurement_request.sta_stats.meas_duration >
-	    MAX_MEAS_DURATION_FOR_STA_STATS) {
-		pe_err("Dropping req measurement duration > threshold %d",
-		       sta_stats_req->measurement_request.sta_stats.meas_duration);
-		return eRRM_INCAPABLE;
-	}
+	    MIN_MEAS_DURATION_FOR_STA_STATS)
+		meas_duration =
+		sta_stats_req->measurement_request.sta_stats.meas_duration;
 
+	if (meas_duration > max_meas_duration) {
+		if (sta_stats_req->durationMandatory) {
+			pe_nofl_err("Dropping the req: duration mandatory & max duration > meas duration");
+			return eRRM_REFUSED;
+		}
+		meas_duration = max_meas_duration;
+	}
 	if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)
 	    sta_stats_req->measurement_request.sta_stats.peer_mac_addr)) {
 		pe_err("Dropping req: broadcast address not supported");
@@ -922,9 +985,6 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
 	}
 
 	rrm_sta_statistics = &mac->rrm.rrmPEContext.rrm_sta_stats;
-	if (sta_stats_req->measurement_request.sta_stats.meas_duration)
-		meas_duration =
-		sta_stats_req->measurement_request.sta_stats.meas_duration;
 
 	rrm_sta_statistics->rrm_report.token = pCurrentReq->token;
 	rrm_sta_statistics->rrm_report.type = pCurrentReq->type;
@@ -946,12 +1006,8 @@ rrm_process_sta_stats_report_req(struct mac_context *mac,
 			return eRRM_REFUSED;
 		mac->lim.lim_timers.rrm_sta_stats_resp_timer.sessionId =
 							pe_session->peSessionId;
-		/*
-		 * Start timer of 1 sec even if meas duration is 0.
-		 * To get stats from FW.
-		 */
 		tx_timer_change(&mac->lim.lim_timers.rrm_sta_stats_resp_timer,
-				SYS_MS_TO_TICKS(meas_duration * 1000), 0);
+				SYS_MS_TO_TICKS(meas_duration), 0);
 		/* Activate sta stats resp timer */
 		if (tx_timer_activate(
 		    &mac->lim.lim_timers.rrm_sta_stats_resp_timer) !=
@@ -1120,48 +1176,6 @@ failure:
 	return QDF_STATUS_E_FAILURE;
 }
 
-/* -------------------------------------------------------------------- */
-/**
- * rrm_get_max_meas_duration() - calculate max measurement duration for a
- * rrm req
- * @mac: global mac context
- * @pe_session: per vdev pe context
- *
- * Return: max measurement duration
- */
-static uint16_t rrm_get_max_meas_duration(struct mac_context *mac,
-					  struct pe_session *pe_session)
-{
-	int8_t max_dur;
-	uint16_t max_meas_dur, sign;
-
-	/*
-	 * The logic here is to check the measurement duration passed in the
-	 * beacon request. Following are the cases handled.
-	 * Case 1: If measurement duration received in the beacon request is
-	 * greater than the max measurement duration advertised in the RRM
-	 * capabilities(Assoc Req), and Duration Mandatory bit is set to 1,
-	 * REFUSE the beacon request.
-	 * Case 2: If measurement duration received in the beacon request is
-	 * greater than the max measurement duration advertised in the RRM
-	 * capabilities(Assoc Req), and Duration Mandatory bit is set to 0,
-	 * perform measurement for the duration advertised in the
-	 * RRM capabilities
-	 * maxMeasurementDuration = 2^(nonOperatingChanMax - 4) * BeaconInterval
-	 */
-	max_dur = mac->rrm.rrmPEContext.rrmEnabledCaps.nonOperatingChanMax - 4;
-	sign = (max_dur < 0) ? 1 : 0;
-	max_dur = (1L << ABS(max_dur));
-	if (!sign)
-		max_meas_dur =
-			max_dur * pe_session->beaconParams.beaconInterval;
-	else
-		max_meas_dur =
-			pe_session->beaconParams.beaconInterval / max_dur;
-
-	return max_meas_dur;
-}
-
 /**
  * rrm_process_beacon_report_req
  *
@@ -1241,7 +1255,7 @@ rrm_process_beacon_report_req(struct mac_context *mac,
 					   pBeaconReq->measurement_request.Beacon.meas_mode,
 					   pBeaconReq->measurement_request.Beacon.regClass,
 					   pBeaconReq->measurement_request.Beacon.channel,
-					   req_mode, measDuration, wlan_vdev_get_id(pe_session->vdev));
+					   req_mode, measDuration, pe_session);
 
 	if (measDuration == 0 &&
 	    pBeaconReq->measurement_request.Beacon.meas_mode !=
@@ -1254,8 +1268,8 @@ rrm_process_beacon_report_req(struct mac_context *mac,
 		if (pBeaconReq->durationMandatory) {
 			pe_nofl_err("RX: [802.11 BCN_RPT] Dropping the req: duration mandatory & maxduration > measduration");
 			return eRRM_REFUSED;
-		} else
-			measDuration = maxMeasduration;
+		}
+		measDuration = maxMeasduration;
 	}
 
 	pe_debug("measurement duration %d", measDuration);
@@ -2044,6 +2058,9 @@ rrm_process_channel_load_req(struct mac_context *mac,
 	uint8_t op_class, channel, reporting_condition;
 	uint16_t randomization_intv, meas_duration, max_meas_duration;
 	bool present;
+	uint8_t country[WNI_CFG_COUNTRY_CODE_LEN];
+	qdf_freq_t chan_freq;
+	bool is_freq_enabled;
 
 	present = chan_load_req->measurement_request.channel_load.rrm_reporting.present;
 	reporting_condition = chan_load_req->measurement_request.channel_load.rrm_reporting.reporting_condition;
@@ -2063,11 +2080,11 @@ rrm_process_channel_load_req(struct mac_context *mac,
 		if (chan_load_req->durationMandatory) {
 			pe_nofl_err("RX:[802.11 CH_LOAD] Dropping the req: duration mandatory & max duration > meas duration");
 			return eRRM_REFUSED;
-		} else {
-			meas_duration = max_meas_duration;
 		}
+		meas_duration = max_meas_duration;
 	}
-	pe_debug("RX:[802.11 CH_LOAD] seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d",
+	pe_debug("RX:[802.11 CH_LOAD] vdev :%d, seq:%d Token:%d op_c:%d ch:%d meas_dur:%d, rand intv: %d, max_dur:%d",
+		 pe_session->vdev_id,
 		 mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
 		 chan_load_req->measurement_token, op_class,
 		 channel, meas_duration, randomization_intv,
@@ -2075,6 +2092,33 @@ rrm_process_channel_load_req(struct mac_context *mac,
 	if (!meas_duration || meas_duration > RRM_SCAN_MAX_DWELL_TIME)
 		return eRRM_REFUSED;
 
+	if (!wlan_reg_is_6ghz_supported(mac->psoc) &&
+	    (wlan_reg_is_6ghz_op_class(mac->pdev, op_class))) {
+		pe_debug("RX: [802.11 CH_LOAD] Ch belongs to 6 ghz spectrum, abort");
+		return eRRM_INCAPABLE;
+	}
+
+	rrm_get_country_code_from_connected_profile(mac, pe_session->vdev_id,
+						    country);
+	chan_freq = wlan_reg_country_chan_opclass_to_freq(mac->pdev,
+							  country, channel,
+							  op_class, false);
+	if (!chan_freq) {
+		pe_debug("Invalid ch freq for country code %c%c 0x%x",
+			 country[0], country[1], country[2]);
+		return eRRM_INCAPABLE;
+	}
+
+	pe_debug("freq:%d, country code %c%c 0x%x", chan_freq, country[0],
+		 country[1], country[2]);
+
+	is_freq_enabled = wlan_reg_is_freq_enabled(mac->pdev, chan_freq,
+						   REG_CURRENT_PWR_MODE);
+	if (!is_freq_enabled) {
+		pe_debug("No channels populated with requested operation class and current country, Hence abort the rrm operation");
+		return eRRM_INCAPABLE;
+	}
+
 	/* Prepare the request to send to SME. */
 	load_ind = qdf_mem_malloc(sizeof(struct ch_load_ind));
 	if (!load_ind)
@@ -2582,6 +2626,8 @@ QDF_STATUS rrm_initialize(struct mac_context *mac)
 	pRRMCaps->APChanReport = 1;
 	pRRMCaps->fine_time_meas_rpt = 1;
 	pRRMCaps->lci_capability = 1;
+	pRRMCaps->ChannelLoad = 1;
+	pRRMCaps->statistics = 1;
 
 	pRRMCaps->operatingChanMax = 3;
 	pRRMCaps->nonOperatingChanMax = 3;

+ 15 - 20
core/mac/src/pe/sch/sch_beacon_process.c

@@ -507,29 +507,24 @@ static void lim_detect_change_in_srp(struct mac_context *mac_ctx,
 				     tpSchBeaconStruct bcn)
 {
 	tDot11fIEspatial_reuse sr_ie;
+	int32_t ret = 0;
 
 	sr_ie = sta->parsed_ies.srp_ie;
-	if (!sr_ie.present) {
-		return;
-	} else if (!bcn->srp_ie.present) {
-		pe_err_rl("SRP IE is missing in beacon, disable SR");
-	} else if (!qdf_mem_cmp(&sr_ie, &bcn->srp_ie,
-				sizeof(tDot11fIEspatial_reuse))) {
-		/* No change in beacon SRP IE */
-		return;
+	if (sr_ie.present || bcn->srp_ie.present) {
+		ret = qdf_mem_cmp(&sr_ie, &bcn->srp_ie,
+				  sizeof(tDot11fIEspatial_reuse));
+
+		if (ret) {
+			/*
+			 * If SRP IE has changes, update the new params.
+			 */
+			sta->parsed_ies.srp_ie = bcn->srp_ie;
+			lim_update_vdev_sr_elements(session, sta);
+
+			lim_handle_sr_cap(session->vdev,
+					  SR_REASON_CODE_BCN_IE_CHANGE);
+		}
 	}
-
-	/*
-	 * If SRP IE has changes, update the new params.
-	 * Else if the SRP IE is missing, disable SR
-	 */
-	sta->parsed_ies.srp_ie = bcn->srp_ie;
-	if (bcn->srp_ie.present)
-		lim_update_vdev_sr_elements(session, sta);
-	else
-		wlan_vdev_mlme_set_sr_ctrl(session->vdev, SR_DISABLE);
-
-	lim_handle_sr_cap(session->vdev, SR_REASON_CODE_BCN_IE_CHANGE);
 }
 #else
 static void lim_detect_change_in_srp(struct mac_context *mac_ctx,

+ 14 - 10
core/mac/src/sys/legacy/src/utils/src/parser_api.c

@@ -7706,24 +7706,28 @@ populate_dot11f_sr_info(struct mac_context *mac_ctx,
 	uint8_t non_srg_pd_offset;
 	uint8_t sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(session->vdev);
 	bool sr_enabled = wlan_vdev_mlme_get_he_spr_enabled(session->vdev);
-	bool sr_disabled_due_conc =
-		wlan_vdev_mlme_is_sr_disable_due_conc(session->vdev);
 
-	if (!sr_enabled || !sr_ctrl || sr_disabled_due_conc ||
-	    (sr_ctrl & WLAN_HE_NON_SRG_PD_SR_DISALLOWED) ||
-	    !(sr_ctrl & WLAN_HE_NON_SRG_OFFSET_PRESENT))
+	if (!sr_enabled)
 		return QDF_STATUS_SUCCESS;
 
-	non_srg_pd_offset = wlan_vdev_mlme_get_non_srg_pd_offset(session->vdev);
 	sr_info->present = 1;
 	sr_info->psr_disallow = 1;
-	sr_info->non_srg_pd_sr_disallow = 0;
-	sr_info->srg_info_present = 0;
-	sr_info->non_srg_offset_present = 1;
 	sr_info->srg_info_present = 0;
+	sr_info->non_srg_offset_present = 0;
+	sr_info->non_srg_pd_sr_disallow = !!(sr_ctrl &
+					   WLAN_HE_NON_SRG_PD_SR_DISALLOWED);
+
+	if ((!sr_info->non_srg_pd_sr_disallow) &&
+	    (sr_ctrl & WLAN_HE_NON_SRG_OFFSET_PRESENT)) {
+		non_srg_pd_offset =
+			wlan_vdev_mlme_get_non_srg_pd_offset(session->vdev);
+		sr_info->non_srg_offset_present = 1;
+		sr_info->non_srg_offset.info.non_srg_pd_max_offset =
+							non_srg_pd_offset;
+	}
+
 	if (sr_ctrl & WLAN_HE_SIGA_SR_VAL15_ALLOWED)
 		sr_info->sr_value15_allow = 1;
-	sr_info->non_srg_offset.info.non_srg_pd_max_offset = non_srg_pd_offset;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 25 - 4
core/sap/inc/sap_api.h

@@ -460,11 +460,11 @@ struct sap_acs_cfg {
 	/* ACS Algo Input */
 	uint8_t    acs_mode;
 	eCsrPhyMode hw_mode;
-	uint32_t    start_ch_freq;
-	uint32_t    end_ch_freq;
-	uint32_t   *freq_list;
+	qdf_freq_t    start_ch_freq;
+	qdf_freq_t    end_ch_freq;
+	qdf_freq_t   *freq_list;
 	uint8_t    ch_list_count;
-	uint32_t   *master_freq_list;
+	qdf_freq_t   *master_freq_list;
 	uint8_t    master_ch_list_count;
 	bool master_ch_list_updated;
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
@@ -1936,6 +1936,27 @@ void wlansap_update_ll_lt_sap_acs_result(struct sap_context *sap_ctx,
  */
 int wlansap_update_sap_chan_list(struct sap_config *sap_config,
 				 qdf_freq_t *freq_list, uint16_t count);
+
+/**
+ * wlansap_sort_channel_list() - Sort channel list
+ * @vdev_id: Vdev Id
+ * @list: List of channels which needs to sort
+ * @ch_info: Fill sorted channels list in ch_info
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlansap_sort_channel_list(uint8_t vdev_id, qdf_list_t *list,
+				     struct sap_sel_ch_info *ch_info);
+
+/**
+ * wlansap_get_user_config_acs_ch_list() - Get user config ACS channel list
+ * @vdev_id: Vdev Id
+ * @filter: Filter to apply to get scan result
+ *
+ * Return: None
+ */
+void wlansap_get_user_config_acs_ch_list(uint8_t vdev_id,
+					 struct scan_filter *filter);
 #ifdef __cplusplus
 }
 #endif

+ 16 - 11
core/sap/src/sap_ch_select.c

@@ -2772,23 +2772,22 @@ sap_acs_next_lower_bandwidth(enum phy_ch_width ch_width)
 	return wlan_reg_get_next_lower_bandwidth(ch_width);
 }
 
-static void sap_sort_channel_list(struct mac_context *mac_ctx,
-				  uint8_t vdev_id,
-				  qdf_list_t *ch_list,
-				  struct sap_sel_ch_info *ch_info,
-				  v_REGDOMAIN_t *domain,
-				  uint32_t *operating_band)
+void sap_sort_channel_list(struct mac_context *mac_ctx, uint8_t vdev_id,
+			   qdf_list_t *ch_list, struct sap_sel_ch_info *ch_info,
+			   v_REGDOMAIN_t *domain, uint32_t *operating_band)
 {
 	uint8_t country[CDS_COUNTRY_CODE_LEN + 1];
 	struct sap_context *sap_ctx;
 	enum phy_ch_width cur_bw;
+	v_REGDOMAIN_t reg_domain;
+	uint32_t op_band;
 
 	sap_ctx = mac_ctx->sap.sapCtxList[vdev_id].sap_context;
 	cur_bw = sap_ctx->acs_cfg->ch_width;
 
 	/* Initialize the structure pointed by spect_info */
 	if (!sap_chan_sel_init(mac_ctx, ch_info, sap_ctx, false)) {
-		sap_err("Ch Select initialization failed");
+		sap_err("vdev %d ch select initialization failed", vdev_id);
 		return;
 	}
 
@@ -2801,14 +2800,20 @@ static void sap_sort_channel_list(struct mac_context *mac_ctx,
 #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */
 
 	wlan_reg_read_current_country(mac_ctx->psoc, country);
-	wlan_reg_get_domain_from_country_code(domain, country, SOURCE_DRIVER);
+	wlan_reg_get_domain_from_country_code(&reg_domain, country,
+					      SOURCE_DRIVER);
 
-	SET_ACS_BAND(*operating_band, sap_ctx);
+	SET_ACS_BAND(op_band, sap_ctx);
 
 	/* Sort the ch lst as per the computed weights, lesser weight first. */
-	sap_sort_chl_weight_all(mac_ctx, sap_ctx, ch_info, *operating_band,
-				*domain, &cur_bw);
+	sap_sort_chl_weight_all(mac_ctx, sap_ctx, ch_info, op_band,
+				reg_domain, &cur_bw);
 	sap_ctx->acs_cfg->ch_width = cur_bw;
+
+	if (domain)
+		*domain = reg_domain;
+	if (operating_band)
+		*operating_band = op_band;
 }
 
 uint32_t sap_select_channel(mac_handle_t mac_handle,

+ 17 - 0
core/sap/src/sap_internal.h

@@ -316,6 +316,23 @@ QDF_STATUS wlansap_pre_start_bss_acs_scan_callback(mac_handle_t mac_handle,
 						   uint32_t scanid,
 						   eCsrScanStatus scan_status);
 
+/**
+ * sap_sort_channel_list() - Sort channel list based on channel weight
+ * @mac_ctx: Pointer to mac_context
+ * @vdev_id: Vdev ID
+ * @ch_list: Pointer to qdf_list_t
+ * @ch_info: Pointer to sap_sel_ch_info structure
+ * @domain: Regulatory Domain
+ * @operating_band: Operating band
+ *
+ * Return: None
+ *
+ */
+void
+sap_sort_channel_list(struct mac_context *mac_ctx, uint8_t vdev_id,
+		      qdf_list_t *ch_list, struct sap_sel_ch_info *ch_info,
+		      v_REGDOMAIN_t *domain, uint32_t *operating_band);
+
 /**
  * sap_select_channel() - select SAP channel
  * @mac_handle: Opaque handle to the global MAC context

+ 54 - 3
core/sap/src/sap_module.c

@@ -4006,9 +4006,9 @@ qdf_freq_t wlansap_get_chan_band_restrict(struct sap_context *sap_ctx,
 				  restart_freq);
 			*csa_reason = CSA_REASON_BAND_RESTRICTED;
 		}
-	} else if (wlan_reg_is_disable_for_pwrmode(mac->pdev,
-						   sap_ctx->chan_freq,
-						   REG_CURRENT_PWR_MODE) &&
+	} else if (wlan_reg_is_disable_in_secondary_list_for_freq(
+							mac->pdev,
+							sap_ctx->chan_freq) &&
 		   !utils_dfs_is_freq_in_nol(mac->pdev, sap_ctx->chan_freq)) {
 		sap_debug("channel is disabled");
 		*csa_reason = CSA_REASON_CHAN_DISABLED;
@@ -4344,3 +4344,54 @@ void wlansap_update_ll_lt_sap_acs_result(struct sap_context *sap_ctx,
 	sap_ctx->acs_cfg->pri_ch_freq = last_acs_freq;
 	sap_ctx->acs_cfg->ht_sec_ch_freq = 0;
 }
+
+QDF_STATUS wlansap_sort_channel_list(uint8_t vdev_id, qdf_list_t *list,
+				     struct sap_sel_ch_info *ch_info)
+{
+	struct mac_context *mac_ctx;
+
+	mac_ctx = sap_get_mac_context();
+	if (!mac_ctx) {
+		sap_err("Invalid MAC context");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	sap_sort_channel_list(mac_ctx, vdev_id, list,
+			      ch_info, NULL, NULL);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+void wlansap_get_user_config_acs_ch_list(uint8_t vdev_id,
+					 struct scan_filter *filter)
+{
+	struct mac_context *mac_ctx;
+	struct sap_context *sap_ctx;
+	uint8_t ch_count = 0;
+
+	mac_ctx = sap_get_mac_context();
+	if (!mac_ctx) {
+		sap_err("Invalid MAC context");
+		return;
+	}
+
+	if (vdev_id >= WLAN_UMAC_VDEV_ID_MAX)
+		return;
+
+	sap_ctx = mac_ctx->sap.sapCtxList[vdev_id].sap_context;
+
+	if (!sap_ctx) {
+		sap_err("vdev %d sap_ctx is NULL", vdev_id);
+		return;
+	}
+
+	ch_count = sap_ctx->acs_cfg->master_ch_list_count;
+
+	if (!ch_count || ch_count > NUM_CHANNELS)
+		return;
+
+	filter->num_of_channels = ch_count;
+	qdf_mem_copy(filter->chan_freq_list, sap_ctx->acs_cfg->master_freq_list,
+		     filter->num_of_channels *
+		     sizeof(filter->chan_freq_list[0]));
+}

+ 22 - 0
core/sme/src/common/sme_api.c

@@ -15100,6 +15100,7 @@ void sme_reset_he_caps(mac_handle_t mac_handle, uint8_t vdev_id)
 
 	if (mac_ctx->usr_cfg_disable_rsp_tx)
 		sme_set_cfg_disable_tx(mac_handle, vdev_id, 0);
+	mac_ctx->is_usr_cfg_amsdu_enabled = true;
 }
 #endif
 
@@ -15275,6 +15276,24 @@ void sme_set_per_link_ba_mode(mac_handle_t mac_handle, uint8_t val)
 	}
 }
 
+static inline
+void sme_set_mcs_15_tx_rx_disable(uint8_t vdev_id)
+{
+	uint32_t tx_disable[2] = {67, 0};
+	uint32_t rx_disable[3] = {125, 0, 1};
+	QDF_STATUS status;
+
+	sme_debug("Send MCS 15 rx/tx disable to FW");
+
+	status = sme_send_unit_test_cmd(vdev_id, 10, 2, tx_disable);
+	if (status)
+		sme_err("Failed to send MCS 15 tx disable");
+
+	status = sme_send_unit_test_cmd(vdev_id, 67, 3, rx_disable);
+	if (status)
+		sme_err("Failed to send MCS 15 rx disable");
+}
+
 void sme_reset_eht_caps(mac_handle_t mac_handle, uint8_t vdev_id)
 {
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
@@ -15310,6 +15329,9 @@ void sme_reset_eht_caps(mac_handle_t mac_handle, uint8_t vdev_id)
 	if (QDF_IS_STATUS_SUCCESS(status))
 		ucfg_mlme_set_bss_color_collision_det_sta(mac_ctx->psoc, val);
 	sme_set_per_link_ba_mode(mac_handle, ba_mode_auto);
+	sme_set_mcs_15_tx_rx_disable(vdev_id);
+	wlan_mlme_set_btm_abridge_flag(mac_ctx->psoc, false);
+	wlan_mlme_set_eht_mld_id(mac_ctx->psoc, 0);
 }
 
 void sme_update_eht_cap_nss(mac_handle_t mac_handle, uint8_t vdev_id,

+ 10 - 0
core/sme/src/csr/csr_util.c

@@ -636,6 +636,16 @@ uint16_t csr_check_concurrent_channel_overlap(struct mac_context *mac_ctx,
 		if ((op_mode == QDF_STA_MODE ||
 		     op_mode == QDF_P2P_CLIENT_MODE) &&
 		    cm_is_vdevid_connected(mac_ctx->pdev, i)) {
+			if (op_mode == QDF_STA_MODE &&
+			    policy_mgr_is_ml_vdev_id(mac_ctx->psoc,
+						     session->vdev_id) &&
+			    policy_mgr_vdev_is_force_inactive(
+							mac_ctx->psoc,
+							session->vdev_id)) {
+				sme_debug("skip inactive ml sta vdev %d",
+					  session->vdev_id);
+				continue;
+			}
 			wlan_get_op_chan_freq_info_vdev_id(mac_ctx->pdev,
 					   session->vdev_id,
 					   &intf_ch_freq, &intf_cfreq,

+ 6 - 3
core/sme/src/rrm/sme_rrm.c

@@ -1153,9 +1153,6 @@ sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	sme_debug("opclass: %d, channel: %d freq:%d, country code %c%c 0x%x",
-		  sme_rrm_ctx->regClass, channel, scan_freq,
-		  country_code[0], country_code[1], country_code[2]);
 	if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev, sme_rrm_ctx->regClass))
 		chan_space = wlan_reg_get_op_class_width
 			(mac_ctx->pdev, sme_rrm_ctx->regClass, true);
@@ -1163,6 +1160,12 @@ sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
 		chan_space = wlan_reg_dmn_get_chanwidth_from_opclass_auto(
 							country_code, channel,
 							sme_rrm_ctx->regClass);
+
+	sme_debug("opclass: %d, channel: %d freq:%d, country code %c%c 0x%x, chan_space:%d",
+		  sme_rrm_ctx->regClass, channel, scan_freq,
+		  country_code[0], country_code[1], country_code[2],
+		  chan_space);
+
 	switch (chan_space) {
 	case 320:
 		fallthrough;

+ 12 - 8
core/wma/src/wma_dev_if.c

@@ -3368,15 +3368,19 @@ QDF_STATUS wma_vdev_pre_start(uint8_t vdev_id, bool restart)
 	if (QDF_IS_STATUS_ERROR(status))
 		wma_err("failed to set aggregation sizes(status = %d)", status);
 
-	status = wlan_mlme_get_max_amsdu_num(wma->psoc, &amsdu_val);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		wma_err("failed to get amsdu aggr.size(status = %d)", status);
-	} else {
-		status = wma_set_tx_rx_aggr_size(vdev_id, amsdu_val, amsdu_val,
-					WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU);
-		if (QDF_IS_STATUS_ERROR(status))
-			wma_err("failed to set amsdu aggr.size(status = %d)",
+	if (mac_ctx->is_usr_cfg_amsdu_enabled) {
+		status = wlan_mlme_get_max_amsdu_num(wma->psoc, &amsdu_val);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			wma_err("failed to get amsdu aggr.size(status = %d)",
 				status);
+		} else {
+			status = wma_set_tx_rx_aggr_size(
+					vdev_id, amsdu_val, amsdu_val,
+					WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU);
+			if (QDF_IS_STATUS_ERROR(status))
+				wma_err("failed to set amsdu aggr.size(status = %d)",
+					status);
+		}
 	}
 
 	if (mlme_obj->mgmt.generic.type == WMI_VDEV_TYPE_STA) {

+ 231 - 44
core/wma/src/wma_features.c

@@ -78,6 +78,9 @@
 #include "hif.h"
 #include "wlan_cmn_ieee80211.h"
 #include "wlan_mlo_mgr_cmn.h"
+#include "wlan_mlo_mgr_peer.h"
+#include "wlan_mlo_mgr_sta.h"
+
 /**
  * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE
  * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile
@@ -752,10 +755,11 @@ enum wlan_phymode wma_chan_phy_mode(uint32_t freq, enum phy_ch_width chan_width,
 					phymode = WLAN_PHYMODE_11AXG_HE40;
 				break;
 			default:
-				phymode = wma_eht_chan_phy_mode(freq,
-								dot11_mode,
-								bw_val,
-								chan_width);
+				phymode = wma_eht_chan_phy_mode(
+							freq,
+							dot11_mode,
+							bw_val,
+							chan_width);
 				break;
 			}
 		}
@@ -811,10 +815,11 @@ enum wlan_phymode wma_chan_phy_mode(uint32_t freq, enum phy_ch_width chan_width,
 					phymode = WLAN_PHYMODE_11AXA_HE80_80;
 				break;
 			default:
-				phymode = wma_eht_chan_phy_mode(freq,
-								dot11_mode,
-								bw_val,
-								chan_width);
+				phymode = wma_eht_chan_phy_mode(
+							freq,
+							dot11_mode,
+							bw_val,
+							chan_width);
 				break;
 			}
 		}
@@ -1313,6 +1318,203 @@ QDF_STATUS wma_parse_bw_indication_ie(uint8_t *ie,
 }
 #endif
 
+static bool fill_csa_offload_params(
+			wmi_csa_event_fixed_param *csa_event,
+			struct csa_offload_params *csa_offload_event,
+			struct wlan_objmgr_pdev *pdev)
+{
+	struct ieee80211_channelswitch_ie *csa_ie;
+	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
+	uint8_t is_csa_ie_present = false;
+
+	if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
+		csa_ie = (struct ieee80211_channelswitch_ie *)
+					(&csa_event->csa_ie[0]);
+		csa_offload_event->channel = csa_ie->newchannel;
+		csa_offload_event->csa_chan_freq =
+		wlan_reg_legacy_chan_to_freq(pdev,
+					     csa_ie->newchannel);
+		csa_offload_event->switch_mode = csa_ie->switchmode;
+		csa_offload_event->ies_present_flag |= MLME_CSA_IE_PRESENT;
+		is_csa_ie_present = true;
+	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
+		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
+						(&csa_event->xcsa_ie[0]);
+		csa_offload_event->channel = xcsa_ie->newchannel;
+		csa_offload_event->switch_mode = xcsa_ie->switchmode;
+		csa_offload_event->new_op_class = xcsa_ie->newClass;
+		if (wlan_reg_is_6ghz_op_class(pdev, xcsa_ie->newClass)) {
+			csa_offload_event->csa_chan_freq =
+				wlan_reg_chan_band_to_freq
+					(pdev, xcsa_ie->newchannel,
+					 BIT(REG_BAND_6G));
+		} else {
+			csa_offload_event->csa_chan_freq =
+				wlan_reg_legacy_chan_to_freq
+					(pdev, xcsa_ie->newchannel);
+		}
+		csa_offload_event->ies_present_flag |= MLME_XCSA_IE_PRESENT;
+		is_csa_ie_present = true;
+	}
+	return is_csa_ie_present;
+}
+
+#ifdef WLAN_FEATURE_11BE
+static bool handle_csa_standby_link(wmi_csa_event_fixed_param *csa_event,
+				    struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_pdev *pdev)
+{
+	struct mlo_link_info *link_info;
+	struct wlan_mlo_dev_context *mldev;
+	uint8_t mld_addr[QDF_MAC_ADDR_SIZE];
+	struct csa_offload_params csa_param = {0};
+	struct mlo_link_bss_params params = {0};
+	uint8_t is_csa_standby = false;
+	uint8_t link_id;
+	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!psoc) {
+		wma_err("null psoc");
+		return is_csa_standby;
+	}
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->mld_mac_address,
+				   &mld_addr[0]);
+	wlan_mlo_get_mlpeer_by_peer_mladdr(
+			(struct qdf_mac_addr *)&mld_addr[0],
+			&mldev);
+	if (!mldev) {
+		wma_err("NULL ml dev ctx");
+		return is_csa_standby;
+	}
+
+	link_id =  csa_event->link_id;
+	link_info = mlo_mgr_get_ap_link_by_link_id(mldev,
+						   link_id);
+	if (!link_info) {
+		wma_err("NULL link info ");
+		return is_csa_standby;
+	}
+
+	if (link_info->vdev_id != WLAN_INVALID_VDEV_ID) {
+		wma_debug("vdev id %d link id %d ", link_info->vdev_id,
+			  link_id);
+		return is_csa_standby;
+	}
+
+	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
+	if (!mlo_tx_ops) {
+		wma_err("tx_ops is null!");
+		return is_csa_standby;
+	}
+
+	if (!fill_csa_offload_params(csa_event, &csa_param, pdev)) {
+		wma_err("CSA Event error: No CSA IE present");
+		return is_csa_standby;
+	}
+
+	mlo_mgr_update_csa_link_info(mldev, &csa_param, link_id);
+
+	params.link_id = link_info->link_id;
+	params.chan = qdf_mem_malloc(sizeof(struct wlan_channel));
+	if (!params.chan) {
+		wma_err("no mem acquired");
+		return is_csa_standby;
+	}
+
+	qdf_copy_macaddr((struct qdf_mac_addr *)&params.ap_mld_mac[0],
+			 &link_info->ap_link_addr);
+
+	params.chan->ch_freq = link_info->link_chan_info->ch_freq;
+	params.chan->ch_cfreq1 = link_info->link_chan_info->ch_cfreq1;
+	params.chan->ch_cfreq2 = link_info->link_chan_info->ch_cfreq2;
+	params.chan->ch_phymode = link_info->link_chan_info->ch_phymode;
+
+	mlo_debug("link id %d chan freq %d cfreq1 %d cfreq2 %d host phymode %d ap mld mac " QDF_MAC_ADDR_FMT,
+		  link_info->link_id, link_info->link_chan_info->ch_freq,
+		  link_info->link_chan_info->ch_cfreq1,
+		  link_info->link_chan_info->ch_cfreq2,
+		  link_info->link_chan_info->ch_phymode,
+		  QDF_MAC_ADDR_REF(&params.ap_mld_mac[0]));
+
+	if (!mlo_tx_ops->send_link_set_bss_params_cmd) {
+		wma_err("handler is not registered");
+		qdf_mem_free(params.chan);
+		return is_csa_standby;
+	}
+
+	status = mlo_tx_ops->send_link_set_bss_params_cmd(psoc, &params);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		wma_err("failed to send link set bss request command to FW");
+		qdf_mem_free(params.chan);
+		return is_csa_standby;
+	}
+
+	is_csa_standby = true;
+	qdf_mem_free(params.chan);
+
+	return is_csa_standby;
+}
+
+static int fill_peer_mac_addr(wmi_csa_event_fixed_param *csa_event,
+			      uint8_t *bssid)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t mld_addr[QDF_MAC_ADDR_SIZE];
+	uint8_t link_addr[QDF_MAC_ADDR_SIZE];
+	uint8_t link_id;
+	struct mlo_link_info *link_info;
+	struct wlan_mlo_dev_context *mldev;
+
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->mld_mac_address,
+				   &mld_addr[0]);
+	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->link_mac_address,
+				   &link_addr[0]);
+	wlan_mlo_get_mlpeer_by_peer_mladdr(
+				(struct qdf_mac_addr *)&mld_addr[0],
+				&mldev);
+	if (!mldev) {
+		wma_err("NULL ml dev ctx");
+		return -EINVAL;
+	}
+
+	link_id =  csa_event->link_id;
+	link_info = mlo_mgr_get_ap_link_by_link_id(mldev,
+						   link_id);
+	if (!link_info) {
+		wma_err("NULL link info ");
+		return -EINVAL;
+	}
+
+	qdf_copy_macaddr((struct qdf_mac_addr *)&bssid[0],
+			 &link_info->ap_link_addr);
+	wma_debug("csa event link id %d vdev id %d peer mld addr" QDF_MAC_ADDR_FMT "peer link addr" QDF_MAC_ADDR_FMT "host link info ap_link_addr" QDF_MAC_ADDR_FMT,
+		  link_id, link_info->vdev_id,
+		  QDF_MAC_ADDR_REF(&mld_addr[0]),
+		  QDF_MAC_ADDR_REF(&link_addr[0]),
+		  QDF_MAC_ADDR_REF(link_info->ap_link_addr.bytes));
+
+	return status;
+}
+
+#else
+static int fill_peer_mac_addr(wmi_csa_event_fixed_param *csa_event,
+			      uint8_t *bssid)
+{
+	return 0;
+}
+
+static bool handle_csa_standby_link(wmi_csa_event_fixed_param *csa_event,
+				    struct wlan_objmgr_psoc *psoc,
+				    struct wlan_objmgr_pdev *pdev)
+{
+	return false;
+}
+
+#endif
+
 /**
  * wma_csa_offload_handler() - CSA event handler
  * @handle: wma handle
@@ -1331,9 +1533,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 	uint8_t bssid[QDF_MAC_ADDR_SIZE];
 	uint8_t vdev_id = 0;
 	uint8_t cur_chan = 0;
-	struct ieee80211_channelswitch_ie *csa_ie;
 	struct csa_offload_params *csa_offload_event;
-	struct ieee80211_extendedchannelswitch_ie *xcsa_ie;
 	struct ieee80211_ie_wide_bw_switch *wb_ie;
 	struct wlan_objmgr_peer *peer;
 	struct wlan_objmgr_vdev *vdev;
@@ -1349,7 +1549,20 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 		return -EINVAL;
 	}
 	csa_event = param_buf->fixed_param;
-	WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, &bssid[0]);
+
+	if (csa_event->link_id_present &&
+	    csa_event->mld_mac_address_present) {
+		status = fill_peer_mac_addr(csa_event, &bssid[0]);
+		if (status)
+			return -EINVAL;
+
+		/* check standby link and return */
+		if (handle_csa_standby_link(csa_event, wma->psoc, wma->pdev))
+			return 0;
+		} else {
+			WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2,
+						   &bssid[0]);
+		}
 
 	peer = wlan_objmgr_get_peer_by_mac(wma->psoc,
 					   bssid, WLAN_LEGACY_WMA_ID);
@@ -1383,33 +1596,7 @@ int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len)
 	qdf_copy_macaddr(&csa_offload_event->bssid,
 			 (struct qdf_mac_addr *)bssid);
 
-	if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) {
-		csa_ie = (struct ieee80211_channelswitch_ie *)
-						(&csa_event->csa_ie[0]);
-		csa_offload_event->channel = csa_ie->newchannel;
-		csa_offload_event->csa_chan_freq =
-			wlan_reg_legacy_chan_to_freq(wma->pdev,
-						     csa_ie->newchannel);
-		csa_offload_event->switch_mode = csa_ie->switchmode;
-		csa_offload_event->ies_present_flag |= MLME_CSA_IE_PRESENT;
-	} else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) {
-		xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *)
-						(&csa_event->xcsa_ie[0]);
-		csa_offload_event->channel = xcsa_ie->newchannel;
-		csa_offload_event->switch_mode = xcsa_ie->switchmode;
-		csa_offload_event->new_op_class = xcsa_ie->newClass;
-		if (wlan_reg_is_6ghz_op_class(wma->pdev, xcsa_ie->newClass)) {
-			csa_offload_event->csa_chan_freq =
-				wlan_reg_chan_band_to_freq
-					(wma->pdev, xcsa_ie->newchannel,
-					 BIT(REG_BAND_6G));
-		} else {
-			csa_offload_event->csa_chan_freq =
-				wlan_reg_legacy_chan_to_freq
-					(wma->pdev, xcsa_ie->newchannel);
-		}
-		csa_offload_event->ies_present_flag |= MLME_XCSA_IE_PRESENT;
-	} else {
+	if (!fill_csa_offload_params(csa_event, csa_offload_event, wma->pdev)) {
 		wma_err("CSA Event error: No CSA IE present");
 		qdf_mem_free(csa_offload_event);
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
@@ -2324,7 +2511,7 @@ static void wma_log_pkt_icmpv6(uint8_t *data, uint32_t length)
 	pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET);
 	seq_num = *(uint16_t *)(data + ICMPV6_SEQ_NUM_OFFSET);
 	wma_debug("Pkt_len: %u, Seq_num: %u",
-		 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
+		  qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num));
 }
 
 static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length)
@@ -2344,10 +2531,10 @@ static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length)
 		      ip_addr[2], ip_addr[3]);
 	src_port = *(uint16_t *)(data + IPV4_SRC_PORT_OFFSET);
 	dst_port = *(uint16_t *)(data + IPV4_DST_PORT_OFFSET);
-	wma_info("Pkt_len: %u, src_port: %u, dst_port: %u",
-		qdf_cpu_to_be16(pkt_len),
-		qdf_cpu_to_be16(src_port),
-		qdf_cpu_to_be16(dst_port));
+	wma_debug("Pkt_len: %u, src_port: %u, dst_port: %u",
+		  qdf_cpu_to_be16(pkt_len),
+		  qdf_cpu_to_be16(src_port),
+		  qdf_cpu_to_be16(dst_port));
 }
 
 static void wma_log_pkt_ipv6(uint8_t *data, uint32_t length)
@@ -2768,7 +2955,7 @@ static int wma_wake_event_packet(
 	case WOW_REASON_DELAYED_WAKEUP_HOST_CFG_TIMER_ELAPSED:
 	case WOW_REASON_DELAYED_WAKEUP_DATA_STORE_LIST_FULL:
 		wma_info("Wake event packet:");
-		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_INFO,
+		qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG,
 				   packet, packet_len);
 
 		vdev = &wma->interfaces[wake_info->vdev_id];

+ 5 - 2
core/wma/src/wma_sar_public_structs.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018 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
@@ -25,7 +25,10 @@ struct sar_limit_event;
 enum sar_version {
 	SAR_VERSION_1,
 	SAR_VERSION_2,
-	SAR_VERSION_3
+	SAR_VERSION_3,
+	SAR_VERSION_4,
+	SAR_VERSION_5,
+	SAR_VERSION_6,
 };
 
 /**

+ 10 - 5
wlan_qcacld3_modules.bzl

@@ -6,6 +6,10 @@ _target_chipset_map = {
     "pineapple": [
 	"kiwi-v2",
     ],
+    "sun": [
+        "peach",
+        "kiwi-v2",
+    ],
 }
 
 _chipset_hw_map = {
@@ -1883,6 +1887,11 @@ _conditional_srcs = {
             "core/hdd/src/wlan_hdd_sysfs_roam_trigger_bitmap.c",
         ],
     },
+    "CONFIG_WLAN_SYSFS_RF_TEST_MODE": {
+        True: [
+            "core/hdd/src/wlan_hdd_sysfs_rf_test_mode.c",
+        ],
+    },
     "CONFIG_WLAN_SYSFS_DP_STATS": {
         True: [
             "core/hdd/src/wlan_hdd_sysfs_txrx_stats_console.c",
@@ -2102,11 +2111,6 @@ def _define_module_for_target_variant_chipset(target, variant, chipset):
         copts.append(i)
 
     feature_grep_map = [
-        {
-            "pattern": "walt_get_cpus_taken",
-            "file": "kernel/sched/walt/walt.c",
-            "flag": "WALT_GET_CPU_TAKEN_SUPPORT",
-        },
         {
             "pattern": "nl80211_validate_key_link_id",
             "file": "net/wireless/nl80211.c",
@@ -2158,6 +2162,7 @@ def _define_module_for_target_variant_chipset(target, variant, chipset):
         cmd = cmd,
     )
 
+    copts.append("-Wno-format")
     copts.append("-include")
     copts.append("$(location :{}_grep_defines)".format(tvc))