Browse Source

Merge 9fa101bd7e88dd333948288152a1fe48fc0677ba on remote branch

Change-Id: Ibfb3b7aab53ff29f8481404b765e8228e521244b
Linux Build Service Account 1 year ago
parent
commit
3e501955f2
100 changed files with 2490 additions and 470 deletions
  1. 9 2
      Kbuild
  2. 13 1
      components/cmn_services/interface_mgr/src/wlan_if_mgr_sap.c
  3. 9 4
      components/cmn_services/logging/inc/wlan_connectivity_logging.h
  4. 3 2
      components/cmn_services/logging/src/wlan_connectivity_logging.c
  5. 11 0
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_api.h
  6. 71 0
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_ll_sap.h
  7. 3 1
      components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h
  8. 11 2
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_action.c
  9. 23 1
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
  10. 234 0
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_ll_sap.c
  11. 0 1
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c
  12. 6 0
      components/dp/core/inc/wlan_dp_wfds.h
  13. 12 2
      components/dp/core/src/wlan_dp_wfds.c
  14. 3 0
      components/mlme/core/inc/wlan_mlme_main.h
  15. 4 2
      components/mlme/core/src/wlan_mlme_main.c
  16. 26 1
      components/mlme/dispatcher/inc/cfg_mlme_feature_flag.h
  17. 19 7
      components/mlme/dispatcher/inc/cfg_mlme_wifi_pos.h
  18. 12 0
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  19. 2 0
      components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
  20. 13 0
      components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
  21. 18 0
      components/mlme/dispatcher/src/wlan_mlme_api.c
  22. 7 0
      components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c
  23. 2 0
      components/nan/core/src/nan_main_i.h
  24. 25 2
      components/nan/dispatcher/inc/cfg_nan.h
  25. 16 1
      components/nan/dispatcher/inc/cfg_nan_api.h
  26. 16 0
      components/nan/dispatcher/inc/wlan_nan_api_i.h
  27. 13 0
      components/nan/dispatcher/src/cfg_nan.c
  28. 2 0
      components/nan/dispatcher/src/nan_ucfg_api.c
  29. 6 0
      components/nan/dispatcher/src/wlan_nan_api.c
  30. 0 1
      components/target_if/connection_mgr/src/target_if_cm_roam_event.c
  31. 55 0
      components/target_if/sap/ll_sap/inc/target_if_ll_sap.h
  32. 149 0
      components/target_if/sap/ll_sap/src/target_if_ll_sap.c
  33. 10 0
      components/tdls/core/src/wlan_tdls_ct.c
  34. 34 22
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  35. 5 2
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h
  36. 2 0
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c
  37. 20 11
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h
  38. 27 6
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  39. 1 1
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c
  40. 34 0
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h
  41. 22 3
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h
  42. 63 4
      components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c
  43. 36 13
      components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c
  44. 68 9
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_bearer_switch.c
  45. 11 5
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.c
  46. 2 2
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.h
  47. 46 6
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_sap_main.c
  48. 26 0
      components/umac/mlme/sap/ll_sap/core/src/wlan_ll_sap_main.h
  49. 19 0
      components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_api.h
  50. 27 0
      components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_public_structs.h
  51. 29 2
      components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_ucfg_api.h
  52. 41 0
      components/umac/mlme/sap/ll_sap/dispatcher/src/wlan_ll_sap_api.c
  53. 12 2
      components/umac/mlme/sap/ll_sap/dispatcher/src/wlan_ll_sap_ucfg_api.c
  54. 51 0
      components/wmi/inc/wmi_unified_ll_sap_api.h
  55. 46 0
      components/wmi/src/wmi_unified_ll_sap_api.c
  56. 130 0
      components/wmi/src/wmi_unified_ll_sap_tlv.c
  57. 51 0
      components/wmi/src/wmi_unified_ll_sap_tlv.h
  58. 21 1
      components/wmi/src/wmi_unified_mlme_tlv.c
  59. 1 1
      components/wmi/src/wmi_unified_roam_tlv.c
  60. 10 0
      core/hdd/inc/wlan_hdd_main.h
  61. 176 22
      core/hdd/src/wlan_hdd_cfg.c
  62. 27 9
      core/hdd/src/wlan_hdd_cfg80211.c
  63. 1 4
      core/hdd/src/wlan_hdd_cm_connect.c
  64. 8 1
      core/hdd/src/wlan_hdd_cm_disconnect.c
  65. 7 5
      core/hdd/src/wlan_hdd_hostapd.c
  66. 41 16
      core/hdd/src/wlan_hdd_main.c
  67. 3 1
      core/hdd/src/wlan_hdd_mlo.c
  68. 9 4
      core/hdd/src/wlan_hdd_p2p.c
  69. 13 14
      core/hdd/src/wlan_hdd_stats.c
  70. 3 3
      core/mac/inc/qwlan_version.h
  71. 17 0
      core/mac/inc/sir_api.h
  72. 6 6
      core/mac/src/cfg/cfgUtil/dot11f.frms
  73. 7 7
      core/mac/src/include/dot11f.h
  74. 11 0
      core/mac/src/pe/include/lim_api.h
  75. 2 2
      core/mac/src/pe/include/lim_session.h
  76. 43 48
      core/mac/src/pe/lim/lim_api.c
  77. 104 92
      core/mac/src/pe/lim/lim_process_auth_frame.c
  78. 19 3
      core/mac/src/pe/lim/lim_process_mlm_req_messages.c
  79. 5 2
      core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
  80. 53 13
      core/mac/src/pe/lim/lim_process_sme_req_messages.c
  81. 3 3
      core/mac/src/pe/lim/lim_send_management_frames.c
  82. 2 1
      core/mac/src/pe/lim/lim_session.c
  83. 27 8
      core/mac/src/pe/lim/lim_utils.c
  84. 2 0
      core/mac/src/pe/lim/lim_utils.h
  85. 3 3
      core/mac/src/pe/rrm/rrm_api.c
  86. 3 4
      core/mac/src/pe/sch/sch_beacon_gen.c
  87. 49 49
      core/mac/src/sys/legacy/src/utils/src/dot11f.c
  88. 6 2
      core/mac/src/sys/legacy/src/utils/src/parser_api.c
  89. 57 0
      core/sap/src/sap_ch_select.c
  90. 2 0
      core/sap/src/sap_ch_select.h
  91. 9 0
      core/sap/src/sap_fsm.c
  92. 2 0
      core/sap/src/sap_module.c
  93. 2 3
      core/sme/inc/sme_api.h
  94. 33 5
      core/sme/src/common/sme_api.c
  95. 17 6
      core/sme/src/csr/csr_api_roam.c
  96. 49 2
      core/sme/src/csr/csr_util.c
  97. 4 0
      core/wma/inc/wma.h
  98. 4 2
      core/wma/inc/wma_types.h
  99. 1 1
      core/wma/src/wma_data.c
  100. 22 9
      core/wma/src/wma_dev_if.c

+ 9 - 2
Kbuild

@@ -1637,9 +1637,13 @@ MLME_OBJS += $(WFA_TGT_IF_DIR)/src/target_if_wfa_testcmd.o \
 ####### LL_SAP #######
 LL_SAP_DIR := components/umac/mlme/sap/ll_sap
 LL_SAP_OS_IF_DIR := os_if/mlme/sap/ll_sap
+LL_SAP_TARGET_IF_DIR := components/target_if/sap/ll_sap
+LL_SAP_WMI_DIR := components/wmi/
 
 LL_SAP_INC := -I$(WLAN_ROOT)/$(LL_SAP_DIR)/dispatcher/inc \
-		-I$(WLAN_ROOT)/$(LL_SAP_OS_IF_DIR)/inc
+		-I$(WLAN_ROOT)/$(LL_SAP_OS_IF_DIR)/inc \
+		-I$(WLAN_ROOT)/$(LL_SAP_TARGET_IF_DIR)/inc \
+		-I$(WLAN_ROOT)/$(LL_SAP_WMI_DIR)/inc
 
 MLME_INC += $(LL_SAP_INC)
 
@@ -1649,7 +1653,10 @@ MLME_OBJS += $(LL_SAP_DIR)/dispatcher/src/wlan_ll_sap_ucfg_api.o \
 		$(LL_SAP_DIR)/core/src/wlan_ll_sap_main.o \
 		$(LL_SAP_DIR)/core/src/wlan_ll_lt_sap_main.o \
 		$(LL_SAP_DIR)/core/src/wlan_ll_lt_sap_bearer_switch.o \
-		$(LL_SAP_OS_IF_DIR)/src/os_if_ll_sap.o
+		$(LL_SAP_OS_IF_DIR)/src/os_if_ll_sap.o \
+		$(LL_SAP_TARGET_IF_DIR)/src/target_if_ll_sap.o \
+		$(LL_SAP_WMI_DIR)/src/wmi_unified_ll_sap_api.o \
+		$(LL_SAP_WMI_DIR)/src/wmi_unified_ll_sap_tlv.o
 endif
 
 $(call add-wlan-objs,mlme,$(MLME_OBJS))

+ 13 - 1
components/cmn_services/interface_mgr/src/wlan_if_mgr_sap.c

@@ -32,6 +32,7 @@
 #include "wlan_p2p_ucfg_api.h"
 #include "wlan_vdev_mgr_utils_api.h"
 #include "wlan_tdls_tgt_api.h"
+#include "wlan_policy_mgr_ll_sap.h"
 
 QDF_STATUS if_mgr_ap_start_bss(struct wlan_objmgr_vdev *vdev,
 			       struct if_mgr_event_data *event_data)
@@ -112,7 +113,12 @@ if_mgr_ap_start_bss_complete(struct wlan_objmgr_vdev *vdev,
 		policy_mgr_check_sap_go_force_scc(psoc, vdev,
 						  CSA_REASON_GO_BSS_STARTED);
 	ifmgr_debug("check for SAP restart");
-	policy_mgr_check_concurrent_intf_and_restart_sap(psoc,
+
+	if (policy_mgr_is_vdev_ll_lt_sap(psoc, wlan_vdev_get_id(vdev)))
+		policy_mgr_ll_lt_sap_restart_concurrent_sap(psoc, true);
+	else
+		policy_mgr_check_concurrent_intf_and_restart_sap(
+				psoc,
 				wlan_util_vdev_mgr_get_acs_mode_for_vdev(vdev));
 	/*
 	 * Enable TDLS again on concurrent STA
@@ -161,11 +167,17 @@ if_mgr_ap_stop_bss_complete(struct wlan_objmgr_vdev *vdev,
 		if_mgr_enable_roaming(pdev, vdev, RSO_START_BSS);
 	}
 
+	ifmgr_debug("SAP/P2P-GO is stopped, re-enable roaming if it's stopped due to SAP/P2P-GO CSA");
+	if_mgr_enable_roaming(pdev, vdev, RSO_SAP_CHANNEL_CHANGE);
+
 	policy_mgr_get_mcc_scc_switch(psoc, &mcc_scc_switch);
 	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_GO_MODE &&
 	    mcc_scc_switch == QDF_MCC_TO_SCC_SWITCH_WITH_FAVORITE_CHANNEL)
 		policy_mgr_check_concurrent_intf_and_restart_sap(psoc, false);
 
+	if (policy_mgr_is_vdev_ll_lt_sap(psoc, wlan_vdev_get_id(vdev)))
+		policy_mgr_ll_lt_sap_restart_concurrent_sap(psoc, false);
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 9 - 4
components/cmn_services/logging/inc/wlan_connectivity_logging.h

@@ -367,6 +367,7 @@ struct wlan_diag_sta_info {
  * @vdev_id: vdev id associated with the link
  * @tid_ul: TID-to-link mapping information on the uplink
  * @tid_dl: TID-to-link mapping information on the downlink
+ * @status: MLO setup status. 0 - Success, 1 - failure
  * @link_addr: Link address of the link.
  */
 struct wlan_diag_mlo_cmn_info {
@@ -377,7 +378,7 @@ struct wlan_diag_mlo_cmn_info {
 	uint8_t tid_dl;
 	uint8_t status;
 	uint8_t link_addr[QDF_MAC_ADDR_SIZE];
-};
+} qdf_packed;
 
 #define DIAG_MLO_SETUP_VERSION 1
 #define DIAG_MLO_SETUP_VERSION_V2 2
@@ -1427,10 +1428,13 @@ static inline void wlan_connectivity_logging_stop(void)
  * wlan_connectivity_sta_info_event() - APi to send STA info event
  * @psoc: Pointer to global psoc object
  * @vdev_id: Vdev id
+ * @is_roam: Is sta info event for roaming stats
+ *
+ * Return: None
  */
 void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
-				 uint8_t vdev_id);
+				 uint8_t vdev_id, bool is_roam);
 
 /**
  * wlan_connectivity_connecting_event() - API to log connecting event
@@ -1535,10 +1539,11 @@ wlan_populate_vsie(struct wlan_objmgr_vdev *vdev,
  * wlan_connectivity_sta_info_event() - APi to send STA info event
  * @psoc: Pointer to global psoc object
  * @vdev_id: Vdev id
+ * @is_roam: Is sta info event for roaming stats
  */
 void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
-				 uint8_t vdev_id);
+				 uint8_t vdev_id, bool is_roam);
 
 /**
  * wlan_convert_freq_to_diag_band() - API to convert frequency to band value
@@ -1639,7 +1644,7 @@ wlan_connectivity_mlo_reconfig_event(struct wlan_objmgr_vdev *vdev)
 
 static inline void
 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc,
-				 uint8_t vdev_id)
+				 uint8_t vdev_id, bool is_roam)
 {}
 
 static inline void

+ 3 - 2
components/cmn_services/logging/src/wlan_connectivity_logging.c

@@ -847,7 +847,8 @@ wlan_cdp_set_peer_freq(struct wlan_objmgr_psoc *psoc, uint8_t *peer_mac,
 }
 
 void
-wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
+wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+				 bool is_roam)
 {
 	QDF_STATUS status;
 	struct wlan_objmgr_vdev *vdev = NULL;
@@ -867,7 +868,7 @@ wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id)
 	      wlan_vdev_mlme_is_mlo_link_vdev(vdev))))
 		goto out;
 
-	if (!wlan_cm_is_first_candidate_connect_attempt(vdev))
+	if (!is_roam && !wlan_cm_is_first_candidate_connect_attempt(vdev))
 		goto out;
 
 	wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us();

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

@@ -5712,4 +5712,15 @@ QDF_STATUS policy_mgr_get_pcl_ch_list_for_ll_sap(
 					struct connection_info *info,
 					uint8_t *connection_count);
 #endif
+
+/**
+ * policy_mgr_is_given_freq_5g_low() - API to check whether given freq
+ * is 5GHz low or not
+ * @psoc: psoc object
+ * @given_freq: given freq
+ *
+ * Return: True if it 5GHz low otherwise false
+ */
+bool policy_mgr_is_given_freq_5g_low(struct wlan_objmgr_psoc *psoc,
+				     qdf_freq_t given_freq);
 #endif /* __WLAN_POLICY_MGR_API_H */

+ 71 - 0
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_ll_sap.h

@@ -17,10 +17,39 @@
 /**
  * DOC: contains policy manager ll_sap definitions specific to the ll_sap module
  */
+#ifndef WLAN_POLICY_MGR_LL_SAP_H
+#define WLAN_POLICY_MGR_LL_SAP_H
 
 #include "wlan_objmgr_psoc_obj.h"
 
 #ifdef WLAN_FEATURE_LL_LT_SAP
+/**
+ * policy_mgr_ll_lt_sap_get_valid_freq() - Check and get valid frequency for
+ * the current interface (SAP/P2PGO/LL_LT_SAP)
+ * @psoc: PSOC object
+ * @pdev: PDEV pointer
+ * @vdev_id: Vdev id of the current interface
+ * @sap_ch_freq: Frequency of the current interface
+ * @cc_switch_mode: Channel switch mode
+ * @new_sap_freq: Updated frequency
+ * @is_ll_lt_sap_present: Indicates if ll_lt_sap is present or not
+ *
+ * This API checks if ll_lt_sap is present or not and if ll_lt_sap is present
+ * then if current frequency of the ll_lt_sap or concurrent SAP or concurrent
+ * P2PGO is valid or not according to ll_lt_sap concurrency, if valid, does not
+ * fill anything in the new_sap_freq and if not valid, update the new_sap_freq
+ * with some new valid frequency.
+ *
+ * Return: true/false
+ */
+void policy_mgr_ll_lt_sap_get_valid_freq(struct wlan_objmgr_psoc *psoc,
+					 struct wlan_objmgr_pdev *pdev,
+					 uint8_t vdev_id,
+					 qdf_freq_t sap_ch_freq,
+					 uint8_t cc_switch_mode,
+					 qdf_freq_t *new_sap_freq,
+					 bool *is_ll_lt_sap_present);
+
 /**
  * wlan_policy_mgr_get_ll_lt_sap_vdev_id() - Get ll_lt_sap vdev id
  * @psoc: PSOC object
@@ -46,6 +75,30 @@ bool __policy_mgr_is_ll_lt_sap_restart_required(struct wlan_objmgr_psoc *psoc,
 
 #define policy_mgr_is_ll_lt_sap_restart_required(psoc) \
 	__policy_mgr_is_ll_lt_sap_restart_required(psoc, __func__)
+
+/**
+ * policy_mgr_ll_lt_sap_restart_concurrent_sap() - Check and restart
+ * concurrent SAP or ll_lt_sap
+ * @psoc: PSOC object
+ * @is_ll_lt_sap_enabled: Indicates if ll_lt_sap is getting enabled or
+ * getting disabled
+ *
+ * This API checks and restarts concurrent SAP or ll_lt_sap when ll_lt_sap comes
+ * up or goes down.
+ * Concurrent SAP and ll_lt_sap should always be on different MAC.
+ * restart the concurrent SAP in below scenario:
+ * If ll_lt_sap is coming up and HW is not sbs capable and concurrent SAP is
+ * operating on 5 GHz, then move concurrent SAP to 2.4 Ghz MAC to allow
+ * ll_lt_sap on 5 GHz
+ * If ll_lt_sap is going down and if concurrent SAP is on 2.4 GHz then try to
+ * restart concurrent SAP on its original user configured frequency
+ * If ll_lt_sap interface has come up and in parallel if some other interface
+ * comes up on the ll_lt_sap frequency, then ll_lt_sap needs to be restarted.
+ *
+ * Return: None
+ */
+void policy_mgr_ll_lt_sap_restart_concurrent_sap(struct wlan_objmgr_psoc *psoc,
+						 bool is_ll_lt_sap_enabled);
 #else
 
 static inline bool
@@ -54,9 +107,27 @@ policy_mgr_is_ll_lt_sap_restart_required(struct wlan_objmgr_psoc *psoc)
 	return false;
 }
 
+static inline
+void policy_mgr_ll_lt_sap_get_valid_freq(struct wlan_objmgr_psoc *psoc,
+					 struct wlan_objmgr_pdev *pdev,
+					 uint8_t vdev_id,
+					 qdf_freq_t sap_ch_freq,
+					 uint8_t cc_switch_mode,
+					 qdf_freq_t *new_sap_freq,
+					 bool *is_ll_lt_sap_present)
+{
+}
+
 static inline
 uint8_t wlan_policy_mgr_get_ll_lt_sap_vdev_id(struct wlan_objmgr_psoc *psoc)
 {
 	return WLAN_INVALID_VDEV_ID;
 }
+
+static inline void
+policy_mgr_ll_lt_sap_restart_concurrent_sap(struct wlan_objmgr_psoc *psoc,
+					    bool is_ll_lt_sap_enabled)
+{
+}
 #endif
+#endif /* WLAN_POLICY_MGR_LL_SAP_H */

+ 3 - 1
components/cmn_services/policy_mgr/inc/wlan_policy_mgr_public_struct.h

@@ -96,6 +96,7 @@ typedef int (*send_mode_change_event_cb)(void);
  * @CSA_REASON_GO_BSS_STARTED: P2P go started
  * @CSA_REASON_SAP_ACS: 2.4 GHz preferred SAP ACS starting
  * @CSA_REASON_SAP_FIX_CH_CONC_WITH_GO: SAP fix channel start
+ * @CSA_REASON_CONCURRENT_LL_LT_SAP_EVENT: LL_LT_SAP concurrency
  *  and move GO to other band
  */
 enum sap_csa_reason_code {
@@ -114,7 +115,8 @@ enum sap_csa_reason_code {
 	CSA_REASON_CHAN_PASSIVE,
 	CSA_REASON_GO_BSS_STARTED,
 	CSA_REASON_SAP_ACS,
-	CSA_REASON_SAP_FIX_CH_CONC_WITH_GO
+	CSA_REASON_SAP_FIX_CH_CONC_WITH_GO,
+	CSA_REASON_CONCURRENT_LL_LT_SAP_EVENT
 };
 
 /*

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

@@ -1144,6 +1144,12 @@ policy_mgr_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
 	struct scan_cache_entry *entry;
 	bool eht_capab =  false, check_sap_bw_downgrade = false;
 	enum phy_ch_width cur_bw = CH_WIDTH_INVALID;
+	struct wlan_objmgr_vdev *vdev;
+
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_POLICY_MGR_ID);
+	if (!vdev)
+		goto end;
 
 	if (policy_mgr_is_hwmode_offload_enabled(psoc)) {
 		/*
@@ -1155,7 +1161,8 @@ policy_mgr_check_for_hw_mode_change(struct wlan_objmgr_psoc *psoc,
 		if (eht_capab &&
 		    QDF_IS_STATUS_SUCCESS(policy_mgr_get_sap_bw(psoc,
 								&cur_bw)) &&
-						cur_bw == CH_WIDTH_320MHZ)
+						cur_bw == CH_WIDTH_320MHZ &&
+		    !mlo_mgr_is_link_switch_in_progress(vdev))
 			check_sap_bw_downgrade = true;
 		else
 			goto end;
@@ -1214,6 +1221,9 @@ ch_width_update:
 	}
 
 end:
+	if (vdev)
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+
 	return ch_freq;
 }
 
@@ -1226,7 +1236,6 @@ policy_mgr_change_hw_mode_sta_connect(struct wlan_objmgr_psoc *psoc,
 	uint32_t ch_freq;
 
 	ch_freq = policy_mgr_check_for_hw_mode_change(psoc, scan_list, vdev_id);
-
 	if (!ch_freq)
 		return QDF_STATUS_E_ALREADY;
 

+ 23 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -5677,8 +5677,15 @@ static bool policy_mgr_is_concurrency_allowed_4_port(
 {
 	uint32_t i;
 	struct policy_mgr_psoc_priv_obj *pm_ctx = NULL;
-	uint8_t sap_cnt, go_cnt;
+	uint8_t sap_cnt, go_cnt, ll_lt_sap_vdev_id;
 
+	ll_lt_sap_vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
+
+	if (ll_lt_sap_vdev_id != WLAN_INVALID_VDEV_ID) {
+		policy_mgr_debug("LL_LT_SAP vdev %d present avoid 4th port concurrency",
+				 ll_lt_sap_vdev_id);
+		return false;
+	}
 	/* new STA may just have ssid, no channel until bssid assigned */
 	if (ch_freq == 0 && mode == PM_STA_MODE)
 		return true;
@@ -12684,3 +12691,18 @@ policy_mgr_get_connection_max_channel_width(struct wlan_objmgr_psoc *psoc)
 	return bw;
 }
 
+bool policy_mgr_is_given_freq_5g_low(struct wlan_objmgr_psoc *psoc,
+				     qdf_freq_t given_freq)
+{
+	qdf_freq_t sbs_cut_off_freq;
+
+	sbs_cut_off_freq = policy_mgr_get_sbs_cut_off_freq(psoc);
+	if (!sbs_cut_off_freq)
+		return false;
+
+	if (given_freq < sbs_cut_off_freq &&
+	    WLAN_REG_IS_5GHZ_CH_FREQ(given_freq))
+		return true;
+
+	return false;
+}

+ 234 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_ll_sap.c

@@ -23,6 +23,65 @@
 #include "wlan_policy_mgr_api.h"
 #include "wlan_policy_mgr_i.h"
 #include "wlan_cmn.h"
+#include "wlan_ll_sap_api.h"
+
+void policy_mgr_ll_lt_sap_get_valid_freq(struct wlan_objmgr_psoc *psoc,
+					 struct wlan_objmgr_pdev *pdev,
+					 uint8_t vdev_id,
+					 qdf_freq_t sap_ch_freq,
+					 uint8_t cc_switch_mode,
+					 qdf_freq_t *new_sap_freq,
+					 bool *is_ll_lt_sap_present)
+{
+	enum sap_csa_reason_code csa_reason;
+	enum policy_mgr_con_mode conn_mode;
+	qdf_freq_t ll_lt_sap_freq = 0;
+	*is_ll_lt_sap_present = false;
+
+	/* If Vdev is ll_lt_sap, check if the frequency on which it is
+	 * coming up is correct, else, get new frequency
+	 */
+	if (policy_mgr_is_vdev_ll_lt_sap(psoc, vdev_id)) {
+		*new_sap_freq = wlan_get_ll_lt_sap_restart_freq(pdev,
+								sap_ch_freq,
+								vdev_id,
+								&csa_reason);
+		*is_ll_lt_sap_present = true;
+	}
+
+	ll_lt_sap_freq = policy_mgr_get_ll_lt_sap_freq(psoc);
+	if (!ll_lt_sap_freq)
+		return;
+
+	conn_mode = policy_mgr_get_mode_by_vdev_id(psoc, vdev_id);
+
+	if (conn_mode == PM_SAP_MODE) {
+		/* If ll_lt_sap and concurrent SAP are on same MAC,
+		 * update the frequency of concurrent SAP, else return.
+		 */
+		if (!policy_mgr_are_2_freq_on_same_mac(psoc, sap_ch_freq,
+						       ll_lt_sap_freq))
+			return;
+		goto policy_mgr_check_scc;
+	} else if (conn_mode == PM_P2P_GO_MODE) {
+		/* If ll_lt_sap and P2P_GO are in SCC,
+		 * update the frequency of concurrent GO else, return.
+		 */
+		if (ll_lt_sap_freq != sap_ch_freq)
+			return;
+		goto policy_mgr_check_scc;
+	} else {
+		policy_mgr_debug("Invalid con mode %d vdev %d", conn_mode,
+				 vdev_id);
+		return;
+	}
+
+policy_mgr_check_scc:
+	policy_mgr_check_scc_channel(psoc, new_sap_freq, sap_ch_freq, vdev_id,
+				     cc_switch_mode);
+	policy_mgr_debug("vdev_id %d old_freq %d new_freq %d", vdev_id,
+			 sap_ch_freq, new_sap_freq);
+}
 
 uint8_t wlan_policy_mgr_get_ll_lt_sap_vdev_id(struct wlan_objmgr_psoc *psoc)
 {
@@ -91,3 +150,178 @@ bool __policy_mgr_is_ll_lt_sap_restart_required(struct wlan_objmgr_psoc *psoc,
 
 	return false;
 }
+
+/**
+ * policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap() - Get restart frequency
+ * for concurrent SAP which is in concurrency with LL_LT_SAP
+ * @pm_ctx: Policy manager context
+ * @vdev_id: Vdev id of the SAP for which restart freq is required
+ * @curr_freq: Current frequency of the SAP for which restart freq is required
+ * @ll_lt_sap_enabled: Indicates if ll_lt_sap is getting enabled or disabled
+ *
+ * This API returns user configured frequency if ll_lt_sap is going down and
+ * if ll_lt_sap is coming up it returns frequency according to ll_lt_sap
+ * concurrency.
+ *
+ * Return: Restart frequency
+ */
+static qdf_freq_t
+policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap(
+					struct policy_mgr_psoc_priv_obj *pm_ctx,
+					uint8_t vdev_id,
+					qdf_freq_t curr_freq,
+					bool ll_lt_sap_enabled)
+{
+	qdf_freq_t user_config_freq;
+	uint8_t i;
+	QDF_STATUS status;
+	uint32_t channel_list[NUM_CHANNELS];
+	uint32_t num_channels;
+	qdf_freq_t restart_freq = 0;
+
+	/*
+	 * If ll_lt_sap is getting disabled, return user configured frequency
+	 * for concurrent SAP restart, if user configured frequency is not valid
+	 * frequency, remain on the same frequency and do not restart the SAP
+	 */
+	if (!ll_lt_sap_enabled) {
+		user_config_freq = policy_mgr_get_user_config_sap_freq(
+								pm_ctx->psoc,
+								vdev_id);
+		if (wlan_reg_is_enable_in_secondary_list_for_freq(
+							pm_ctx->pdev,
+							user_config_freq) &&
+		    policy_mgr_is_safe_channel(pm_ctx->psoc, user_config_freq))
+			return user_config_freq;
+		return curr_freq;
+	}
+
+	status = policy_mgr_get_valid_chans(pm_ctx->psoc, channel_list,
+					    &num_channels);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		policy_mgr_err("Error in getting valid channels");
+		return curr_freq;
+	}
+
+	/* return first valid 2.4 GHz frequency */
+	for (i = 0; i < num_channels; i++) {
+		if (wlan_reg_is_24ghz_ch_freq(channel_list[i])) {
+			if (!restart_freq)
+				restart_freq = channel_list[i];
+			/* Prefer SCC frequency */
+			if (policy_mgr_get_connection_count_with_ch_freq(
+							channel_list[i])) {
+				restart_freq = channel_list[i];
+				break;
+			}
+		}
+	}
+	return restart_freq;
+}
+
+void policy_mgr_ll_lt_sap_restart_concurrent_sap(struct wlan_objmgr_psoc *psoc,
+						 bool is_ll_lt_sap_enabled)
+{
+	struct policy_mgr_psoc_priv_obj *pm_ctx;
+	struct policy_mgr_conc_connection_info sap_info = {0};
+	qdf_freq_t restart_freq;
+	struct ch_params ch_params = {0};
+	uint8_t i;
+	enum sap_csa_reason_code csa_reason;
+
+	pm_ctx = policy_mgr_get_context(psoc);
+	if (!pm_ctx) {
+		policy_mgr_err("Invalid pm context");
+		return;
+	}
+
+	qdf_mem_zero(&sap_info, sizeof(sap_info));
+
+	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)
+			continue;
+		if (PM_SAP_MODE == pm_conc_connection_list[i].mode ||
+		    PM_LL_LT_SAP_MODE == pm_conc_connection_list[i].mode) {
+			qdf_mem_copy(&sap_info, &pm_conc_connection_list[i],
+				     sizeof(sap_info));
+			break;
+		}
+	}
+	qdf_mutex_release(&pm_ctx->qdf_conc_list_lock);
+
+	/* No concurrent SAP or ll_lt_sap present, return */
+	if (!sap_info.in_use)
+		return;
+
+	if (sap_info.mode == PM_SAP_MODE) {
+		/*
+		 * For SBS case, no need to restart concurrent SAP as LL_LT_SAP
+		 * and concurrent SAP can be on different MACs
+		 */
+		if (policy_mgr_is_hw_sbs_capable(psoc))
+			return;
+
+		/*
+		 * If concurrent SAP is 2.4 GHz and ll_lt_sap is getting enabled
+		 * then there is no need to restart the concurrent SAP
+		 */
+		if (is_ll_lt_sap_enabled &&
+		    wlan_reg_is_24ghz_ch_freq(sap_info.freq))
+			return;
+
+		/*
+		 * If concurrent SAP is 5 GHz/6 GHz and ll_lt_sap is getting
+		 * disabled then there is no need to restart the concurrent SAP
+		 */
+		else if (!is_ll_lt_sap_enabled &&
+			 (wlan_reg_is_5ghz_ch_freq(sap_info.freq) ||
+			 wlan_reg_is_6ghz_chan_freq(sap_info.freq)))
+			return;
+
+		restart_freq =
+		policy_mgr_ll_lt_sap_get_restart_freq_for_concurent_sap(
+							pm_ctx,
+							sap_info.vdev_id,
+							sap_info.freq,
+							is_ll_lt_sap_enabled);
+		csa_reason = CSA_REASON_CONCURRENT_LL_LT_SAP_EVENT;
+	} else {
+		restart_freq = wlan_get_ll_lt_sap_restart_freq(pm_ctx->pdev,
+							       sap_info.freq,
+							       sap_info.vdev_id,
+							       &csa_reason);
+	}
+
+	if (pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress &&
+	    pm_ctx->hdd_cbacks.hdd_is_chan_switch_in_progress()) {
+		policy_mgr_debug("channel switch is already in progress");
+		return;
+	}
+
+	if (!restart_freq) {
+		policy_mgr_err("Restart freq not found for vdev %d",
+			       sap_info.vdev_id);
+		return;
+	}
+	if (restart_freq == sap_info.freq) {
+		policy_mgr_debug("vdev %d restart freq %d same as current freq",
+				 sap_info.vdev_id, restart_freq);
+		return;
+	}
+	ch_params.ch_width = policy_mgr_get_ch_width(sap_info.bw);
+	wlan_reg_set_channel_params_for_pwrmode(pm_ctx->pdev, restart_freq,
+						0, &ch_params,
+						REG_CURRENT_PWR_MODE);
+	policy_mgr_debug("Restart SAP vdev %d with %d freq width %d",
+			 sap_info.vdev_id, restart_freq, ch_params.ch_width);
+
+	if (pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason)
+		pm_ctx->hdd_cbacks.wlan_hdd_set_sap_csa_reason(psoc,
+							       sap_info.vdev_id,
+							       csa_reason);
+
+	policy_mgr_change_sap_channel_with_csa(psoc, sap_info.vdev_id,
+					       restart_freq,
+					       ch_params.ch_width, true);
+}

+ 0 - 1
components/cmn_services/policy_mgr/src/wlan_policy_mgr_pcl.c

@@ -546,7 +546,6 @@ policy_mgr_reg_chan_change_callback(struct wlan_objmgr_psoc *psoc,
 		return;
 	}
 
-	wlan_reg_decide_6g_ap_pwr_type(pdev);
 	policy_mgr_update_valid_ch_freq_list(pm_ctx, chan_list, false);
 
 	if (!avoid_freq_ind) {

+ 6 - 0
components/dp/core/inc/wlan_dp_wfds.h

@@ -24,6 +24,8 @@
 #include "wlan_qmi_public_struct.h"
 #include "wlan_qmi_wfds_api.h"
 
+#define DP_WFDS_CE_MAX_SRNG QMI_WFDS_CE_MAX_SRNG
+
 /**
  * enum dp_wfds_msg - WFDS message type
  * @DP_WFDS_REQ_MEM_IND_MSG: Memory request indication message
@@ -109,6 +111,8 @@ struct dp_direct_link_iommu_config {
  * @num_mem_arenas: Number of memory arenas requested by QMI server
  * @mem_arena_pages: Pointer to array of mem multi page structure for arenas
  * @ipcc_dma_addr: ipcc dma address
+ * @ipcc_ce_id: ids of CEs that are configured with IPCC MSI info
+ * @ipcc_ce_id_len: number of valid entries in ipcc_ce_id array
  * @iommu_cfg: direct link iommu configuration
  */
 struct dp_direct_link_wfds_context {
@@ -121,6 +125,8 @@ struct dp_direct_link_wfds_context {
 	uint32_t num_mem_arenas;
 	struct qdf_mem_multi_page_t *mem_arena_pages;
 	uint32_t ipcc_dma_addr;
+	uint8_t ipcc_ce_id[DP_WFDS_CE_MAX_SRNG];
+	uint8_t ipcc_ce_id_len;
 	struct dp_direct_link_iommu_config iommu_cfg;
 };
 

+ 12 - 2
components/dp/core/src/wlan_dp_wfds.c

@@ -540,11 +540,15 @@ dp_wfds_handle_ipcc_map_n_cfg_ind(struct wlan_qmi_wfds_ipcc_map_n_cfg_ind_msg *i
 	pld_smmu_map(qdf_ctx->dev, ipcc_msg->ipcc_ce_info[0].ipcc_trig_addr,
 		     &dl_wfds->ipcc_dma_addr, sizeof(uint32_t));
 
-	for (i = 0; i < ipcc_msg->ipcc_ce_info_len; i++)
+	dl_wfds->ipcc_ce_id_len = ipcc_msg->ipcc_ce_info_len;
+
+	for (i = 0; i < ipcc_msg->ipcc_ce_info_len; i++) {
+		dl_wfds->ipcc_ce_id[i] = ipcc_msg->ipcc_ce_info[i].ce_id;
 		hif_set_irq_config_by_ceid(hif_ctx,
 				      ipcc_msg->ipcc_ce_info[i].ce_id,
 				      dl_wfds->ipcc_dma_addr,
 				      ipcc_msg->ipcc_ce_info[i].ipcc_trig_data);
+	}
 
 	dp_wfds_event_post(dl_wfds, DP_WFDS_IPCC_MAP_N_CFG, NULL);
 }
@@ -586,9 +590,15 @@ void dp_wfds_del_server(void)
 		       DP_WFDS_SVC_DISCONNECTED);
 
 	if (dl_wfds_state >= DP_WFDS_SVC_IPCC_MAP_N_CFG_DONE &&
-	    dl_wfds->ipcc_dma_addr)
+	    dl_wfds->ipcc_dma_addr) {
+		for (i = 0; i < dl_wfds->ipcc_ce_id_len; i++)
+			hif_set_irq_config_by_ceid(hif_ctx,
+						   dl_wfds->ipcc_ce_id[i],
+						   0, 0);
+
 		pld_smmu_unmap(qdf_ctx->dev, dl_wfds->ipcc_dma_addr,
 			       sizeof(uint32_t));
+	}
 
 	if (dl_wfds_state >= DP_WFDS_SVC_MEM_CONFIG_DONE) {
 		uint64_t *dma_addr = NULL;

+ 3 - 0
components/mlme/core/inc/wlan_mlme_main.h

@@ -428,6 +428,8 @@ struct assoc_channel_info {
  * @ext_cap_ie: Ext CAP IE
  * @assoc_btm_cap: BSS transition management cap used in (re)assoc req
  * @assoc_chan_info: store channel info at the time of association
+ * @force_20mhz_in_24ghz: Only 20 MHz BW allowed in 2.4 GHz
+ *
  */
 struct mlme_connect_info {
 	uint8_t timing_meas_cap;
@@ -454,6 +456,7 @@ struct mlme_connect_info {
 	uint8_t ext_cap_ie[DOT11F_IE_EXTCAP_MAX_LEN + 2];
 	bool assoc_btm_cap;
 	struct assoc_channel_info assoc_chan_info;
+	bool force_20mhz_in_24ghz;
 };
 
 /** struct wait_for_key_timer - wait for key timer object

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

@@ -1969,6 +1969,8 @@ static void mlme_init_feature_flag_in_cfg(
 			cfg_get(psoc, CFG_CHANNEL_BONDING_MODE_24GHZ);
 	feature_flags->channel_bonding_mode_5ghz =
 			cfg_get(psoc, CFG_CHANNEL_BONDING_MODE_5GHZ);
+	feature_flags->update_cw_allowed =
+			cfg_get(psoc, CFG_ALLOW_UPDATE_CHANNEL_WIDTH);
 }
 
 static void mlme_init_sap_protection_cfg(struct wlan_objmgr_psoc *psoc,
@@ -3369,8 +3371,8 @@ mlme_init_wifi_pos_11az_config(struct wlan_objmgr_psoc *psoc,
 {
 	bool rsta_sec_ltf_enabled =
 			cfg_get(psoc, CFG_RESPONDER_SECURE_LTF_SUPPORT);
-	bool rsta_11az_ranging_enabled = cfg_get(psoc,
-						 CFG_RESPONDER_11AZ_SUPPORT);
+	uint32_t rsta_11az_ranging_enabled =
+				cfg_get(psoc, CFG_RESPONDER_11AZ_SUPPORT);
 
 	wifi_pos_set_rsta_11az_ranging_cap(rsta_11az_ranging_enabled);
 	wifi_pos_set_rsta_sec_ltf_cap(rsta_sec_ltf_enabled);

+ 26 - 1
components/mlme/dispatcher/inc/cfg_mlme_feature_flag.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2021 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
@@ -222,6 +223,29 @@
 	CFG_VALUE_OR_DEFAULT, \
 	"Configures Channel Bonding in 5 GHz")
 
+/*
+ * <ini>
+ * update_cw_allowed - process set channel width or not
+ * @Min: 0
+ * @Max: 1
+ * @Default: 1
+ *
+ * This ini is used to check whether driver allowed to process set channel
+ * width request from upper layer or not.
+ *
+ * Related: None
+ *
+ * Supported Feature: STA
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_ALLOW_UPDATE_CHANNEL_WIDTH CFG_INI_BOOL( \
+					"update_cw_allowed", \
+					1, \
+					"is update chan width allowed")
+
 #define CFG_FEATURE_FLAG_ALL \
 	CFG(CFG_ACCEPT_SHORT_SLOT_ASSOC_ONLY) \
 	CFG(CFG_HCF_ENABLED) \
@@ -235,7 +259,8 @@
 	CFG(CFG_BLOCK_ACK_ENABLED) \
 	CFG(CFG_ENABLE_AMPDUPS) \
 	CFG(CFG_CHANNEL_BONDING_MODE_24GHZ) \
-	CFG(CFG_CHANNEL_BONDING_MODE_5GHZ)
+	CFG(CFG_CHANNEL_BONDING_MODE_5GHZ) \
+	CFG(CFG_ALLOW_UPDATE_CHANNEL_WIDTH)
 
 #endif /* __CFG_MLME_FEATURE_FLAG_H */
 

+ 19 - 7
components/mlme/dispatcher/inc/cfg_mlme_wifi_pos.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2020 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
@@ -119,13 +119,22 @@
 /*
  * <ini>
  * enable_responder_11az_support - R-STA 11az ranging support
- * @Min: false
- * @Max: true
- * @Default: false
+ * @Min: 0
+ * @Max: 3
+ * @Default: 0
  *
- * This ini is used to enable R-STA advertising 11az ranging
+ * This ini is used to enable TB and NTB of R-STA advertising 11az ranging
  * capabilities.
  *
+ * +-----------+----------+-------+
+ * |  Value    |   TB     |  NTB  |
+ * +-----------+----------+-------+
+ * |   0x0     |    0     |   0   |
+ * |   0x1     |    0     |   1   |
+ * |   0x2     |    1     |   0   |
+ * |   0x3     |    1     |   1   |
+ * +-----------+----------+-------+
+ *
  * Related: None
  *
  * Supported Feature: WIFI POS
@@ -134,9 +143,12 @@
  *
  * </ini>
  */
-#define CFG_RESPONDER_11AZ_SUPPORT CFG_INI_BOOL( \
+#define CFG_RESPONDER_11AZ_SUPPORT CFG_INI_UINT( \
 		"enable_responder_11az_support", \
-		false, \
+		0, \
+		3, \
+		0, \
+		CFG_VALUE_OR_DEFAULT, \
 		"enable Responder 11az support")
 
 #define CFG_WIFI_POS_ALL \

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

@@ -4569,6 +4569,18 @@ QDF_STATUS
 wlan_mlme_get_tx_retry_multiplier(struct wlan_objmgr_psoc *psoc,
 				  uint32_t *tx_retry_multiplier);
 
+/**
+ * wlan_mlme_get_update_chan_width_allowed  - Get value of INI
+ * is_update_chan_width_allowed
+ * @psoc: pointer to psoc object
+ * @value: pointer to the value which will be filled for the caller
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_mlme_get_update_chan_width_allowed(struct wlan_objmgr_psoc *psoc,
+					bool *value);
+
 /**
  * wlan_mlme_get_channel_bonding_5ghz  - Get the channel bonding
  * val for 5ghz freq

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

@@ -1199,6 +1199,7 @@ struct wlan_mlme_rates {
  * @enable_block_ack: enable block ack feature
  * @channel_bonding_mode_24ghz: configures Channel Bonding in 24 GHz
  * @channel_bonding_mode_5ghz:  configures Channel Bonding in 5 GHz
+ * @update_cw_allowed: to check update chan width allowed or not
  */
 struct wlan_mlme_feature_flag {
 	bool accept_short_slot_assoc;
@@ -1214,6 +1215,7 @@ struct wlan_mlme_feature_flag {
 	uint32_t enable_block_ack;
 	uint32_t channel_bonding_mode_24ghz;
 	uint32_t channel_bonding_mode_5ghz;
+	bool update_cw_allowed;
 };
 
 /**

+ 13 - 0
components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h

@@ -4681,6 +4681,18 @@ QDF_STATUS ucfg_mlme_set_restricted_80p80_bw_supp(struct wlan_objmgr_psoc *psoc,
  */
 bool ucfg_mlme_get_restricted_80p80_bw_supp(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * ucfg_mlme_get_update_chan_width_allowed  - Get value of INI
+ * is_update_chan_width_allowed
+ * @psoc: pointer to psoc object
+ * @value: pointer to the value which will be filled for the caller
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+ucfg_mlme_get_update_chan_width_allowed(struct wlan_objmgr_psoc *psoc,
+					bool *value);
+
 /**
  * ucfg_mlme_get_channel_bonding_24ghz() - get channel bonding mode of 24ghz
  * @psoc:   pointer to psoc object
@@ -4702,6 +4714,7 @@ ucfg_mlme_get_channel_bonding_24ghz(struct wlan_objmgr_psoc *psoc,
 QDF_STATUS
 ucfg_mlme_set_channel_bonding_24ghz(struct wlan_objmgr_psoc *psoc,
 				    uint32_t value);
+
 /**
  * ucfg_mlme_get_channel_bonding_5ghz() - get channel bonding mode of 5ghz
  * @psoc:   pointer to psoc object

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

@@ -1490,6 +1490,7 @@ QDF_STATUS wlan_mlme_get_sta_ch_width(struct wlan_objmgr_vdev *vdev,
 		phymode = wlan_peer_get_phymode(peer);
 		wlan_peer_obj_unlock(peer);
 		*ch_width = wlan_mlme_get_ch_width_from_phymode(phymode);
+		status = QDF_STATUS_SUCCESS;
 	}
 
 	return  status;
@@ -6821,6 +6822,23 @@ wlan_mlme_get_tx_retry_multiplier(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS
+wlan_mlme_get_update_chan_width_allowed(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) {
+		*value = cfg_default(CFG_ALLOW_UPDATE_CHANNEL_WIDTH);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	*value = mlme_obj->cfg.feature_flags.update_cw_allowed;
+
+	return QDF_STATUS_SUCCESS;
+}
+
 QDF_STATUS
 wlan_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc,
 				   uint32_t *value)

+ 7 - 0
components/mlme/dispatcher/src/wlan_mlme_ucfg_api.c

@@ -1865,6 +1865,13 @@ ucfg_mlme_set_channel_bonding_24ghz(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+QDF_STATUS
+ucfg_mlme_get_update_chan_width_allowed(struct wlan_objmgr_psoc *psoc,
+					   bool *value)
+{
+	return wlan_mlme_get_update_chan_width_allowed(psoc, value);
+}
+
 QDF_STATUS
 ucfg_mlme_get_channel_bonding_5ghz(struct wlan_objmgr_psoc *psoc,
 				   uint32_t *value)

+ 2 - 0
components/nan/core/src/nan_main_i.h

@@ -103,6 +103,7 @@ enum nan_disc_state {
  *                      configuration in firmware. It's sent to firmware through
  *                      wmi_vdev_param_enable_disable_nan_config_features
  * @disable_6g_nan: Disable NAN in 6GHz frequency band
+ * @enable_nan_eht_cap: Enable(1)/Disable(0) NAN EHT capability
  */
 struct nan_cfg_params {
 	bool enable;
@@ -116,6 +117,7 @@ struct nan_cfg_params {
 	uint32_t max_ndi;
 	uint32_t nan_feature_config;
 	bool disable_6g_nan;
+	bool enable_nan_eht_cap;
 };
 
 /**

+ 25 - 2
components/nan/dispatcher/inc/cfg_nan.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -295,6 +295,28 @@
 					0, \
 					"Disable NAN Support in 6GHz")
 
+/*
+ * <ini>
+ * g_nan_enable_eht_cap- enable/disable NAN EHT CAP
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to enable/disable NAN EHT capability
+ *
+ * Related: None
+ *
+ * Supported Feature: NAN
+ *
+ * Usage: Internal/External
+ *
+ * </ini>
+ */
+#define CFG_NAN_ENABLE_EHT_CAP CFG_INI_BOOL("g_nan_enable_eht_cap", \
+					     0, \
+					     "Enable NAN EHT CAP")
+
+
 #ifdef WLAN_FEATURE_NAN
 #define CFG_NAN_DISC CFG(CFG_NAN_ENABLE) \
 			CFG(CFG_DISABLE_6G_NAN) \
@@ -313,6 +335,7 @@
 			CFG_NAN_DP \
 			CFG(CFG_NDP_MAX_SESSIONS) \
 			CFG(CFG_NDI_MAX_SUPPORT) \
-			CFG(CFG_NAN_FEATURE_CONFIG)
+			CFG(CFG_NAN_FEATURE_CONFIG) \
+			CFG(CFG_NAN_ENABLE_EHT_CAP)
 
 #endif

+ 16 - 1
components/nan/dispatcher/inc/cfg_nan_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2020 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
@@ -110,6 +110,15 @@ bool cfg_nan_get_support_mp0_discovery(struct wlan_objmgr_psoc *psoc);
  * Return: true on sta roam disable by nan else false
  */
 bool cfg_nan_is_roam_config_disabled(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * cfg_nan_is_eht_cap_enable() - Get NAN EHT capability
+ * @psoc: pointer to psoc object
+ *
+ * Return: Boolean flag indicating whether the NAN EHT capability is
+ * disabled or not
+ */
+bool cfg_nan_is_eht_cap_enable(struct wlan_objmgr_psoc *psoc);
 #else
 static inline
 bool cfg_nan_is_roam_config_disabled(struct wlan_objmgr_psoc *psoc)
@@ -165,6 +174,12 @@ static inline bool cfg_nan_get_support_mp0_discovery(
 	return false;
 }
 
+
+static inline bool cfg_nan_is_eht_cap_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
+
 #endif
 
 #endif

+ 16 - 0
components/nan/dispatcher/inc/wlan_nan_api_i.h

@@ -54,6 +54,16 @@ uint8_t wlan_nan_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev,
  * Return: True if Discovery is active
  */
 bool wlan_nan_is_disc_active(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_nan_is_eht_capable() - Get NAN EHT capability
+ * @psoc: pointer to psoc object
+ *
+ * Return: Boolean flag indicating whether the NAN EHT capability is
+ * disabled or not
+ */
+bool wlan_nan_is_eht_capable(struct wlan_objmgr_psoc *psoc);
+
 #else
 static inline
 enum nan_datapath_state wlan_nan_get_ndi_state(struct wlan_objmgr_vdev *vdev)
@@ -74,5 +84,11 @@ bool wlan_nan_is_disc_active(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
 }
+
+static inline bool
+wlan_nan_is_eht_capable(struct wlan_objmgr_psoc *psoc)
+{
+	return false;
+}
 #endif /*WLAN_FEATURE_NAN */
 #endif /*_WLAN_NAN_API_I_H_ */

+ 13 - 0
components/nan/dispatcher/src/cfg_nan.c

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 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
@@ -149,3 +150,15 @@ bool cfg_nan_is_roam_config_disabled(struct wlan_objmgr_psoc *psoc)
 
 	return false;
 }
+
+bool cfg_nan_is_eht_cap_enable(struct wlan_objmgr_psoc *psoc)
+{
+	struct nan_psoc_priv_obj *nan_obj = cfg_nan_get_priv_obj(psoc);
+
+	if (!nan_obj) {
+		nan_err("nan psoc priv object is NULL");
+		return cfg_default(CFG_NAN_ENABLE_EHT_CAP);
+	}
+
+	return nan_obj->cfg_param.enable_nan_eht_cap;
+}

+ 2 - 0
components/nan/dispatcher/src/nan_ucfg_api.c

@@ -65,6 +65,8 @@ static void nan_cfg_init(struct wlan_objmgr_psoc *psoc,
 	nan_obj->cfg_param.nan_feature_config =
 					cfg_get(psoc, CFG_NAN_FEATURE_CONFIG);
 	nan_obj->cfg_param.disable_6g_nan = cfg_get(psoc, CFG_DISABLE_6G_NAN);
+	nan_obj->cfg_param.enable_nan_eht_cap =
+					cfg_get(psoc, CFG_NAN_ENABLE_EHT_CAP);
 }
 
 /**

+ 6 - 0
components/nan/dispatcher/src/wlan_nan_api.c

@@ -23,6 +23,7 @@
 #include "../../core/src/nan_main_i.h"
 #include "wlan_objmgr_vdev_obj.h"
 #include "wlan_nan_api_i.h"
+#include "cfg_nan_api.h"
 
 inline enum nan_datapath_state wlan_nan_get_ndi_state(
 					struct wlan_objmgr_vdev *vdev)
@@ -53,3 +54,8 @@ bool wlan_nan_is_disc_active(struct wlan_objmgr_psoc *psoc)
 {
 	return nan_is_disc_active(psoc);
 }
+
+bool wlan_nan_is_eht_capable(struct wlan_objmgr_psoc *psoc)
+{
+	return cfg_nan_is_eht_cap_enable(psoc);
+}

+ 0 - 1
components/target_if/connection_mgr/src/target_if_cm_roam_event.c

@@ -228,7 +228,6 @@ target_if_cm_roam_sync_frame_event(ol_scn_t scn,
 	}
 
 	frame_ind_ptr = qdf_mem_malloc(sizeof(*frame_ind_ptr));
-
 	if (!frame_ind_ptr)
 		return -ENOMEM;
 

+ 55 - 0
components/target_if/sap/ll_sap/inc/target_if_ll_sap.h

@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+/**
+ * DOC: contains ll_lt_sap declarations specific to the bearer
+ * switch functionalities
+ */
+#include "wlan_ll_sap_public_structs.h"
+
+/**
+ * target_if_ll_sap_register_tx_ops() - register ll_lt_sap tx ops
+ * @tx_ops: pointer to ll_sap tx ops
+ *
+ * Return: None
+ */
+void target_if_ll_sap_register_tx_ops(struct wlan_ll_sap_tx_ops *tx_ops);
+
+/**
+ * target_if_ll_sap_register_rx_ops() - register ll_lt_sap rx ops
+ * @rx_ops: pointer to ll_sap rx ops
+ *
+ * Return: None
+ */
+void target_if_ll_sap_register_rx_ops(struct wlan_ll_sap_rx_ops *rx_ops);
+
+/**
+ * target_if_ll_sap_register_events() - register ll_lt_sap fw event handlers
+ * @psoc: pointer to psoc
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS target_if_ll_sap_register_events(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * target_if_ll_sap_deregister_events() - deregister ll_lt_sap fw event handlers
+ * @psoc: pointer to psoc
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+target_if_ll_sap_deregister_events(struct wlan_objmgr_psoc *psoc);
+

+ 149 - 0
components/target_if/sap/ll_sap/src/target_if_ll_sap.c

@@ -0,0 +1,149 @@
+/*
+ * 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 "target_if.h"
+#include "target_if_ll_sap.h"
+#include "wlan_ll_sap_public_structs.h"
+#include "wmi_unified_ll_sap_api.h"
+#include "../../umac/mlme/sap/ll_sap/core/src/wlan_ll_sap_main.h"
+#include "wlan_ll_sap_api.h"
+
+/**
+ * target_if_send_audio_transport_switch_resp() - Send audio transport switch
+ * response to fw
+ * @psoc: pointer to psoc
+ * @req_type: Bearer switch request type
+ * @status: Status of the bearer switch request
+ *
+ * Return: pointer to tx ops
+ */
+static QDF_STATUS target_if_send_audio_transport_switch_resp(
+					struct wlan_objmgr_psoc *psoc,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status)
+{
+	struct wmi_unified *wmi_handle;
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null.");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	return wmi_unified_audio_transport_switch_resp_send(wmi_handle,
+							    req_type, status);
+}
+
+static int target_if_send_audio_transport_switch_req_event_handler(
+							ol_scn_t scn,
+							uint8_t *event,
+							uint32_t len)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct ll_sap_psoc_priv_obj *psoc_ll_sap_obj;
+	enum bearer_switch_req_type req_type;
+	struct wmi_unified *wmi_handle;
+	struct wlan_ll_sap_rx_ops *rx_ops;
+	QDF_STATUS qdf_status;
+
+	psoc = target_if_get_psoc_from_scn_hdl(scn);
+	if (!psoc) {
+		target_if_err("psoc is null");
+		return -EINVAL;
+	}
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		target_if_err("wmi_handle is null");
+		return -EINVAL;
+	}
+
+	psoc_ll_sap_obj = wlan_objmgr_psoc_get_comp_private_obj(
+							psoc,
+							WLAN_UMAC_COMP_LL_SAP);
+
+	if (!psoc_ll_sap_obj) {
+		target_if_err("psoc_ll_sap_obj is null");
+		return -EINVAL;
+	}
+
+	rx_ops = &psoc_ll_sap_obj->rx_ops;
+	if (!rx_ops || !rx_ops->audio_transport_switch_req) {
+		target_if_err("Invalid ll_sap rx ops");
+		return -EINVAL;
+	}
+
+	qdf_status = wmi_extract_audio_transport_switch_req_event(wmi_handle,
+								  event, len,
+								  &req_type);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		target_if_err("parsing of event failed, %d", qdf_status);
+		return -EINVAL;
+	}
+	rx_ops->audio_transport_switch_req(psoc, req_type);
+
+	return 0;
+}
+
+void
+target_if_ll_sap_register_tx_ops(struct wlan_ll_sap_tx_ops *tx_ops)
+{
+	tx_ops->send_audio_transport_switch_resp =
+		target_if_send_audio_transport_switch_resp;
+}
+
+void
+target_if_ll_sap_register_rx_ops(struct wlan_ll_sap_rx_ops *rx_ops)
+{
+	rx_ops->audio_transport_switch_req =
+		wlan_ll_sap_fw_bearer_switch_req;
+}
+
+QDF_STATUS
+target_if_ll_sap_register_events(struct wlan_objmgr_psoc *psoc)
+{
+	QDF_STATUS ret;
+	wmi_unified_t handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+	if (!handle) {
+		target_if_err("handle is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	ret = wmi_unified_register_event_handler(
+			handle,
+			wmi_audio_transport_switch_type_event_id,
+			target_if_send_audio_transport_switch_req_event_handler,
+			WMI_RX_SERIALIZER_CTX);
+	return ret;
+}
+
+QDF_STATUS
+target_if_ll_sap_deregister_events(struct wlan_objmgr_psoc *psoc)
+{
+	QDF_STATUS ret;
+	wmi_unified_t handle = get_wmi_unified_hdl_from_psoc(psoc);
+
+	if (!handle) {
+		target_if_err("handle is NULL");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	ret = wmi_unified_unregister_event_handler(
+			handle,
+			wmi_audio_transport_switch_type_event_id);
+	return ret;
+}

+ 10 - 0
components/tdls/core/src/wlan_tdls_ct.c

@@ -213,6 +213,16 @@ static void tdls_reset_tx_rx(struct tdls_vdev_priv_obj *tdls_vdev)
 	qdf_list_node_t *p_node;
 	struct tdls_peer *peer;
 	QDF_STATUS status;
+	struct tdls_soc_priv_obj *tdls_soc;
+
+	tdls_soc = wlan_vdev_get_tdls_soc_obj(tdls_vdev->vdev);
+	if (!tdls_soc)
+		return;
+
+	/* reset stale connection tracker */
+	qdf_spin_lock_bh(&tdls_soc->tdls_ct_spinlock);
+	tdls_vdev->valid_mac_entries = 0;
+	qdf_spin_unlock_bh(&tdls_soc->tdls_ct_spinlock);
 
 	for (i = 0; i < WLAN_TDLS_PEER_LIST_SIZE; i++) {
 		head = &tdls_vdev->peer_list[i];

+ 34 - 22
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -6460,7 +6460,6 @@ void cm_roam_result_info_event(struct wlan_objmgr_psoc *psoc,
 {
 	uint8_t i;
 	struct qdf_mac_addr bssid = {0};
-	bool ap_found_in_roam_scan = false;
 	bool roam_abort = (res->fail_reason == ROAM_FAIL_REASON_SYNC ||
 			   res->fail_reason == ROAM_FAIL_REASON_DISCONNECT ||
 			   res->fail_reason == ROAM_FAIL_REASON_HOST ||
@@ -6479,30 +6478,33 @@ void cm_roam_result_info_event(struct wlan_objmgr_psoc *psoc,
 	populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id,
 			  (uint64_t)res->timestamp, NULL);
 
-	for (i = 0; i < scan_data->num_ap && scan_data->present; i++) {
-		if (i >= MAX_ROAM_CANDIDATE_AP)
-			break;
-
-		if (scan_data->ap[i].type == WLAN_ROAM_SCAN_ROAMED_AP ||
-		    scan_data->ap[i].type == WLAN_ROAM_SCAN_CANDIDATE_AP) {
-			ap_found_in_roam_scan = true;
-			break;
-		}
-	}
-
 	wlan_diag_event.version = DIAG_ROAM_RESULT_VERSION;
 	wlan_diag_event.roam_fail_reason = res->fail_reason;
 	/*
-	 * Print ROAM if:
-	 * 1. Roaming is successful to AP
-	 * 2. Atleast one candidate AP found during scan
+	 * Print ROAM if,
+	 * 1. FW sends res->status == 0 on successful roaming to AP
+	 * 2. FW sends res->status == 1 if FW triggered roaming but failed due
+	 *    to the reason other than below reasons
 	 *
-	 * Print NO_ROAM only if:
-	 * 1. No candidate AP found(even though other APs are found in scan)
+	 * Print NO_ROAM for below reasons where either candidate AP is not
+	 * found or we roamed to current AP itself irrespective of the
+	 * res->status value:
+	 * ROAM_FAIL_REASON_NO_AP_FOUND
+	 * ROAM_FAIL_REASON_NO_CAND_AP_FOUND
+	 * ROAM_FAIL_REASON_NO_AP_FOUND_AND_FINAL_BMISS_SENT
+	 * ROAM_FAIL_REASON_NO_CAND_AP_FOUND_AND_FINAL_BMISS_SENT
+	 * ROAM_FAIL_REASON_CURR_AP_STILL_OK
 	 */
-	wlan_diag_event.is_roam_successful = (res->status == 0) ||
-		(ap_found_in_roam_scan &&
-		 res->fail_reason != ROAM_FAIL_REASON_NO_CAND_AP_FOUND);
+	wlan_diag_event.is_roam_successful = true;
+
+	if (res->fail_reason == ROAM_FAIL_REASON_NO_AP_FOUND ||
+	    res->fail_reason == ROAM_FAIL_REASON_NO_CAND_AP_FOUND ||
+	    res->fail_reason == ROAM_FAIL_REASON_CURR_AP_STILL_OK ||
+	    res->fail_reason ==
+		ROAM_FAIL_REASON_NO_CAND_AP_FOUND_AND_FINAL_BMISS_SENT ||
+	    res->fail_reason ==
+		ROAM_FAIL_REASON_NO_AP_FOUND_AND_FINAL_BMISS_SENT)
+		wlan_diag_event.is_roam_successful = false;
 
 	for (i = 0; i < scan_data->num_ap; i++) {
 		if (i >= MAX_ROAM_CANDIDATE_AP)
@@ -7055,7 +7057,8 @@ wlan_convert_bitmap_to_band(uint8_t bitmap)
 QDF_STATUS
 cm_roam_mgmt_frame_event(struct wlan_objmgr_vdev *vdev,
 			 struct roam_frame_info *frame_data,
-			 struct wmi_roam_scan_data *scan_data)
+			 struct wmi_roam_scan_data *scan_data,
+			 struct wmi_roam_result *result)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	uint8_t i;
@@ -7135,9 +7138,18 @@ cm_roam_mgmt_frame_event(struct wlan_objmgr_vdev *vdev,
 
 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, diag_event);
 	if (wlan_diag_event.subtype == WLAN_CONN_DIAG_REASSOC_RESP_EVENT ||
-	    wlan_diag_event.subtype == WLAN_CONN_DIAG_ASSOC_RESP_EVENT)
+	    wlan_diag_event.subtype == WLAN_CONN_DIAG_ASSOC_RESP_EVENT) {
 		wlan_connectivity_mlo_setup_event(vdev);
 
+		/*
+		 * Send STA info event when roaming is successful
+		 */
+		if (result->present && !result->status)
+			wlan_connectivity_sta_info_event(wlan_vdev_get_psoc(vdev),
+							 wlan_vdev_get_id(vdev),
+							 true);
+	}
+
 	return status;
 }
 

+ 5 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h

@@ -591,13 +591,15 @@ cm_handle_mlo_rso_state_change(struct wlan_objmgr_pdev *pdev, uint8_t *vdev_id,
  * @vdev: vdev pointer
  * @frame_data: frame_data
  * @scan_data: Roam scan data
+ * @result: Roam result
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS
 cm_roam_mgmt_frame_event(struct wlan_objmgr_vdev *vdev,
 			 struct roam_frame_info *frame_data,
-			 struct wmi_roam_scan_data *scan_data);
+			 struct wmi_roam_scan_data *scan_data,
+			 struct wmi_roam_result *result);
 
 /**
  * cm_roam_btm_req_event  - Send BTM request related logging event
@@ -675,7 +677,8 @@ cm_roam_neigh_rpt_resp_event(struct wmi_neighbor_report_data *neigh_rpt,
 static inline QDF_STATUS
 cm_roam_mgmt_frame_event(struct wlan_objmgr_vdev *vdev,
 			 struct roam_frame_info *frame_data,
-			 struct wmi_roam_scan_data *scan_data)
+			 struct wmi_roam_scan_data *scan_data,
+			 struct wmi_roam_result *result)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }

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

@@ -473,6 +473,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 	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.rssi = sync_frame_ind->rssi;
 		roam_candidate.roam_offload_candidate_frm = false;
 		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
 							  &roam_candidate);
@@ -482,6 +483,7 @@ cm_roam_sync_frame_event_handler(struct wlan_objmgr_psoc *psoc,
 		roam_candidate.frame_length =
 					sync_frame_ind->link_bcn_probe_rsp_len;
 		roam_candidate.frame = sync_frame_ind->link_bcn_probe_rsp;
+		roam_candidate.rssi = sync_frame_ind->rssi;
 		roam_candidate.roam_offload_candidate_frm = false;
 		wlan_cm_add_all_link_probe_rsp_to_scan_db(psoc,
 							  &roam_candidate);

+ 20 - 11
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h

@@ -41,13 +41,13 @@
  * struct cm_vdev_join_req - connect req from legacy CM to vdev manager
  * @vdev_id: vdev id
  * @cm_id: Connect manager id
- * @force_24ghz_in_ht20: force 24ghz_in ht20
  * @force_rsne_override: force the arbitrary rsne received in connect req to be
  * used with out validation, used for the scenarios where the device is used
  * as a testbed device with special functionality and not recommended
  * for production.
  * @is_wps_connection: is wps connection
- * @is_osen_connection: is osen connectgion
+ * @is_osen_connection: is osen connection
+ * @is_ssid_hidden: AP SSID is hidden
  * @assoc_ie: assoc ie to be used in assoc req
  * @scan_ie: Default scan ie to be used in the uncast probe req
  * @entry: scan entry for the candidate
@@ -58,10 +58,10 @@
 struct cm_vdev_join_req {
 	uint8_t vdev_id;
 	wlan_cm_id cm_id;
-	uint8_t force_24ghz_in_ht20:1,
-		force_rsne_override:1,
+	uint8_t force_rsne_override:1,
 		is_wps_connection:1,
-		is_osen_connection:1;
+		is_osen_connection:1,
+		is_ssid_hidden:1;
 	struct element_info assoc_ie;
 	struct element_info scan_ie;
 	struct scan_cache_entry *entry;
@@ -300,6 +300,15 @@ QDF_STATUS cm_get_rssi_snr_by_bssid(struct wlan_objmgr_pdev *pdev,
  */
 void cm_csr_send_set_ie(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * cm_csr_get_vdev_dot11_mode() - Wrapper for CM to get the dot11mode for
+ * the vdev id
+ * @vdev_id: vdev id
+ *
+ * Return: dot11 mode
+ */
+uint16_t cm_csr_get_vdev_dot11_mode(uint8_t vdev_id);
+
 static inline QDF_STATUS
 cm_ext_hdl_create(struct wlan_objmgr_vdev *vdev, cm_ext_t **ext_cm_ptr)
 {
@@ -355,8 +364,8 @@ QDF_STATUS cm_csr_handle_join_req(struct wlan_objmgr_vdev *vdev,
 				  bool reassoc);
 
 /**
- * cm_handle_connect_req() - Connection manager ext connect request to start
- * vdev and peer assoc state machine
+ * cm_handle_connect_req() - Connection manager ext connect request to
+ * start vdev and peer assoc state machine
  * @vdev: VDEV object
  * @req: Vdev connect request
  *
@@ -364,7 +373,7 @@ QDF_STATUS cm_csr_handle_join_req(struct wlan_objmgr_vdev *vdev,
  */
 QDF_STATUS
 cm_handle_connect_req(struct wlan_objmgr_vdev *vdev,
-		      struct wlan_cm_vdev_connect_req *req);
+			    struct wlan_cm_vdev_connect_req *req);
 
 /**
  * cm_send_bss_peer_create_req() - Connection manager ext bss peer create
@@ -505,7 +514,7 @@ cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev,
 			   struct wlan_cm_discon_rsp *rsp);
 
 /**
- * cm_csr_diconnect_done_ind() - Connection manager call to csr to update
+ * cm_csr_disconnect_done_ind() - Connection manager call to csr to update
  * legacy structures on disconnect complete
  * @vdev: VDEV object
  * @rsp: Connection manager disconnect response
@@ -517,8 +526,8 @@ cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev,
  * Return: QDF_STATUS
  */
 QDF_STATUS
-cm_csr_diconnect_done_ind(struct wlan_objmgr_vdev *vdev,
-			  struct wlan_cm_discon_rsp *rsp);
+cm_csr_disconnect_done_ind(struct wlan_objmgr_vdev *vdev,
+			   struct wlan_cm_discon_rsp *rsp);
 
 /**
  * cm_send_vdev_down_req() - Connection manager ext req to send vdev down

+ 27 - 6
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1325,6 +1325,7 @@ cm_copy_join_params(struct wlan_objmgr_vdev *vdev,
 	join_req->force_rsne_override = req->force_rsne_override;
 	join_req->is_wps_connection = req->is_wps_connection;
 	join_req->is_osen_connection = req->is_osen_connection;
+	join_req->is_ssid_hidden = req->bss->entry->is_hidden_ssid;
 
 	return QDF_STATUS_SUCCESS;
 }
@@ -1422,7 +1423,7 @@ cm_update_hlp_data_from_assoc_ie(struct wlan_objmgr_vdev *vdev,
 
 QDF_STATUS
 cm_handle_connect_req(struct wlan_objmgr_vdev *vdev,
-		      struct wlan_cm_vdev_connect_req *req)
+			    struct wlan_cm_vdev_connect_req *req)
 {
 	struct cm_vdev_join_req *join_req;
 	struct scheduler_msg msg;
@@ -1473,9 +1474,6 @@ cm_handle_connect_req(struct wlan_objmgr_vdev *vdev,
 			   req->bss->entry->bssid.bytes,
 			   req->bss->entry->neg_sec_info.key_mgmt,
 			   req->bss->entry->channel.chan_freq);
-	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g &&
-	    !(req->ht_caps & WLAN_HTCAP_C_CHWIDTH40))
-		join_req->force_24ghz_in_ht20 = true;
 
 	msg.bodyptr = join_req;
 	msg.type = CM_CONNECT_REQ;
@@ -1669,11 +1667,11 @@ static void
 cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 {
 	struct wlan_crypto_key *crypto_key;
+	struct wlan_crypto_params *crypto_params;
 	enum QDF_OPMODE op_mode;
 	uint16_t i;
 	bool pairwise;
-	uint8_t vdev_id;
-	uint8_t link_id;
+	uint8_t vdev_id, link_id;
 	bool key_present = false;
 	uint16_t max_key_index = WLAN_CRYPTO_MAXKEYIDX +
 				 WLAN_CRYPTO_MAXIGTKKEYIDX +
@@ -1688,6 +1686,16 @@ cm_install_link_vdev_keys(struct wlan_objmgr_vdev *vdev)
 	    !wlan_vdev_mlme_is_mlo_link_vdev(vdev))
 		return;
 
+	crypto_params = wlan_crypto_vdev_get_crypto_params(vdev);
+	if (!crypto_params) {
+		mlme_err("crypto params is null");
+		return;
+	}
+
+	if (!crypto_params->ucastcipherset ||
+	    QDF_HAS_PARAM(crypto_params->ucastcipherset, WLAN_CRYPTO_CIPHER_NONE))
+		return;
+
 	link_id = wlan_vdev_get_link_id(vdev);
 
 	if (!mlo_is_set_key_defered(vdev, link_id) &&
@@ -1724,6 +1732,8 @@ cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev,
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	enum QDF_OPMODE op_mode;
+	bool eht_capab = false;
+	QDF_STATUS status;
 
 	if (!vdev || !rsp) {
 		mlme_err("vdev or rsp is NULL");
@@ -1775,6 +1785,17 @@ cm_connect_complete_ind(struct wlan_objmgr_vdev *vdev,
 		wlan_p2p_status_connect(vdev);
 		cm_update_tid_mapping(vdev);
 		cm_update_associated_ch_info(vdev, true);
+
+		wlan_psoc_mlme_get_11be_capab(psoc, &eht_capab);
+		if (eht_capab) {
+			status = policy_mgr_current_connections_update(
+					psoc, vdev_id,
+					rsp->freq,
+					POLICY_MGR_UPDATE_REASON_STA_CONNECT,
+					POLICY_MGR_DEF_REQ_ID);
+			if (status == QDF_STATUS_E_FAILURE)
+				mlme_debug("Failed to take next action after connect");
+		}
 	}
 
 	mlo_roam_connect_complete(vdev);

+ 1 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_disconnect.c

@@ -241,7 +241,7 @@ cm_disconnect_complete_ind(struct wlan_objmgr_vdev *vdev,
 		mlme_err("vdev or rsp is NULL");
 		return QDF_STATUS_E_INVAL;
 	}
-	cm_csr_diconnect_done_ind(vdev, rsp);
+	cm_csr_disconnect_done_ind(vdev, rsp);
 
 	vdev_id = wlan_vdev_get_id(vdev);
 	op_mode = wlan_vdev_mlme_get_opmode(vdev);

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

@@ -2080,6 +2080,40 @@ wlan_cm_get_assoc_btm_cap(struct wlan_objmgr_vdev *vdev);
  */
 bool wlan_cm_is_self_mld_roam_supported(struct wlan_objmgr_psoc *psoc);
 
+/**
+ * wlan_cm_set_force_20mhz_in_24ghz() - Sets the config to (dis)allow
+ * the 40 MHz connection in 2.4 GHz
+ *
+ * @vdev: pointer to vdev
+ * @is_40mhz_cap: is 40 MHz supported
+ *
+ * Return: None
+ */
+void
+wlan_cm_set_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev,
+				 bool is_40mhz_cap);
+
+/**
+ * wlan_cm_get_force_20mhz_in_24ghz - Gets the 40 MHz (dis)allowed on 2.4 GHz
+ * config
+ * @vdev: pointer to vdev
+ *
+ * Return: 40 MHz allowed on 2.4 GHz
+ */
+bool
+wlan_cm_get_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * cm_send_ies_for_roam_invoke - Send IEs to firmware based on the reassoc
+ * req received from the userspace
+ * @vdev: vdev
+ * @dot11_mode: dot11 mode
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_send_ies_for_roam_invoke(struct wlan_objmgr_vdev *vdev, uint16_t dot11_mode);
+
 #ifdef WLAN_FEATURE_11BE_MLO
 /**
  * wlan_cm_is_sae_auth_addr_conversion_required() - check whether address

+ 22 - 3
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_public_struct.h

@@ -384,7 +384,8 @@ enum roam_fail_params {
  * @ROAM_FAIL_REASON_AUTH_RECV: Authentication response received with
  * error status code
  * @ROAM_FAIL_REASON_REASSOC_SEND: Reassoc request TX failed
- * @ROAM_FAIL_REASON_REASSOC_RECV: Reassoc response frame not received
+ * @ROAM_FAIL_REASON_REASSOC_RECV: Reassoc response frame received with failure
+ * status
  * @ROAM_FAIL_REASON_NO_REASSOC_RESP: No reassociation response received
  * @ROAM_FAIL_REASON_EAPOL_TIMEOUT: EAPoL timedout
  * @ROAM_FAIL_REASON_MLME: MLME internal error
@@ -430,8 +431,8 @@ enum wlan_roam_failure_reason_code {
 	/* Failure reasons after roam scan is complete */
 	ROAM_FAIL_REASON_HOST,
 	ROAM_FAIL_REASON_AUTH_SEND,
-	ROAM_FAIL_REASON_NO_AUTH_RESP,
 	ROAM_FAIL_REASON_AUTH_RECV,
+	ROAM_FAIL_REASON_NO_AUTH_RESP,
 	ROAM_FAIL_REASON_REASSOC_SEND,
 	ROAM_FAIL_REASON_REASSOC_RECV,
 	ROAM_FAIL_REASON_NO_REASSOC_RESP,
@@ -477,6 +478,23 @@ struct reassoc_timer_ctx {
 };
 #endif
 
+/**
+ * struct roam_synch_frame_ind  - Structure to hold the information on frames
+ * received during roam synch frame indication.
+ * @bcn_probe_rsp_len: Length of the beacon/probe response frame
+ * @bcn_probe_rsp: Beacon probe response frame pointer
+ * @is_beacon: Flag to indicate if received frame is beacon or probe response
+ * @link_bcn_probe_rsp_len: Length of the link beacon/probe response frame
+ * @link_bcn_probe_rsp: Link beacon probe response frame pointer
+ * @is_link_beacon: Flag to indicate if received frame is link beacon or probe
+ * response
+ * @reassoc_req_len: Reassoc request frame length
+ * @reassoc_req: Reassoc request frame pointer
+ * @reassoc_rsp_len: Reassoc response frame length
+ * @reassoc_rsp: Reassoc response frame pointer
+ * @vdev_id: Vdev id
+ * @rssi: RSSI of the frame
+ */
 struct roam_synch_frame_ind {
 	uint32_t bcn_probe_rsp_len;
 	uint8_t *bcn_probe_rsp;
@@ -489,6 +507,7 @@ struct roam_synch_frame_ind {
 	uint32_t reassoc_rsp_len;
 	uint8_t *reassoc_rsp;
 	uint8_t vdev_id;
+	int8_t rssi;
 };
 
 /**
@@ -2851,7 +2870,7 @@ struct roam_offload_synch_ind {
 	struct wlan_ssid ssid;
 	int8_t tx_mgmt_power;
 	uint32_t auth_status;
-	uint8_t rssi;
+	int8_t rssi;
 	uint8_t roam_reason;
 	uint32_t chan_freq;
 	uint8_t kck[MAX_KCK_LEN];

+ 63 - 4
components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c

@@ -3434,7 +3434,8 @@ static void
 cm_roam_print_frame_info(struct wlan_objmgr_psoc *psoc,
 			 struct wlan_objmgr_vdev *vdev,
 			 struct roam_frame_stats *frame_data,
-			 struct wmi_roam_scan_data *scan_data)
+			 struct wmi_roam_scan_data *scan_data,
+			 struct wmi_roam_result *result)
 {
 	struct roam_frame_info *frame_info;
 	char time[TIME_STRING_LEN];
@@ -3478,7 +3479,7 @@ cm_roam_print_frame_info(struct wlan_objmgr_psoc *psoc,
 				       frame_info->status_code,
 				       frame_info->seq_num);
 
-		cm_roam_mgmt_frame_event(vdev, frame_info, scan_data);
+		cm_roam_mgmt_frame_event(vdev, frame_info, scan_data, result);
 	}
 }
 
@@ -3620,7 +3621,8 @@ cm_roam_handle_btm_stats(struct wlan_objmgr_psoc *psoc,
 	if (stats_info->frame_stats[i].num_frame)
 		cm_roam_print_frame_info(psoc, vdev,
 					 &stats_info->frame_stats[i],
-					 &stats_info->scan[i]);
+					 &stats_info->scan[i],
+					 &stats_info->result[i]);
 
 log_btm_frames_only:
 
@@ -4387,7 +4389,8 @@ cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc,
 			cm_roam_print_frame_info(psoc,
 						 vdev,
 						 &stats_info->frame_stats[i],
-						 &stats_info->scan[i]);
+						 &stats_info->scan[i],
+						 &stats_info->result[i]);
 
 		wlan_cm_update_roam_stats_info(psoc, stats_info, i);
 
@@ -4931,6 +4934,62 @@ bool wlan_cm_is_self_mld_roam_supported(struct wlan_objmgr_psoc *psoc)
 				   wmi_service_self_mld_roam_between_dbs_and_hbs);
 }
 
+void
+wlan_cm_set_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev,
+				 bool is_40mhz_cap)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+	struct mlme_legacy_priv *mlme_priv;
+	uint16_t dot11_mode;
+	bool send_ie_to_fw = false;
+
+	if (!vdev)
+		return;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc)
+		return;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj || !mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g)
+		return;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv)
+		return;
+
+	/*
+	 * Force 20 MHz in 2.4 GHz only if "override_ht20_40_24g" ini
+	 * is set and userspace connect req doesn't have 40 MHz HT caps
+	 */
+	if (mlme_priv->connect_info.force_20mhz_in_24ghz != !is_40mhz_cap)
+		send_ie_to_fw = true;
+
+	mlme_priv->connect_info.force_20mhz_in_24ghz = !is_40mhz_cap;
+
+	if (cm_is_vdev_connected(vdev) && send_ie_to_fw) {
+		dot11_mode =
+			cm_csr_get_vdev_dot11_mode(wlan_vdev_get_id(vdev));
+		cm_send_ies_for_roam_invoke(vdev, dot11_mode);
+	}
+}
+
+bool
+wlan_cm_get_force_20mhz_in_24ghz(struct wlan_objmgr_vdev *vdev)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	if (!vdev)
+		return true;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv)
+		return true;
+
+	return mlme_priv->connect_info.force_20mhz_in_24ghz;
+}
+
 #ifdef WLAN_FEATURE_ROAM_OFFLOAD
 QDF_STATUS
 wlan_cm_update_offload_ssid_from_candidate(struct wlan_objmgr_pdev *pdev,

+ 36 - 13
components/umac/mlme/mlo_mgr/src/wlan_mlo_mgr_roam.c

@@ -302,32 +302,55 @@ QDF_STATUS mlo_fw_roam_sync_req(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
 }
 
 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE
+static struct mlo_link_info *
+mlo_mgr_get_link_info_by_self_addr(struct wlan_objmgr_vdev *vdev,
+				   struct qdf_mac_addr *self_addr)
+{
+	uint8_t iter;
+	struct mlo_link_info *mlo_link;
+
+	if (!vdev || !vdev->mlo_dev_ctx || !vdev->mlo_dev_ctx->link_ctx ||
+	    !self_addr || qdf_is_macaddr_zero(self_addr))
+		return NULL;
+
+	for (iter = 0; iter < WLAN_MAX_ML_BSS_LINKS; iter++) {
+		mlo_link = &vdev->mlo_dev_ctx->link_ctx->links_info[iter];
+
+		if (qdf_is_macaddr_equal(&mlo_link->link_addr, self_addr))
+			return mlo_link;
+	}
+
+	return NULL;
+}
+
 void mlo_mgr_roam_update_ap_link_info(struct wlan_objmgr_vdev *vdev,
 				      struct ml_setup_link_param *src_link_info,
 				      struct wlan_channel *channel)
 {
 	struct mlo_link_info *link_info;
-	uint8_t iter;
 
-	if (!vdev || !vdev->mlo_dev_ctx || !vdev->mlo_dev_ctx->link_ctx ||
-	    !src_link_info)
+	if (!src_link_info)
 		return;
 
-	for (iter = 0; iter < WLAN_MAX_ML_BSS_LINKS; iter++) {
-		link_info = &vdev->mlo_dev_ctx->link_ctx->links_info[iter];
-		if (qdf_is_macaddr_zero(&link_info->ap_link_addr))
-			break;
+	link_info = mlo_mgr_get_link_info_by_self_addr(vdev,
+						       &src_link_info->self_link_addr);
+	if (!link_info) {
+		mlo_err("No link info found for vdev %d with " QDF_MAC_ADDR_FMT,
+			src_link_info->vdev_id,
+			QDF_MAC_ADDR_REF(src_link_info->self_link_addr.bytes));
+		QDF_BUG(0);
+		return;
 	}
 
-	if (iter == WLAN_MAX_ML_BSS_LINKS)
+	if (link_info->vdev_id != src_link_info->vdev_id) {
+		mlo_err("Host(%d)-FW(%d) VDEV-MAC addr mismatch",
+			link_info->vdev_id, src_link_info->vdev_id);
+		QDF_BUG(0);
 		return;
+	}
 
 	link_info->link_id = src_link_info->link_id;
-	link_info->vdev_id = src_link_info->vdev_id;
-	qdf_mem_copy(&link_info->ap_link_addr, src_link_info->link_addr.bytes,
-		     QDF_MAC_ADDR_SIZE);
-	qdf_mem_copy(&link_info->link_addr, src_link_info->self_link_addr.bytes,
-		     QDF_MAC_ADDR_SIZE);
+	qdf_copy_macaddr(&link_info->ap_link_addr, &src_link_info->link_addr);
 	qdf_mem_copy(link_info->link_chan_info, channel, sizeof(*channel));
 
 	mlo_debug("link_id: %d, vdev_id:%d freq:%d ap_link_addr: "QDF_MAC_ADDR_FMT", self_link_addr: "QDF_MAC_ADDR_FMT,

+ 68 - 9
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_bearer_switch.c

@@ -81,6 +81,46 @@ bool __ll_lt_sap_is_bs_req_valid(struct wlan_bearer_switch_request *bs_req,
 	return true;
 }
 
+/**
+ * ll_lt_sap_deliver_audio_transport_switch_resp_to_fw() - Deliver audio
+ * transport switch response to FW
+ * @vdev: Vdev on which the request is received
+ * @req_type: Transport switch type for which the response is received
+ * @status: Status of the response
+ *
+ * Return: None
+ */
+static void
+ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(
+					struct wlan_objmgr_vdev *vdev,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status)
+{
+	struct wlan_objmgr_psoc *psoc;
+	struct ll_sap_psoc_priv_obj *psoc_ll_sap_obj;
+	struct wlan_ll_sap_tx_ops *tx_ops;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+
+	psoc_ll_sap_obj = wlan_objmgr_psoc_get_comp_private_obj(
+						psoc,
+						WLAN_UMAC_COMP_LL_SAP);
+
+	if (!psoc_ll_sap_obj) {
+		ll_sap_err("psoc_ll_sap_obj is null");
+		return;
+	}
+
+	tx_ops = &psoc_ll_sap_obj->tx_ops;
+
+	if (!tx_ops->send_audio_transport_switch_resp) {
+		ll_sap_err("deliver_audio_transport_switch_resp op is NULL");
+		return;
+	}
+
+	tx_ops->send_audio_transport_switch_resp(psoc, req_type, status);
+}
+
 /**
  * bs_req_timeout_cb() - Callback which will be invoked on bearer switch req
  * timeout
@@ -245,7 +285,11 @@ ll_lt_sap_bs_increament_ref_count(struct bearer_switch_info *bs_ctx,
 	uint32_t total_ref_count;
 
 	total_ref_count = qdf_atomic_inc_return(&bs_ctx->total_ref_count);
-	ref_count = qdf_atomic_inc_return(&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
+	if (bs_req->source == BEARER_SWITCH_REQ_FW)
+		ref_count = qdf_atomic_inc_return(&bs_ctx->fw_ref_count);
+	else
+		ref_count = qdf_atomic_inc_return(
+			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
 
 	ll_sap_nofl_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count %d Total ref count %d",
 			  BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
@@ -276,16 +320,27 @@ ll_lt_sap_bs_decreament_ref_count(struct bearer_switch_info *bs_ctx,
 	 * module did not requested for wlan to non wlan transition earlier, so
 	 * reject this operation.
 	 */
-	if (!qdf_atomic_read(&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source])) {
+	if (bs_req->source == BEARER_SWITCH_REQ_FW) {
+		if (!qdf_atomic_read(&bs_ctx->fw_ref_count)) {
+			ll_sap_debug(BS_PREFIX_FMT "ref_count is zero for FW",
+				     BS_PREFIX_REF(
+						wlan_vdev_get_id(bs_ctx->vdev),
+						bs_req->request_id));
+			return QDF_STATUS_E_INVAL;
+		}
+		ref_count = qdf_atomic_dec_return(&bs_ctx->fw_ref_count);
+	} else if (!qdf_atomic_read(
+			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source])) {
 		ll_sap_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count is zero",
 			     BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
 					   bs_req->request_id),
 			     bs_req->vdev_id, bs_req->source);
 		return QDF_STATUS_E_INVAL;
+	} else {
+		ref_count = qdf_atomic_dec_return(
+			&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
 	}
 	total_ref_count = qdf_atomic_dec_return(&bs_ctx->total_ref_count);
-	ref_count = qdf_atomic_dec_return(&bs_ctx->ref_count[bs_req->vdev_id][bs_req->source]);
-
 	ll_sap_nofl_debug(BS_PREFIX_FMT "req_vdev %d src %d ref_count %d Total ref count %d",
 			  BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
 					bs_req->request_id),
@@ -850,11 +905,6 @@ ll_lt_sap_handle_bs_to_non_wlan_in_wlan_state(
 		ll_sap_err(BS_PREFIX_FMT "Failed to start timer",
 			   BS_PREFIX_REF(wlan_vdev_get_id(bs_ctx->vdev),
 					 bs_req->request_id));
-	/*
-	 * Todo, upon receiving response for non-wlan request, deliver event
-	 * WLAN_BS_SM_EV_SWITCH_TO_NON_WLAN_COMPLETED from the vendor command
-	 * path
-	 */
 }
 
 /**
@@ -957,6 +1007,12 @@ ll_lt_sap_handle_bs_to_wlan_timeout(
 {
 	bs_sm_transition_to(bs_ctx, BEARER_WLAN);
 
+	if (bs_req->source == BEARER_SWITCH_REQ_FW)
+		ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(
+							bs_ctx->vdev,
+							bs_req->req_type,
+							WLAN_BS_STATUS_TIMEOUT);
+
 	bs_ctx->last_status = QDF_STATUS_E_TIMEOUT;
 
 	ll_lt_sap_switch_to_non_wlan_from_wlan(bs_ctx);
@@ -1717,6 +1773,9 @@ ll_lt_sap_deliver_audio_transport_switch_resp(
 				enum bearer_switch_req_type req_type,
 				enum bearer_switch_status status)
 {
+	ll_lt_sap_deliver_audio_transport_switch_resp_to_fw(vdev, req_type,
+							   status);
+
 	if (req_type == WLAN_BS_REQ_TO_NON_WLAN)
 		ll_lt_sap_deliver_non_wlan_audio_transport_switch_resp(
 								vdev,

+ 11 - 5
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_lt_sap_main.c

@@ -22,13 +22,19 @@
 #include "wlan_ll_sap_main.h"
 #include "wlan_ll_lt_sap_bearer_switch.h"
 #include "wlan_scan_api.h"
+#include "target_if.h"
 
-bool ll_lt_sap_is_supported(void)
+bool ll_lt_sap_is_supported(struct wlan_objmgr_psoc *psoc)
 {
-	/* To do, check the FW capability to decide if this is supported
-	 * or not supported.
-	 */
-	return true;
+	struct wmi_unified *wmi_handle;
+
+	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
+	if (!wmi_handle) {
+		ll_sap_err("Invalid WMI handle");
+		return false;
+	}
+
+	return wmi_service_enabled(wmi_handle, wmi_service_xpan_support);
 }
 
 /**

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

@@ -30,10 +30,10 @@
 
 /**
  * ll_lt_sap_is_supported() - Check if ll_lt_sap is supported or not
- *
+ * @psoc: Pointer to psoc object
  * Return: True/False
  */
-bool ll_lt_sap_is_supported(void);
+bool ll_lt_sap_is_supported(struct wlan_objmgr_psoc *psoc);
 
 /**
  * ll_lt_sap_get_freq_list() - API to get frequency list for LL_LT_SAP

+ 46 - 6
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_sap_main.c

@@ -18,30 +18,60 @@
 #include <wlan_objmgr_global_obj.h>
 #include "qca_vendor.h"
 #include "wlan_ll_lt_sap_main.h"
+#include "target_if_ll_sap.h"
 
 struct ll_sap_ops *global_ll_sap_ops;
 
 static QDF_STATUS ll_sap_psoc_obj_created_notification(struct wlan_objmgr_psoc *psoc, void *arg_list)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct ll_sap_psoc_priv_obj *ll_sap_psoc_obj;
+
+	ll_sap_psoc_obj = qdf_mem_malloc(sizeof(*ll_sap_psoc_obj));
+	if (!ll_sap_psoc_obj)
+		return QDF_STATUS_E_NOMEM;
+
+	status = wlan_objmgr_psoc_component_obj_attach(psoc,
+						       WLAN_UMAC_COMP_LL_SAP,
+						       ll_sap_psoc_obj,
+						       QDF_STATUS_SUCCESS);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ll_sap_err("ll_sap obj attach with psoc failed");
+		goto ll_sap_psoc_obj_fail;
+	}
+
+	target_if_ll_sap_register_tx_ops(&ll_sap_psoc_obj->tx_ops);
+	target_if_ll_sap_register_rx_ops(&ll_sap_psoc_obj->rx_ops);
 
 	ll_sap_debug("ll sap psoc object created");
 
-	/* attach ll_sap_psoc object which will contain cfg items,
-	 * tx and rx ops
-	 */
+	return status;
+
+ll_sap_psoc_obj_fail:
+	qdf_mem_free(ll_sap_psoc_obj);
+
 	return status;
 }
 
 static QDF_STATUS ll_sap_psoc_obj_destroyed_notification(struct wlan_objmgr_psoc *psoc, void *arg_list)
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct ll_sap_psoc_priv_obj *ll_sap_psoc_obj;
+
+	ll_sap_psoc_obj =
+		wlan_objmgr_psoc_get_comp_private_obj(psoc,
+						      WLAN_UMAC_COMP_LL_SAP);
+
+	status = wlan_objmgr_psoc_component_obj_detach(psoc,
+						       WLAN_UMAC_COMP_LL_SAP,
+						       ll_sap_psoc_obj);
+	if (QDF_IS_STATUS_ERROR(status))
+		ll_sap_err("ll_sap detach failed");
+
+	qdf_mem_free(ll_sap_psoc_obj);
 
 	ll_sap_debug("ll sap psoc object destroyed");
 
-	/* detach ll_sap_psoc object which will contain cfg items,
-	 * tx and rx ops
-	 */
 	return status;
 }
 
@@ -238,3 +268,13 @@ struct ll_sap_ops *ll_sap_get_osif_cbk(void)
 {
 	return global_ll_sap_ops;
 }
+
+QDF_STATUS ll_sap_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return target_if_ll_sap_register_events(psoc);
+}
+
+QDF_STATUS ll_sap_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	return target_if_ll_sap_deregister_events(psoc);
+}

+ 26 - 0
components/umac/mlme/sap/ll_sap/core/src/wlan_ll_sap_main.h

@@ -36,6 +36,16 @@
 #define ll_sap_nofl_debug(params...) \
 	QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_LL_SAP, params)
 
+/**
+ * struct ll_sap_psoc_priv_obj - ll_sap private psoc obj
+ * @tx_ops: Tx ops registered with Target IF interface
+ * @rx_ops: Rx  ops registered with Target IF interface
+ */
+struct ll_sap_psoc_priv_obj {
+	struct wlan_ll_sap_tx_ops tx_ops;
+	struct wlan_ll_sap_rx_ops rx_ops;
+};
+
 /**
  * struct ll_sap_vdev_priv_obj - ll sap private vdev obj
  * @bearer_switch_ctx: Bearer switch context
@@ -102,4 +112,20 @@ void ll_sap_unregister_os_if_cb(void);
  */
 struct ll_sap_ops *ll_sap_get_osif_cbk(void);
 
+/**
+ * ll_sap_psoc_enable() - Enable ll_lt_sap psoc
+ * @psoc: objmgr psoc pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ll_sap_psoc_enable(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * ll_sap_psoc_disable() - Disable ll_lt_sap psoc
+ * @psoc: objmgr psoc pointer
+ *
+ * Return: None
+ */
+QDF_STATUS ll_sap_psoc_disable(struct wlan_objmgr_psoc *psoc);
+
 #endif /* _WLAN_LL_SAP_MAIN_H_ */

+ 19 - 0
components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_api.h

@@ -162,6 +162,16 @@ wlan_get_ll_lt_sap_restart_freq(struct wlan_objmgr_pdev *pdev,
 				uint8_t vdev_id,
 				enum sap_csa_reason_code *csa_reason);
 
+/**
+ * wlan_ll_sap_fw_bearer_switch_req() - FW bearer switch request
+ * @psoc: Pointer to psoc object
+ * @req_type: Bearer switch request type
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_ll_sap_fw_bearer_switch_req(struct wlan_objmgr_psoc *psoc,
+				 enum bearer_switch_req_type req_type);
 #else
 static inline wlan_bs_req_id
 wlan_ll_lt_sap_bearer_switch_get_id(struct wlan_objmgr_vdev *vdev)
@@ -210,5 +220,14 @@ qdf_freq_t wlan_ll_lt_sap_override_freq(struct wlan_objmgr_psoc *psoc,
 {
 	return chan_freq;
 }
+
+static inline
+qdf_freq_t wlan_get_ll_lt_sap_restart_freq(struct wlan_objmgr_pdev *pdev,
+					   qdf_freq_t chan_freq,
+					   uint8_t vdev_id,
+					   enum sap_csa_reason_code *csa_reason)
+{
+	return 0;
+}
 #endif /* WLAN_FEATURE_LL_LT_SAP */
 #endif /* _WLAN_LL_LT_SAP_API_H_ */

+ 27 - 0
components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_public_structs.h

@@ -47,10 +47,12 @@ enum bearer_switch_req_type {
  * @WLAN_BS_STATUS_REJECTED: Bearer switch request rejected
  * @WLAN_BS_STATUS_COMPLETED: Bearer switch request completed
  * @WLAN_BS_STATUS_INVALID: Invalid bearer switch request
+ * @WLAN_BS_STATUS_TIMEOUT: Bearer switch request timedout
  */
 enum bearer_switch_status {
 	WLAN_BS_STATUS_REJECTED = 0,
 	WLAN_BS_STATUS_COMPLETED = 1,
+	WLAN_BS_STATUS_TIMEOUT = 2,
 	WLAN_BS_STATUS_INVALID,
 };
 
@@ -152,6 +154,31 @@ struct wlan_bearer_switch_request {
 	void *arg;
 };
 
+/**
+ * struct wlan_ll_sap_tx_ops - defines southbound tx callbacks for
+ * LL_SAP (low latency sap) component
+ * @send_audio_transport_switch_resp: function pointer to indicate audio
+ * transport switch response to FW
+ */
+struct wlan_ll_sap_tx_ops {
+	QDF_STATUS (*send_audio_transport_switch_resp)(
+					struct wlan_objmgr_psoc *psoc,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status);
+};
+
+/**
+ * struct wlan_ll_sap_rx_ops - defines southbound rx callbacks for
+ * LL_SAP (low latency SAP) component
+ * @audio_transport_switch_req: function pointer to indicate audio
+ * transport switch request from FW
+ */
+struct wlan_ll_sap_rx_ops {
+	QDF_STATUS (*audio_transport_switch_req)(
+					struct wlan_objmgr_psoc *psoc,
+					enum bearer_switch_req_type req_type);
+};
+
 /**
  * struct ll_sap_ops - ll_sap osif callbacks
  * @ll_sap_send_audio_transport_switch_req_cb: Send audio transport request to

+ 29 - 2
components/umac/mlme/sap/ll_sap/dispatcher/inc/wlan_ll_sap_ucfg_api.h

@@ -42,10 +42,11 @@ QDF_STATUS ucfg_ll_sap_deinit(void);
 
 /**
  * ucfg_is_ll_lt_sap_supported() - Check if ll_lt_sap is supported or not
+ *@psoc: Psoc pointer
  *
  * Return: True/False
  */
-bool ucfg_is_ll_lt_sap_supported(void);
+bool ucfg_is_ll_lt_sap_supported(struct wlan_objmgr_psoc *psoc);
 
 /**
  * ucfg_ll_lt_sap_request_for_audio_transport_switch() - Request to switch the
@@ -88,6 +89,22 @@ void ucfg_ll_sap_register_cb(struct ll_sap_ops *ll_sap_global_ops);
  */
 void ucfg_ll_sap_unregister_cb(void);
 
+/**
+ * ucfg_ll_sap_psoc_enable() - Enable ll_lt_sap psoc
+ * @psoc: objmgr psoc pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ucfg_ll_sap_psoc_enable(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * ucfg_ll_sap_psoc_disable() - Disable ll_lt_sap psoc
+ * @psoc: objmgr psoc pointer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS ucfg_ll_sap_psoc_disable(struct wlan_objmgr_psoc *psoc);
+
 #else
 static inline QDF_STATUS ucfg_ll_sap_init(void)
 {
@@ -99,7 +116,7 @@ static inline QDF_STATUS ucfg_ll_sap_deinit(void)
 	return QDF_STATUS_SUCCESS;
 }
 
-static inline bool ucfg_is_ll_lt_sap_supported(void)
+static inline bool ucfg_is_ll_lt_sap_supported(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
 }
@@ -128,6 +145,16 @@ static inline void ucfg_ll_sap_unregister_cb(void)
 {
 }
 
+static inline QDF_STATUS ucfg_ll_sap_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static inline QDF_STATUS ucfg_ll_sap_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
 #endif /* WLAN_FEATURE_LL_LT_SAP */
 #endif /* _WLAN_LL_SAP_UCFG_API_H_ */
 

+ 41 - 0
components/umac/mlme/sap/ll_sap/dispatcher/src/wlan_ll_sap_api.c

@@ -222,3 +222,44 @@ get_new_ll_lt_sap_freq:
 		     vdev_id, chan_freq, restart_freq, *csa_reason);
 	return restart_freq;
 }
+
+static void fw_bearer_switch_requester_cb(struct wlan_objmgr_psoc *psoc,
+					  uint8_t vdev_id,
+					  wlan_bs_req_id request_id,
+					  QDF_STATUS status,
+					  uint32_t req_value,
+					  void *request_params)
+{
+	/*
+	 * Drop this response as all the responses to the FW is always
+	 * forwarded
+	 */
+}
+
+QDF_STATUS
+wlan_ll_sap_fw_bearer_switch_req(struct wlan_objmgr_psoc *psoc,
+				 enum bearer_switch_req_type req_type)
+{
+	struct wlan_bearer_switch_request bs_request = {0};
+	QDF_STATUS status;
+	uint8_t ll_lt_sap_vdev_id;
+
+	ll_lt_sap_vdev_id = wlan_policy_mgr_get_ll_lt_sap_vdev_id(psoc);
+
+	bs_request.vdev_id = ll_lt_sap_vdev_id;
+	bs_request.request_id = ll_lt_sap_bearer_switch_get_id(psoc);
+	bs_request.req_type = req_type;
+	bs_request.source = BEARER_SWITCH_REQ_FW;
+	bs_request.requester_cb = fw_bearer_switch_requester_cb;
+
+	if (req_type == WLAN_BS_REQ_TO_WLAN)
+		status = ll_lt_sap_switch_bearer_to_wlan(psoc, &bs_request);
+
+	else
+		status = ll_lt_sap_switch_bearer_to_ble(psoc, &bs_request);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		return QDF_STATUS_E_ALREADY;
+
+	return QDF_STATUS_SUCCESS;
+}

+ 12 - 2
components/umac/mlme/sap/ll_sap/dispatcher/src/wlan_ll_sap_ucfg_api.c

@@ -34,9 +34,9 @@ QDF_STATUS ucfg_ll_sap_deinit(void)
 	return ll_sap_deinit();
 }
 
-bool ucfg_is_ll_lt_sap_supported(void)
+bool ucfg_is_ll_lt_sap_supported(struct wlan_objmgr_psoc *psoc)
 {
-	return ll_lt_sap_is_supported();
+	return ll_lt_sap_is_supported(psoc);
 }
 
 QDF_STATUS ucfg_ll_lt_sap_request_for_audio_transport_switch(
@@ -64,3 +64,13 @@ void ucfg_ll_sap_unregister_cb(void)
 {
 	ll_sap_unregister_os_if_cb();
 }
+
+QDF_STATUS ucfg_ll_sap_psoc_enable(struct wlan_objmgr_psoc *psoc)
+{
+	return ll_sap_psoc_enable(psoc);
+}
+
+QDF_STATUS ucfg_ll_sap_psoc_disable(struct wlan_objmgr_psoc *psoc)
+{
+	return ll_sap_psoc_disable(psoc);
+}

+ 51 - 0
components/wmi/inc/wmi_unified_ll_sap_api.h

@@ -0,0 +1,51 @@
+/*
+ * 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 "qdf_status.h"
+#include "wlan_ll_sap_public_structs.h"
+#include "wmi_unified_param.h"
+
+#ifdef WLAN_FEATURE_LL_LT_SAP
+/**
+ * wmi_unified_audio_transport_switch_resp_send() - Send audio transport switch
+ * response to fw
+ * @wmi_hdl: WMI handle
+ * @req_type: Bearer switch request type
+ * @status: Status of the bearer switch request
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wmi_unified_audio_transport_switch_resp_send(
+					wmi_unified_t wmi_hdl,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status);
+
+/**
+ * wmi_extract_audio_transport_switch_req_event() - Extract audio transport
+ * switch request from fw
+ * @wmi_handle: WMI handle
+ * @event: WMI event from fw
+ * @len: Length of the event
+ * @req_type: Type of the bearer switch request from fw
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wmi_extract_audio_transport_switch_req_event(
+				wmi_unified_t wmi_handle,
+				uint8_t *event, uint32_t len,
+				enum bearer_switch_req_type *req_type);
+#endif

+ 46 - 0
components/wmi/src/wmi_unified_ll_sap_api.c

@@ -0,0 +1,46 @@
+/*
+ * 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 <wmi.h>
+#include <wmi_unified_priv.h>
+#include "wmi_unified_ll_sap_api.h"
+#include "wmi_unified_param.h"
+
+QDF_STATUS wmi_unified_audio_transport_switch_resp_send(
+					wmi_unified_t wmi_hdl,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status)
+{
+	if (wmi_hdl->ops->send_audio_transport_switch_resp)
+		return wmi_hdl->ops->send_audio_transport_switch_resp(wmi_hdl,
+								      req_type,
+								      status);
+
+	return QDF_STATUS_E_FAILURE;
+}
+
+QDF_STATUS
+wmi_extract_audio_transport_switch_req_event(
+				wmi_unified_t wmi_handle,
+				uint8_t *event, uint32_t len,
+				enum bearer_switch_req_type *req_type)
+{
+	if (wmi_handle->ops->extract_audio_transport_switch_req_event)
+		return wmi_handle->ops->extract_audio_transport_switch_req_event(
+					wmi_handle, event, len, req_type);
+	return QDF_STATUS_E_FAILURE;
+}
+

+ 130 - 0
components/wmi/src/wmi_unified_ll_sap_tlv.c

@@ -0,0 +1,130 @@
+/*
+ * 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 "wmi_unified.h"
+#include "wmi_unified_param.h"
+#include <wmi_unified_priv.h>
+#include <wmi.h>
+#include "wmi_unified_ll_sap_tlv.h"
+
+static WMI_AUDIO_TRANSPORT_SWITCH_RESPONSE_STATUS
+wmi_convert_host_to_target_audio_switch_status(enum bearer_switch_status status)
+{
+	if (status == WLAN_BS_STATUS_COMPLETED)
+		return WMI_AUDIO_TRANSPORT_SWITCH_STATUS_SUCCESS;
+	else if (status == WLAN_BS_STATUS_REJECTED)
+		return WMI_AUDIO_TRANSPORT_SWITCH_STATUS_FAIL;
+	else
+		return WMI_AUDIO_TRANSPORT_SWITCH_STATUS_TIMEOUT;
+}
+
+static WMI_AUDIO_TRANSPORT_SWITCH_TYPE
+wmi_convert_host_to_target_audio_switch_type(
+					enum bearer_switch_req_type req_type)
+{
+	if (req_type == WLAN_BS_REQ_TO_NON_WLAN)
+		return WMI_AUDIO_TRANSPORT_SWITCH_TYPE_NON_WLAN;
+	else
+		return WMI_AUDIO_TRANSPORT_SWITCH_TYPE_WLAN;
+}
+
+static enum bearer_switch_req_type
+wmi_convert_target_to_host_audio_switch_type(uint32_t req_type)
+{
+	if (req_type == WMI_AUDIO_TRANSPORT_SWITCH_TYPE_NON_WLAN)
+		return WLAN_BS_REQ_TO_NON_WLAN;
+	else if (req_type == WMI_AUDIO_TRANSPORT_SWITCH_TYPE_WLAN)
+		return WLAN_BS_REQ_TO_WLAN;
+	else
+		return WLAN_BS_REQ_INVALID;
+}
+
+QDF_STATUS audio_transport_switch_resp_tlv(
+					wmi_unified_t wmi_hdl,
+					enum bearer_switch_req_type req_type,
+					enum bearer_switch_status status)
+{
+	wmi_audio_transport_switch_resp_status_cmd_fixed_param *cmd;
+	wmi_buf_t buf;
+	QDF_STATUS qdf_status;
+
+	buf = wmi_buf_alloc(wmi_hdl, sizeof(*cmd));
+	if (!buf)
+		return QDF_STATUS_E_FAILURE;
+
+	cmd = (wmi_audio_transport_switch_resp_status_cmd_fixed_param *)wmi_buf_data(buf);
+
+	WMITLV_SET_HDR(
+	&cmd->tlv_header,
+	WMITLV_TAG_STRUC_wmi_audio_transport_switch_resp_status_cmd_fixed_param,
+	WMITLV_GET_STRUCT_TLVLEN
+	(wmi_audio_transport_switch_resp_status_cmd_fixed_param));
+
+	cmd->switch_type = wmi_convert_host_to_target_audio_switch_type(
+								req_type);
+	cmd->switch_response_status =
+		wmi_convert_host_to_target_audio_switch_status(status);
+
+	wmi_nofl_debug("LL_LT_SAP Audio switch type %d status %d",
+		       cmd->switch_type, cmd->switch_response_status);
+
+	qdf_status = wmi_unified_cmd_send(
+				wmi_hdl, buf, sizeof(*cmd),
+				WMI_AUDIO_TRANSPORT_SWITCH_RESP_STATUS_CMDID);
+
+	if (QDF_IS_STATUS_ERROR(qdf_status))
+		wmi_buf_free(buf);
+
+	return qdf_status;
+}
+
+QDF_STATUS
+extract_audio_transport_switch_req_event_tlv(
+				wmi_unified_t wmi_handle,
+				uint8_t *event, uint32_t len,
+				enum bearer_switch_req_type *req_type)
+{
+	WMI_AUDIO_TRANSPORT_SWITCH_TYPE_EVENTID_param_tlvs *param_buf = NULL;
+	wmi_audio_transport_switch_type_event_fixed_param *fixed_param = NULL;
+
+	if (!event || !len) {
+		wmi_debug("Empty transport switch request event");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	param_buf = (WMI_AUDIO_TRANSPORT_SWITCH_TYPE_EVENTID_param_tlvs *)event;
+	if (!param_buf) {
+		wmi_err("received null buf from target");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	fixed_param = (wmi_audio_transport_switch_type_event_fixed_param *)
+					param_buf->fixed_param;
+	if (!fixed_param) {
+		wmi_err("received null event data from target");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	*req_type = wmi_convert_target_to_host_audio_switch_type(
+						fixed_param->switch_type);
+
+	wmi_nofl_debug("LL_LT_SAP FW requested bearer switch to %d", *req_type);
+
+	if (*req_type == WLAN_BS_REQ_TO_WLAN)
+		return QDF_STATUS_E_INVAL;
+
+	return QDF_STATUS_SUCCESS;
+}

+ 51 - 0
components/wmi/src/wmi_unified_ll_sap_tlv.h

@@ -0,0 +1,51 @@
+/*
+ * 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 "qdf_status.h"
+#include "wlan_ll_sap_public_structs.h"
+#include "wmi_unified_param.h"
+
+#ifdef WLAN_FEATURE_LL_LT_SAP
+/**
+ * audio_transport_switch_resp_tlv() - AUdio transport switch response tlv
+ * @wmi_hdl: WMI handle
+ * @req_type: Bearer switch request type
+ * @status: Bearer switch status
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+audio_transport_switch_resp_tlv(wmi_unified_t wmi_hdl,
+				enum bearer_switch_req_type req_type,
+				enum bearer_switch_status status);
+
+/**
+ * extract_audio_transport_switch_req_event_tlv() - AUdio transport switch
+ * request tlv
+ * @wmi_handle: WMI handle
+ * @event: Event received from the FW
+ * @len: Length of the event
+ * @req_type: Bearer switch request type
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+extract_audio_transport_switch_req_event_tlv(
+				wmi_unified_t wmi_handle,
+				uint8_t *event, uint32_t len,
+				enum bearer_switch_req_type *req_type);
+
+#endif

+ 21 - 1
components/wmi/src/wmi_unified_mlme_tlv.c

@@ -22,6 +22,7 @@
 #include <wmi_unified_priv.h>
 #include "wmi.h"
 #include "wlan_mlme_api.h"
+#include "wmi_unified_ll_sap_tlv.h"
 
 static QDF_STATUS csa_event_status_ind_tlv(wmi_unified_t wmi_handle,
 					   struct csa_event_status_ind params)
@@ -53,6 +54,25 @@ static QDF_STATUS csa_event_status_ind_tlv(wmi_unified_t wmi_handle,
 	return status;
 }
 
+#ifdef WLAN_FEATURE_LL_LT_SAP
+/**
+ * wmi_mlme_attach_ll_lt_sap_tlv() - attach ll_lt_sap tlv handlers
+ * @ops: wmi ops
+ *
+ * Return: void
+ */
+static void wmi_mlme_attach_ll_lt_sap_tlv(struct wmi_ops *ops)
+{
+	ops->send_audio_transport_switch_resp = audio_transport_switch_resp_tlv;
+	ops->extract_audio_transport_switch_req_event =
+				extract_audio_transport_switch_req_event_tlv;
+}
+#else
+static inline void wmi_mlme_attach_ll_lt_sap_tlv(struct wmi_ops *ops)
+{
+}
+#endif
+
 /**
  * wmi_mlme_attach_tlv() - attach MLME tlv handlers
  * @wmi_handle: wmi handle
@@ -64,5 +84,5 @@ void wmi_mlme_attach_tlv(wmi_unified_t wmi_handle)
 	struct wmi_ops *ops = wmi_handle->ops;
 
 	ops->send_csa_event_status_ind = csa_event_status_ind_tlv;
+	wmi_mlme_attach_ll_lt_sap_tlv(ops);
 }
-

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

@@ -2349,7 +2349,7 @@ wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle,
 	roam_sync_ind->roamed_vdev_id = synch_event->vdev_id;
 	roam_sync_ind->auth_status = synch_event->auth_status;
 	roam_sync_ind->roam_reason = synch_event->roam_reason;
-	roam_sync_ind->rssi = synch_event->rssi;
+	roam_sync_ind->rssi = -1 * synch_event->rssi;
 	roam_sync_ind->is_beacon = synch_event->is_beacon;
 
 	WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid,

+ 10 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -2409,6 +2409,16 @@ struct hdd_chwidth_info {
 	int bonding_mode;
 };
 
+/**
+ * struct mac_addr_set_priv: Set MAC addr private context
+ * @fw_resp_status: F/W response status
+ * @pending_rsp_cnt: Pending response count
+ */
+struct mac_addr_set_priv {
+	uint32_t fw_resp_status;
+	qdf_atomic_t pending_rsp_cnt;
+};
+
 /*
  * Function declarations and documentation
  */

+ 176 - 22
core/hdd/src/wlan_hdd_cfg.c

@@ -2437,13 +2437,185 @@ hdd_update_bss_rate_flags(struct wlan_hdd_link_info *link_info,
 					       vht_present, ht_present);
 }
 
+/**
+ * struct sme_config_msg_ctx - sme config update message ctx
+ * @vdev: vdev object
+ * @chwidth: channel width
+ * @is_restore: restore default or not
+ * @bonding_mode: bonding mode
+ */
+struct sme_config_msg_ctx {
+	struct wlan_objmgr_vdev *vdev;
+	enum eSirMacHTChannelWidth chwidth;
+	bool is_restore;
+	uint32_t bonding_mode;
+};
+
+/**
+ * hdd_restore_sme_config_cb() - restore bonding mode sme config cb
+ * @msg: msg data
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS hdd_restore_sme_config_cb(struct scheduler_msg *msg)
+{
+	struct hdd_context *hdd_ctx;
+	mac_handle_t mac_handle;
+	struct sme_config_params *sme_config = NULL;
+	struct sme_config_msg_ctx *sme_config_msg_ctx = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+	uint8_t vdev_id;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	if (!msg) {
+		hdd_debug("msg is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	sme_config_msg_ctx = msg->bodyptr;
+	if (!sme_config_msg_ctx) {
+		hdd_debug("bodyptr is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	vdev = sme_config_msg_ctx->vdev;
+	if (!vdev)
+		goto end;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	if (wlan_hdd_validate_context(hdd_ctx))
+		goto end;
+
+	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
+	if (!mac_handle)
+		goto end;
+
+	if (!hdd_ctx->psoc)
+		goto end;
+
+	sme_config = qdf_mem_malloc(sizeof(*sme_config));
+	if (!sme_config)
+		goto end;
+
+	vdev_id = wlan_vdev_get_id(vdev);
+	hdd_debug("vdev id %d is_restore %d bonding_mode %d chwdith %d",
+		  vdev_id,
+		  sme_config_msg_ctx->is_restore,
+		  sme_config_msg_ctx->bonding_mode,
+		  sme_config_msg_ctx->chwidth);
+	sme_get_config_param(mac_handle, sme_config);
+	if (sme_config_msg_ctx->is_restore) {
+		sme_config->csr_config.channelBondingMode5GHz =
+			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_5GHZ);
+		sme_config->csr_config.channelBondingMode24GHz =
+			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_24GHZ);
+	} else {
+		sme_config->csr_config.channelBondingMode5GHz =
+					sme_config_msg_ctx->bonding_mode;
+		sme_config->csr_config.channelBondingMode24GHz =
+					sme_config_msg_ctx->bonding_mode;
+	}
+	sme_update_config(mac_handle, sme_config);
+	sme_set_he_bw_cap(hdd_ctx->mac_handle, vdev_id,
+			  sme_config_msg_ctx->chwidth);
+	sme_set_eht_bw_cap(hdd_ctx->mac_handle, vdev_id,
+			   sme_config_msg_ctx->chwidth);
+
+	status = QDF_STATUS_SUCCESS;
+end:
+	qdf_mem_free(sme_config);
+	if (vdev)
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
+	qdf_mem_free(sme_config_msg_ctx);
+
+	return status;
+}
+
+/**
+ * hdd_restore_sme_config_flush_cb() - bonding mode sme config flush cb
+ * @msg: msg data
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS hdd_restore_sme_config_flush_cb(struct scheduler_msg *msg)
+{
+	struct sme_config_msg_ctx *sme_config_msg_ctx;
+
+	if (!msg) {
+		hdd_debug("msg is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	sme_config_msg_ctx = msg->bodyptr;
+	if (!sme_config_msg_ctx) {
+		hdd_debug("bodyptr is null");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	if (sme_config_msg_ctx->vdev)
+		hdd_objmgr_put_vdev_by_user(sme_config_msg_ctx->vdev,
+					    WLAN_HDD_ID_OBJ_MGR);
+	else
+		hdd_debug("vdev is null");
+
+	qdf_mem_free(sme_config_msg_ctx);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hdd_restore_sme_config() - restore bonding mode for sme config
+ * @link_info: link info
+ * @chwidth: channel width
+ * @is_restore: msg data
+ * @bonding_mode: bonding mode
+ *
+ * Return: void
+ */
+static void hdd_restore_sme_config(struct wlan_hdd_link_info *link_info,
+				   enum eSirMacHTChannelWidth chwidth,
+				   bool is_restore, uint32_t bonding_mode)
+{
+	struct scheduler_msg msg = {0};
+	QDF_STATUS status;
+	struct wlan_objmgr_vdev *vdev;
+	struct sme_config_msg_ctx *sme_config_msg_ctx;
+
+	sme_config_msg_ctx = qdf_mem_malloc(sizeof(*sme_config_msg_ctx));
+	if (!sme_config_msg_ctx)
+		return;
+
+	vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_HDD_ID_OBJ_MGR);
+	if (!vdev) {
+		qdf_mem_free(sme_config_msg_ctx);
+		hdd_debug("no vdev from link info");
+		return;
+	}
+
+	sme_config_msg_ctx->vdev = vdev;
+	sme_config_msg_ctx->chwidth = chwidth;
+	sme_config_msg_ctx->is_restore = is_restore;
+	sme_config_msg_ctx->bonding_mode = bonding_mode;
+	msg.bodyptr = sme_config_msg_ctx;
+	msg.callback = hdd_restore_sme_config_cb;
+	msg.flush_callback = hdd_restore_sme_config_flush_cb;
+
+	status = scheduler_post_message(QDF_MODULE_ID_HDD,
+					QDF_MODULE_ID_OS_IF,
+					QDF_MODULE_ID_OS_IF, &msg);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_debug("status %d", status);
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_HDD_ID_OBJ_MGR);
+		qdf_mem_free(sme_config_msg_ctx);
+	}
+}
+
 int hdd_update_channel_width(struct wlan_hdd_link_info *link_info,
 			     enum eSirMacHTChannelWidth chwidth,
 			     uint32_t bonding_mode, uint8_t link_id,
 			     bool is_restore)
 {
 	struct hdd_context *hdd_ctx;
-	struct sme_config_params *sme_config;
 	int ret;
 	enum phy_ch_width ch_width = CH_WIDTH_INVALID;
 	struct wlan_objmgr_vdev *link_vdev;
@@ -2526,30 +2698,12 @@ int hdd_update_channel_width(struct wlan_hdd_link_info *link_info,
 			return -EIO;
 	}
 
-	sme_config = qdf_mem_malloc(sizeof(*sme_config));
-	if (!sme_config)
-		return -ENOMEM;
-
 	ret = wma_cli_set_command(link_vdev_id, wmi_vdev_param_chwidth,
 				  chwidth, VDEV_CMD);
 	if (ret)
-		goto free_config;
+		return ret;
 
-	sme_get_config_param(hdd_ctx->mac_handle, sme_config);
-	if (is_restore) {
-		sme_config->csr_config.channelBondingMode5GHz =
-			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_5GHZ);
-		sme_config->csr_config.channelBondingMode24GHz =
-			cfg_get(hdd_ctx->psoc, CFG_CHANNEL_BONDING_MODE_24GHZ);
-	} else {
-		sme_config->csr_config.channelBondingMode5GHz = bonding_mode;
-		sme_config->csr_config.channelBondingMode24GHz = bonding_mode;
-	}
-	sme_update_config(hdd_ctx->mac_handle, sme_config);
-	sme_set_he_bw_cap(hdd_ctx->mac_handle, link_vdev_id, chwidth);
-	sme_set_eht_bw_cap(hdd_ctx->mac_handle, link_vdev_id, chwidth);
-free_config:
-	qdf_mem_free(sme_config);
-	return ret;
+	hdd_restore_sme_config(link_info_t, chwidth, is_restore, bonding_mode);
 
+	return 0;
 }

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

@@ -4012,7 +4012,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 	uint8_t vht_ch_width;
 	uint32_t channel_bonding_mode_2g;
 	uint32_t last_scan_ageout_time;
-	bool ll_lt_sap = false;
 	struct wlan_hdd_link_info *link_info = adapter->deflink;
 
 	/* ***Note*** Donot set SME config related to ACS operation here because
@@ -4039,8 +4038,11 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 	ucfg_mlme_get_channel_bonding_24ghz(hdd_ctx->psoc,
 					    &channel_bonding_mode_2g);
 
-	if (policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc, link_info->vdev_id))
+	if (policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc, link_info->vdev_id)) {
 		is_ll_lt_sap = true;
+		policy_mgr_ll_lt_sap_restart_concurrent_sap(hdd_ctx->psoc,
+							    true);
+	}
 
 	if (is_ll_lt_sap || sap_force_11n_for_11ac)
 		sap_force_11n = true;
@@ -4279,9 +4281,6 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 
 	sap_config->acs_cfg.acs_mode = true;
 
-	ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(hdd_ctx->psoc,
-						 link_info->vdev_id);
-
 	if (wlan_reg_get_keep_6ghz_sta_cli_connection(hdd_ctx->pdev))
 		hdd_remove_6ghz_freq_from_acs_list(
 					sap_config->acs_cfg.freq_list,
@@ -4289,7 +4288,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 
 	if ((is_external_acs_policy &&
 	    policy_mgr_is_force_scc(hdd_ctx->psoc) &&
-	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || ll_lt_sap) {
+	    policy_mgr_get_connection_count(hdd_ctx->psoc)) || is_ll_lt_sap) {
 		if (adapter->device_mode == QDF_SAP_MODE)
 			is_vendor_unsafe_ch_present =
 				wlansap_filter_vendor_unsafe_ch_freq(sap_ctx,
@@ -4302,7 +4301,7 @@ static int __wlan_hdd_cfg80211_do_acs(struct wiphy *wiphy,
 		if (!sap_config->acs_cfg.ch_list_count &&
 		    sap_config->acs_cfg.master_ch_list_count &&
 		    !is_vendor_unsafe_ch_present &&
-		    !ll_lt_sap)
+		    !is_ll_lt_sap)
 			wlan_hdd_handle_zero_acs_list(
 				hdd_ctx,
 				sap_config->acs_cfg.freq_list,
@@ -5062,12 +5061,17 @@ static inline void wlan_hdd_set_ndi_feature(uint8_t *feature_flags)
 }
 #endif
 
-static inline void wlan_hdd_set_ll_lt_sap_feature(uint8_t *feature_flags)
+static inline void wlan_hdd_set_ll_lt_sap_feature(struct wlan_objmgr_psoc *psoc,
+						  uint8_t *feature_flags)
 {
 	/* To Do: Once FW feature capability changes for ll_lt_sap feature are
 	 * merged, then this feature will be set based on that feature set
 	 * capability
 	 */
+	if (!ucfg_is_ll_lt_sap_supported(psoc)) {
+		hdd_debug("ll_lt_sap feature is disabled in FW");
+		return;
+	}
 	wlan_hdd_cfg80211_set_feature(feature_flags,
 				      QCA_WLAN_VENDOR_FEATURE_ENHANCED_AUDIO_EXPERIENCE_OVER_WLAN);
 }
@@ -5194,7 +5198,7 @@ __wlan_hdd_cfg80211_get_features(struct wiphy *wiphy,
 				feature_flags,
 				QCA_WLAN_VENDOR_FEATURE_AP_ALLOWED_FREQ_LIST);
 	wlan_wifi_pos_cfg80211_set_features(hdd_ctx->psoc, feature_flags);
-	wlan_hdd_set_ll_lt_sap_feature(feature_flags);
+	wlan_hdd_set_ll_lt_sap_feature(hdd_ctx->psoc, feature_flags);
 
 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
 						       sizeof(feature_flags) +
@@ -11096,6 +11100,20 @@ static int hdd_set_channel_width(struct wlan_hdd_link_info *link_info,
 	struct nlattr *chn_bd = NULL;
 	struct nlattr *mlo_link_id;
 	enum eSirMacHTChannelWidth chwidth;
+	struct wlan_objmgr_psoc *psoc;
+	bool update_cw_allowed;
+
+	psoc = wlan_vdev_get_psoc(link_info->vdev);
+	if (!psoc) {
+		hdd_debug("psoc is null");
+		return -EINVAL;
+	}
+
+	ucfg_mlme_get_update_chan_width_allowed(psoc, &update_cw_allowed);
+	if (!update_cw_allowed) {
+		hdd_debug("update_channel_width is disabled via INI");
+		return -EINVAL;
+	}
 
 	if (!tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS])
 		goto skip_mlo;

+ 1 - 4
core/hdd/src/wlan_hdd_cm_connect.c

@@ -1102,10 +1102,7 @@ static void hdd_cm_save_bss_info(struct wlan_hdd_link_info *link_info,
 				      rsp->connect_ies.bcn_probe_rsp.len,
 				      &hdd_sta_ctx->conn_info.hs20vendor_ie);
 
-	status = sme_unpack_assoc_rsp(mac_handle,
-				      rsp->connect_ies.assoc_rsp.ptr,
-				      rsp->connect_ies.assoc_rsp.len,
-				      assoc_resp);
+	status = sme_unpack_assoc_rsp(mac_handle, rsp, assoc_resp);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("could not parse assoc response");
 		qdf_mem_free(assoc_resp);

+ 8 - 1
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -612,7 +612,14 @@ hdd_cm_disconnect_complete_post_user_update(struct wlan_objmgr_vdev *vdev,
 	 * connect in max BW.
 	 */
 	hdd_cm_restore_ch_width(vdev, link_info);
-	hdd_cm_set_default_wlm_mode(adapter);
+
+	/*
+	 * same WLM configuration is applicable for all links, So no need to
+	 * restore it while processing disconnection due to link switch.
+	 */
+	if (rsp->req.req.source != CM_MLO_LINK_SWITCH_DISCONNECT)
+		hdd_cm_set_default_wlm_mode(adapter);
+
 	__hdd_cm_disconnect_handler_post_user_update(link_info, vdev,
 						     rsp->req.req.source);
 	wlan_twt_concurrency_update(hdd_ctx);

+ 7 - 5
core/hdd/src/wlan_hdd_hostapd.c

@@ -116,6 +116,7 @@
 #include "wlan_osif_features.h"
 #include "wlan_pre_cac_ucfg_api.h"
 #include <wlan_dp_ucfg_api.h>
+#include "wlan_twt_ucfg_ext_cfg.h"
 #include "wlan_twt_ucfg_ext_api.h"
 #include "wlan_twt_ucfg_api.h"
 #include "wlan_vdev_mgr_ucfg_api.h"
@@ -4364,7 +4365,6 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter,
 	bool acs_with_more_param = 0;
 	uint8_t enable_sifs_burst = 0;
 	bool is_6g_sap_fd_enabled = 0;
-	enum reg_6g_ap_type ap_pwr_type;
 	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
@@ -4397,9 +4397,6 @@ QDF_STATUS hdd_init_ap_mode(struct hdd_adapter *adapter,
 	/* Allocate the Wireless Extensions state structure */
 	phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR(adapter->deflink);
 
-	ap_pwr_type = wlan_reg_decide_6g_ap_pwr_type(hdd_ctx->pdev);
-	hdd_debug("selecting AP power type %d", ap_pwr_type);
-
 	/* Zero the memory.  This zeros the profile structure. */
 	memset(phostapdBuf, 0, sizeof(struct hdd_hostapd_state));
 
@@ -7661,11 +7658,16 @@ hdd_sap_nan_check_and_disable_unsupported_ndi(struct wlan_objmgr_psoc *psoc,
 void wlan_hdd_configure_twt_responder(struct hdd_context *hdd_ctx,
 				      bool twt_responder)
 {
-	bool twt_res_svc_cap, enable_twt;
+	bool twt_res_svc_cap, enable_twt, twt_res_cfg;
 	uint32_t reason;
 
 	enable_twt = ucfg_twt_cfg_is_twt_enabled(hdd_ctx->psoc);
 	ucfg_twt_get_responder(hdd_ctx->psoc, &twt_res_svc_cap);
+	ucfg_twt_cfg_get_responder(hdd_ctx->psoc, &twt_res_cfg);
+	if (!twt_res_cfg && !twt_responder) {
+		hdd_debug("TWT responder already disable, skip");
+		return;
+	}
 	ucfg_twt_cfg_set_responder(hdd_ctx->psoc,
 				   QDF_MIN(twt_res_svc_cap,
 					   (enable_twt &&

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

@@ -5760,6 +5760,8 @@ bool hdd_is_dynamic_set_mac_addr_allowed(struct hdd_adapter *adapter)
 			hdd_info_rl("VDEV is not in disconnected state, set mac address isn't supported");
 			return false;
 		}
+		fallthrough;
+	case QDF_P2P_DEVICE_MODE:
 		return true;
 	case QDF_SAP_MODE:
 		if (test_bit(SOFTAP_BSS_STARTED,
@@ -5784,14 +5786,15 @@ int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
 	int ret;
 	void *cookie;
 	bool update_mld_addr;
-	uint32_t *fw_resp_status;
+	uint32_t fw_resp_status;
 	QDF_STATUS status;
 	struct osif_request *request;
 	struct wlan_objmgr_vdev *vdev;
 	struct hdd_adapter *adapter = link_info->adapter;
 	struct hdd_context *hdd_ctx = adapter->hdd_ctx;
+	struct mac_addr_set_priv *priv;
 	static const struct osif_request_params params = {
-		.priv_size = sizeof(*fw_resp_status),
+		.priv_size = sizeof(*priv),
 		.timeout_ms = WLAN_SET_MAC_ADDR_TIMEOUT
 	};
 
@@ -5799,13 +5802,14 @@ int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
 	if (!vdev)
 		return -EINVAL;
 
-	status = ucfg_vdev_mgr_cdp_vdev_detach(vdev);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		hdd_err("Failed to detach CDP vdev. Status:%d", status);
-		ret = qdf_status_to_os_return(status);
-		goto vdev_ref;
+	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_P2P_DEVICE_MODE) {
+		status = ucfg_vdev_mgr_cdp_vdev_detach(vdev);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			hdd_err("Failed to detach CDP vdev. Status:%d", status);
+			ret = qdf_status_to_os_return(status);
+			goto vdev_ref;
+		}
 	}
-
 	request = osif_request_alloc(&params);
 	if (!request) {
 		ret = -ENOMEM;
@@ -5822,6 +5826,22 @@ int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
 	cookie = osif_request_cookie(request);
 	hdd_update_set_mac_addr_req_ctx(adapter, cookie);
 
+	priv = (struct mac_addr_set_priv *)osif_request_priv(request);
+
+	/* For p2p device mode, need send delete self peer cmd to F/W,
+	 * To avoid p2p new DP vdev is created before old DP vdev deleted,
+	 * don't create new DP vdev until both self peer delete rsp and set
+	 * mac addr rsp received, so initialize pending_rsp_cnt as 2.
+	 *
+	 * For other mode like STA/SAP, don't need send delete self peer cmd
+	 * to F/W, only need wait set mad addr rsp, so initialize
+	 * pending_rsp_cnt as 1.
+	 */
+	if (wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_DEVICE_MODE)
+		qdf_atomic_set(&priv->pending_rsp_cnt, 2);
+	else
+		qdf_atomic_set(&priv->pending_rsp_cnt, 1);
+
 	status = sme_send_set_mac_addr(mac_addr, mld_addr, vdev);
 	ret = qdf_status_to_os_return(status);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -5834,10 +5854,10 @@ int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
 		if (ret) {
 			hdd_err("Set MAC address response timed out");
 		} else {
-			fw_resp_status = (uint32_t *)osif_request_priv(request);
-			if (*fw_resp_status) {
+			fw_resp_status = priv->fw_resp_status;
+			if (fw_resp_status) {
 				hdd_err("Set MAC address failed in FW. Status: %d",
-					*fw_resp_status);
+					fw_resp_status);
 				ret = -EAGAIN;
 			}
 		}
@@ -5858,7 +5878,6 @@ int hdd_dynamic_mac_address_set(struct wlan_hdd_link_info *link_info,
 		ret = qdf_status_to_os_return(status);
 
 status_ret:
-	status = ucfg_vdev_mgr_cdp_vdev_attach(vdev);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to attach CDP vdev. status:%d", status);
 		ret = qdf_status_to_os_return(status);
@@ -5894,8 +5913,9 @@ static void hdd_set_mac_addr_event_cb(uint8_t vdev_id, uint8_t status)
 	struct hdd_context *hdd_ctx;
 	struct wlan_hdd_link_info *link_info;
 	struct osif_request *req;
-	uint32_t *fw_response_status;
+	struct mac_addr_set_priv *priv;
 
+	osif_debug("enter");
 	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
 	if (!hdd_ctx) {
 		hdd_err("Invalid HDD context");
@@ -5914,10 +5934,13 @@ static void hdd_set_mac_addr_event_cb(uint8_t vdev_id, uint8_t status)
 		return;
 	}
 
-	fw_response_status = (uint32_t *)osif_request_priv(req);
-	*fw_response_status = status;
+	priv = (struct mac_addr_set_priv *)osif_request_priv(req);
+
+	if (qdf_atomic_dec_and_test(&priv->pending_rsp_cnt)) {
+		priv->fw_resp_status = status;
+		osif_request_complete(req);
+	}
 
-	osif_request_complete(req);
 	osif_request_put(req);
 }
 #else
@@ -19391,10 +19414,12 @@ void hdd_component_psoc_enable(struct wlan_objmgr_psoc *psoc)
 	ucfg_tdls_psoc_enable(psoc);
 	ucfg_fwol_psoc_enable(psoc);
 	ucfg_action_oui_psoc_enable(psoc);
+	ucfg_ll_sap_psoc_enable(psoc);
 }
 
 void hdd_component_psoc_disable(struct wlan_objmgr_psoc *psoc)
 {
+	ucfg_ll_sap_psoc_disable(psoc);
 	ucfg_action_oui_psoc_disable(psoc);
 	ucfg_fwol_psoc_disable(psoc);
 	ucfg_tdls_psoc_disable(psoc);

+ 3 - 1
core/hdd/src/wlan_hdd_mlo.c

@@ -925,7 +925,9 @@ int wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
 	ml_link_op = nla_get_u8(link_oper_attr);
 	switch (ml_link_op) {
 	case QCA_WLAN_VENDOR_LINK_STATE_OP_GET:
-		return wlan_hdd_link_state_request(wiphy, hdd_ctx->psoc, vdev);
+		status = wlan_hdd_link_state_request(wiphy, hdd_ctx->psoc,
+						     vdev);
+		return qdf_status_to_os_return(status);
 	case QCA_WLAN_VENDOR_LINK_STATE_OP_SET:
 		if (policy_mgr_is_set_link_in_progress(hdd_ctx->psoc)) {
 			hdd_debug("vdev %d: change link already in progress",

+ 9 - 4
core/hdd/src/wlan_hdd_p2p.c

@@ -56,6 +56,7 @@
 #include "wlan_pre_cac_ucfg_api.h"
 #include "wlan_dp_ucfg_api.h"
 #include "wlan_psoc_mlme_ucfg_api.h"
+#include "os_if_dp_local_pkt_capture.h"
 
 /* Ms to Time Unit Micro Sec */
 #define MS_TO_TU_MUS(x)   ((x) * 1024)
@@ -686,6 +687,14 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 	if (ret)
 		return ERR_PTR(ret);
 
+	status = hdd_nl_to_qdf_iface_type(type, &mode);
+	if (QDF_IS_STATUS_ERROR(status))
+		return ERR_PTR(qdf_status_to_os_return(status));
+
+	if (mode == QDF_MONITOR_MODE &&
+	    !os_if_lpc_mon_intf_creation_allowed(hdd_ctx->psoc))
+		return ERR_PTR(-EOPNOTSUPP);
+
 	wlan_hdd_lpc_handle_concurrency(hdd_ctx, true);
 
 	if (policy_mgr_is_sta_mon_concurrency(hdd_ctx->psoc) &&
@@ -699,10 +708,6 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 		   TRACE_CODE_HDD_ADD_VIRTUAL_INTF,
 		   NO_SESSION, type);
 
-	status = hdd_nl_to_qdf_iface_type(type, &mode);
-	if (QDF_IS_STATUS_ERROR(status))
-		return ERR_PTR(qdf_status_to_os_return(status));
-
 	switch (mode) {
 	case QDF_SAP_MODE:
 	case QDF_P2P_GO_MODE:

+ 13 - 14
core/hdd/src/wlan_hdd_stats.c

@@ -7838,8 +7838,8 @@ wlan_hdd_update_mlo_sinfo(struct wlan_hdd_link_info *link_info,
 
 	/* Update the rate info for link with best RSSI */
 	if (sinfo->signal > hdd_sinfo->signal) {
-		hdd_debug_rl("Updating rates for link_id %d",
-			     sta_ctx->conn_info.ieee_link_id);
+		hdd_nofl_debug("Updating rates for link_id %d",
+			       sta_ctx->conn_info.ieee_link_id);
 		wlan_hdd_update_mlo_rate_info(hdd_sinfo, sinfo);
 	}
 
@@ -8001,16 +8001,15 @@ static int wlan_hdd_send_mlo_station_stats(struct hdd_adapter *adapter,
 		return wlan_hdd_get_sta_stats(adapter->deflink, mac, sinfo);
 	}
 
-	if (!wlan_is_mlo_aggregated_stats_allowed(adapter, mac)) {
-		link_info = hdd_get_link_info_by_bssid(hdd_ctx, mac);
-		if (!link_info) {
-			hdd_debug_rl("Invalid bssid");
-			return -EINVAL;
-		}
-		return wlan_hdd_get_sta_stats(link_info, mac, sinfo);
-	}
+	link_info = hdd_get_link_info_by_bssid(hdd_ctx, mac);
+	if (!link_info) {
+		if (wlan_is_mlo_aggregated_stats_allowed(adapter, mac))
+			return wlan_hdd_get_mlo_sta_stats(adapter, mac, sinfo);
 
-	return wlan_hdd_get_mlo_sta_stats(adapter, mac, sinfo);
+		hdd_debug_rl("Invalid bssid");
+		return -EINVAL;
+	}
+	return wlan_hdd_get_sta_stats(link_info, mac, sinfo);
 }
 
 /**
@@ -8048,8 +8047,8 @@ static int __wlan_hdd_cfg80211_get_station(struct wiphy *wiphy,
 	if (wlan_hdd_validate_vdev_id(link_info->vdev_id))
 		return -EINVAL;
 
-	hdd_debug_rl("Stats request on MAC: " QDF_MAC_ADDR_FMT,
-		     QDF_MAC_ADDR_REF(mac));
+	hdd_nofl_debug("Stats request on MAC: " QDF_MAC_ADDR_FMT,
+		       QDF_MAC_ADDR_REF(mac));
 
 	if (!mac || qdf_is_macaddr_zero((struct qdf_mac_addr *)mac)) {
 		hdd_err("Invalid MAC addr");
@@ -8247,7 +8246,7 @@ static int __wlan_hdd_cfg80211_dump_station(struct wiphy *wiphy,
 		    wlan_hdd_is_per_link_stats_supported(hdd_ctx))
 			return wlan_hdd_get_mlo_sta_stats(adapter, mac, sinfo);
 
-		hdd_debug("Sending Assoc Link stats");
+		hdd_nofl_debug("Sending Assoc Link stats");
 		errno = wlan_hdd_get_sta_stats(adapter->deflink, mac, sinfo);
 	}
 	return errno;

+ 3 - 3
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            "R"
-#define QWLAN_VERSION_BUILD            83
+#define QWLAN_VERSION_EXTRA            "A"
+#define QWLAN_VERSION_BUILD            84
 
-#define QWLAN_VERSIONSTR               "5.2.1.83R"
+#define QWLAN_VERSIONSTR               "5.2.1.84A"
 
 #endif /* QWLAN_VERSION_H */

+ 17 - 0
core/mac/inc/sir_api.h

@@ -640,6 +640,22 @@ typedef QDF_STATUS
 		     uint8_t session_id, uint8_t reason,
 		     enum wlan_cm_rso_control_requestor requestor);
 
+/**
+ * typedef set_ies_fn_t - Set IEs routine pointer
+ * @mac_ctx: Global MAC context
+ * @vdev_id: vdev id
+ * @dot11_mode: dot11 mode
+ * @opmode: device opmode
+ *
+ * This type is for callbacks registered with WMA to set the IEs for a
+ * given vdev id to the firmware.
+ *
+ * Return: Success or Failure
+ */
+typedef QDF_STATUS
+(*set_ies_fn_t)(struct mac_context *mac_ctx, uint8_t vdev_id,
+		uint16_t dot11_mode, enum QDF_OPMODE device_mode);
+
 /* / Definition for indicating all modules ready on STA */
 struct sme_ready_req {
 	uint16_t messageType;   /* eWNI_SME_SYS_READY_IND */
@@ -657,6 +673,7 @@ struct sme_ready_req {
 					uint8_t *deauth_disassoc_frame,
 					uint16_t deauth_disassoc_frame_len,
 					uint16_t reason_code);
+	set_ies_fn_t pe_roam_set_ie_cb;
 };
 
 /**

+ 6 - 6
core/mac/src/cfg/cfgUtil/dot11f.frms

@@ -1836,13 +1836,13 @@ IE MeasurementReport (EID_MEAS_REPORT)    // 7.3.2.22
                 }
                 dot11_bss_average_access_delay (group_id IS 10)
                 {
-                        ap_average_access_delay, 2;
-                        average_access_delay_besteffort, 2;
-                        average_access_delay_background, 2;
-                        average_access_delay_video, 2;
-                        average_access_delay_voice, 2;
+                        ap_average_access_delay, 1;
+                        average_access_delay_besteffort, 1;
+                        average_access_delay_background, 1;
+                        average_access_delay_video, 1;
+                        average_access_delay_voice, 1;
                         station_count, 2;
-                        channel_utilization, 2;
+                        channel_utilization, 1;
                 }
             };
             OPTIE reporting_reason;

+ 7 - 7
core/mac/src/include/dot11f.h

@@ -27,7 +27,7 @@
  *
  *
  * This file was automatically generated by 'framesc'
- * Fri Sep 22 02:08:42 2023 from the following file(s):
+ * Fri Nov 10 10:07:33 2023 from the following file(s):
  *
  * dot11f.frms
  *
@@ -6251,13 +6251,13 @@ typedef struct sDot11fIEMeasurementReport {
 					uint32_t qos_retries_received_count;
 				} dot11_qos_counter; /* group_id = 2 */
 				struct {
-					uint16_t ap_average_access_delay;
-					uint16_t average_access_delay_besteffort;
-					uint16_t average_access_delay_background;
-					uint16_t average_access_delay_video;
-					uint16_t average_access_delay_voice;
+					uint8_t ap_average_access_delay;
+					uint8_t average_access_delay_besteffort;
+					uint8_t average_access_delay_background;
+					uint8_t average_access_delay_video;
+					uint8_t average_access_delay_voice;
 					uint16_t station_count;
-					uint16_t channel_utilization;
+					uint8_t channel_utilization;
 				} dot11_bss_average_access_delay; /* group_id = 10 */
 			} statsgroupdata;
 	tDot11fIEreporting_reason reporting_reason;

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

@@ -371,6 +371,10 @@ pe_disconnect_callback(struct mac_context *mac, uint8_t vdev_id,
 		       uint16_t deauth_disassoc_frame_len,
 		       uint16_t reason_code);
 
+QDF_STATUS
+pe_set_ie_for_roam_invoke(struct mac_context *mac_ctx, uint8_t vdev_id,
+			  uint16_t dot11_mode, enum QDF_OPMODE opmode);
+
 #else
 static inline QDF_STATUS
 pe_roam_synch_callback(struct mac_context *mac_ctx,
@@ -390,6 +394,13 @@ pe_disconnect_callback(struct mac_context *mac, uint8_t vdev_id,
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }
+
+static inline QDF_STATUS
+pe_set_ie_for_roam_invoke(struct mac_context *mac_ctx, uint8_t vdev_id,
+			  uint16_t dot11_mode, enum QDF_OPMODE opmode)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif
 
 /**

+ 2 - 2
core/mac/src/pe/include/lim_session.h

@@ -635,7 +635,6 @@ struct wlan_mlo_ie_info {
  * @deauth_retry:
  * @enable_bcast_probe_rsp:
  * @ht_client_cnt:
- * @force_24ghz_in_ht20:
  * @ch_switch_in_progress:
  * @he_with_wep_tkip:
  * @fils_info:
@@ -679,6 +678,7 @@ struct wlan_mlo_ie_info {
  * @is_oui_auth_assoc_6mbps_2ghz_enable: send auth/assoc req with 6 Mbps rate
  * @is_unexpected_peer_error: true if unexpected peer error
  * on 2.4 GHz
+ * @join_probe_cnt: join probe request count
  */
 struct pe_session {
 	uint8_t available;
@@ -957,7 +957,6 @@ struct pe_session {
 	struct deauth_retry_params deauth_retry;
 	bool enable_bcast_probe_rsp;
 	uint8_t ht_client_cnt;
-	bool force_24ghz_in_ht20;
 	bool ch_switch_in_progress;
 	bool he_with_wep_tkip;
 #ifdef WLAN_FEATURE_FILS_SK
@@ -1008,6 +1007,7 @@ struct pe_session {
 	uint8_t user_edca_set;
 	bool is_oui_auth_assoc_6mbps_2ghz_enable;
 	bool is_unexpected_peer_error;
+	uint8_t join_probe_cnt;
 };
 
 /*-------------------------------------------------------------------------

+ 43 - 48
core/mac/src/pe/lim/lim_api.c

@@ -908,6 +908,7 @@ QDF_STATUS pe_close(struct mac_context *mac)
 		return QDF_STATUS_SUCCESS;
 
 	qdf_hang_event_unregister_notifier(&pe_hang_event_notifier);
+	lim_cleanup_mlm(mac);
 	lim_cleanup(mac);
 	lim_unregister_scan_mbssid_callback(mac);
 	lim_unregister_sap_bcn_callback(mac);
@@ -974,7 +975,6 @@ QDF_STATUS pe_start(struct mac_context *mac)
 
 void pe_stop(struct mac_context *mac)
 {
-	lim_cleanup_mlm(mac);
 	pe_debug(" PE STOP: Set LIM state to eLIM_MLM_OFFLINE_STATE");
 	SET_LIM_MLM_STATE(mac, eLIM_MLM_OFFLINE_STATE);
 	return;
@@ -1369,7 +1369,8 @@ void pe_register_callbacks_with_wma(struct mac_context *mac,
 	status = wma_register_roaming_callbacks(
 			ready_req->csr_roam_auth_event_handle_cb,
 			ready_req->pe_roam_synch_cb,
-			ready_req->pe_disconnect_cb);
+			ready_req->pe_disconnect_cb,
+			ready_req->pe_roam_set_ie_cb);
 	if (status != QDF_STATUS_SUCCESS)
 		pe_err("Registering roaming callbacks with WMA failed");
 }
@@ -2176,7 +2177,7 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	uint8_t *ie = NULL;
 	struct qdf_mac_addr bssid;
-	bool is_mlo_link = false;
+	bool is_mlo_link;
 	uint8_t vdev_id = session->vdev_id;
 	struct element_info frame;
 	struct cm_roam_values_copy mdie_cfg = {0};
@@ -2188,30 +2189,21 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 	frame.ptr = NULL;
 	frame.len = 0;
 	if (is_multi_link_roam(roam_synch_ind)) {
-		if (roam_synch_ind->link_beacon_probe_resp_length) {
-			if (wlan_vdev_mlme_get_is_mlo_link(mac->psoc,
-							   vdev_id)) {
-				bcn_proberesp_ptr = (uint8_t *)roam_synch_ind +
-				roam_synch_ind->link_beacon_probe_resp_offset;
-				bcn_proberesp_len =
-				roam_synch_ind->link_beacon_probe_resp_length;
-			}
-		} else {
-			mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind,
-						  &bssid);
-			status = wlan_scan_get_entry_by_mac_addr(mac->pdev,
-								 &bssid,
-								 &frame);
-			if (QDF_IS_STATUS_ERROR(status) && !frame.len) {
-				pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT,
-				       QDF_MAC_ADDR_REF(bssid.bytes));
-				return status;
-			}
-			bcn_proberesp_ptr = frame.ptr;
-			bcn_proberesp_len = frame.len;
+		mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind, &bssid);
+		is_mlo_link = wlan_vdev_mlme_get_is_mlo_link(mac->psoc, vdev_id);
+
+		status = wlan_scan_get_entry_by_mac_addr(mac->pdev, &bssid,
+							 &frame);
+		if (QDF_IS_STATUS_ERROR(status) || !frame.len) {
+			pe_err("Failed to get scan entry for " QDF_MAC_ADDR_FMT,
+			       QDF_MAC_ADDR_REF(bssid.bytes));
+			return status;
 		}
-		if (wlan_vdev_mlme_get_is_mlo_link(mac->psoc, vdev_id))
-			is_mlo_link = true;
+		bcn_proberesp_ptr = frame.ptr;
+		bcn_proberesp_len = frame.len;
+	} else {
+		bssid = roam_synch_ind->bssid;
+		is_mlo_link = false;
 	}
 
 	mac_hdr = (tpSirMacMgmtHdr)bcn_proberesp_ptr;
@@ -2228,11 +2220,6 @@ lim_roam_fill_bss_descr(struct mac_context *mac,
 		goto done;
 	}
 
-	if (is_multi_link_roam(roam_synch_ind))
-		mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind, &bssid);
-	else
-		bssid = roam_synch_ind->bssid;
-
 	pe_debug("LFR3:Beacon/Prb Rsp: %d bssid " QDF_MAC_ADDR_FMT
 		 " beacon " QDF_MAC_ADDR_FMT,
 		 is_mlo_link ? roam_synch_ind->is_link_beacon :
@@ -3184,6 +3171,20 @@ roam_sync_fail:
 	pe_delete_session(mac_ctx, ft_session_ptr);
 	return status;
 }
+
+QDF_STATUS
+pe_set_ie_for_roam_invoke(struct mac_context *mac_ctx, uint8_t vdev_id,
+			  uint16_t dot11_mode, enum QDF_OPMODE opmode)
+{
+	QDF_STATUS status;
+
+	if (!mac_ctx)
+		return QDF_STATUS_E_FAILURE;
+
+	status = lim_send_ies_per_band(mac_ctx, vdev_id, dot11_mode, opmode);
+	return status;
+}
+
 #endif
 
 static bool lim_is_beacon_miss_scenario(struct mac_context *mac,
@@ -3294,15 +3295,21 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
 		if (!vdev)
 			return eMGMT_DROP_SPURIOUS_FRAME;
 
+		if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE &&
+		    wlan_cm_is_vdev_roam_started(vdev) &&
+		    (subType == SIR_MAC_MGMT_DISASSOC ||
+		     subType == SIR_MAC_MGMT_DEAUTH)) {
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+			return eMGMT_DROP_DEAUTH_DURING_ROAM_STARTED;
+		}
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+
 		peer = wlan_objmgr_get_peer_by_mac(mac->psoc,
 						   pHdr->sa,
 						   WLAN_LEGACY_MAC_ID);
 		if (!peer) {
-			if (subType == SIR_MAC_MGMT_ASSOC_REQ) {
-				wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+			if (subType == SIR_MAC_MGMT_ASSOC_REQ)
 				return eMGMT_DROP_NO_DROP;
-			}
-			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
 			return eMGMT_DROP_SPURIOUS_FRAME;
 		}
 
@@ -3310,23 +3317,11 @@ tMgmtFrmDropReason lim_is_pkt_candidate_for_drop(struct mac_context *mac,
 							WLAN_UMAC_COMP_MLME);
 		if (!peer_priv) {
 			wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
-			if (subType == SIR_MAC_MGMT_ASSOC_REQ) {
-				wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
+			if (subType == SIR_MAC_MGMT_ASSOC_REQ)
 				return eMGMT_DROP_NO_DROP;
-			}
-			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
 			return eMGMT_DROP_SPURIOUS_FRAME;
 		}
 
-		if (QDF_STA_MODE == wlan_vdev_mlme_get_opmode(vdev) &&
-		    wlan_cm_is_vdev_roam_started(vdev) &&
-		    (subType == SIR_MAC_MGMT_DISASSOC ||
-		     subType == SIR_MAC_MGMT_DEAUTH)) {
-			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
-			return eMGMT_DROP_DEAUTH_DURING_ROAM_STARTED;
-		}
-		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID);
-
 		if (subType == SIR_MAC_MGMT_ASSOC_REQ)
 			timestamp =
 			   &peer_priv->last_assoc_received_time;

+ 104 - 92
core/mac/src/pe/lim/lim_process_auth_frame.c

@@ -316,7 +316,8 @@ static void lim_process_auth_open_system_algo(struct mac_context *mac_ctx,
 static QDF_STATUS
 lim_validate_mac_address_in_auth_frame(struct mac_context *mac_ctx,
 				       tpSirMacMgmtHdr mac_hdr,
-				       struct qdf_mac_addr *mld_addr)
+				       struct qdf_mac_addr *mld_addr,
+				       uint8_t vdev_id)
 {
 	struct wlan_objmgr_vdev *vdev;
 
@@ -329,7 +330,7 @@ lim_validate_mac_address_in_auth_frame(struct mac_context *mac_ctx,
 		return QDF_STATUS_E_ALREADY;
 	}
 
-	if (mlo_mgr_ml_peer_exist_on_diff_ml_ctx(mac_hdr->sa, NULL))
+	if (mlo_mgr_ml_peer_exist_on_diff_ml_ctx(mac_hdr->sa, &vdev_id))
 		return QDF_STATUS_E_ALREADY;
 
 	if (qdf_is_macaddr_zero(mld_addr))
@@ -343,7 +344,7 @@ lim_validate_mac_address_in_auth_frame(struct mac_context *mac_ctx,
 		return QDF_STATUS_E_ALREADY;
 	}
 
-	if (mlo_mgr_ml_peer_exist_on_diff_ml_ctx(mld_addr->bytes, NULL))
+	if (mlo_mgr_ml_peer_exist_on_diff_ml_ctx(mld_addr->bytes, &vdev_id))
 		return QDF_STATUS_E_ALREADY;
 
 	return QDF_STATUS_SUCCESS;
@@ -663,6 +664,73 @@ static QDF_STATUS lim_update_link_to_mld_address(struct mac_context *mac_ctx,
 }
 #endif
 
+static bool
+lim_check_and_trigger_pmf_sta_deletion(struct mac_context *mac,
+				       struct pe_session *pe_session,
+				       tpSirMacMgmtHdr mac_hdr)
+{
+	tpDphHashNode sta_ds_ptr = NULL;
+	tLimMlmDisassocReq *mlm_disassoc_req = NULL;
+	tLimMlmDeauthReq *mlm_deauth_req = NULL;
+	bool is_connected = true;
+	uint16_t associd = 0;
+
+	sta_ds_ptr = dph_lookup_hash_entry(mac, mac_hdr->sa, &associd,
+					   &pe_session->dph.dphHashTable);
+	if (!sta_ds_ptr)
+		return false;
+
+	mlm_disassoc_req = mac->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
+	if (mlm_disassoc_req &&
+	    !qdf_mem_cmp(mac_hdr->sa, &mlm_disassoc_req->peer_macaddr.bytes,
+			 QDF_MAC_ADDR_SIZE)) {
+		pe_debug("TODO:Ack pending for disassoc frame Issue del sta for "
+			 QDF_MAC_ADDR_FMT,
+			 QDF_MAC_ADDR_REF(mlm_disassoc_req->peer_macaddr.bytes));
+		lim_process_disassoc_ack_timeout(mac);
+		is_connected = false;
+	}
+
+	mlm_deauth_req = mac->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
+	if (mlm_deauth_req &&
+	    !qdf_mem_cmp(mac_hdr->sa, &mlm_deauth_req->peer_macaddr.bytes,
+			 QDF_MAC_ADDR_SIZE)) {
+		pe_debug("TODO:Ack for deauth frame is pending Issue del sta for "
+			 QDF_MAC_ADDR_FMT,
+			 QDF_MAC_ADDR_REF(mlm_deauth_req->peer_macaddr.bytes));
+		lim_process_deauth_ack_timeout(mac, pe_session->vdev_id);
+		is_connected = false;
+	}
+
+	/*
+	 * pStaDS != NULL and is_connected = 1 means the STA is already
+	 * connected, But SAP received the Auth from that station. For non-PMF
+	 * connection send Deauth frame as STA will retry to connect back. The
+	 * reason for above logic is captured in CR620403. If we silently drop
+	 * the auth, the subsequent EAPOL exchange will fail & peer STA will
+	 * keep trying until DUT SAP/GO gets a kickout event from FW & cleans
+	 * up.
+	 *
+	 * For PMF connection the AP should not tear down or otherwise modify
+	 * the state of the existing association until the SA-Query procedure
+	 * determines that the original SA is invalid.
+	 */
+	if (is_connected && !sta_ds_ptr->rmfEnabled) {
+		pe_err("STA is already connected but received auth frame"
+		       "Send the Deauth and lim Delete Station Context"
+		       "(associd: %d) sta mac" QDF_MAC_ADDR_FMT,
+		       associd, QDF_MAC_ADDR_REF(mac_hdr->sa));
+
+		lim_send_deauth_mgmt_frame(mac, REASON_UNSPEC_FAILURE,
+					   mac_hdr->sa, pe_session, false);
+		lim_trigger_sta_deletion(mac, sta_ds_ptr, pe_session);
+
+		return true;
+	}
+
+	return false;
+}
+
 /**
  * lim_process_sae_auth_frame()-Process SAE authentication frame
  * @mac_ctx: MAC context
@@ -687,9 +755,17 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
 
-	pe_nofl_rl_info("vdev:%d SAE Auth RX type %d subtype %d from " QDF_MAC_ADDR_FMT,
+	auth_algo = *(uint16_t *)body_ptr;
+	if (frame_len >= (SAE_AUTH_STATUS_CODE_OFFSET + 2)) {
+		sae_auth_seq = *(uint16_t *)(body_ptr + SAE_AUTH_SEQ_NUM_OFFSET);
+		sae_status_code = *(uint16_t *)(body_ptr +
+						SAE_AUTH_STATUS_CODE_OFFSET);
+	}
+
+	pe_nofl_rl_info("vdev:%d SAE Auth RX type %d subtype %d trans_seq_num:%d from " QDF_MAC_ADDR_FMT,
 			pe_session->vdev_id,
 			mac_hdr->fc.type, mac_hdr->fc.subType,
+			sae_auth_seq,
 			QDF_MAC_ADDR_REF(mac_hdr->sa));
 
 	if (LIM_IS_STA_ROLE(pe_session) &&
@@ -702,13 +778,13 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 		struct qdf_mac_addr peer_mld = {0};
 
 		rx_flags = RXMGMT_FLAG_EXTERNAL_AUTH;
-		/* Add preauth node when the first SAE authentication frame
+		/*
+		 * Add preauth node when the first SAE authentication frame
 		 * is received and mark state as authenticating.
 		 * It's not good to track SAE authentication frames with
 		 * authTransactionSeqNumber as it's subjected to
 		 * SAE protocol optimizations.
 		 */
-		/* Extract pre-auth context for the STA, if any. */
 		pre_auth_node = lim_search_pre_auth_list(mac_ctx, mac_hdr->sa);
 		if (!pre_auth_node ||
 		    (pre_auth_node->mlmState != eLIM_MLM_WT_SAE_AUTH_STATE)) {
@@ -730,7 +806,8 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 						frame_len, &peer_mld);
 			status = lim_validate_mac_address_in_auth_frame(mac_ctx,
 									mac_hdr,
-									&peer_mld);
+									&peer_mld,
+									pe_session->vdev_id);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				pe_debug("Drop SAE auth, duplicate entity found");
 				return;
@@ -758,9 +835,9 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 	sae_retry = mlme_get_sae_auth_retry(pe_session->vdev);
 	if (LIM_IS_STA_ROLE(pe_session) && sae_retry &&
 	    sae_retry->sae_auth.ptr) {
-		if (lim_is_sae_auth_algo_match(
-		    sae_retry->sae_auth.ptr, sae_retry->sae_auth.len,
-		     rx_pkt_info))
+		if (lim_is_sae_auth_algo_match(sae_retry->sae_auth.ptr,
+					       sae_retry->sae_auth.len,
+					       rx_pkt_info))
 			lim_sae_auth_cleanup_retry(mac_ctx,
 						   pe_session->vdev_id);
 	}
@@ -771,22 +848,13 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
 		 * So call the Connectivity logging API before address
 		 * translation while forwarding the frame to userspace.
 		 */
-		auth_algo = *(uint16_t *)body_ptr;
-		if (frame_len >= (SAE_AUTH_STATUS_CODE_OFFSET + 2)) {
-			sae_auth_seq =
-				*(uint16_t *)(body_ptr +
-					      SAE_AUTH_SEQ_NUM_OFFSET);
-			sae_status_code =
-				*(uint16_t *)(body_ptr +
-					      SAE_AUTH_STATUS_CODE_OFFSET);
-		}
-
 		wlan_connectivity_mgmt_event(
-			mac_ctx->psoc,
-			(struct wlan_frame_hdr *)mac_hdr, pe_session->vdev_id,
-			sae_status_code, 0,
-			WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info), auth_algo,
-			sae_auth_seq, sae_auth_seq, 0, WLAN_AUTH_RESP);
+				mac_ctx->psoc,
+				(struct wlan_frame_hdr *)mac_hdr,
+				pe_session->vdev_id, sae_status_code, 0,
+				WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
+				auth_algo, sae_auth_seq, sae_auth_seq, 0,
+				WLAN_AUTH_RESP);
 
 		status = lim_update_link_to_mld_address(mac_ctx,
 							pe_session->vdev,
@@ -944,70 +1012,10 @@ static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
 	uint16_t associd = 0;
 	QDF_STATUS status;
 
-	/* AuthFrame 1 */
-	sta_ds_ptr = dph_lookup_hash_entry(mac_ctx, mac_hdr->sa,
-				&associd, &pe_session->dph.dphHashTable);
-	if (sta_ds_ptr) {
-		tLimMlmDisassocReq *pMlmDisassocReq = NULL;
-		tLimMlmDeauthReq *pMlmDeauthReq = NULL;
-		bool is_connected = true;
-
-		pMlmDisassocReq =
-			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDisassocReq;
-		if (pMlmDisassocReq &&
-			(!qdf_mem_cmp((uint8_t *) mac_hdr->sa, (uint8_t *)
-				&pMlmDisassocReq->peer_macaddr.bytes,
-				QDF_MAC_ADDR_SIZE))) {
-			pe_debug("TODO:Ack for disassoc frame is pending Issue delsta for "
-				QDF_MAC_ADDR_FMT,
-				QDF_MAC_ADDR_REF(
-					pMlmDisassocReq->peer_macaddr.bytes));
-			lim_process_disassoc_ack_timeout(mac_ctx);
-			is_connected = false;
-		}
-		pMlmDeauthReq =
-			mac_ctx->lim.limDisassocDeauthCnfReq.pMlmDeauthReq;
-		if (pMlmDeauthReq &&
-			(!qdf_mem_cmp((uint8_t *) mac_hdr->sa, (uint8_t *)
-				&pMlmDeauthReq->peer_macaddr.bytes,
-				QDF_MAC_ADDR_SIZE))) {
-			pe_debug("TODO:Ack for deauth frame is pending Issue delsta for "
-				QDF_MAC_ADDR_FMT,
-				QDF_MAC_ADDR_REF(
-					pMlmDeauthReq->peer_macaddr.bytes));
-			lim_process_deauth_ack_timeout(mac_ctx,
-						       pe_session->vdev_id);
-			is_connected = false;
-		}
+	if (lim_check_and_trigger_pmf_sta_deletion(mac_ctx, pe_session,
+						   mac_hdr))
+		return;
 
-		/*
-		 * pStaDS != NULL and is_connected = 1 means the STA is already
-		 * connected, But SAP received the Auth from that station.
-		 * For non PMF connection send Deauth frame as STA will retry
-		 * to connect back. The reason for above logic is captured in
-		 * CR620403. If we silently drop the auth, the subsequent EAPOL
-		 * exchange will fail & peer STA will keep trying until DUT
-		 * SAP/GO gets a kickout event from FW & cleans up.
-		 *
-		 * For PMF connection the AP should not tear down or otherwise
-		 * modify the state of the existing association until the
-		 * SA-Query procedure determines that the original SA is
-		 * invalid.
-		 */
-		if (is_connected && !sta_ds_ptr->rmfEnabled) {
-			pe_err("STA is already connected but received auth frame"
-			       "Send the Deauth and lim Delete Station Context"
-			       "(associd: %d) sta mac" QDF_MAC_ADDR_FMT,
-			       associd, QDF_MAC_ADDR_REF(mac_hdr->sa));
-			lim_send_deauth_mgmt_frame(mac_ctx,
-				REASON_UNSPEC_FAILURE,
-				(uint8_t *) mac_hdr->sa,
-				pe_session, false);
-			lim_trigger_sta_deletion(mac_ctx, sta_ds_ptr,
-				pe_session);
-			return;
-		}
-	}
 	/* Check if there exists pre-auth context for this STA */
 	auth_node = lim_search_pre_auth_list(mac_ctx, mac_hdr->sa);
 	if (auth_node) {
@@ -1042,16 +1050,18 @@ static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
 		 *  SAP dphHashTable.size = 8
 		 */
 		for (associd = 0; associd < pe_session->dph.dphHashTable.size;
-			associd++) {
+		     associd++) {
 			sta_ds_ptr = dph_get_hash_entry(mac_ctx, associd,
-						&pe_session->dph.dphHashTable);
+							&pe_session->dph.dphHashTable);
 			if (!sta_ds_ptr)
 				continue;
+
 			if (sta_ds_ptr->valid && (!qdf_mem_cmp(
 					(uint8_t *)&sta_ds_ptr->staAddr,
 					(uint8_t *) &(mac_hdr->sa),
 					(uint8_t) sizeof(tSirMacAddr))))
 				break;
+
 			sta_ds_ptr = NULL;
 		}
 
@@ -1068,9 +1078,10 @@ static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
 			return;
 		}
 	}
+
 	maxnum_preauth = mac_ctx->mlme_cfg->lfr.max_num_pre_auth;
 	if (mac_ctx->lim.gLimNumPreAuthContexts == maxnum_preauth &&
-			!lim_delete_open_auth_pre_auth_node(mac_ctx)) {
+	    !lim_delete_open_auth_pre_auth_node(mac_ctx)) {
 		pe_err("Max no of preauth context reached");
 		/*
 		 * Maximum number of pre-auth contexts reached.
@@ -1095,7 +1106,8 @@ static void lim_process_auth_frame_type1(struct mac_context *mac_ctx,
 
 		status = lim_validate_mac_address_in_auth_frame(mac_ctx,
 								mac_hdr,
-								mld_addr);
+								mld_addr,
+								pe_session->vdev_id);
 		if (QDF_IS_STATUS_ERROR(status)) {
 			pe_err("Duplicate MAC address found, reject auth");
 			auth_frame->authAlgoNumber =

+ 19 - 3
core/mac/src/pe/lim/lim_process_mlm_req_messages.c

@@ -1713,6 +1713,7 @@ void lim_process_join_failure_timeout(struct mac_context *mac_ctx)
 		rssi_log->rssi = session->rssi;
 	WLAN_HOST_DIAG_LOG_REPORT(rssi_log);
 #endif
+	session->join_probe_cnt = 0;
 
 	if (session->limMlmState == eLIM_MLM_WT_JOIN_BEACON_STATE) {
 		len = sizeof(tSirMacAddr);
@@ -1764,6 +1765,8 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct
 {
 	struct pe_session *session;
 	tSirMacSSid ssid;
+	tSirMacAddr bssid;
+	tSirMacAddr bcast_mac = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 
 	session = pe_find_session_by_session_id(mac_ctx,
 	      mac_ctx->lim.lim_timers.gLimPeriodicJoinProbeReqTimer.sessionId);
@@ -1780,9 +1783,21 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct
 		qdf_mem_copy(ssid.ssId, session->ssId.ssId,
 			     session->ssId.length);
 		ssid.length = session->ssId.length;
-		lim_send_probe_req_mgmt_frame(mac_ctx, &ssid,
-			session->pLimMlmJoinReq->bssDescription.bssId,
-			session->curr_op_freq,
+		sir_copy_mac_addr(bssid,
+				  session->pLimMlmJoinReq->bssDescription.bssId);
+
+		/*
+		 * Some APs broadcasting hidden SSID doesn't respond to unicast
+		 * probe requests, however those APs respond to broadcast probe
+		 * requests. Therefore for hidden ssid connections, after 3
+		 * unicast probe requests, try the pending probes with broadcast
+		 * mac.
+		 */
+		if (session->ssidHidden && session->join_probe_cnt > 2)
+			sir_copy_mac_addr(bssid, bcast_mac);
+
+		lim_send_probe_req_mgmt_frame(mac_ctx, &ssid, bssid,
+					      session->curr_op_freq,
 			session->self_mac_addr, session->dot11mode,
 			&session->lim_join_req->addIEScan.length,
 			session->lim_join_req->addIEScan.addIEdata);
@@ -1795,6 +1810,7 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct
 			pe_warn("could not activate Periodic Join req failure timer");
 			return;
 		}
+		session->join_probe_cnt++;
 	}
 }
 

+ 5 - 2
core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c

@@ -307,8 +307,10 @@ void lim_process_mlm_join_cnf(struct mac_context *mac_ctx,
 		return;
 	}
 
-	wlan_connectivity_sta_info_event(mac_ctx->psoc, session_entry->vdev_id);
+	wlan_connectivity_sta_info_event(mac_ctx->psoc, session_entry->vdev_id,
+					 false);
 
+	session_entry->join_probe_cnt = 0;
 	if (session_entry->limSmeState != eLIM_SME_WT_JOIN_STATE) {
 		pe_err("received unexpected MLM_JOIN_CNF in state %X",
 			session_entry->limSmeState);
@@ -3045,7 +3047,7 @@ lim_update_mlo_mgr_ap_link_info_mbssid_connect(struct pe_session *session)
 
 		mlo_mgr_update_ap_link_info(session->vdev,
 					    partner_link_info->link_id,
-					    partner_link_info->ap_link_addr.bytes,
+					    partner_link_info->link_addr.bytes,
 					    channel);
 	}
 }
@@ -3250,6 +3252,7 @@ static void lim_process_switch_channel_join_req(
 		goto error;
 	}
 
+	session_entry->join_probe_cnt++;
 	return;
 error:
 	if (session_entry) {

+ 53 - 13
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -429,6 +429,7 @@ static bool __lim_process_sme_sys_ready_ind(struct mac_context *mac,
 	if (ANI_DRIVER_TYPE(mac) != QDF_DRIVER_TYPE_MFG) {
 		ready_req->pe_roam_synch_cb = pe_roam_synch_callback;
 		ready_req->pe_disconnect_cb = pe_disconnect_callback;
+		ready_req->pe_roam_set_ie_cb = pe_set_ie_for_roam_invoke;
 		pe_register_mgmt_rx_frm_callback(mac);
 		pe_register_callbacks_with_wma(mac, ready_req);
 		mac->lim.sme_msg_callback = ready_req->sme_msg_cb;
@@ -2791,11 +2792,15 @@ lim_fill_dot11_mode(struct mac_context *mac_ctx, struct pe_session *session,
 	if (QDF_IS_STATUS_ERROR(status))
 		return status;
 
-	session->dot11mode = intersected_mode;
 	pe_debug("vdev id %d opmode %d self dot11mode %d bss_dot11 mode %d intersected %d",
 		 session->vdev_id, session->opmode, self_dot11_mode,
 		 bss_dot11_mode, intersected_mode);
 
+	if (wlan_vdev_mlme_is_mlo_link_vdev(session->vdev) &&
+	    !IS_DOT11_MODE_EHT(intersected_mode))
+		return QDF_STATUS_E_INVAL;
+
+	session->dot11mode = intersected_mode;
 	lim_verify_dot11_mode_with_crypto(session);
 
 	return status;
@@ -3277,8 +3282,9 @@ lim_fill_pe_session(struct mac_context *mac_ctx, struct pe_session *session,
 	}
 	cb_mode = wlan_get_cb_mode(mac_ctx, session->curr_op_freq, ie_struct,
 				   session);
+
 	if (WLAN_REG_IS_24GHZ_CH_FREQ(bss_desc->chan_freq) &&
-	    session->force_24ghz_in_ht20)
+	    wlan_cm_get_force_20mhz_in_24ghz(session->vdev))
 		cb_mode = PHY_SINGLE_CHANNEL_CENTERED;
 
 	status = wlan_get_rate_set(mac_ctx, ie_struct, session);
@@ -4551,8 +4557,7 @@ lim_fill_session_params(struct mac_context *mac_ctx,
 	session->ssId.length = req->entry->ssid.length;
 	qdf_mem_copy(session->ssId.ssId, req->entry->ssid.ssid,
 		     session->ssId.length);
-
-	session->force_24ghz_in_ht20 = req->force_24ghz_in_ht20;
+	session->ssidHidden = req->is_ssid_hidden;
 
 	status = lim_fill_pe_session(mac_ctx, session, bss_desc);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -9930,6 +9935,9 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx,
 	QDF_STATUS status;
 	enum phy_ch_width ch_width;
 	uint32_t target_ch_freq;
+	bool is_vdev_ll_lt_sap = false;
+	uint8_t peer_count;
+	uint16_t max_wait_for_bcn_tx_complete;
 
 	if (!msg_buf) {
 		pe_err("Buffer is Pointing to NULL");
@@ -9960,8 +9968,6 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx,
 	target_ch_freq = dfs_csa_ie_req->target_chan_freq;
 	/* Channel switch announcement needs to be included in beacon */
 	session_entry->dfsIncludeChanSwIe = true;
-	session_entry->gLimChannelSwitch.switchCount =
-		 dfs_csa_ie_req->ch_switch_beacon_cnt;
 
 	wlan_reg_set_create_punc_bitmap(&dfs_csa_ie_req->ch_params, false);
 	wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev,
@@ -9978,9 +9984,21 @@ static void lim_process_sme_dfs_csa_ie_request(struct mac_context *mac_ctx,
 	session_entry->gLimChannelSwitch.ch_width = ch_width;
 	session_entry->gLimChannelSwitch.sec_ch_offset =
 				 dfs_csa_ie_req->ch_params.sec_ch_offset;
-	if (mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch == false)
-		session_entry->gLimChannelSwitch.switchMode =
-			 dfs_csa_ie_req->ch_switch_mode;
+
+	is_vdev_ll_lt_sap = policy_mgr_is_vdev_ll_lt_sap(
+						mac_ctx->psoc,
+						session_entry->vdev_id);
+
+	if (is_vdev_ll_lt_sap) {
+		session_entry->gLimChannelSwitch.switchCount = 1;
+		session_entry->gLimChannelSwitch.switchMode = 0;
+	} else {
+		session_entry->gLimChannelSwitch.switchCount =
+			dfs_csa_ie_req->ch_switch_beacon_cnt;
+		if (!mac_ctx->sap.SapDfsInfo.disable_dfs_ch_switch)
+			session_entry->gLimChannelSwitch.switchMode =
+					dfs_csa_ie_req->ch_switch_mode;
+	}
 
 	/*
 	 * Validate if SAP is operating HT or VHT/HE mode and set the Channel
@@ -10055,11 +10073,23 @@ skip_vht:
 	session_entry->cac_duration_ms = dfs_csa_ie_req->new_chan_cac_ms;
 	wlan_util_vdev_mgr_set_cac_timeout_for_vdev(
 		session_entry->vdev, dfs_csa_ie_req->new_chan_cac_ms);
+
+	peer_count = wlan_vdev_get_peer_sta_count(session_entry->vdev);
+
+	if (is_vdev_ll_lt_sap && !peer_count) {
+		pe_debug("Peer count is 0 for LL_LT_SAP, continue CSA directly");
+		/* initiate vdev restart if no peer connected on XPAN */
+		lim_send_csa_tx_complete(session_entry->vdev_id);
+		/* Clear CSA IE count and update beacon */
+		lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
+		return;
+	}
+
 	/* Send CSA IE request from here */
 	lim_send_dfs_chan_sw_ie_update(mac_ctx, session_entry);
 
 	/*
-	 * Wait for MAX_WAIT_FOR_BCN_TX_COMPLETE ms for tx complete for beacon.
+	 * Wait for max_wait_for_bcn_tx_complete ms for tx complete for beacon.
 	 * If tx complete for beacon is received before this timer expire,
 	 * stop this timer and then this will be restarted for every beacon
 	 * interval until switchCount become 0 and bcn template with new
@@ -10070,8 +10100,14 @@ skip_vht:
 	 * become 0 and bcn template with new switchCount will be sent to
 	 * firmware.
 	 */
+	if (is_vdev_ll_lt_sap)
+		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE_FOR_LL_SAP;
+	else
+		max_wait_for_bcn_tx_complete = MAX_WAIT_FOR_BCN_TX_COMPLETE;
+
 	status = qdf_mc_timer_start(&session_entry->ap_ecsa_timer,
-				    MAX_WAIT_FOR_BCN_TX_COMPLETE);
+				    max_wait_for_bcn_tx_complete);
+
 	if (QDF_IS_STATUS_ERROR(status))
 		pe_err("cannot start ap_ecsa_timer");
 
@@ -10083,10 +10119,14 @@ skip_vht:
 		 session_entry->dfsIncludeChanWrapperIe,
 		 session_entry->gLimChannelSwitch.sec_ch_offset);
 
-	/* Send ECSA/CSA Action frame after updating the beacon */
+	/*
+	 * Send ECSA/CSA Action frame after updating the beacon.
+	 * For LL_LT_SAP, send ECSA action frame only
+	 */
 	if (CHAN_HOP_ALL_BANDS_ENABLE &&
 	    session_entry->lim_non_ecsa_cap_num &&
-	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq))
+	    !WLAN_REG_IS_6GHZ_CHAN_FREQ(target_ch_freq) &&
+	    !is_vdev_ll_lt_sap)
 		lim_send_chan_switch_action_frame
 			(mac_ctx,
 			 session_entry->gLimChannelSwitch.primaryChannel,

+ 3 - 3
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -5569,8 +5569,8 @@ lim_send_link_report_action_frame(struct mac_context *mac,
 			nStatus);
 	}
 
-	pe_warn("RRM: Sending Link Report to "QDF_MAC_ADDR_FMT" on vdev[%d]",
-		QDF_MAC_ADDR_REF(peer), vdev_id);
+	pe_warn_rl("RRM: Sending Link Report to "QDF_MAC_ADDR_FMT" on vdev[%d]",
+		   QDF_MAC_ADDR_REF(peer), vdev_id);
 
 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
@@ -5589,7 +5589,7 @@ lim_send_link_report_action_frame(struct mac_context *mac,
 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
 			 pe_session->peSessionId, qdf_status));
 	if (QDF_STATUS_SUCCESS != qdf_status) {
-		pe_err("wma_tx_frame FAILED! Status [%d]", qdf_status);
+		pe_err_rl("wma_tx_frame FAILED! Status [%d]", qdf_status);
 		status_code = QDF_STATUS_E_FAILURE;
 		/* Pkt will be freed up by the callback */
 		return status_code;

+ 2 - 1
core/mac/src/pe/lim/lim_session.c

@@ -670,6 +670,7 @@ struct pe_session *pe_create_session(struct mac_context *mac,
 	session_ptr->prev_auth_seq_num = 0xFFFF;
 
 	session_ptr->user_edca_set = 0;
+	session_ptr->join_probe_cnt = 0;
 
 	return &mac->lim.gpSession[i];
 
@@ -1124,7 +1125,7 @@ void lim_dump_session_info(struct mac_context *mac_ctx,
 
 	pe_nofl_debug(" MaxTxPwr %d RMF %d force_20_24 %d UAPSD flag 0x%2x auth type %d privacy %d",
 		      pe_session->maxTxPower, pe_session->limRmfEnabled,
-		      pe_session->force_24ghz_in_ht20,
+		      wlan_cm_get_force_20mhz_in_24ghz(pe_session->vdev),
 		      pe_session->gUapsdPerAcBitmask,
 		      mac_ctx->mlme_cfg->wep_params.auth_type,
 		      mac_ctx->mlme_cfg->wep_params.is_privacy_enabled);

+ 27 - 8
core/mac/src/pe/lim/lim_utils.c

@@ -84,6 +84,7 @@
 #include "parser_api.h"
 #include "wlan_mlo_mgr_link_switch.h"
 #include "wlan_epcs_api.h"
+#include "wlan_nan_api_i.h"
 
 /** -------------------------------------------------------------
    \fn lim_delete_dialogue_token_list
@@ -3823,7 +3824,7 @@ uint8_t lim_get_cb_mode_for_freq(struct mac_context *mac,
 	uint8_t cb_mode = mac->roam.configParam.channelBondingMode5GHz;
 
 	if (WLAN_REG_IS_24GHZ_CH_FREQ(chan_freq)) {
-		if (session->force_24ghz_in_ht20) {
+		if (wlan_cm_get_force_20mhz_in_24ghz(session->vdev)) {
 			cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
 			pe_debug_rl("vdev %d force 20 Mhz in 2.4 GHz",
 				    session->vdev_id);
@@ -3839,14 +3840,22 @@ static
 uint8_t lim_get_sta_cb_mode_for_24ghz(struct mac_context *mac,
 				      uint8_t vdev_id)
 {
-	struct pe_session *session;
+	struct wlan_objmgr_vdev *vdev;
 	uint8_t cb_mode = mac->roam.configParam.channelBondingMode24GHz;
 
-	session = pe_find_session_by_vdev_id(mac, vdev_id);
-	if (!session || !session->force_24ghz_in_ht20)
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc,
+						    vdev_id, WLAN_MLME_SB_ID);
+	if (!vdev)
 		return cb_mode;
 
-	return WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+	if (!wlan_cm_get_force_20mhz_in_24ghz(vdev))
+		goto end;
+
+	cb_mode = WNI_CFG_CHANNEL_BONDING_MODE_DISABLE;
+
+end:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
+	return cb_mode;
 }
 
 void lim_update_sta_run_time_ht_switch_chnl_params(struct mac_context *mac,
@@ -6042,6 +6051,7 @@ QDF_STATUS lim_send_ies_per_band(struct mac_context *mac_ctx, uint8_t vdev_id,
 	QDF_STATUS status_ht = QDF_STATUS_SUCCESS;
 	QDF_STATUS status_vht = QDF_STATUS_SUCCESS;
 	QDF_STATUS status_he = QDF_STATUS_SUCCESS;
+	QDF_STATUS status_eht = QDF_STATUS_SUCCESS;
 
 	/*
 	 * Note: Do not use Dot11f VHT structure, since 1 byte present flag in
@@ -6062,12 +6072,21 @@ QDF_STATUS lim_send_ies_per_band(struct mac_context *mac_ctx, uint8_t vdev_id,
 								vdev_id);
 	}
 
-	if (is_dot11mode_support_eht_cap(dot11_mode))
-		status_he = lim_send_eht_caps_ie(mac_ctx, device_mode, vdev_id);
+	if (is_dot11mode_support_eht_cap(dot11_mode)) {
+		if ((device_mode == QDF_NAN_DISC_MODE ||
+		     device_mode == QDF_NDI_MODE) &&
+		    !wlan_nan_is_eht_capable(mac_ctx->psoc))
+			goto end;
 
+		status_eht = lim_send_eht_caps_ie(mac_ctx, device_mode,
+						  vdev_id);
+	}
+
+end:
 	if (QDF_IS_STATUS_SUCCESS(status_ht) &&
 	    QDF_IS_STATUS_SUCCESS(status_vht) &&
-	    QDF_IS_STATUS_SUCCESS(status_he))
+	    QDF_IS_STATUS_SUCCESS(status_he) &&
+	    QDF_IS_STATUS_SUCCESS(status_eht))
 		return QDF_STATUS_SUCCESS;
 
 	return QDF_STATUS_E_FAILURE;

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

@@ -107,7 +107,9 @@
 /* To check if HT 20mhz detection bit set */
 #define OBSS_DETECTION_IS_HT_20MHZ(_m) ((_m) & OBSS_DETECTION_HT_20MHZ_BIT_MASK)
 
+#define MAX_WAIT_FOR_BCN_TX_COMPLETE_FOR_LL_SAP 500
 #define MAX_WAIT_FOR_BCN_TX_COMPLETE 4000
+
 #define MAX_WAKELOCK_FOR_CSA         5000
 #define MAX_WAIT_FOR_CH_WIDTH_UPDATE_COMPLETE 200
 

+ 3 - 3
core/mac/src/pe/rrm/rrm_api.c

@@ -347,15 +347,15 @@ rrm_process_link_measurement_request(struct mac_context *mac,
 			pe_session->maxTxPower = LinkReport.txPower;
 		}
 	}
-	pe_warn("Link Request Tx Pwr: %d Link Report Tx Pwr: %d",
-		pLinkReq->MaxTxPower.maxTxPower, LinkReport.txPower);
+	pe_warn_rl("Link Request Tx Pwr: %d Link Report Tx Pwr: %d",
+		   pLinkReq->MaxTxPower.maxTxPower, LinkReport.txPower);
 
 	LinkReport.dialogToken = pLinkReq->DialogToken.token;
 	LinkReport.rxAntenna = 0;
 	LinkReport.txAntenna = 0;
 	currentRSSI = WMA_GET_RX_RSSI_RAW(pRxPacketInfo);
 
-	pe_info("Received Link report frame with %d", currentRSSI);
+	pe_info_rl("Received Link report frame with %d", currentRSSI);
 
 	rrm_calculate_and_fill_rcpi(&LinkReport.rcpi, currentRSSI);
 	LinkReport.rsni = WMA_GET_RX_SNR(pRxPacketInfo);

+ 3 - 4
core/mac/src/pe/sch/sch_beacon_gen.c

@@ -727,6 +727,9 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess
 	if (session->dot11mode != MLME_DOT11_MODE_11B)
 		populate_dot11f_erp_info(mac_ctx, &bcn_2->ERPInfo, session);
 
+	populate_dot11f_qcn_ie(mac_ctx, session, &bcn_2->qcn_ie,
+			       QCN_IE_ATTR_ID_ALL);
+
 	if (session->htCapability) {
 		populate_dot11f_ht_caps(mac_ctx, session, &bcn_2->HTCaps);
 		populate_dot11f_ht_info(mac_ctx, &bcn_2->HTInfo, session);
@@ -746,8 +749,6 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess
 					     session->curr_op_freq,
 					     &bcn_2->num_transmit_power_env,
 					     false);
-		populate_dot11f_qcn_ie(mac_ctx, session, &bcn_2->qcn_ie,
-				       QCN_IE_ATTR_ID_ALL);
 	}
 
 	if (wlan_reg_is_6ghz_chan_freq(session->curr_op_freq)) {
@@ -757,8 +758,6 @@ sch_set_fixed_beacon_fields(struct mac_context *mac_ctx, struct pe_session *sess
 					     session->curr_op_freq,
 					     &bcn_2->num_transmit_power_env,
 					     false);
-		populate_dot11f_qcn_ie(mac_ctx, session, &bcn_2->qcn_ie,
-				       QCN_IE_ATTR_ID_ALL);
 	}
 
 	if (lim_is_session_he_capable(session)) {

+ 49 - 49
core/mac/src/sys/legacy/src/utils/src/dot11f.c

@@ -25,7 +25,7 @@
  *
  *
  * This file was automatically generated by 'framesc'
- * Fri Sep 22 02:08:42 2023 from the following file(s):
+ * Fri Nov 10 10:07:33 2023 from the following file(s):
  *
  * dot11f.frms
  *
@@ -6059,46 +6059,46 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx,
 				ielen -= (uint8_t)4;
 				break;
 			case 10:
-				if (unlikely(ielen < 2)) {
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.ap_average_access_delay, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
-				if (unlikely(ielen < 2)) {
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.ap_average_access_delay = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_besteffort, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
-				if (unlikely(ielen < 2)) {
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_besteffort = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_background, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
-				if (unlikely(ielen < 2)) {
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_background = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_video, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
-				if (unlikely(ielen < 2)) {
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_video = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_voice, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_voice = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
 				if (unlikely(ielen < 2)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
@@ -6107,14 +6107,14 @@ uint32_t dot11f_unpack_ie_measurement_report(tpAniSirGlobal pCtx,
 				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.station_count, pBuf, 0);
 				pBuf += 2;
 				ielen -= (uint8_t)2;
-				if (unlikely(ielen < 2)) {
+				if (unlikely(ielen < 1)) {
 					pDst->present = 0;
 					return DOT11F_INCOMPLETE_IE;
 				}
 
-				framesntohs(pCtx, &pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.channel_utilization, pBuf, 0);
-				pBuf += 2;
-				ielen -= (uint8_t)2;
+				pDst->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.channel_utilization = *pBuf;
+				pBuf += 1;
+				ielen -= (uint8_t)1;
 				break;
 			}
 			status |= unpack_core(pCtx,
@@ -18245,13 +18245,13 @@ uint32_t dot11f_get_packed_ie_measurement_report(tpAniSirGlobal pCtx,
 					*pnNeeded += 4;
 					break;
 				case 10:
+					*pnNeeded += 1;
+					*pnNeeded += 1;
+					*pnNeeded += 1;
+					*pnNeeded += 1;
+					*pnNeeded += 1;
 					*pnNeeded += 2;
-					*pnNeeded += 2;
-					*pnNeeded += 2;
-					*pnNeeded += 2;
-					*pnNeeded += 2;
-					*pnNeeded += 2;
-					*pnNeeded += 2;
+					*pnNeeded += 1;
 					break;
 				}
 				status = get_packed_size_core(pCtx, (uint8_t *)pIe, pnNeeded, IES_reportsta_stats);
@@ -26981,27 +26981,27 @@ uint32_t dot11f_pack_ie_measurement_report(tpAniSirGlobal pCtx,
 					pBuf += 4;
 					break;
 				case 10:
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.ap_average_access_delay, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_besteffort, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_background, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_video, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_voice, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.ap_average_access_delay;
+					*pnConsumed += 1;
+					pBuf += 1;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_besteffort;
+					*pnConsumed += 1;
+					pBuf += 1;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_background;
+					*pnConsumed += 1;
+					pBuf += 1;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_video;
+					*pnConsumed += 1;
+					pBuf += 1;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.average_access_delay_voice;
+					*pnConsumed += 1;
+					pBuf += 1;
 					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.station_count, 0);
 					*pnConsumed += 2;
 					pBuf += 2;
-					frameshtons(pCtx, pBuf, pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.channel_utilization, 0);
-					*pnConsumed += 2;
-					pBuf += 2;
+					*pBuf = pSrc->report.sta_stats.statsgroupdata.dot11_bss_average_access_delay.channel_utilization;
+					*pnConsumed += 1;
+					pBuf += 1;
 					break;
 				}
 				status = pack_core(pCtx,

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

@@ -1653,6 +1653,9 @@ static void populate_dot11f_qcn_ie_he_params(struct mac_context *mac,
 {
 	uint16_t mcs_12_13_supp;
 
+	if (!lim_is_session_he_capable(pe_session))
+		return;
+
 	/* To fix WAPI IoT issue.*/
 	if (pe_session->encryptType == eSIR_ED_WPI)
 		return;
@@ -1733,7 +1736,8 @@ void populate_dot11f_qcn_ie(struct mac_context *mac,
 		qcn_ie->qcn_version.version = QCN_IE_VERSION_SUPPORTED;
 		qcn_ie->qcn_version.sub_version = QCN_IE_SUBVERSION_SUPPORTED;
 	}
-	if (mac->mlme_cfg->vht_caps.vht_cap_info.vht_mcs_10_11_supp) {
+	if (pe_session->vhtCapability &&
+	    mac->mlme_cfg->vht_caps.vht_cap_info.vht_mcs_10_11_supp) {
 		qcn_ie->present = 1;
 		qcn_ie->vht_mcs11_attr.present = 1;
 		qcn_ie->vht_mcs11_attr.vht_mcs_10_11_supp = 1;
@@ -3790,7 +3794,7 @@ sir_convert_assoc_resp_frame2_mlo_struct(struct mac_context *mac,
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	struct mlo_partner_info partner_info;
 
-	if (ar->mlo_ie.present)
+	if (!ar->mlo_ie.present)
 		return status;
 
 	status = util_find_mlie(frame + WLAN_ASSOC_RSP_IES_OFFSET,

+ 57 - 0
core/sap/src/sap_ch_select.c

@@ -1472,6 +1472,59 @@ static void sap_update_6ghz_max_weight(struct sap_sel_ch_info *ch_info_params,
 	}
 }
 
+/**
+ * sap_update_5ghz_low_freq_weight() - Update weight of 5GHz low frequency
+ * @psoc: Pointer to psoc
+ * @ch_info_params: Pointer to sap_sel_ch_info structure
+ *
+ * This api helps to lower the 5GHz low frequency weight by
+ * SAP_NORMALISE_ACS_WEIGHT so that it will get more preference to get
+ * selected during ACS.
+ *
+ * Return: void
+ */
+static void sap_update_5ghz_low_freq_weight(
+					struct wlan_objmgr_psoc *psoc,
+					struct sap_sel_ch_info *ch_info_params)
+{
+	uint8_t ch_num;
+	qdf_freq_t freq;
+	uint32_t weight;
+
+	if (!policy_mgr_is_hw_sbs_capable(psoc))
+		return;
+
+	for (ch_num = 0; ch_num < ch_info_params->num_ch; ch_num++) {
+		freq = ch_info_params->ch_info[ch_num].chan_freq;
+		weight = ch_info_params->ch_info[ch_num].weight;
+		if (policy_mgr_is_given_freq_5g_low(psoc, freq)) {
+			/*
+			 * Lower the weight by SAP_NORMALISE_ACS_WEIGHT i.e 5%
+			 * from channel weight itself. Later if required, modify
+			 * this value.
+			 * Here are the few observation captured which results
+			 * to go with SAP_NORMALISE_ACS_WEIGHT.
+			 *
+			 * +-----------+-------------+------------+---------------+--------------------------------------+
+			 * |   freq    |  bss_count  |    rssi    |     weight    |              observation             |
+			 * +---------------------------------------------------------------------------------------------+
+			 * |  5G low   |    >6       | -76 - -56  | 17419 - 17774 | Diff b/w 5G low & 5G high min weight |
+			 * |  5G high  |    <4       | -100 - -50 | 16842 - 17685 | is ~5% of 5G low min weight		 |
+			 * |	       |	     |		  |		  |					 |
+			 * |  5G low   |    >6       | -77 - -54  | 17419 - 17730 | Diff b/w 5G low & 5G high min weight |
+			 * |  5G high  |    <4	     | -100 - -50 | 16842 - 17552 | is ~5% of 5G low min weight		 |
+			 * |	       |	     |		  |		  |					 |
+			 * |  5G low   |    >5       | -77 - -57  | 17286 - 17552 | Diff b/w 5G low & 5G high min weight |
+			 * |  5G high  |    <4       | -100 - -50 | 16842 - 17596 | is ~5% of 5G low min weight		 |
+			 * +-----------+-------------+------------+---------------+--------------------------------------+
+			 */
+
+			weight = weight - ((weight * SAP_NORMALISE_ACS_WEIGHT ) / 100);
+			ch_info_params->ch_info[ch_num].weight = weight;
+		}
+	}
+}
+
 /**
  * sap_compute_spect_weight() - Compute spectrum weight
  * @ch_info_params: Pointer to the tSpectInfoParams structure
@@ -1652,6 +1705,10 @@ debug_info:
 	}
 	sap_update_6ghz_max_weight(ch_info_params,
 				   max_valid_weight_6ghz);
+
+	if (policy_mgr_is_vdev_ll_lt_sap(mac->psoc, sap_ctx->vdev_id))
+		sap_update_5ghz_low_freq_weight(mac->psoc, ch_info_params);
+
 	sap_clear_channel_status(mac);
 }
 

+ 2 - 0
core/sap/src/sap_ch_select.h

@@ -58,6 +58,8 @@
 #define REG_MAX_EIRP_POWER 36
 #define REG_MIN_EIRP_POWER 14
 
+#define SAP_NORMALISE_ACS_WEIGHT 5
+
 /* In HT40/VHT80, Effect of primary Channel RSSi on Subband1 */
 #define SAP_SUBBAND1_RSSI_EFFECT_PRIMARY  (-20)
 /* In VHT80, Effect of primary Channel RSSI on Subband2 */

+ 9 - 0
core/sap/src/sap_fsm.c

@@ -63,6 +63,7 @@
 #include "wlan_pre_cac_api.h"
 #include <wlan_cmn_ieee80211.h>
 #include <target_if.h>
+#include "wlan_ll_sap_api.h"
 
 /*----------------------------------------------------------------------------
  * Preprocessor Definitions and Constants
@@ -1156,6 +1157,14 @@ sap_validate_chan(struct sap_context *sap_context,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, sap_context->vdev_id)) {
+		sap_context->chan_freq = wlan_ll_lt_sap_override_freq(
+							mac_ctx->psoc,
+							sap_context->vdev_id,
+							sap_context->chan_freq);
+		return QDF_STATUS_SUCCESS;
+	}
+
 	if (sap_context->vdev &&
 	    sap_context->vdev->vdev_mlme.vdev_opmode == QDF_P2P_GO_MODE) {
 	       /*

+ 2 - 0
core/sap/src/sap_module.c

@@ -1496,6 +1496,8 @@ const char *sap_get_csa_reason_str(enum sap_csa_reason_code reason)
 		return "CSA_REASON_SAP_ACS";
 	case CSA_REASON_SAP_FIX_CH_CONC_WITH_GO:
 		return "SAP_FIX_CH_CONC_WITH_GO";
+	case CSA_REASON_CONCURRENT_LL_LT_SAP_EVENT:
+		return "CONCURRENT_LL_LT_SAP_EVENT";
 	default:
 		return "UNKNOWN";
 	}

+ 2 - 3
core/sme/inc/sme_api.h

@@ -2911,14 +2911,13 @@ uint32_t sme_unpack_rsn_ie(mac_handle_t mac_handle, uint8_t *buf,
 /**
  * sme_unpack_assoc_rsp() - wrapper to unpack assoc response
  * @mac_handle: handle returned by mac_open
- * @frame: assoc response buffer pointer
- * @frame_len: assoc response buffer length
+ * @rsp: Pointer to connect rsp
  * @assoc_resp: output assoc response structure
  *
  * Return: parse status
  */
 QDF_STATUS sme_unpack_assoc_rsp(mac_handle_t mac_handle,
-				uint8_t *frame, uint32_t frame_len,
+				struct wlan_cm_connect_resp *rsp,
 				struct sDot11fAssocResponse *assoc_resp);
 
 /**

+ 33 - 5
core/sme/src/common/sme_api.c

@@ -87,6 +87,8 @@
 #include <wlan_mlo_link_force.h>
 #include "wma_eht.h"
 #include "wlan_policy_mgr_ll_sap.h"
+#include "wlan_vdev_mgr_ucfg_api.h"
+#include "wlan_vdev_mlme_main.h"
 
 static QDF_STATUS init_sme_cmd_list(struct mac_context *mac);
 
@@ -967,6 +969,11 @@ QDF_STATUS sme_update_config(mac_handle_t mac_handle,
 		sme_err("SME config params empty");
 		return status;
 	}
+	status = sme_acquire_global_lock(&mac->sme);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		sme_err("SME lock error %d", status);
+		return status;
+	}
 
 	status = csr_change_default_config_param(mac, &pSmeConfigParams->
 						csr_config);
@@ -980,7 +987,9 @@ QDF_STATUS sme_update_config(mac_handle_t mac_handle,
 	if (csr_is_all_session_disconnected(mac))
 		csr_set_global_cfgs(mac);
 
-	return status;
+	sme_release_global_lock(&mac->sme);
+
+	return QDF_STATUS_SUCCESS;
 }
 
 QDF_STATUS sme_update_roam_params(mac_handle_t mac_handle,
@@ -4970,7 +4979,14 @@ QDF_STATUS sme_vdev_self_peer_delete_resp(struct del_vdev_params *del_vdev_req)
 		return QDF_STATUS_E_INVAL;
 	}
 
-	wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
+	if (vdev->obj_state == WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
+		wma_debug("vdev delete");
+	} else {
+		wlan_vdev_mlme_notify_set_mac_addr_response(vdev,
+							    del_vdev_req->status);
+		wma_debug("mac update");
+	}
 
 	status = del_vdev_req->status;
 	qdf_mem_free(del_vdev_req);
@@ -14395,13 +14411,24 @@ uint32_t sme_unpack_rsn_ie(mac_handle_t mac_handle, uint8_t *buf,
 }
 
 QDF_STATUS sme_unpack_assoc_rsp(mac_handle_t mac_handle,
-				uint8_t *frame, uint32_t frame_len,
+				struct wlan_cm_connect_resp *rsp,
 				struct sDot11fAssocResponse *assoc_resp)
 {
+	QDF_STATUS status;
+	uint8_t ies_offset = WLAN_ASSOC_RSP_IES_OFFSET;
 	struct mac_context *mac_ctx = MAC_CONTEXT(mac_handle);
 
-	return dot11f_parse_assoc_response(mac_ctx, frame, frame_len,
-					   assoc_resp, false);
+	status = dot11f_parse_assoc_response(mac_ctx,
+					     rsp->connect_ies.assoc_rsp.ptr,
+					     rsp->connect_ies.assoc_rsp.len,
+					     assoc_resp, false);
+
+	lim_strip_and_decode_eht_cap(rsp->connect_ies.assoc_rsp.ptr + ies_offset,
+				     rsp->connect_ies.assoc_rsp.len - ies_offset,
+				     &assoc_resp->eht_cap,
+				     assoc_resp->he_cap,
+				     rsp->freq);
+	return status;
 }
 
 void sme_get_hs20vendor_ie(mac_handle_t mac_handle, uint8_t *frame,
@@ -16805,6 +16832,7 @@ QDF_STATUS sme_update_vdev_mac_addr(struct wlan_objmgr_vdev *vdev,
 	wlan_vdev_mlme_set_macaddr(vdev, mac_addr.bytes);
 	wlan_vdev_mlme_set_linkaddr(vdev, mac_addr.bytes);
 
+	ucfg_vdev_mgr_cdp_vdev_attach(vdev);
 p2p_self_peer_create:
 	if (vdev_opmode == QDF_P2P_DEVICE_MODE) {
 		vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);

+ 17 - 6
core/sme/src/csr/csr_api_roam.c

@@ -5760,8 +5760,10 @@ cm_csr_connect_done_ind(struct wlan_objmgr_vdev *vdev,
 	 * Update the IEs after connection to reconfigure
 	 * any capability that changed during connection.
 	 */
-	sme_set_vdev_ies_per_band(mac_handle, vdev_id,
-				  wlan_vdev_mlme_get_opmode(vdev));
+	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g)
+		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
+					  wlan_vdev_mlme_get_opmode(vdev));
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -5818,12 +5820,13 @@ QDF_STATUS cm_csr_handle_diconnect_req(struct wlan_objmgr_vdev *vdev,
 }
 
 QDF_STATUS
-cm_csr_diconnect_done_ind(struct wlan_objmgr_vdev *vdev,
-			  struct wlan_cm_discon_rsp *rsp)
+cm_csr_disconnect_done_ind(struct wlan_objmgr_vdev *vdev,
+			   struct wlan_cm_discon_rsp *rsp)
 {
 	mac_handle_t mac_handle;
 	struct mac_context *mac_ctx;
 	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
 
 	/*
 	 * This API is to update legacy struct and should be removed once
@@ -5836,6 +5839,10 @@ cm_csr_diconnect_done_ind(struct wlan_objmgr_vdev *vdev,
 	if (!mac_ctx)
 		return QDF_STATUS_E_INVAL;
 
+	mlme_obj = mlme_get_psoc_ext_obj(mac_ctx->psoc);
+	if (!mlme_obj)
+		return QDF_STATUS_E_INVAL;
+
 	cm_csr_set_idle(vdev_id);
 	if (cm_is_vdev_roaming(vdev))
 		sme_qos_update_hand_off(vdev_id, false);
@@ -5846,8 +5853,12 @@ cm_csr_diconnect_done_ind(struct wlan_objmgr_vdev *vdev,
 	 * any connection specific capability change and
 	 * to reset back to self cap
 	 */
-	sme_set_vdev_ies_per_band(mac_handle, vdev_id,
-				  wlan_vdev_mlme_get_opmode(vdev));
+	if (mlme_obj->cfg.obss_ht40.is_override_ht20_40_24g) {
+		wlan_cm_set_force_20mhz_in_24ghz(vdev, true);
+		sme_set_vdev_ies_per_band(mac_handle, vdev_id,
+					  wlan_vdev_mlme_get_opmode(vdev));
+	}
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 49 - 2
core/sme/src/csr/csr_util.c

@@ -38,6 +38,7 @@
 #include <../../core/src/wlan_cm_vdev_api.h>
 #include <wlan_mlo_mgr_public_structs.h>
 #include "wlan_objmgr_vdev_obj.h"
+#include "wlan_policy_mgr_ll_sap.h"
 
 #define CASE_RETURN_STR(n) {\
 	case (n): return (# n);\
@@ -303,6 +304,22 @@ bool csr_is_conn_state_wds(struct mac_context *mac, uint32_t sessionId)
 	       csr_is_conn_state_disconnected_wds(mac, sessionId);
 }
 
+uint16_t cm_csr_get_vdev_dot11_mode(uint8_t vdev_id)
+{
+	mac_handle_t mac_handle;
+	struct mac_context *mac_ctx;
+	enum csr_cfgdot11mode curr_dot11_mode;
+
+	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
+	mac_ctx = MAC_CONTEXT(mac_handle);
+	if (!mac_ctx)
+		return eCSR_CFG_DOT11_MODE_AUTO;
+
+	curr_dot11_mode = mac_ctx->roam.configParam.uCfgDot11Mode;
+
+	return csr_get_vdev_dot11_mode(mac_ctx, vdev_id, curr_dot11_mode);
+}
+
 enum csr_cfgdot11mode
 csr_get_vdev_dot11_mode(struct mac_context *mac,
 			uint8_t vdev_id,
@@ -607,12 +624,42 @@ uint16_t csr_check_concurrent_channel_overlap(struct mac_context *mac_ctx,
 	enum phy_ch_width ch_width;
 	enum channel_state state;
 
+#ifdef WLAN_FEATURE_LL_LT_SAP
+	qdf_freq_t new_sap_freq = 0;
+	bool is_ll_lt_sap_present = false;
+#endif
+
 	if (mac_ctx->roam.configParam.cc_switch_mode ==
 			QDF_MCC_TO_SCC_SWITCH_DISABLE)
 		return 0;
 
-	if (policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, vdev_id))
-		return 0;
+	/*
+	 * This is temporary code and will be removed once this feature flag
+	 * is enabled
+	 */
+#ifndef WLAN_FEATURE_LL_LT_SAP
+		if (policy_mgr_is_vdev_ll_lt_sap(mac_ctx->psoc, vdev_id))
+			return 0;
+#else
+	policy_mgr_ll_lt_sap_get_valid_freq(
+				mac_ctx->psoc, mac_ctx->pdev,
+				vdev_id, sap_ch_freq,
+				mac_ctx->roam.configParam.cc_switch_mode,
+				&new_sap_freq,
+				&is_ll_lt_sap_present);
+	/*
+	 * If ll_lt_sap is present, then it has already updated the frequency
+	 * according to current concurrency, so, return from here
+	 */
+	if (is_ll_lt_sap_present) {
+		if (new_sap_freq == sap_ch_freq)
+			return 0;
+
+		sme_debug("LL_LT_SAP concurrency updated freq %d for vdev %d",
+			  new_sap_freq, vdev_id);
+		return new_sap_freq;
+	}
+#endif
 
 	if (sap_ch_freq != 0) {
 		sap_cfreq = sap_ch_freq;

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

@@ -889,6 +889,7 @@ struct wma_wlm_stats_data {
  * @pe_roam_synch_cb: pe callback for firmware Roam Sync events
  * @csr_roam_auth_event_handle_cb: CSR callback for target authentication
  * offload event.
+ * @pe_roam_set_ie_cb: PE callback to set IEs to firmware.
  * @wmi_cmd_rsp_wake_lock: wmi command response wake lock
  * @wmi_cmd_rsp_runtime_lock: wmi command response bus lock
  * @active_uc_apf_mode: Setting that determines how APF is applied in
@@ -1017,6 +1018,9 @@ typedef struct {
 					uint8_t *deauth_disassoc_frame,
 					uint16_t deauth_disassoc_frame_len,
 					uint16_t reason_code);
+	QDF_STATUS (*pe_roam_set_ie_cb)(struct mac_context *mac_ctx,
+					uint8_t vdev_id, uint16_t dot11_mode,
+					enum QDF_OPMODE device_mode);
 	qdf_wake_lock_t wmi_cmd_rsp_wake_lock;
 	qdf_runtime_lock_t wmi_cmd_rsp_runtime_lock;
 	qdf_runtime_lock_t sap_prevent_runtime_pm_lock;

+ 4 - 2
core/wma/inc/wma_types.h

@@ -746,7 +746,8 @@ QDF_STATUS wma_register_roaming_callbacks(
 			uint8_t vdev_id,
 			uint8_t *deauth_disassoc_frame,
 			uint16_t deauth_disassoc_frame_len,
-			uint16_t reason_code));
+			uint16_t reason_code),
+		set_ies_fn_t pe_roam_set_ie_cb);
 #else
 static inline QDF_STATUS wma_register_roaming_callbacks(
 		QDF_STATUS (*csr_roam_auth_event_handle_cb)(
@@ -759,7 +760,8 @@ static inline QDF_STATUS wma_register_roaming_callbacks(
 			uint8_t vdev_id,
 			uint8_t *deauth_disassoc_frame,
 			uint16_t deauth_disassoc_frame_len,
-			uint16_t reason_code))
+			uint16_t reason_code),
+		set_ies_fn_t pe_roam_set_ie_cb)
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }

+ 1 - 1
core/wma/src/wma_data.c

@@ -2782,7 +2782,7 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen,
 
 	wlan_objmgr_peer_release_ref(peer, WLAN_MGMT_NB_ID);
 	if (status != QDF_STATUS_SUCCESS) {
-		wma_err("mgmt tx failed");
+		wma_err_rl("mgmt tx failed");
 		qdf_nbuf_free((qdf_nbuf_t)tx_frame);
 		goto error;
 	}

+ 22 - 9
core/wma/src/wma_dev_if.c

@@ -472,7 +472,11 @@ wma_release_vdev_ref(struct wma_txrx_node *iface)
 	struct wlan_objmgr_vdev *vdev;
 
 	vdev = iface->vdev;
-
+	wma_debug("vdev state: %d", vdev->obj_state);
+	if (vdev->obj_state != WLAN_OBJ_STATE_LOGICALLY_DELETED) {
+		wma_debug("no vdev delete");
+		return;
+	}
 	iface->vdev_active = false;
 	iface->vdev = NULL;
 	if (vdev)
@@ -555,13 +559,6 @@ static QDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle,
 	wma_debug("P2P Device: removing self peer "QDF_MAC_ADDR_FMT,
 		  QDF_MAC_ADDR_REF(del_vdev_req->self_mac_addr));
 
-	qdf_status = wma_remove_peer(wma_handle, del_vdev_req->self_mac_addr,
-				     vdev_id, false);
-	if (QDF_IS_STATUS_ERROR(qdf_status)) {
-		wma_err("wma_remove_peer is failed");
-		goto error;
-	}
-
 	if (wmi_service_enabled(wma_handle->wmi_handle,
 				wmi_service_sync_delete_cmds)) {
 		sta_self_wmi_rsp =
@@ -588,6 +585,17 @@ static QDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle,
 		}
 	}
 
+	 qdf_status = wma_remove_peer(wma_handle, del_vdev_req->self_mac_addr,
+				      vdev_id, false);
+	if (QDF_IS_STATUS_ERROR(qdf_status)) {
+		wma_err("wma_remove_peer is failed");
+		wma_remove_req(wma_handle, vdev_id,
+			       WMA_DEL_P2P_SELF_STA_RSP_START);
+		qdf_mem_free(sta_self_wmi_rsp);
+
+		goto error;
+	}
+
 error:
 	return qdf_status;
 }
@@ -4662,7 +4670,7 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta)
 	QDF_STATUS status;
 	int32_t ret;
 	struct wma_txrx_node *iface = NULL;
-	struct wma_target_req *msg;
+	struct wma_target_req *msg = NULL;
 	bool peer_assoc_cnf = false;
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	uint32_t i, j;
@@ -4794,6 +4802,11 @@ static void wma_add_sta_req_ap_mode(tp_wma_handle wma, tpAddStaParams add_sta)
 	ret = wma_send_peer_assoc(wma, add_sta->nwType, add_sta);
 	if (ret) {
 		add_sta->status = QDF_STATUS_E_FAILURE;
+		if (msg) {
+			wma_remove_req(wma, add_sta->smesessionId,
+				       WMA_PEER_ASSOC_CNF_START);
+			peer_assoc_cnf = false;
+		}
 		wma_remove_peer(wma, add_sta->staMac, add_sta->smesessionId,
 				false);
 		goto send_rsp;

Some files were not shown because too many files changed in this diff