浏览代码

Merge 848ed61f59f92f32cbe67d61421bf2109b3a3377 on remote branch

Change-Id: I880682a5ac3e7b424aa6f230f87a6c7d6d9e4fb1
Linux Build Service Account 1 年之前
父节点
当前提交
0855e8efb9
共有 67 个文件被更改,包括 1761 次插入286 次删除
  1. 15 2
      components/cmn_services/logging/inc/wlan_connectivity_logging.h
  2. 1 2
      components/cmn_services/logging/src/wlan_connectivity_logging.c
  3. 81 32
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
  4. 5 2
      components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c
  5. 9 1
      components/dp/core/inc/wlan_dp_main.h
  6. 14 1
      components/dp/core/inc/wlan_dp_priv.h
  7. 74 2
      components/dp/core/src/wlan_dp_main.c
  8. 2 2
      components/dp/core/src/wlan_dp_softap_txrx.c
  9. 2 2
      components/dp/core/src/wlan_dp_txrx.c
  10. 11 1
      components/dp/dispatcher/src/wlan_dp_ucfg_api.c
  11. 16 1
      components/mlme/core/src/wlan_mlme_main.c
  12. 28 1
      components/mlme/dispatcher/inc/cfg_mlme_generic.h
  13. 21 1
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  14. 9 3
      components/mlme/dispatcher/inc/wlan_mlme_public_struct.h
  15. 15 1
      components/mlme/dispatcher/src/wlan_mlme_api.c
  16. 45 1
      components/target_if/connection_mgr/src/target_if_cm_roam_offload.c
  17. 2 1
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c
  18. 21 2
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  19. 21 1
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h
  20. 7 2
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c
  21. 3 5
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h
  22. 58 12
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  23. 23 1
      components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h
  24. 8 1
      components/umac/mlme/connection_mgr/dispatcher/src/wlan_cm_roam_api.c
  25. 33 1
      components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h
  26. 63 3
      components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c
  27. 15 1
      components/umac/mlme/mlo_mgr/src/wlan_t2lm_api.c
  28. 4 2
      components/wmi/src/wmi_unified_roam_tlv.c
  29. 4 2
      core/cds/src/cds_api.c
  30. 17 2
      core/dp/txrx/ol_txrx.c
  31. 4 1
      core/dp/txrx/ol_txrx_types.h
  32. 37 2
      core/hdd/inc/hdd_config.h
  33. 5 1
      core/hdd/inc/wlan_hdd_cfg.h
  34. 5 1
      core/hdd/inc/wlan_hdd_main.h
  35. 19 3
      core/hdd/inc/wlan_hdd_mlo.h
  36. 3 2
      core/hdd/inc/wlan_hdd_power.h
  37. 8 1
      core/hdd/inc/wlan_hdd_tdls.h
  38. 74 2
      core/hdd/src/wlan_hdd_assoc.c
  39. 94 6
      core/hdd/src/wlan_hdd_cfg80211.c
  40. 52 1
      core/hdd/src/wlan_hdd_ioctl.c
  41. 67 2
      core/hdd/src/wlan_hdd_main.c
  42. 126 7
      core/hdd/src/wlan_hdd_mlo.c
  43. 4 2
      core/hdd/src/wlan_hdd_power.c
  44. 4 1
      core/hdd/src/wlan_hdd_regulatory.c
  45. 63 2
      core/hdd/src/wlan_hdd_stats.c
  46. 14 1
      core/hdd/src/wlan_hdd_stats.h
  47. 28 2
      core/hdd/src/wlan_hdd_tdls.c
  48. 3 3
      core/hdd/src/wlan_hdd_tx_rx.c
  49. 3 3
      core/mac/inc/qwlan_version.h
  50. 3 0
      core/mac/src/include/sir_debug.h
  51. 25 1
      core/mac/src/pe/include/lim_api.h
  52. 3 3
      core/mac/src/pe/lim/lim_admit_control.c
  53. 98 13
      core/mac/src/pe/lim/lim_api.c
  54. 7 1
      core/mac/src/pe/lim/lim_process_action_frame.c
  55. 148 11
      core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c
  56. 3 1
      core/mac/src/pe/lim/lim_process_cfg_updates.c
  57. 64 33
      core/mac/src/pe/lim/lim_process_message_queue.c
  58. 2 1
      core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
  59. 5 6
      core/mac/src/pe/lim/lim_process_sme_req_messages.c
  60. 88 15
      core/mac/src/pe/lim/lim_send_management_frames.c
  61. 16 0
      core/mac/src/pe/lim/lim_utils.c
  62. 21 33
      core/mac/src/pe/rrm/rrm_api.c
  63. 3 4
      core/sme/src/common/sme_api.c
  64. 26 23
      core/sme/src/rrm/sme_rrm.c
  65. 2 2
      core/wma/src/wma_dev_if.c
  66. 2 1
      core/wma/src/wma_mgmt.c
  67. 5 4
      os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c

+ 15 - 2
components/cmn_services/logging/inc/wlan_connectivity_logging.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -168,6 +168,7 @@ enum wlan_main_tag {
  * @WLAN_CONN_DIAG_BCN_RPT_RESP_EVENT: Beacon report response
  * @WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT: MLO T2LM request
  * @WLAN_CONN_DIAG_MLO_T2LM_RESP_EVENT: MLO T2LM response
+ * @WLAN_CONN_DIAG_BTM_BLOCK_EVENT: BTM-drop indication
  * @WLAN_CONN_DIAG_MAX: MAX tag
  */
 enum qca_conn_diag_log_event_type {
@@ -218,6 +219,7 @@ enum qca_conn_diag_log_event_type {
 	WLAN_CONN_DIAG_BCN_RPT_RESP_EVENT,
 	WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT,
 	WLAN_CONN_DIAG_MLO_T2LM_RESP_EVENT,
+	WLAN_CONN_DIAG_BTM_BLOCK_EVENT,
 	WLAN_CONN_DIAG_MAX
 };
 
@@ -323,6 +325,17 @@ enum wlan_diag_connect_fail_reason {
 	WLAN_DIAG_VALID_CANDIDATE_CHECK_FAIL,
 };
 
+/**
+ * enum wlan_diag_btm_block_reason - BTM drop/ignore reason code
+ * @WLAN_DIAG_BTM_BLOCK_MBO_WO_PMF: Connected to MBO without PMF capable AP
+ * @WLAN_DIAG_BTM_BLOCK_UNSUPPORTED_P2P_CONC: p2p go/cli is present which
+ *  restricts BTM roaming
+ */
+enum wlan_diag_btm_block_reason {
+	WLAN_DIAG_BTM_BLOCK_MBO_WO_PMF = 1,
+	WLAN_DIAG_BTM_BLOCK_UNSUPPORTED_P2P_CONC = 2,
+};
+
 /**
  * struct wlan_connectivity_log_diag_cmn - Structure for diag event
  * @bssid: bssid
@@ -1314,7 +1327,7 @@ void wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev);
  * @token: dialog Token
  * @t2lm_status: T2LM response status code. Refer enum wlan_t2lm_resp_frm_type
  * @tx_status: TX status
- * @freq: Frame received/transmitted frequency
+ * @freq: frequency on which frame was transmitted/received
  * @is_rx: Flag to inidcate packet being received
  * @subtype: Determine whether the evnt sent is for t2lm request
  * or t2lm response

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -892,7 +892,6 @@ wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
 	}
 
 	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_STA_INFO);
-	wlan_connectivity_connecting_event(vdev, NULL);
 out:
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID);
 }

+ 81 - 32
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -8547,9 +8547,8 @@ policy_mgr_is_restart_sap_required_with_mlo_sta(struct wlan_objmgr_psoc *psoc,
 /**
  * policy_mgr_is_new_force_allowed() - Check if the new force command is allowed
  * @psoc: PSOC object information
- * @active_link_bitmap: Active link bitmap
- * @force_inactive_num_bitmap: Force inactive number bitmap
- * @force_inactive_num: Number of links to be forced inactive
+ * @vdev: ml sta vdev object
+ * @active_link_bitmap: Active link bitmap from user request
  *
  * If ML STA associates in 3-link (2.4 GHz + 5 GHz + 6 GHz), Host sends force
  * inactive num command between 5 GHz and 6 GHz links to firmware as it's a DBS
@@ -8561,23 +8560,54 @@ policy_mgr_is_restart_sap_required_with_mlo_sta(struct wlan_objmgr_psoc *psoc,
  */
 static bool
 policy_mgr_is_new_force_allowed(struct wlan_objmgr_psoc *psoc,
-				uint32_t active_link_bitmap,
-				uint16_t force_inactive_num_bitmap,
-				uint8_t force_inactive_num)
+				struct wlan_objmgr_vdev *vdev,
+				uint32_t active_link_bitmap)
 {
 	uint32_t link_bitmap = 0;
 	uint8_t link_num = 0;
-
-	link_bitmap = ~active_link_bitmap & force_inactive_num_bitmap;
-	if (force_inactive_num_bitmap) {
+	struct set_link_req conc_link_req;
+
+	qdf_mem_zero(&conc_link_req, sizeof(conc_link_req));
+	ml_nlink_get_force_link_request(psoc, vdev, &conc_link_req,
+					SET_LINK_FROM_CONCURRENCY);
+	/* If force inactive num is present due to MCC link(DBS RD) or
+	 * concurrency with legacy intf, don't allow force active if
+	 * left inactive link number doesn't meet concurrency
+	 * requirement.
+	 */
+	if (conc_link_req.force_inactive_num_bitmap ||
+	    conc_link_req.force_inactive_num) {
+		link_bitmap = ~active_link_bitmap &
+		conc_link_req.force_inactive_num_bitmap;
 		if (!link_bitmap) {
-			policy_mgr_err("New force bitmap not allowed");
+			policy_mgr_err("New force bitmap 0x%x not allowed due to force_inactive_num_bitmap 0x%x",
+				       active_link_bitmap,
+				       conc_link_req.
+				       force_inactive_num_bitmap);
 			return false;
 		}
 		link_num = convert_link_bitmap_to_link_ids(link_bitmap,
 							   0, NULL);
-		if (link_num < force_inactive_num)
+		if (link_num < conc_link_req.force_inactive_num) {
+			policy_mgr_debug("force inact num exists with %d don't allow act bitmap 0x%x",
+					 conc_link_req.force_active_num,
+					 active_link_bitmap);
+			return false;
+		}
+	}
+	/* If force inactive bitmap is present due to link removal or
+	 * concurrency with legacy intf, don't allow force active if
+	 * it is conflict with existing concurrency requirement.
+	 */
+	if (conc_link_req.force_inactive_bitmap) {
+		link_bitmap = active_link_bitmap &
+			conc_link_req.force_inactive_bitmap;
+		if (link_bitmap) {
+			policy_mgr_err("New force act bitmap 0x%x not allowed due to conc force inact bitmap 0x%x",
+				       active_link_bitmap,
+				       conc_link_req.force_inactive_bitmap);
 			return false;
+		}
 	}
 
 	return true;
@@ -8659,26 +8689,17 @@ void policy_mgr_activate_mlo_links_nlink(struct wlan_objmgr_psoc *psoc,
 		policy_mgr_debug("Concurrency exists, cannot enter EMLSR mode");
 		goto done;
 	} else {
-		ml_nlink_get_curr_force_state(psoc, vdev, &curr);
-		if (curr.force_inactive_num || curr.force_active_num) {
-			if (curr.force_inactive_num) {
-				if (!policy_mgr_is_new_force_allowed(
-						psoc, active_link_bitmap,
-						curr.force_inactive_num_bitmap,
-						curr.force_inactive_num)) {
-					policy_mgr_debug("force num exists with act %d %d don't enter EMLSR mode",
-							 curr.force_active_num,
-							 curr.force_inactive_num);
-					goto done;
-				}
-			}
-		}
+		if (!policy_mgr_is_new_force_allowed(
+			psoc, vdev, active_link_bitmap))
+			goto done;
+
 		/* If current force inactive bitmap exists, we have to remove
 		 * the new active bitmap from the existing inactive bitmap,
 		 * e.g. a link id can't be present in active bitmap and
 		 * inactive bitmap at same time, so update inactive bitmap
 		 * as well.
 		 */
+		ml_nlink_get_curr_force_state(psoc, vdev, &curr);
 		if (curr.force_inactive_bitmap && !inactive_link_cnt) {
 			inactive_link_bitmap = curr.force_inactive_bitmap &
 						~active_link_bitmap;
@@ -8722,7 +8743,7 @@ done:
 
 void policy_mgr_activate_mlo_links(struct wlan_objmgr_psoc *psoc,
 				   uint8_t session_id, uint8_t num_links,
-				   struct qdf_mac_addr active_link_addr[2])
+				   struct qdf_mac_addr *active_link_addr)
 {
 	uint8_t idx, link, active_vdev_cnt = 0, inactive_vdev_cnt = 0;
 	uint16_t ml_vdev_cnt = 0;
@@ -11218,7 +11239,9 @@ bool policy_mgr_is_sap_allowed_on_dfs_freq(struct wlan_objmgr_pdev *pdev,
 {
 	struct wlan_objmgr_psoc *psoc;
 	uint32_t sta_sap_scc_on_dfs_chan;
-	uint32_t sta_cnt, gc_cnt;
+	uint32_t sta_cnt, gc_cnt, idx;
+	uint8_t vdev_id_list[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0};
+	struct wlan_objmgr_vdev *vdev;
 
 	psoc = wlan_pdev_get_psoc(pdev);
 	if (!psoc)
@@ -11226,10 +11249,12 @@ bool policy_mgr_is_sap_allowed_on_dfs_freq(struct wlan_objmgr_pdev *pdev,
 
 	sta_sap_scc_on_dfs_chan =
 		policy_mgr_is_sta_sap_scc_allowed_on_dfs_chan(psoc);
-	sta_cnt = policy_mgr_mode_specific_connection_count(psoc,
-							    PM_STA_MODE, NULL);
-	gc_cnt = policy_mgr_mode_specific_connection_count(psoc,
-						PM_P2P_CLIENT_MODE, NULL);
+	sta_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
+							 vdev_id_list,
+							 PM_STA_MODE);
+	gc_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
+							&vdev_id_list[sta_cnt],
+							PM_P2P_CLIENT_MODE);
 
 	policy_mgr_debug("sta_sap_scc_on_dfs_chan %u, sta_cnt %u, gc_cnt %u",
 			 sta_sap_scc_on_dfs_chan, sta_cnt, gc_cnt);
@@ -11245,6 +11270,30 @@ bool policy_mgr_is_sap_allowed_on_dfs_freq(struct wlan_objmgr_pdev *pdev,
 		return false;
 	}
 
+	/*
+	 * Check if any of the concurrent STA/ML-STA link/P2P client are in
+	 * disconnecting state and disallow current SAP CSA. Concurrencies
+	 * would be re-evaluated upon disconnect completion and SAP would be
+	 * moved to right channel.
+	 */
+	for (idx = 0; idx < sta_cnt + gc_cnt; idx++) {
+		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
+							    vdev_id_list[idx],
+							    WLAN_POLICY_MGR_ID);
+		if (!vdev) {
+			policy_mgr_err("Invalid vdev");
+			return false;
+		}
+		if (wlan_cm_is_vdev_disconnecting(vdev) ||
+		    mlo_is_any_link_disconnecting(vdev)) {
+			policy_mgr_err("SAP is not allowed to move to DFS channel at this time, vdev %d",
+				       vdev_id_list[idx]);
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+			return false;
+		}
+		wlan_objmgr_vdev_release_ref(vdev, WLAN_POLICY_MGR_ID);
+	}
+
 	return true;
 }
 

+ 5 - 2
components/cp_stats/dispatcher/src/wlan_cp_stats_mc_tgt_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -862,7 +862,7 @@ static void tgt_mc_cp_stats_extract_vdev_summary_stats(
 					struct wlan_objmgr_psoc *psoc,
 					struct stats_event *ev)
 {
-	uint8_t i, vdev_id;
+	uint8_t i, vdev_id = WLAN_INVALID_VDEV_ID;
 	QDF_STATUS status;
 	struct wlan_objmgr_peer *peer = NULL;
 	struct request_info last_req = {0};
@@ -895,6 +895,9 @@ static void tgt_mc_cp_stats_extract_vdev_summary_stats(
 		return;
 	}
 
+	if (vdev_id == WLAN_INVALID_VDEV_ID)
+		return;
+
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 						    WLAN_CP_STATS_ID);
 	if (!vdev) {

+ 9 - 1
components/dp/core/inc/wlan_dp_main.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -967,6 +967,14 @@ QDF_STATUS wlan_dp_select_profile_cfg(struct wlan_objmgr_psoc *psoc)
 }
 #endif
 
+/**
+ * wlan_dp_link_cdp_vdev_delete_notification() - CDP vdev delete notification
+ * @context: osif_vdev handle
+ *
+ * Return: None
+ */
+void wlan_dp_link_cdp_vdev_delete_notification(void *context);
+
 /* DP CFG APIs - START */
 
 #ifdef WLAN_SUPPORT_RX_FISA

+ 14 - 1
components/dp/core/inc/wlan_dp_priv.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -701,6 +701,11 @@ struct wlan_dp_intf {
  * @vdev: object manager vdev context
  * @vdev_lock: vdev spin lock
  * @conn_info: STA connection information
+ * @destroyed: flag to indicate dp_link destroyed (logical delete)
+ * @cdp_vdev_registered: flag to indicate if corresponding CDP vdev
+ *			 is registered
+ * @cdp_vdev_deleted: flag to indicate if corresponding CDP vdev is deleted
+ * @inactive_list_elem: list node for membership in dp link inactive list
  */
 struct wlan_dp_link {
 	qdf_list_node_t node;
@@ -710,6 +715,10 @@ struct wlan_dp_link {
 	struct wlan_objmgr_vdev *vdev;
 	qdf_spinlock_t vdev_lock;
 	struct wlan_dp_conn_info conn_info;
+	uint8_t destroyed : 1,
+		cdp_vdev_registered : 1,
+		cdp_vdev_deleted : 1;
+	TAILQ_ENTRY(wlan_dp_link) inactive_list_elem;
 };
 
 /**
@@ -805,6 +814,8 @@ struct dp_direct_link_context {
  * @skip_fisa_param.skip_fisa: Flag to skip FISA aggr inside @skip_fisa_param
  * @skip_fisa_param.fisa_force_flush: Force flush inside @skip_fisa_param
  * @fst_cmem_size: CMEM size for FISA flow table
+ * @inactive_dp_link_list: inactive DP links list
+ * @dp_link_del_lock: DP link delete operation lock
  */
 struct wlan_dp_psoc_context {
 	struct wlan_objmgr_psoc *psoc;
@@ -905,6 +916,8 @@ struct wlan_dp_psoc_context {
 	uint64_t fst_cmem_size;
 
 #endif
+	TAILQ_HEAD(, wlan_dp_link) inactive_dp_link_list;
+	qdf_spinlock_t dp_link_del_lock;
 };
 
 #ifdef WLAN_DP_PROFILE_SUPPORT

+ 74 - 2
components/dp/core/src/wlan_dp_main.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -80,6 +80,7 @@ QDF_STATUS dp_allocate_ctx(void)
 
 	qdf_spinlock_create(&dp_ctx->intf_list_lock);
 	qdf_list_create(&dp_ctx->intf_list, 0);
+	TAILQ_INIT(&dp_ctx->inactive_dp_link_list);
 
 	dp_attach_ctx(dp_ctx);
 
@@ -1246,10 +1247,32 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	return status;
 }
 
+static void dp_link_handle_cdp_vdev_delete(struct wlan_dp_psoc_context *dp_ctx,
+					   struct wlan_dp_link *dp_link)
+{
+	qdf_spin_lock_bh(&dp_ctx->dp_link_del_lock);
+
+	if (!dp_link->cdp_vdev_registered || dp_link->cdp_vdev_deleted) {
+		/* CDP vdev is not created/registered or already deleted */
+		qdf_mem_free(dp_link);
+	} else {
+		/*
+		 * Add it to inactive dp_link list, and it will be freed when
+		 * the CDP vdev gets deleted
+		 */
+		TAILQ_INSERT_TAIL(&dp_ctx->inactive_dp_link_list, dp_link,
+				  inactive_list_elem);
+		dp_link->destroyed = 1;
+	}
+
+	qdf_spin_unlock_bh(&dp_ctx->dp_link_del_lock);
+}
+
 QDF_STATUS
 dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 
 {
+	struct wlan_dp_psoc_context *dp_ctx;
 	struct wlan_dp_intf *dp_intf;
 	struct wlan_dp_link *dp_link;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -1264,6 +1287,7 @@ dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 	}
 
 	dp_intf = dp_link->dp_intf;
+	dp_ctx = dp_intf->dp_ctx;
 
 	qdf_spin_lock_bh(&dp_intf->dp_link_list_lock);
 	qdf_list_remove_node(&dp_intf->dp_link_list, &dp_link->node);
@@ -1324,7 +1348,8 @@ dp_vdev_obj_destroy_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 		return status;
 	}
 
-	qdf_mem_free(dp_link);
+	dp_link_handle_cdp_vdev_delete(dp_ctx, dp_link);
+
 	return status;
 }
 
@@ -1978,6 +2003,53 @@ wlan_dp_fisa_resume(struct wlan_dp_psoc_context *dp_ctx)
 }
 #endif
 
+void wlan_dp_link_cdp_vdev_delete_notification(void *context)
+{
+	struct wlan_dp_link *dp_link = (struct wlan_dp_link *)context;
+	struct wlan_dp_link *tmp_dp_link;
+	struct wlan_dp_intf *dp_intf = NULL;
+	struct wlan_dp_psoc_context *dp_ctx = NULL;
+	uint8_t found = 0;
+
+	/* TODO - What will happen if cdp vdev was never created ? */
+
+	/* dp_link will not be freed before this point. */
+	if (!dp_link)
+		return;
+
+	dp_intf = dp_link->dp_intf;
+	dp_ctx = dp_intf->dp_ctx;
+
+	qdf_spin_lock_bh(&dp_ctx->dp_link_del_lock);
+
+	if (dp_link->destroyed) {
+		/*
+		 * dp_link has been destroyed as a part of vdev_obj_destroy
+		 * notification and will be present in inactive list
+		 */
+		TAILQ_FOREACH(tmp_dp_link, &dp_ctx->inactive_dp_link_list,
+			      inactive_list_elem) {
+			if (tmp_dp_link == dp_link) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			TAILQ_REMOVE(&dp_ctx->inactive_dp_link_list, dp_link,
+				     inactive_list_elem);
+		else
+			qdf_assert_always(0);
+
+		qdf_mem_free(dp_link);
+	} else {
+		/* dp_link not yet destroyed */
+		dp_link->cdp_vdev_deleted = 1;
+	}
+
+	qdf_spin_unlock_bh(&dp_ctx->dp_link_del_lock);
+}
+
 QDF_STATUS __wlan_dp_runtime_suspend(ol_txrx_soc_handle soc, uint8_t pdev_id)
 {
 	struct wlan_dp_psoc_context *dp_ctx;

+ 2 - 2
components/dp/core/src/wlan_dp_softap_txrx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -483,7 +483,7 @@ static QDF_STATUS dp_softap_validate_peer_state(struct wlan_dp_link *dp_link,
 	QDF_BUG(soc);
 	dp_wds_replace_peer_mac(soc, dp_link, mac_addr.bytes);
 	peer_state = cdp_peer_state_get(soc, dp_link->link_id,
-					mac_addr.bytes);
+					mac_addr.bytes, false);
 
 	if (peer_state == OL_TXRX_PEER_STATE_INVALID) {
 		dp_debug_rl("Failed to find right station");

+ 2 - 2
components/dp/core/src/wlan_dp_txrx.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -123,7 +123,7 @@ static int dp_intf_is_tx_allowed(qdf_nbuf_t nbuf,
 {
 	enum ol_txrx_peer_state peer_state;
 
-	peer_state = cdp_peer_state_get(soc, intf_id, peer_mac);
+	peer_state = cdp_peer_state_get(soc, intf_id, peer_mac, false);
 	if (qdf_likely(OL_TXRX_PEER_STATE_AUTH == peer_state))
 		return true;
 	if (OL_TXRX_PEER_STATE_CONN == peer_state &&

+ 11 - 1
components/dp/dispatcher/src/wlan_dp_ucfg_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -1176,6 +1176,7 @@ QDF_STATUS ucfg_dp_sta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	txrx_ops.tx.tx_comp = dp_sta_notify_tx_comp_cb;
 	txrx_ops.tx.tx = NULL;
 	txrx_ops.get_tsf_time = wlan_dp_get_tsf_time;
+	txrx_ops.vdev_del_notify = wlan_dp_link_cdp_vdev_delete_notification;
 	cdp_vdev_register(soc, dp_link->link_id, (ol_osif_vdev_handle)dp_link,
 			  &txrx_ops);
 	if (!txrx_ops.tx.tx) {
@@ -1183,6 +1184,7 @@ QDF_STATUS ucfg_dp_sta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	dp_link->cdp_vdev_registered = 1;
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1227,6 +1229,7 @@ QDF_STATUS ucfg_dp_tdlsta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	txrx_ops.tx.tx_comp = dp_sta_notify_tx_comp_cb;
 	txrx_ops.tx.tx = NULL;
 
+	txrx_ops.vdev_del_notify = wlan_dp_link_cdp_vdev_delete_notification;
 	cdp_vdev_register(soc, dp_link->link_id, (ol_osif_vdev_handle)dp_link,
 			  &txrx_ops);
 
@@ -1235,6 +1238,7 @@ QDF_STATUS ucfg_dp_tdlsta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	dp_link->cdp_vdev_registered = 1;
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1259,6 +1263,7 @@ QDF_STATUS ucfg_dp_ocb_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
 	txrx_ops.rx.rx = dp_rx_packet_cbk;
 	txrx_ops.rx.stats_rx = dp_tx_rx_collect_connectivity_stats_info;
+	txrx_ops.vdev_del_notify = wlan_dp_link_cdp_vdev_delete_notification;
 
 	cdp_vdev_register(soc, dp_link->link_id, (ol_osif_vdev_handle)dp_link,
 			  &txrx_ops);
@@ -1267,6 +1272,7 @@ QDF_STATUS ucfg_dp_ocb_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	dp_link->cdp_vdev_registered = 1;
 	dp_intf->txrx_ops = txrx_ops;
 
 	qdf_copy_macaddr(&dp_link->conn_info.peer_macaddr,
@@ -1293,10 +1299,12 @@ QDF_STATUS ucfg_dp_mon_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	qdf_mem_zero(&txrx_ops, sizeof(txrx_ops));
 	txrx_ops.rx.rx = dp_mon_rx_packet_cbk;
 	dp_monitor_set_rx_monitor_cb(&txrx_ops, dp_rx_monitor_callback);
+	txrx_ops.vdev_del_notify = wlan_dp_link_cdp_vdev_delete_notification;
 	cdp_vdev_register(soc, dp_link->link_id,
 			  (ol_osif_vdev_handle)dp_link,
 			  &txrx_ops);
 
+	dp_link->cdp_vdev_registered = 1;
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1333,6 +1341,7 @@ QDF_STATUS ucfg_dp_softap_register_txrx_ops(struct wlan_objmgr_vdev *vdev,
 	}
 
 	txrx_ops->get_tsf_time = wlan_dp_get_tsf_time;
+	txrx_ops->vdev_del_notify = wlan_dp_link_cdp_vdev_delete_notification;
 	cdp_vdev_register(soc,
 			  dp_link->link_id,
 			  (ol_osif_vdev_handle)dp_link,
@@ -1342,6 +1351,7 @@ QDF_STATUS ucfg_dp_softap_register_txrx_ops(struct wlan_objmgr_vdev *vdev,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	dp_link->cdp_vdev_registered = 1;
 	dp_intf->txrx_ops = *txrx_ops;
 	dp_intf->sap_tx_block_mask &= ~DP_TX_FN_CLR;
 

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1152,6 +1152,20 @@ static void mlme_init_pmf_cfg(struct wlan_objmgr_psoc *psoc,
 		cfg_get(psoc, CFG_PMF_SA_QUERY_RETRY_INTERVAL);
 }
 
+#ifdef WLAN_FEATURE_11BE
+static inline void mlme_init_oem_eht_mlo_cfg(struct wlan_objmgr_psoc *psoc,
+					     struct wlan_mlme_generic *gen)
+{
+	gen->oem_eht_mlo_crypto_bitmap =
+				cfg_get(psoc, CFG_OEM_EHT_MLO_CRYPTO_BITMAP);
+}
+#else
+static inline void mlme_init_oem_eht_mlo_cfg(struct wlan_objmgr_psoc *psoc,
+					     struct wlan_mlme_generic *gen)
+{
+}
+#endif /* WLAN_FEATURE_11BE */
+
 #ifdef WLAN_FEATURE_LPSS
 static inline void
 mlme_init_lpass_support_cfg(struct wlan_objmgr_psoc *psoc,
@@ -1377,6 +1391,7 @@ static void mlme_init_generic_cfg(struct wlan_objmgr_psoc *psoc,
 		cfg_get(psoc, CFG_ENABLE_DEAUTH_TO_DISASSOC_MAP);
 	gen->wls_6ghz_capable = cfg_get(psoc, CFG_WLS_6GHZ_CAPABLE);
 	mlme_init_pmf_cfg(psoc, gen);
+	mlme_init_oem_eht_mlo_cfg(psoc, gen);
 	mlme_init_lpass_support_cfg(psoc, gen);
 	gen->enabled_rf_test_mode = cfg_default(CFG_RF_TEST_MODE_SUPP_ENABLED);
 	gen->enabled_11h = cfg_get(psoc, CFG_11H_SUPPORT_ENABLED);

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -234,6 +234,32 @@ enum wlan_epcs_frame {
 		CFG_VALUE_OR_DEFAULT, \
 		"PMF SA query retry interval for SAP")
 
+#ifdef WLAN_FEATURE_11BE
+/*
+ * oem_eht_mlo_crypto_bitmap - OEM control to allow various EHT connection
+ * options using bitmap based on following ENUM (Name of ENUM to be added)
+ * @Min: 0x0
+ * @Max: 0xFFFFFFFF
+ * @Default: 0x0
+ *
+ * This INI is used to control the driver candidate selection and EHT
+ * connection choice based on OEM configuration. The bitmap follows the
+ * implementation from this ENUM (name of the ENUM to be added)
+ */
+#define CFG_OEM_EHT_MLO_CRYPTO_BITMAP CFG_INI_UINT( \
+		"oem_eht_mlo_crypto_bitmap", \
+		0x0, \
+		0xFFFFFFFF, \
+		0x0, \
+		CFG_VALUE_OR_DEFAULT, \
+		"OEM control to allow/disallow crypto to EHT configuration")
+
+#define CFG_OEM_EHT_MLO_CRYPTO_BITMAP_SUPPORTED \
+			CFG(CFG_OEM_EHT_MLO_CRYPTO_BITMAP)
+#else
+#define CFG_OEM_EHT_MLO_CRYPTO_BITMAP_SUPPORTED
+#endif
+
 /*
  * <ini>
  * enable_rtt_mac_randomization - Enable/Disable rtt mac randomization
@@ -1235,6 +1261,7 @@ enum wlan_epcs_frame {
 	CFG(CFG_ENABLE_DEBUG_PACKET_LOG) \
 	CFG(CFG_PMF_SA_QUERY_MAX_RETRIES) \
 	CFG(CFG_PMF_SA_QUERY_RETRY_INTERVAL) \
+	CFG_OEM_EHT_MLO_CRYPTO_BITMAP_SUPPORTED \
 	CFG(CFG_ENABLE_RTT_MAC_RANDOMIZATION) \
 	CFG(CFG_RTT3_ENABLE) \
 	CFG(CFG_11H_SUPPORT_ENABLED) \

+ 21 - 1
components/mlme/dispatcher/inc/wlan_mlme_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -2695,6 +2695,18 @@ bool mlme_get_bss_11be_allowed(struct wlan_objmgr_psoc *psoc,
 			       struct qdf_mac_addr *bssid,
 			       uint8_t *ie_data,
 			       uint32_t ie_length);
+
+/**
+ * wlan_mlme_get_oem_eht_mlo_config() - Get the OEM EHT configuration.
+ * @psoc: PSOC object manager.
+ * @oem_eht_cfg: Pointer to fill OEM cfg
+ *
+ * Returns success of retrieving OEM cfg else failure.
+ *
+ * Return: QDF_STATUS.
+ */
+QDF_STATUS wlan_mlme_get_oem_eht_mlo_config(struct wlan_objmgr_psoc *psoc,
+					    uint32_t *oem_eht_cfg);
 #else
 static inline
 bool mlme_get_bss_11be_allowed(struct wlan_objmgr_psoc *psoc,
@@ -2704,6 +2716,14 @@ bool mlme_get_bss_11be_allowed(struct wlan_objmgr_psoc *psoc,
 {
 	return false;
 }
+
+static inline QDF_STATUS
+wlan_mlme_get_oem_eht_mlo_config(struct wlan_objmgr_psoc *psoc,
+				 uint32_t *oem_eht_cfg)
+{
+	*oem_eht_cfg = 0x0;
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 /**

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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 +222,7 @@ struct mlme_edca_ac_vo {
 /**
  * enum mlme_dot11_mode - Dot11 mode of the vdev
  * @MLME_DOT11_MODE_ALL: vdev supports all dot11 modes
+ * @MLME_DOT11_MODE_ABG: vdev supports just 11A, 11B and 11G modes
  * @MLME_DOT11_MODE_11A: vdev just supports 11A mode
  * @MLME_DOT11_MODE_11B: vdev supports 11B mode, and modes above it
  * @MLME_DOT11_MODE_11G: vdev supports 11G mode, and modes above it
@@ -234,10 +235,11 @@ struct mlme_edca_ac_vo {
  * @MLME_DOT11_MODE_11AX_ONLY: vdev just supports 11AX mode
  * @MLME_DOT11_MODE_11BE: vdev supports 11BE mode, and modes above it
  * @MLME_DOT11_MODE_11BE_ONLY: vdev just supports 11BE mode
- * @MLME_DOT11_MODE_ABG: vdev supports just 11A, 11B and 11G modes
  */
 enum mlme_dot11_mode {
 	MLME_DOT11_MODE_ALL,
+	/* Initial dot11 modes should come first */
+	MLME_DOT11_MODE_ABG,
 	MLME_DOT11_MODE_11A,
 	MLME_DOT11_MODE_11B,
 	MLME_DOT11_MODE_11G,
@@ -250,7 +252,6 @@ enum mlme_dot11_mode {
 	MLME_DOT11_MODE_11AX_ONLY,
 	MLME_DOT11_MODE_11BE,
 	MLME_DOT11_MODE_11BE_ONLY,
-	MLME_DOT11_MODE_ABG
 };
 
 /**
@@ -1478,6 +1479,8 @@ struct wlan_mlme_aux_dev_caps {
  * @t2lm_negotiation_support: T2LM negotiation supported enum value
  * @enable_emlsr_mode: 11BE eMLSR mode support
  * @mld_id: MLD ID of requested BSS within ML probe request frame
+ * @oem_eht_mlo_crypto_bitmap: Bitmap of APs allowed by OEMs to connect
+ * in EHT/MLO.
  * @safe_mode_enable: safe mode to bypass some strict 6 GHz checks for
  * connection, bypass strict power levels
  * @sr_enable_modes: modes for which SR(Spatial Reuse) is enabled
@@ -1541,6 +1544,9 @@ struct wlan_mlme_generic {
 	enum t2lm_negotiation_support t2lm_negotiation_support;
 	uint8_t mld_id;
 #endif
+#ifdef WLAN_FEATURE_11BE
+	uint32_t oem_eht_mlo_crypto_bitmap;
+#endif
 #ifdef WLAN_FEATURE_MCC_QUOTA
 	struct wlan_user_mcc_quota user_mcc_quota;
 #endif

+ 15 - 1
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -4840,6 +4840,20 @@ bool mlme_get_bss_11be_allowed(struct wlan_objmgr_psoc *psoc,
 
 	return false;
 }
+
+QDF_STATUS wlan_mlme_get_oem_eht_mlo_config(struct wlan_objmgr_psoc *psoc,
+					    uint32_t *oem_eht_cfg)
+{
+	struct wlan_mlme_psoc_ext_obj *mlme_obj;
+
+	mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	if (!mlme_obj)
+		return QDF_STATUS_E_FAILURE;
+
+	*oem_eht_cfg = mlme_obj->cfg.gen.oem_eht_mlo_crypto_bitmap;
+
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 QDF_STATUS wlan_mlme_is_sap_uapsd_enabled(struct wlan_objmgr_psoc *psoc,

+ 45 - 1
components/target_if/connection_mgr/src/target_if_cm_roam_offload.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1416,6 +1416,47 @@ target_if_cm_roam_send_time_sync_cmd(wmi_unified_t wmi_handle)
 	return wmi_send_time_stamp_sync_cmd_tlv(wmi_handle);
 }
 
+#ifdef WLAN_FEATURE_11BE
+static QDF_STATUS
+target_if_cm_roam_oem_eht_mlo_bitmap(struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	wmi_unified_t wmi_handle;
+	uint32_t oem_eht_bitmap;
+	struct wlan_objmgr_psoc *psoc;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!psoc) {
+		target_if_err("psoc handle is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	wmi_handle = target_if_cm_roam_get_wmi_handle_from_vdev(vdev);
+	if (!wmi_handle)
+		return status;
+
+	status = wlan_mlme_get_oem_eht_mlo_config(psoc, &oem_eht_bitmap);
+	if (QDF_IS_STATUS_ERROR(status))
+		return status;
+
+	status = target_if_roam_set_param(wmi_handle,
+					  wlan_vdev_get_id(vdev),
+					  WMI_ROAM_PARAM_CRYPTO_EHT_CONFIG,
+					  oem_eht_bitmap);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		target_if_err("Failed to set roam oem eht bitmap");
+
+	return status;
+}
+#else
+static inline QDF_STATUS
+target_if_cm_roam_oem_eht_mlo_bitmap(struct wlan_objmgr_vdev *vdev)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 #ifdef WLAN_FEATURE_11BE_MLO
 /**
  * target_if_cm_roam_send_mlo_config() - Send roam mlo related commands
@@ -1641,6 +1682,7 @@ target_if_cm_roam_send_start(struct wlan_objmgr_vdev *vdev,
 		target_if_cm_roam_rssi_diff_6ghz(vdev,
 						 req->wlan_roam_rssi_diff_6ghz);
 
+	status = target_if_cm_roam_oem_eht_mlo_bitmap(vdev);
 	/* add other wmi commands */
 end:
 	return status;
@@ -2145,6 +2187,8 @@ target_if_cm_roam_send_update_config(struct wlan_objmgr_vdev *vdev,
 		if (req->wlan_roam_rssi_diff_6ghz)
 			target_if_cm_roam_rssi_diff_6ghz(
 					vdev, req->wlan_roam_rssi_diff_6ghz);
+
+		status = target_if_cm_roam_oem_eht_mlo_bitmap(vdev);
 	}
 end:
 	return status;

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1216,6 +1216,7 @@ cm_get_and_disable_link_from_roam_ind(struct wlan_objmgr_psoc *psoc,
 			ml_nlink_set_curr_force_inactive_state(
 				psoc, vdev, 1 << synch_data->ml_link[i].link_id,
 				LINK_ADD);
+			ml_nlink_init_concurrency_link_request(psoc, vdev);
 			wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID);
 			break;
 		}

+ 21 - 2
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -42,7 +42,6 @@
 #include "connection_mgr/core/src/wlan_cm_main.h"
 #include "connection_mgr/core/src/wlan_cm_sm.h"
 #include "wlan_reg_ucfg_api.h"
-#include "wlan_connectivity_logging.h"
 #include "wlan_if_mgr_roam.h"
 #include "wlan_roam_debug.h"
 #include "wlan_mlo_mgr_roam.h"
@@ -7081,6 +7080,26 @@ cm_roam_btm_req_event(struct wmi_roam_btm_trigger_data *btm_data,
 	return status;
 }
 
+QDF_STATUS
+cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			enum wlan_diag_btm_block_reason reason)
+{
+	WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_btm_info);
+
+	qdf_mem_zero(&wlan_diag_event, sizeof(wlan_diag_event));
+
+	populate_diag_cmn(&wlan_diag_event.diag_cmn, vdev_id, 0, NULL);
+
+	wlan_diag_event.subtype = WLAN_CONN_DIAG_BTM_BLOCK_EVENT;
+	wlan_diag_event.version = DIAG_BTM_VERSION_2;
+	wlan_diag_event.token = token;
+	wlan_diag_event.sub_reason = reason;
+
+	WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_BTM);
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static enum wlan_diag_wifi_band
 wlan_convert_bitmap_to_band(uint8_t bitmap)
 {

+ 21 - 1
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -28,6 +28,7 @@
 
 #include "qdf_str.h"
 #include "wlan_cm_roam_public_struct.h"
+#include "wlan_connectivity_logging.h"
 
 #if defined(CONNECTIVITY_DIAG_EVENT) && \
 	defined(WLAN_FEATURE_ROAM_OFFLOAD)
@@ -673,6 +674,18 @@ cm_roam_neigh_rpt_req_event(struct wmi_neighbor_report_data *neigh_rpt,
 void
 cm_roam_neigh_rpt_resp_event(struct wmi_neighbor_report_data *neigh_rpt,
 			     uint8_t vdev_id);
+
+/**
+ * cm_roam_btm_block_event() - Send BTM block/drop logging event
+ * @vdev_id: vdev id
+ * @token: BTM token
+ * @reason: Reason for dropping the BTM frame
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			enum wlan_diag_btm_block_reason reason);
 #else
 static inline QDF_STATUS
 cm_roam_mgmt_frame_event(struct wlan_objmgr_vdev *vdev,
@@ -725,6 +738,13 @@ cm_roam_neigh_rpt_resp_event(struct wmi_neighbor_report_data *neigh_rpt,
 			     uint8_t vdev_id)
 {
 }
+
+static inline QDF_STATUS
+cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			enum wlan_diag_btm_block_reason reason)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif /* FEATURE_CONNECTIVITY_LOGGING */
 
 /**

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -504,9 +504,14 @@ QDF_STATUS cm_roam_sync_key_event_handler(struct wlan_objmgr_psoc *psoc,
 
 	for (i = 0; i < num_keys; i++) {
 		status = wlan_crypto_add_key_entry(psoc, &keys[i]);
-		if (QDF_IS_STATUS_ERROR(status))
+		if (QDF_IS_STATUS_ERROR(status)) {
 			mlme_err("Failed to add key entry for link:%d",
 				 keys[i].link_id);
+			wlan_crypto_free_key(&keys[i].keys);
+			qdf_mem_zero(&keys[i],
+				     sizeof(struct wlan_crypto_key_entry));
+			qdf_mem_free(&keys[i]);
+		}
 	}
 
 	return status;

+ 3 - 5
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -766,14 +766,12 @@ cm_send_rso_stop(struct wlan_objmgr_vdev *vdev)
 /**
  * cm_get_ml_partner_info() - Fill ML partner info from scan entry
  * @pdev: PDEV object
- * @scan_entry: Scan entry
- * @partner_info: Partner info to be filled
+ * @conn_req: Connect request pointer
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS
 cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev,
-		       struct scan_cache_entry *scan_entry,
-		       struct mlo_partner_info *partner_info);
+		       struct cm_connect_req *conn_req);
 #endif
 #endif /* __WLAN_CM_VDEV_API_H__ */

+ 58 - 12
components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2015, 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1162,14 +1162,61 @@ set_partner_info_for_2link_sap(struct scan_cache_entry *scan_entry,
 }
 #endif
 
+static void
+cm_check_nontx_mbssid_partner_entries(struct cm_connect_req *conn_req)
+{
+	uint8_t idx;
+	struct scan_cache_entry *entry, *partner_entry;
+	qdf_list_t *candidate_list = conn_req->candidate_list;
+	struct qdf_mac_addr *mld_addr;
+	struct partner_link_info *partner_info;
+
+	entry = conn_req->cur_candidate->entry;
+	mld_addr = util_scan_entry_mldaddr(entry);
+
+	/*
+	 * If the entry is not one of following, return gracefully:
+	 *   -AP is not ML type
+	 *   -AP is SLO
+	 *   -AP is not a member of MBSSID set
+	 *   -AP BSSID equals to TxBSSID in MBSSID set
+	 */
+	if (!mld_addr || !entry->ml_info.num_links ||
+	    !entry->mbssid_info.profile_num ||
+	    !qdf_mem_cmp(entry->mbssid_info.trans_bssid, &entry->bssid,
+			 QDF_MAC_ADDR_SIZE)) {
+		return;
+	}
+
+	for (idx = 0; idx < entry->ml_info.num_links; idx++) {
+		if (!entry->ml_info.link_info[idx].is_valid_link)
+			continue;
+
+		partner_info = &entry->ml_info.link_info[idx];
+		partner_entry = cm_get_entry(candidate_list,
+					     &partner_info->link_addr);
+		/*
+		 * If partner entry is not found in candidate list or if
+		 * the MLD address of the entry is not equal to current
+		 * candidate MLD address, treat it as entry not found.
+		 */
+		if (!partner_entry ||
+		    !qdf_is_macaddr_equal(mld_addr,
+					  &partner_entry->ml_info.mld_mac_addr)) {
+			partner_info->is_scan_entry_not_found = true;
+		}
+	}
+}
+
 QDF_STATUS
 cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev,
-		       struct scan_cache_entry *scan_entry,
-		       struct mlo_partner_info *partner_info)
+		       struct cm_connect_req *conn_req)
 {
 	uint8_t i, j = 0;
 	uint8_t mlo_support_link_num;
 	struct wlan_objmgr_psoc *psoc;
+	struct scan_cache_entry *scan_entry = conn_req->cur_candidate->entry;
+	struct mlo_partner_info *partner_info = &conn_req->req.ml_parnter_info;
 
 	/* Initialize number of partner links as zero */
 	partner_info->num_partner_links = 0;
@@ -1208,24 +1255,23 @@ cm_get_ml_partner_info(struct wlan_objmgr_pdev *pdev,
 		if (mlo_support_link_num && j >= mlo_support_link_num - 1)
 			break;
 
-		if (scan_entry->ml_info.link_info[i].is_valid_link) {
-			partner_info->partner_link_info[j].link_addr =
+		if (!scan_entry->ml_info.link_info[i].is_valid_link)
+			continue;
+
+		partner_info->partner_link_info[j].link_addr =
 				scan_entry->ml_info.link_info[i].link_addr;
-			partner_info->partner_link_info[j].link_id =
+		partner_info->partner_link_info[j].link_id =
 				scan_entry->ml_info.link_info[i].link_id;
-			partner_info->partner_link_info[j].chan_freq =
+		partner_info->partner_link_info[j].chan_freq =
 				scan_entry->ml_info.link_info[i].freq;
-			j++;
-			continue;
-		}
-
-		scan_entry->ml_info.link_info[i].is_valid_link = false;
+		j++;
 	}
 
 	partner_info->num_partner_links = j;
 	mlme_debug("sta and ap intersect num of partner link: %d", j);
 
 	set_partner_info_for_2link_sap(scan_entry, partner_info);
+	cm_check_nontx_mbssid_partner_entries(conn_req);
 
 	return QDF_STATUS_SUCCESS;
 }

+ 23 - 1
components/umac/mlme/connection_mgr/dispatcher/inc/wlan_cm_roam_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -30,6 +30,7 @@
 #include "wlan_mlme_api.h"
 #include "wlan_reg_ucfg_api.h"
 #include "wlan_cm_tgt_if_tx_api.h"
+#include "wlan_connectivity_logging.h"
 
 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD)
 /**
@@ -1396,6 +1397,20 @@ wlan_cm_add_all_link_probe_rsp_to_scan_db(struct wlan_objmgr_psoc *psoc,
  */
 bool wlan_cm_is_mbo_ap_without_pmf(struct wlan_objmgr_psoc *psoc,
 				   uint8_t vdev_id);
+
+/**
+ * wlan_cm_roam_btm_block_event() - Send BTM block/drop logging event
+ * @vdev_id: vdev id
+ * @token: BTM token
+ * @reason: Reason for dropping the BTM frame
+ *
+ * This is wrapper for cm_roam_btm_block_event()
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			     enum wlan_diag_btm_block_reason reason);
 #else
 static inline
 void wlan_cm_roam_activate_pcl_per_vdev(struct wlan_objmgr_psoc *psoc,
@@ -1671,6 +1686,13 @@ bool wlan_cm_is_mbo_ap_without_pmf(struct wlan_objmgr_psoc *psoc,
 {
 	return false;
 }
+
+static inline QDF_STATUS
+wlan_cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			     enum wlan_diag_btm_block_reason reason)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */
 
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_FEATURE_ROAM_OFFLOAD)

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -4738,6 +4738,13 @@ bool wlan_cm_is_mbo_ap_without_pmf(struct wlan_objmgr_psoc *psoc,
 {
 	return cm_is_mbo_ap_without_pmf(psoc, vdev_id);
 }
+
+QDF_STATUS
+wlan_cm_roam_btm_block_event(uint8_t vdev_id, uint8_t token,
+			     enum wlan_diag_btm_block_reason reason)
+{
+	return cm_roam_btm_block_event(vdev_id, token, reason);
+}
 #else
 QDF_STATUS
 cm_roam_stats_event_handler(struct wlan_objmgr_psoc *psoc,

+ 33 - 1
components/umac/mlme/mlo_mgr/inc/wlan_mlo_link_force.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024 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
@@ -359,6 +359,38 @@ ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc,
 				    uint16_t *dynamic_link_bitmap,
 				    uint16_t *force_link_bitmap);
 
+/**
+ * ml_nlink_init_concurrency_link_request() - Init concurrency force
+ * link request
+ * link bitmap
+ * @psoc: psoc object
+ * @vdev: vdev object
+ *
+ * When ML STA associated or Roam, initialize the concurrency
+ * force link request based on "current" force link state
+ *
+ * Return: None
+ */
+void ml_nlink_init_concurrency_link_request(
+	struct wlan_objmgr_psoc *psoc,
+	struct wlan_objmgr_vdev *vdev);
+
+/**
+ * ml_nlink_get_force_link_request() - get link request of source
+ * link bitmap
+ * @psoc: psoc object
+ * @vdev: vdev object
+ * @req: set link request
+ * @source: the source to query
+ *
+ * Return: None
+ */
+void
+ml_nlink_get_force_link_request(struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				struct set_link_req *req,
+				enum set_link_source source);
+
 /**
  * ml_nlink_get_curr_force_state() - get link force state
  * @psoc: psoc object

+ 63 - 3
components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024 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
@@ -385,6 +385,61 @@ ml_nlink_update_force_link_request(struct wlan_objmgr_psoc *psoc,
 }
 
 static void
+ml_nlink_update_concurrency_link_request(
+				struct wlan_objmgr_psoc *psoc,
+				struct wlan_objmgr_vdev *vdev,
+				struct ml_link_force_state *force_state,
+				enum mlo_link_force_reason reason)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *req;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	req =
+	&mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[SET_LINK_FROM_CONCURRENCY];
+	req->reason = reason;
+	req->force_active_bitmap = force_state->force_active_bitmap;
+	req->force_inactive_bitmap = force_state->force_inactive_bitmap;
+	req->force_active_num = force_state->force_active_num;
+	req->force_inactive_num = force_state->force_inactive_num;
+	req->force_inactive_num_bitmap =
+		force_state->force_inactive_num_bitmap;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+void ml_nlink_init_concurrency_link_request(
+	struct wlan_objmgr_psoc *psoc,
+	struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct set_link_req *req;
+	struct ml_link_force_state *force_state;
+
+	mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev);
+	if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) {
+		mlo_err("mlo_ctx or sta_ctx null");
+		return;
+	}
+	mlo_dev_lock_acquire(mlo_dev_ctx);
+	force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state;
+	req =
+	&mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[SET_LINK_FROM_CONCURRENCY];
+	req->reason = MLO_LINK_FORCE_REASON_CONNECT;
+	req->force_active_bitmap = force_state->force_active_bitmap;
+	req->force_inactive_bitmap = force_state->force_inactive_bitmap;
+	req->force_active_num = force_state->force_active_num;
+	req->force_inactive_num = force_state->force_inactive_num;
+	req->force_inactive_num_bitmap =
+		force_state->force_inactive_num_bitmap;
+	mlo_dev_lock_release(mlo_dev_ctx);
+}
+
+void
 ml_nlink_get_force_link_request(struct wlan_objmgr_psoc *psoc,
 				struct wlan_objmgr_vdev *vdev,
 				struct set_link_req *req,
@@ -1777,7 +1832,7 @@ ml_nlink_update_force_inactive(struct wlan_objmgr_psoc *psoc,
 		/* Check non forced links allowed by conc */
 		if (!ml_nlink_allow_conc(psoc, vdev, no_force_links,
 					 new->force_inactive_bitmap)) {
-			status = QDF_STATUS_E_INVAL;
+			status = QDF_STATUS_E_NOSUPPORT;
 			goto end;
 		}
 		status = policy_mgr_mlo_sta_set_nlink(
@@ -1951,6 +2006,10 @@ static QDF_STATUS ml_nlink_state_change(struct wlan_objmgr_psoc *psoc,
 	ml_nlink_handle_dynamic_inactive(psoc, vdev, &curr_force_state,
 					 &force_state);
 
+	ml_nlink_update_concurrency_link_request(psoc, vdev,
+						 &force_state,
+						 reason);
+
 	status = ml_nlink_update_no_force_for_all(psoc, vdev,
 						  &curr_force_state,
 						  &force_state,
@@ -1962,7 +2021,8 @@ static QDF_STATUS ml_nlink_state_change(struct wlan_objmgr_psoc *psoc,
 						&curr_force_state,
 						&force_state,
 						reason);
-	if (status == QDF_STATUS_E_PENDING || status != QDF_STATUS_SUCCESS)
+	if (status == QDF_STATUS_E_PENDING ||
+	    (status != QDF_STATUS_SUCCESS && status != QDF_STATUS_E_NOSUPPORT))
 		goto end;
 
 	status = ml_nlink_update_force_inactive_num(psoc, vdev,

+ 15 - 1
components/umac/mlme/mlo_mgr/src/wlan_t2lm_api.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -262,6 +262,7 @@ QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 	struct wlan_mlo_peer_context *ml_peer;
 	struct wlan_t2lm_info *t2lm_info;
 	uint8_t dir;
+	struct wlan_channel *channel;
 
 	if (!peer) {
 		t2lm_err("peer is null");
@@ -314,6 +315,19 @@ QDF_STATUS t2lm_handle_rx_resp(struct wlan_objmgr_vdev *vdev,
 		}
 	}
 
+	channel = wlan_vdev_mlme_get_bss_chan(vdev);
+	if (!channel) {
+		t2lm_err("vdev: %d channel infio not found",
+			 wlan_vdev_get_id(vdev));
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	wlan_connectivity_t2lm_req_resp_event(vdev, t2lm_rsp.dialog_token, 0,
+					      false,
+					      channel->ch_freq,
+					      true,
+					      WLAN_CONN_DIAG_MLO_T2LM_RESP_EVENT);
+
 	return status;
 }
 

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -4145,10 +4145,12 @@ free_keys:
 		if (!key_alloc_buf[k])
 			continue;
 
+		wmi_err_rl("flush keybuf :%d, key is valid", flush_keybuf,
+			   key_alloc_buf[k]->valid);
 		if (!flush_keybuf && key_alloc_buf[k]->valid)
 			continue;
 
-		wmi_debug("Free key allocated at idx:%d", k);
+		wmi_err("Free key allocated at idx:%d", k);
 		qdf_mem_zero(key_alloc_buf[k], sizeof(*key_alloc_buf[k]));
 		qdf_mem_free(key_alloc_buf[k]);
 	}

+ 4 - 2
core/cds/src/cds_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -37,7 +37,9 @@
 #include "wlan_hdd_power.h"
 #include "wlan_hdd_tsf.h"
 #include <linux/vmalloc.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) && defined(MSM_PLATFORM)
+#if (defined(__ANDROID_COMMON_KERNEL__) && \
+	(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)) && \
+	defined(MSM_PLATFORM))
 #include <linux/qcom-iommu-util.h>
 #endif
 #include <scheduler_core.h>

+ 17 - 2
core/dp/txrx/ol_txrx.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -2086,6 +2086,7 @@ static QDF_STATUS ol_txrx_vdev_register(struct cdp_soc_t *soc_hdl,
 	vdev->rx = txrx_ops->rx.rx;
 	vdev->stats_rx = txrx_ops->rx.stats_rx;
 	vdev->tx_comp = txrx_ops->tx.tx_comp;
+	vdev->vdev_del_notify = txrx_ops->vdev_del_notify;
 	txrx_ops->tx.tx = ol_tx_data;
 
 	return QDF_STATUS_SUCCESS;
@@ -2193,6 +2194,8 @@ ol_txrx_vdev_detach(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	ol_txrx_vdev_handle vdev = ol_txrx_get_vdev_from_soc_vdev_id(soc,
 								     vdev_id);
 	struct ol_txrx_pdev_t *pdev;
+	ol_txrx_vdev_delete_cb vdev_del_notify;
+	void *vdev_del_context;
 
 	if (qdf_unlikely(!vdev))
 		return QDF_STATUS_E_FAILURE;
@@ -2204,6 +2207,8 @@ ol_txrx_vdev_detach(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	/* prevent anyone from restarting the ll_pause timer again */
 	qdf_atomic_set(&vdev->delete.detaching, 1);
 
+	vdev_del_notify = vdev->vdev_del_notify;
+	vdev_del_context = vdev->osif_dev;
 	ol_txrx_vdev_tx_queue_free(vdev);
 
 	qdf_spin_lock_bh(&vdev->ll_pause.mutex);
@@ -2288,6 +2293,9 @@ ol_txrx_vdev_detach(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
 	if (callback)
 		callback(context);
 
+	if (vdev_del_notify)
+		vdev_del_notify(vdev_del_context);
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -2715,11 +2723,12 @@ static int ol_txrx_get_opmode(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
  * @soc_hdl: datapath soc handle
  * @vdev_id: virtual interface id
  * @peer_mac: peer mac addr
+ * @slowpath: called from slow path or not
  *
  * Return: return peer state
  */
 static int ol_txrx_get_peer_state(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
-				  uint8_t *peer_mac)
+				  uint8_t *peer_mac, bool slowpath)
 {
 	struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
 	ol_txrx_pdev_handle pdev =
@@ -3330,6 +3339,9 @@ int ol_txrx_peer_release_ref(ol_txrx_peer_handle peer,
 					vdev->delete.callback;
 				void *vdev_delete_context =
 					vdev->delete.context;
+				ol_txrx_vdev_delete_cb vdev_del_notify =
+						vdev->vdev_del_notify;
+				void *vdev_del_context = vdev->osif_dev;
 				/*
 				 * Now that there are no references to the peer,
 				 * we can release the peer reference lock.
@@ -3356,6 +3368,9 @@ int ol_txrx_peer_release_ref(ol_txrx_peer_handle peer,
 				qdf_mem_free(vdev);
 				if (vdev_delete_cb)
 					vdev_delete_cb(vdev_delete_context);
+
+				if (vdev_del_notify)
+					vdev_del_notify(vdev_del_context);
 			} else {
 				qdf_spin_unlock_bh(&pdev->peer_ref_mutex);
 			}

+ 4 - 1
core/dp/txrx/ol_txrx_types.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -1218,6 +1218,9 @@ struct ol_txrx_vdev_t {
 	/* completion function used by this vdev*/
 	ol_txrx_completion_fp tx_comp;
 
+	/* delete notifier to DP component */
+	ol_txrx_vdev_delete_cb vdev_del_notify;
+
 	struct {
 		/*
 		 * If the vdev object couldn't be deleted immediately because

+ 37 - 2
core/hdd/inc/hdd_config.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1194,6 +1194,40 @@ struct dhcp_server {
 #define CFG_WLAN_CLUB_GET_STA_IN_LL_STA_REQ
 #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/*
+ * <ini>
+ * link_state_cache_expiry_time - Expiry time for cached ml link state
+ *
+ * @Min: 0
+ * @Max: 5000
+ * Default: 400
+ *
+ * This ini is used as duration in milliseconds for which cached ml link state
+ * are valid. Driver sends the cached information as response, if it gets the
+ * ml link state request with in this duration. Otherwise driver sends new
+ * request to the firmware to get the updated ml link state.
+ *
+ * Supported Feature: MLO STA
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+#define CFG_LINK_STATE_CACHE_EXPIRY  CFG_INI_UINT( \
+			"link_state_cache_expiry_time", \
+			0, \
+			5000, \
+			400, \
+			CFG_VALUE_OR_DEFAULT, \
+			"link state cache expiry")
+
+#define CFG_LINK_STATE_CACHE_EXPIRY_ALL \
+	CFG(CFG_LINK_STATE_CACHE_EXPIRY)
+#else
+#define CFG_LINK_STATE_CACHE_EXPIRY_ALL
+#endif /* WLAN_FEATURE_11BE_MLO */
+
 /**
  * enum host_log_level - Debug verbose level imposed by user
  * @HOST_LOG_LEVEL_NONE: no trace will be logged.
@@ -1348,5 +1382,6 @@ enum host_log_level {
 	SAR_SAFETY_FEATURE_ALL \
 	CFG_GET_WIFI_FEATURES_ALL \
 	CFG_CPU_CXPC_THRESHOLD_ALL \
-	CFG(CFG_EXCLUDE_SELFTX_FROM_CCA_BUSY_TIME)
+	CFG(CFG_EXCLUDE_SELFTX_FROM_CCA_BUSY_TIME) \
+	CFG_LINK_STATE_CACHE_EXPIRY_ALL
 #endif

+ 5 - 1
core/hdd/inc/wlan_hdd_cfg.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -207,6 +207,10 @@ struct hdd_config {
 	uint16_t cpu_cxpc_threshold;
 #endif
 	bool exclude_selftx_from_cca_busy;
+#ifdef WLAN_FEATURE_11BE_MLO
+	/* ml link state cache expiry time*/
+	qdf_time_t link_state_cache_expiry_time;
+#endif
 };
 
 /**

+ 5 - 1
core/hdd/inc/wlan_hdd_main.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1295,6 +1295,7 @@ struct wlan_hdd_tx_power {
  * @link_info: Data structure to hold link specific information
  * @tx_power: Structure to hold connection tx Power info
  * @tx_latency_cfg: configuration for per-link transmit latency statistics
+ * @link_state_cached_timestamp: link state cached timestamp
  */
 struct hdd_adapter {
 	uint32_t magic;
@@ -1489,6 +1490,9 @@ struct hdd_adapter {
 #ifdef WLAN_FEATURE_TX_LATENCY_STATS
 	struct cdp_tx_latency_config tx_latency_cfg;
 #endif
+#ifdef WLAN_FEATURE_11BE_MLO
+	qdf_time_t link_state_cached_timestamp;
+#endif
 };
 
 #define WLAN_HDD_GET_STATION_CTX_PTR(link_info) (&(link_info)->session.station)

+ 19 - 3
core/hdd/inc/wlan_hdd_mlo.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -280,6 +280,7 @@ void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev);
 
 /**
  * wlan_handle_mlo_link_state_operation() - mlo link state operation
+ * @adapter: HDD adapter
  * @wiphy: wiphy pointer
  * @vdev: vdev handler
  * @hdd_ctx: hdd context
@@ -290,7 +291,8 @@ void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev);
  *
  * Return: 0 on success and error number otherwise.
  */
-int wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
+int wlan_handle_mlo_link_state_operation(struct hdd_adapter *adapter,
+					 struct wiphy *wiphy,
 					 struct wlan_objmgr_vdev *vdev,
 					 struct hdd_context *hdd_ctx,
 					 const void *data, int data_len);
@@ -323,6 +325,13 @@ QDF_STATUS wlan_hdd_send_t2lm_event(struct wlan_objmgr_vdev *vdev,
 int wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
 					    struct wireless_dev *wdev,
 					    const void *data, int data_len);
+/**
+ * hdd_update_link_state_cached_timestamp() - update link state cached timestamp
+ * @adapter: HDD adapter
+ *
+ * Return: none
+ */
+void hdd_update_link_state_cached_timestamp(struct hdd_adapter *adapter);
 
 /**
  * hdd_derive_link_address_from_mld() - Function to derive link address from
@@ -404,7 +413,8 @@ void hdd_mlo_t2lm_unregister_callback(struct wlan_objmgr_vdev *vdev)
 }
 
 static inline int
-wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
+wlan_handle_mlo_link_state_operation(struct hdd_adapter *adapter,
+				     struct wiphy *wiphy,
 				     struct wlan_objmgr_vdev *vdev,
 				     struct hdd_context *hdd_ctx,
 				     const void *data, int data_len)
@@ -435,6 +445,12 @@ QDF_STATUS wlan_hdd_send_t2lm_event(struct wlan_objmgr_vdev *vdev,
 {
 	return QDF_STATUS_E_NOSUPPORT;
 }
+
+static inline
+void hdd_update_link_state_cached_timestamp(struct hdd_adapter *adapter)
+{
+}
+
 #define FEATURE_ML_LINK_STATE_COMMANDS
 #endif
 #endif

+ 3 - 2
core/hdd/inc/wlan_hdd_power.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012, 2014-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -486,7 +486,8 @@ int wlan_hdd_pm_qos_notify(struct notifier_block *nb, unsigned long curr_val,
  * Return: true if there is PM QoS global vote,
  *	   or an false otherwise
  */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) && \
+	defined(__ANDROID_COMMON_KERNEL__))
 bool wlan_hdd_is_cpu_pm_qos_in_progress(struct hdd_context *hdd_ctx);
 #else
 static inline bool

+ 8 - 1
core/hdd/inc/wlan_hdd_tdls.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -142,6 +142,13 @@ int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 				uint16_t status_code, uint32_t peer_capability,
 				bool initiator, const uint8_t *buf,
 				size_t len, int link_id);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
+int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
+				struct net_device *dev, const u8 *peer,
+				int link_id, u8 action_code,
+				u8 dialog_token, u16 status_code,
+				u32 peer_capability, bool initiator,
+				const u8 *buf, size_t len);
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
 int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 				struct net_device *dev, const uint8_t *peer,

+ 74 - 2
core/hdd/src/wlan_hdd_assoc.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1126,7 +1126,79 @@ void hdd_copy_vht_operation(struct hdd_station_ctx *hdd_sta_ctx,
 	hdd_vht_ops->basic_mcs_set = vht_ops->basicMCSSet;
 }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) && \
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0)) && \
+	defined(WLAN_FEATURE_11BE)
+void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
+			    tDot11fIEeht_op *eht_ops)
+{
+	struct ieee80211_eht_operation *hdd_eht_ops =
+		&hdd_sta_ctx->conn_info.eht_operation;
+	struct ieee80211_eht_mcs_nss_supp_20mhz_only  mcs_param;
+	uint32_t filled = 0, len = 0;
+
+	qdf_mem_zero(hdd_eht_ops, sizeof(struct ieee80211_eht_operation));
+
+	if (!eht_ops->eht_op_information_present)
+		return;
+
+	/* Min length if op_info_present */
+	len += 3;
+
+	hdd_eht_ops->params |= IEEE80211_EHT_OPER_INFO_PRESENT;
+
+	if (eht_ops->eht_default_pe_duration)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_EHT_DEF_PE_DURATION;
+	if (eht_ops->group_addr_bu_indication_limit)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_LIMIT;
+	if (eht_ops->group_addr_bu_indication_exponent)
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_GROUP_ADDRESSED_BU_IND_EXP_MASK;
+
+	mcs_param.rx_tx_mcs7_max_nss =
+		eht_ops->basic_rx_max_nss_for_mcs_0_to_7 <<
+					EHT_OPER_BASIC_RX_NSS_MCS_0_TO_7_POS;
+	mcs_param.rx_tx_mcs7_max_nss |=
+		eht_ops->basic_tx_max_nss_for_mcs_0_to_7 <<
+					EHT_OPER_BASIC_TX_NSS_MCS_0_TO_7_POS;
+	mcs_param.rx_tx_mcs9_max_nss =
+		eht_ops->basic_rx_max_nss_for_mcs_8_and_9 <<
+					EHT_OPER_BASIC_RX_NSS_MCS_8_AND_9_POS;
+	mcs_param.rx_tx_mcs9_max_nss |=
+		eht_ops->basic_tx_max_nss_for_mcs_8_and_9 <<
+					EHT_OPER_BASIC_TX_NSS_MCS_8_AND_9_POS;
+	mcs_param.rx_tx_mcs11_max_nss =
+		eht_ops->basic_rx_max_nss_for_mcs_10_and_11 <<
+					EHT_OPER_BASIC_RX_NSS_MCS_10_AND_11_POS;
+	mcs_param.rx_tx_mcs11_max_nss |=
+		eht_ops->basic_tx_max_nss_for_mcs_10_and_11 <<
+					EHT_OPER_BASIC_TX_NSS_MCS_10_AND_11_POS;
+	mcs_param.rx_tx_mcs13_max_nss =
+		eht_ops->basic_rx_max_nss_for_mcs_12_and_13 <<
+					EHT_OPER_BASIC_RX_NSS_MCS_12_AND_13_POS;
+	mcs_param.rx_tx_mcs13_max_nss |=
+		eht_ops->basic_tx_max_nss_for_mcs_12_and_13 <<
+					EHT_OPER_BASIC_TX_NSS_MCS_12_AND_13_POS;
+
+	hdd_eht_ops->basic_mcs_nss = mcs_param;
+	hdd_eht_ops->optional[filled++] = eht_ops->channel_width;
+	hdd_eht_ops->optional[filled++] = eht_ops->ccfs0;
+	hdd_eht_ops->optional[filled++] = eht_ops->ccfs1;
+
+	if (eht_ops->disabled_sub_chan_bitmap_present) {
+		hdd_eht_ops->params |=
+			IEEE80211_EHT_OPER_DISABLED_SUBCHANNEL_BITMAP_PRESENT;
+		len += 2;
+		hdd_eht_ops->optional[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][0];
+		hdd_eht_ops->optional[filled++] =
+				eht_ops->disabled_sub_chan_bitmap[0][1];
+	}
+	hdd_sta_ctx->conn_info.eht_oper_len =
+				sizeof(struct ieee80211_eht_operation) + len;
+}
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0)) && \
 	defined(WLAN_FEATURE_11BE)
 void hdd_copy_eht_operation(struct hdd_station_ctx *hdd_sta_ctx,
 			    tDot11fIEeht_op *eht_ops)

+ 94 - 6
core/hdd/src/wlan_hdd_cfg80211.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1141,6 +1141,85 @@ static struct ieee80211_iface_combination
 #endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
 #endif /* WLAN_FEATURE_NAN */
 };
+
+static struct ieee80211_iface_combination
+	wlan_hdd_non_dbs_iface_combination[] = {
+#ifndef WLAN_FEATURE_NO_P2P_CONCURRENCY
+	/* P2P */
+	{
+		.limits = wlan_hdd_p2p_iface_limit,
+		.num_different_channels = 2,
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_iface_limit),
+	},
+
+	/* SAP + P2P */
+	{
+		.limits = wlan_hdd_sap_p2p_iface_limit,
+		.num_different_channels = 2,
+		/* 1-SAP + 1-P2P */
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_sap_p2p_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+	/* P2P + P2P */
+	{
+		.limits = wlan_hdd_p2p_p2p_iface_limit,
+		.num_different_channels = 2,
+		/* 2-P2P */
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_p2p_p2p_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+#endif
+	/* STA + P2P */
+	{
+		.limits = wlan_hdd_sta_p2p_iface_limit,
+		.num_different_channels = 2,
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_sta_p2p_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+#ifndef WLAN_FEATURE_NO_STA_SAP_CONCURRENCY
+	/* STA + SAP */
+	{
+		.limits = wlan_hdd_sta_ap_iface_limit,
+		.num_different_channels = 2,
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_sta_ap_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+#endif /* WLAN_FEATURE_NO_STA_SAP_CONCURRENCY */
+	/* Monitor */
+	{
+		.limits = wlan_hdd_mon_iface_limit,
+		.max_interfaces = 2,
+		.num_different_channels = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit),
+	},
+#if defined(WLAN_FEATURE_NAN) && \
+	   (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+#ifndef WLAN_FEATURE_NO_STA_NAN_CONCURRENCY
+	/* NAN + STA */
+	{
+		.limits = wlan_hdd_sta_nan_iface_limit,
+		.max_interfaces = 2,
+		.num_different_channels = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_sta_nan_iface_limit),
+	},
+#endif /* WLAN_FEATURE_NO_STA_NAN_CONCURRENCY */
+#ifndef WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY
+	/* NAN + SAP */
+	{
+		.limits = wlan_hdd_sap_nan_iface_limit,
+		.num_different_channels = 2,
+		.max_interfaces = 2,
+		.n_limits = ARRAY_SIZE(wlan_hdd_sap_nan_iface_limit),
+		.beacon_int_infra_match = true,
+	},
+#endif /* !WLAN_FEATURE_NO_SAP_NAN_CONCURRENCY */
+#endif /* WLAN_FEATURE_NAN */
+};
 static struct cfg80211_ops wlan_hdd_cfg80211_ops;
 
 #ifdef WLAN_NL80211_TESTMODE
@@ -12593,7 +12672,8 @@ static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
 	struct nlattr *mlo_bd_info = NULL;
 	uint32_t i = 0;
 	uint32_t link_id = 0;
-	struct wlan_objmgr_vdev *vdev, *link_vdev;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_vdev *link_vdev = NULL;
 	struct wlan_channel *bss_chan;
 	struct wlan_hdd_link_info *link_info_t;
 	struct hdd_station_ctx *sta_ctx;
@@ -12667,13 +12747,14 @@ static int hdd_get_mlo_max_band_info(struct wlan_hdd_link_info *link_info,
 		nla_nest_end(skb, mlo_bd);
 		i++;
 
-		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
+		if (link_vdev)
+			hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
 	}
 	nla_nest_end(skb, mlo_bd_info);
 end:
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
 
-	if (ret)
+	if (link_vdev)
 		hdd_objmgr_put_vdev_by_user(link_vdev, WLAN_OSIF_ID);
 
 	return ret;
@@ -22058,12 +22139,19 @@ void wlan_hdd_update_wiphy(struct hdd_context *hdd_ctx)
 			return;
 		}
 
-		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc) ||
-		    (dbs_one_by_one && !dbs_two_by_two)) {
+		if (!ucfg_policy_mgr_is_fw_supports_dbs(hdd_ctx->psoc)) {
+			/* Update IFACE combination for non-DBS target */
+			wiphy->iface_combinations =
+					wlan_hdd_non_dbs_iface_combination;
+			iface_num =
+				ARRAY_SIZE(wlan_hdd_non_dbs_iface_combination);
+		} else if (dbs_one_by_one && !dbs_two_by_two) {
+			/* Update IFACE combination for 1x1 DBS target */
 			wiphy->iface_combinations =
 						wlan_hdd_derived_combination;
 			iface_num = ARRAY_SIZE(wlan_hdd_derived_combination);
 		} else {
+			/* Update IFACE combination for DBS target */
 			wiphy->iface_combinations = wlan_hdd_iface_combination;
 			iface_num = ARRAY_SIZE(wlan_hdd_iface_combination);
 		}

+ 52 - 1
core/hdd/src/wlan_hdd_ioctl.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -5541,6 +5541,56 @@ static int drv_cmd_get_rssi(struct wlan_hdd_link_info *link_info,
 	return ret;
 }
 
+/**
+ * drv_cmd_get_sap_go_linkspeed() - Driver command to get SAP/P2P Go peer link
+ *                                  speed
+ * @link_info: Link info pointer in HDD adapter
+ * @hdd_ctx: HDD context pointer
+ * @command: Driver command string
+ * @command_len: Driver command string length
+ * @priv_data: Pointer to HDD private data
+ *
+ * Return: 0 if linkspeed data is available, negative errno otherwise
+ */
+static int drv_cmd_get_sap_go_linkspeed(struct wlan_hdd_link_info *link_info,
+					struct hdd_context *hdd_ctx,
+					uint8_t *command,
+					uint8_t command_len,
+					struct hdd_priv_data *priv_data)
+{
+	int ret;
+	uint32_t link_speed = 0;
+	char extra[64];
+	uint8_t len = 0;
+	struct hdd_adapter *adapter = link_info->adapter;
+
+	if (adapter->device_mode == QDF_P2P_GO_MODE ||
+	    adapter->device_mode == QDF_SAP_MODE) {
+		ret = wlan_hdd_get_sap_go_peer_linkspeed(link_info,
+							 &link_speed,
+							 command,
+							 command_len);
+	} else {
+		hdd_err("Link Speed is not allowed in Device mode %s(%d)",
+			qdf_opmode_str(adapter->device_mode),
+			adapter->device_mode);
+		ret = -ENOTSUPP;
+	}
+
+	if (0 != ret)
+		return ret;
+
+	len = scnprintf(extra, sizeof(extra), "%s %d\n",
+			"SOFT-AP LINKSPEED", link_speed);
+	len = QDF_MIN(priv_data->total_len, len + 1);
+	if (copy_to_user(priv_data->buf, &extra, len)) {
+		hdd_err("Failed to copy data to user buffer");
+		ret = -EFAULT;
+	}
+
+	return ret;
+}
+
 static int drv_cmd_get_linkspeed(struct wlan_hdd_link_info *link_info,
 				 struct hdd_context *hdd_ctx,
 				 uint8_t *command,
@@ -7291,6 +7341,7 @@ static const struct hdd_drv_cmd hdd_drv_cmds[] = {
 	{"RXFILTER-STOP",             drv_cmd_dummy, false},
 	{"BTCOEXSCAN-START",          drv_cmd_dummy, false},
 	{"BTCOEXSCAN-STOP",           drv_cmd_dummy, false},
+	{"GET_SOFTAP_LINK_SPEED",     drv_cmd_get_sap_go_linkspeed, true},
 };
 
 /**

+ 67 - 2
core/hdd/src/wlan_hdd_main.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1051,8 +1051,11 @@ static int hdd_netdev_notifier_call(struct notifier_block *nb,
 	}
 
 	errno = osif_vdev_sync_op_start(net_dev, &vdev_sync);
-	if (errno)
+	if (errno) {
+		hdd_debug("%s New Net Device State = %lu, flags 0x%x NOTIFY_DONE",
+			  net_dev->name, state, net_dev->flags);
 		return NOTIFY_DONE;
+	}
 
 	errno = __hdd_netdev_notifier_call(net_dev, state);
 
@@ -1725,6 +1728,35 @@ hdd_init_get_sta_in_ll_stats_config(struct hdd_adapter *adapter)
 }
 #endif /* FEATURE_CLUB_LL_STATS_AND_GET_STATION */
 
+#ifdef WLAN_FEATURE_11BE_MLO
+
+static void
+hdd_init_link_state_cfg(struct hdd_config *config,
+			struct wlan_objmgr_psoc *psoc)
+{
+	config->link_state_cache_expiry_time =
+		cfg_get(psoc, CFG_LINK_STATE_CACHE_EXPIRY);
+}
+
+static void
+hdd_init_link_state_config(struct hdd_adapter *adapter)
+{
+	adapter->link_state_cached_timestamp = 0;
+}
+
+#else
+static void
+hdd_init_link_state_cfg(struct hdd_config *config,
+			struct wlan_objmgr_psoc *psoc)
+{
+}
+
+static void
+hdd_init_link_state_config(struct hdd_adapter *adapter)
+{
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
+
 #ifdef WLAN_FEATURE_IGMP_OFFLOAD
 static void
 hdd_intersect_igmp_offload_setting(struct wlan_objmgr_psoc *psoc,
@@ -6943,6 +6975,7 @@ hdd_alloc_station_adapter(struct hdd_context *hdd_ctx, tSirMacAddr mac_addr,
 
 	qdf_atomic_init(&adapter->is_ll_stats_req_pending);
 	hdd_init_get_sta_in_ll_stats_config(adapter);
+	hdd_init_link_state_config(adapter);
 
 	return adapter;
 
@@ -14534,6 +14567,7 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx)
 
 	config->exclude_selftx_from_cca_busy =
 			cfg_get(psoc, CFG_EXCLUDE_SELFTX_FROM_CCA_BUSY_TIME);
+	hdd_init_link_state_cfg(config, psoc);
 }
 
 #ifdef CONNECTION_ROAMING_CFG
@@ -20006,6 +20040,35 @@ static int __hdd_driver_mode_change(struct hdd_context *hdd_ctx,
 	return 0;
 }
 
+static void hdd_pre_mode_change(enum QDF_GLOBAL_MODE mode)
+{
+	struct osif_psoc_sync *psoc_sync;
+	struct hdd_context *hdd_ctx;
+	int errno;
+	enum QDF_GLOBAL_MODE curr_mode;
+
+	curr_mode = hdd_get_conparam();
+	if (curr_mode != QDF_GLOBAL_MISSION_MODE)
+		return;
+
+	hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	errno = wlan_hdd_validate_context(hdd_ctx);
+	if (errno)
+		return;
+
+	errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
+	if (errno) {
+		hdd_err("psoc op start failed");
+		return;
+	}
+
+	hdd_debug("cleanup scan queue");
+	if (hdd_ctx && hdd_ctx->pdev)
+		wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL);
+
+	osif_psoc_sync_op_stop(psoc_sync);
+}
+
 static int hdd_driver_mode_change(enum QDF_GLOBAL_MODE mode)
 {
 	struct osif_driver_sync *driver_sync;
@@ -20015,6 +20078,8 @@ static int hdd_driver_mode_change(enum QDF_GLOBAL_MODE mode)
 
 	hdd_enter();
 
+	hdd_pre_mode_change(mode);
+
 	status = osif_driver_sync_trans_start_wait(&driver_sync);
 	if (QDF_IS_STATUS_ERROR(status)) {
 		hdd_err("Failed to start 'mode change'; status:%u", status);

+ 126 - 7
core/hdd/src/wlan_hdd_mlo.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -637,8 +637,8 @@ __wlan_hdd_cfg80211_process_ml_link_state(struct wiphy *wiphy,
 	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
 		goto release_ref;
 
-	ret = wlan_handle_mlo_link_state_operation(wiphy, vdev, hdd_ctx,
-						   data, data_len);
+	ret = wlan_handle_mlo_link_state_operation(adapter, wiphy, vdev,
+						   hdd_ctx, data, data_len);
 
 release_ref:
 	hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_ID);
@@ -785,7 +785,112 @@ static char *link_state_status_id_to_str(uint32_t status)
 	return "Undefined link state status ID";
 }
 
-static QDF_STATUS wlan_hdd_link_state_request(struct wiphy *wiphy,
+static bool
+wlan_hdd_link_state_request_needed(struct hdd_adapter *adapter)
+{
+	qdf_time_t link_state_cached_duration = 0;
+
+	link_state_cached_duration =
+				qdf_system_ticks_to_msecs(qdf_system_ticks()) -
+				adapter->link_state_cached_timestamp;
+	if (link_state_cached_duration <=
+		adapter->hdd_ctx->config->link_state_cache_expiry_time)
+		return false;
+
+	return true;
+}
+
+#ifdef WLAN_FEATURE_11BE_MLO
+
+void hdd_update_link_state_cached_timestamp(struct hdd_adapter *adapter)
+{
+	adapter->link_state_cached_timestamp =
+		qdf_system_ticks_to_msecs(qdf_system_ticks());
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
+
+static QDF_STATUS
+wlan_hdd_cached_link_state_request(struct hdd_adapter *adapter,
+				   struct wiphy *wiphy,
+				   struct wlan_objmgr_psoc *psoc,
+				   struct wlan_objmgr_vdev *vdev)
+{
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+	struct ml_link_state_info_event link_state_event = {0};
+	struct wlan_hdd_link_info *link_info;
+	struct hdd_station_ctx *sta_ctx;
+	int skb_len;
+	struct sk_buff *reply_skb = NULL;
+	int errno;
+	struct qdf_mac_addr *mld_addr;
+	uint8_t link_iter = 0;
+
+	hdd_adapter_for_each_link_info(adapter, link_info) {
+
+		if (link_iter >= WLAN_MAX_ML_BSS_LINKS) {
+			hdd_err("Invalid number of link info");
+			return -EINVAL;
+		}
+
+		sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(link_info);
+		link_state_event.link_info[link_iter].link_id =
+				sta_ctx->conn_info.ieee_link_id;
+		link_state_event.link_info[link_iter].link_status =
+				link_info->is_mlo_vdev_active;
+		link_state_event.link_info[link_iter].vdev_id =
+				link_info->vdev_id;
+		link_state_event.link_info[link_iter].chan_freq =
+				sta_ctx->ch_info.freq;
+
+		if (sta_ctx->conn_info.ieee_link_id == WLAN_INVALID_LINK_ID)
+			continue;
+
+		link_iter++;
+
+		hdd_debug_rl("vdev id %d sta_ctx->conn_info.ieee_link_id %d is_mlo_vdev_active %d ",
+			     link_info->vdev_id, sta_ctx->conn_info.ieee_link_id,
+			     link_info->is_mlo_vdev_active);
+	}
+
+	link_state_event.num_mlo_vdev_link_info = link_iter;
+	link_state_event.vdev_id = wlan_vdev_get_id(vdev);
+	link_state_event.status = 0;
+	mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev);
+	link_state_event.mldaddr = *mld_addr;
+
+	hdd_debug_rl("cached link_state_resp: vdev id %d status %d num %d MAC addr " QDF_MAC_ADDR_FMT,
+		     link_state_event.vdev_id, link_state_event.status,
+		     link_state_event.num_mlo_vdev_link_info,
+		     QDF_MAC_ADDR_REF(link_state_event.mldaddr.bytes));
+
+	skb_len = hdd_get_ml_link_state_response_len(&link_state_event);
+
+	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
+	if (!reply_skb) {
+		hdd_err("Get stats - alloc reply_skb failed");
+		status = QDF_STATUS_E_NOMEM;
+		return status;
+	}
+
+	status = hdd_ml_generate_link_state_resp_nlmsg(
+			reply_skb, psoc, &link_state_event,
+			link_state_event.num_mlo_vdev_link_info);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to pack nl response");
+		goto free_skb;
+	}
+
+	errno = wlan_cfg80211_vendor_cmd_reply(reply_skb);
+
+	return qdf_status_from_os_return(errno);
+
+free_skb:
+	wlan_cfg80211_vendor_free_skb(reply_skb);
+	return QDF_STATUS_SUCCESS;
+}
+
+static QDF_STATUS wlan_hdd_link_state_request(struct hdd_adapter *adapter,
+					      struct wiphy *wiphy,
 					      struct wlan_objmgr_psoc *psoc,
 					      struct wlan_objmgr_vdev *vdev)
 {
@@ -807,6 +912,16 @@ static QDF_STATUS wlan_hdd_link_state_request(struct wiphy *wiphy,
 	if (!wiphy || !vdev)
 		return status;
 
+	if (adapter->device_mode != QDF_STA_MODE)
+		return QDF_STATUS_SUCCESS;
+
+	if (!wlan_hdd_link_state_request_needed(adapter)) {
+		hdd_debug_rl("sending cached link state request");
+		status = wlan_hdd_cached_link_state_request(adapter, wiphy,
+							    psoc, vdev);
+		return status;
+	}
+
 	request = osif_request_alloc(&params);
 	if (!request)
 		return QDF_STATUS_E_NOMEM;
@@ -857,6 +972,8 @@ static QDF_STATUS wlan_hdd_link_state_request(struct wiphy *wiphy,
 			  link_state_event->link_info[num_info].link_status);
 	}
 
+	hdd_update_link_state_cached_timestamp(adapter);
+
 	skb_len = hdd_get_ml_link_state_response_len(link_state_event);
 
 	reply_skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(
@@ -879,6 +996,7 @@ static QDF_STATUS wlan_hdd_link_state_request(struct wiphy *wiphy,
 	osif_request_put(request);
 
 	errno = wlan_cfg80211_vendor_cmd_reply(reply_skb);
+
 	return qdf_status_from_os_return(errno);
 
 free_skb:
@@ -891,7 +1009,8 @@ free_event:
 
 #define MLD_MAX_SUPPORTED_LINKS 2
 
-int wlan_handle_mlo_link_state_operation(struct wiphy *wiphy,
+int wlan_handle_mlo_link_state_operation(struct hdd_adapter *adapter,
+					 struct wiphy *wiphy,
 					 struct wlan_objmgr_vdev *vdev,
 					 struct hdd_context *hdd_ctx,
 					 const void *data, int data_len)
@@ -925,8 +1044,8 @@ 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:
-		status = wlan_hdd_link_state_request(wiphy, hdd_ctx->psoc,
-						     vdev);
+		status = wlan_hdd_link_state_request(adapter, 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)) {

+ 4 - 2
core/hdd/src/wlan_hdd_power.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1212,7 +1212,9 @@ int wlan_hdd_pm_qos_notify(struct notifier_block *nb, unsigned long curr_val,
 	return NOTIFY_DONE;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
+/** cpuidle_governor_latency_req() is not exported by upstream kernel **/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) && \
+	defined(__ANDROID_COMMON_KERNEL__))
 bool wlan_hdd_is_cpu_pm_qos_in_progress(struct hdd_context *hdd_ctx)
 {
 	long long curr_val_ns;

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1711,6 +1711,9 @@ static void hdd_country_change_update_sta(struct hdd_context *hdd_ctx)
 							    pdev,
 							    link_info->vdev_id);
 				}
+				sme_set_vdev_ies_per_band(hdd_ctx->mac_handle,
+							  link_info->vdev_id,
+							  QDF_STA_MODE);
 				break;
 			default:
 				break;

+ 63 - 2
core/hdd/src/wlan_hdd_stats.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -3451,8 +3451,10 @@ static int wlan_hdd_send_ll_stats_req(struct wlan_hdd_link_info *link_info,
 		sme_radio_tx_mem_free();
 		ret = -ETIMEDOUT;
 	} else {
-		if (QDF_IS_STATUS_SUCCESS(vdev_req_status))
+		if (QDF_IS_STATUS_SUCCESS(vdev_req_status)) {
 			hdd_update_station_stats_cached_timestamp(adapter);
+			hdd_update_link_state_cached_timestamp(adapter);
+		}
 
 		adapter->ll_stats_failure_count = 0;
 	}
@@ -9106,6 +9108,64 @@ int wlan_hdd_get_link_speed(struct wlan_hdd_link_info *link_info,
 	return 0;
 }
 
+int wlan_hdd_get_sap_go_peer_linkspeed(struct wlan_hdd_link_info *link_info,
+				       uint32_t *link_speed,
+				       uint8_t *command,
+				       uint8_t command_len)
+{
+	int ret;
+	struct qdf_mac_addr mac_address;
+	char macaddr_string[MAC_ADDRESS_STR_LEN + 1];
+	uint8_t *value = command;
+	struct hdd_adapter *adapter = link_info->adapter;
+	struct hdd_station_info *sta_info, *tmp = NULL;
+
+	value = value + command_len;
+	ret = sscanf(value, "%17s", &macaddr_string);
+
+	if (ret != 1)
+		return -EINVAL;
+
+	macaddr_string[MAC_ADDRESS_STR_LEN - 1] = '\0';
+	if (!mac_pton(macaddr_string, mac_address.bytes)) {
+		hdd_err("String to Hex conversion Failed");
+		return -EINVAL;
+	}
+
+	hdd_for_each_sta_ref_safe(adapter->sta_info_list, sta_info, tmp,
+				  STA_INFO_GET_SOFTAP_LINKSPEED) {
+		if (!qdf_is_macaddr_broadcast(&sta_info->sta_mac)) {
+			if (qdf_is_macaddr_equal(&mac_address,
+						 &sta_info->sta_mac)) {
+				ret = wlan_hdd_get_linkspeed_for_peermac(
+							adapter->deflink,
+							&mac_address,
+							link_speed);
+				hdd_put_sta_info_ref(
+						&adapter->sta_info_list,
+						&sta_info, true,
+						STA_INFO_GET_SOFTAP_LINKSPEED);
+				if (tmp)
+					hdd_put_sta_info_ref(
+						&adapter->sta_info_list,
+						&tmp, true,
+						STA_INFO_GET_SOFTAP_LINKSPEED);
+				break;
+			}
+		}
+		hdd_put_sta_info_ref(&adapter->sta_info_list,
+				     &sta_info, true,
+				     STA_INFO_GET_SOFTAP_LINKSPEED);
+	}
+
+	if (ret) {
+		hdd_err("Unable to retrieve SAP/GO linkspeed");
+		return ret;
+	}
+
+	*link_speed = (*link_speed) / 500;
+	return 0;
+}
 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER
 /**
  * wlan_hdd_get_per_peer_stats - get per peer stats if supported by FW
@@ -9233,6 +9293,7 @@ int wlan_hdd_get_station_stats(struct wlan_hdd_link_info *link_info)
 
 	/* update get stats cached time stamp */
 	hdd_update_station_stats_cached_timestamp(link_info->adapter);
+	hdd_update_link_state_cached_timestamp(link_info->adapter);
 	copy_station_stats_to_adapter(link_info, stats);
 out:
 	wlan_cfg80211_mc_cp_stats_free_stats_event(stats);

+ 14 - 1
core/hdd/src/wlan_hdd_stats.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -497,6 +497,19 @@ int wlan_hdd_get_linkspeed_for_peermac(struct wlan_hdd_link_info *link_info,
 int wlan_hdd_get_link_speed(struct wlan_hdd_link_info *link_info,
 			    uint32_t *link_speed);
 
+/**
+ * wlan_hdd_get_sap_go_peer_linkspeed() - Get SAP/GO peer link speed
+ * @link_info:   Link info pointer in HDD adapter
+ * @link_speed:  Pointer to link speed
+ * @command:     Driver command string
+ * @command_len: Driver command string length
+ *
+ * Return: 0 if linkspeed data is available, negative errno otherwise
+ */
+int wlan_hdd_get_sap_go_peer_linkspeed(struct wlan_hdd_link_info *link_info,
+				       uint32_t *link_speed,
+				       uint8_t *command,
+				       uint8_t command_len);
 #ifdef FEATURE_RX_LINKSPEED_ROAM_TRIGGER
 /**
  * wlan_hdd_get_peer_rx_rate_stats() - STA gets rx rate stats

+ 28 - 2
core/hdd/src/wlan_hdd_tdls.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -776,6 +776,16 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 				uint16_t status_code, uint32_t peer_capability,
 				bool initiator, const uint8_t *buf,
 				size_t len, int link_id)
+
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
+static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
+				struct net_device *dev,
+				const u8 *peer, int link_id,
+				u8 action_code, u8 dialog_token,
+				u16 status_code, u32 peer_capability,
+				bool initiator, const u8 *buf,
+				size_t len)
+
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
 static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 				struct net_device *dev, const uint8_t *peer,
@@ -806,7 +816,8 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
 	bool tdls_support;
-#ifndef TDLS_MGMT_VERSION5
+#if !defined(TDLS_MGMT_VERSION5) && \
+	(LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0))
 	int link_id = -1;
 #endif
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
@@ -880,6 +891,16 @@ int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 					u8 dialog_token, u16 status_code,
 					u32 peer_capability, bool initiator,
 					const u8 *buf, size_t len, int link_id)
+
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
+int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
+					struct net_device *dev,
+					const u8 *peer, int link_id,
+					u8 action_code, u8 dialog_token,
+					u16 status_code, u32 peer_capability,
+					bool initiator, const u8 *buf,
+					size_t len)
+
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
 int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 					struct net_device *dev,
@@ -922,6 +943,11 @@ int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 					      dialog_token, status_code,
 					      peer_capability, initiator,
 					      buf, len, link_id);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 5, 0))
+	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, link_id,
+					      action_code, dialog_token,
+					      status_code, peer_capability,
+					      initiator, buf, len);
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS)
 	errno = __wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer, action_code,
 					      dialog_token, status_code,

+ 3 - 3
core/hdd/src/wlan_hdd_tx_rx.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1064,8 +1064,8 @@ void wlan_hdd_netif_queue_control(struct hdd_adapter *adapter,
 	if (hdd_adapter_is_link_adapter(adapter))
 		return;
 
-	hdd_debug("netif_control's vdev_id: %d, action: %d, reason: %d",
-		  adapter->deflink->vdev_id, action, reason);
+	hdd_debug_rl("netif_control's vdev_id: %d, action: %d, reason: %d",
+		     adapter->deflink->vdev_id, action, reason);
 
 	switch (action) {
 

+ 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            "K"
-#define QWLAN_VERSION_BUILD            85
+#define QWLAN_VERSION_EXTRA            "B"
+#define QWLAN_VERSION_BUILD            86
 
-#define QWLAN_VERSIONSTR               "5.2.1.85K"
+#define QWLAN_VERSIONSTR               "5.2.1.86B"
 
 #endif /* QWLAN_VERSION_H */

+ 3 - 0
core/mac/src/include/sir_debug.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2011-2012, 2014-2015, 2017-2019, 2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024 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
@@ -56,6 +57,8 @@
 	QDF_TRACE_INFO_NO_FL(QDF_MODULE_ID_PE, params)
 #define pe_nofl_debug(params...) \
 	QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_PE, params)
+#define pe_nofl_rl_err(params...) \
+	QDF_TRACE_ERROR_RL_NO_FL(QDF_MODULE_ID_PE, params)
 #define pe_nofl_rl_debug(params...) \
 	QDF_TRACE_DEBUG_RL_NO_FL(QDF_MODULE_ID_PE, params)
 #define pe_nofl_rl_info(params...) \

+ 25 - 1
core/mac/src/pe/include/lim_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -649,6 +649,23 @@ lim_fill_pe_session(struct mac_context *mac_ctx,
 		    struct bss_description *bss_desc);
 
 #ifdef WLAN_FEATURE_11BE_MLO
+/*
+ * lim_add_bcn_probe() - Add the generated probe resp to scan DB
+ * @vdev: VDEV object manager
+ * @bcn_probe: Pointer to bcn/probe
+ * @len: Length of frame.
+ * @freq: Freq on frame.
+ * @rssi: RSSI of the frame.
+ *
+ * Prepares the meta data to add the generated bcn/probe frame to
+ * scan DB.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
+		  uint32_t len, qdf_freq_t freq, int32_t rssi);
+
 /**
  * lim_update_mlo_mgr_info() - API to update mlo_mgr link info
  * @mac_ctx: Pointer to mac context
@@ -714,6 +731,13 @@ lim_process_cu_for_probe_rsp(struct mac_context *mac_ctx,
 			     uint32_t probe_rsp_len);
 
 #else
+static inline QDF_STATUS
+lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
+		  uint32_t len, qdf_freq_t freq, int32_t rssi)
+{
+	return QDF_STATUS_E_NOSUPPORT;
+}
+
 static inline QDF_STATUS
 lim_update_mlo_mgr_info(struct mac_context *mac_ctx,
 			struct wlan_objmgr_vdev *vdev,

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -169,7 +169,7 @@ lim_validate_tspec(struct mac_context *mac,
 		retval = lim_validate_tspec_edca(mac, pTspec, pe_session);
 		if (retval != QDF_STATUS_SUCCESS)
 			pe_warn("EDCA tspec invalid");
-			break;
+		break;
 
 	case SIR_MAC_ACCESSPOLICY_HCCA:
 	case SIR_MAC_ACCESSPOLICY_BOTH:
@@ -332,7 +332,7 @@ static QDF_STATUS lim_admit_policy(struct mac_context *mac,
 							   pe_session);
 		if (retval != QDF_STATUS_SUCCESS)
 			pe_err("rejected by BWFactor policy");
-			break;
+		break;
 
 	case WNI_CFG_ADMIT_POLICY_REJECT_ALL:
 		retval = QDF_STATUS_E_FAILURE;

+ 98 - 13
core/mac/src/pe/lim/lim_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1093,7 +1093,7 @@ static QDF_STATUS pe_drop_pending_rx_mgmt_frames(struct mac_context *mac_ctx,
 		if (!(mac_ctx->rx_packet_drop_counter % 100))
 			pe_debug("No.of pending RX management frames reaches to 1/4th of threshold, rx_packet_drop_counter: %d",
 				mac_ctx->rx_packet_drop_counter);
-			mac_ctx->rx_packet_drop_counter++;
+		mac_ctx->rx_packet_drop_counter++;
 	}
 	return QDF_STATUS_SUCCESS;
 }
@@ -3818,7 +3818,7 @@ lim_match_link_info(uint8_t req_link_id,
 	return false;
 }
 
-static QDF_STATUS
+QDF_STATUS
 lim_add_bcn_probe(struct wlan_objmgr_vdev *vdev, uint8_t *bcn_probe,
 		  uint32_t len, qdf_freq_t freq, int32_t rssi)
 {
@@ -4092,7 +4092,7 @@ QDF_STATUS lim_update_mlo_mgr_info(struct mac_context *mac_ctx,
 	is_security_allowed =
 		wlan_cm_is_eht_allowed_for_current_security(
 					wlan_pdev_get_psoc(mac_ctx->pdev),
-					cache_entry);
+					cache_entry, true);
 
 	if (!is_security_allowed) {
 		mlme_debug("current security is not valid for partner link link_addr:" QDF_MAC_ADDR_FMT,
@@ -4140,13 +4140,88 @@ QDF_STATUS lim_check_for_ml_probe_req(struct pe_session *session)
 	return QDF_STATUS_E_FAILURE;
 }
 
-QDF_STATUS
-lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
-				struct pe_session *session_entry,
-				tpSirProbeRespBeacon rcvd_probe_resp,
-				uint8_t *probe_rsp,
-				uint32_t probe_rsp_len,
-				int32_t rssi)
+static QDF_STATUS lim_check_partner_link_for_cmn_akm(struct pe_session *session)
+{
+	struct scan_filter *filter;
+	qdf_list_t *scan_list = NULL;
+	struct wlan_objmgr_pdev *pdev;
+	uint8_t idx;
+	struct mlo_link_info *link_info;
+	struct scan_cache_entry *cur_entry;
+	struct scan_cache_node *link_node;
+	struct mlo_partner_info *partner_info;
+	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	pdev =  wlan_vdev_get_pdev(session->vdev);
+	if (!pdev) {
+		pe_err("PDEV NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	cur_entry =
+		wlan_cm_get_curr_candidate_entry(session->vdev, session->cm_id);
+	if (!cur_entry) {
+		pe_err("Current candidate NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	filter = qdf_mem_malloc(sizeof(*filter));
+	if (!filter) {
+		status = QDF_STATUS_E_NOMEM;
+		goto mem_free;
+	}
+
+	partner_info = &session->lim_join_req->partner_info;
+	for (idx = 0; idx < partner_info->num_partner_links; idx++) {
+		link_info = &partner_info->partner_link_info[idx];
+		qdf_copy_macaddr(&filter->bssid_list[idx],
+				 &link_info->link_addr);
+		filter->num_of_bssid++;
+
+		filter->chan_freq_list[idx] = link_info->chan_freq;
+		filter->num_of_channels++;
+	}
+
+	/* If no.of. scan entries fetched not equal to no.of partner links
+	 * then fail as common AKM is not determined.
+	 */
+	scan_list = wlan_scan_get_result(pdev, filter);
+	qdf_mem_free(filter);
+	if (!scan_list ||
+	    (qdf_list_size(scan_list) != partner_info->num_partner_links)) {
+		status = QDF_STATUS_E_INVAL;
+		goto mem_free;
+	}
+
+	qdf_list_peek_front(scan_list, &cur_node);
+	while (cur_node) {
+		qdf_list_peek_next(scan_list, cur_node, &next_node);
+		link_node = qdf_container_of(cur_node, struct scan_cache_node,
+					     node);
+
+		if (!wlan_scan_entries_contain_cmn_akm(cur_entry,
+						       link_node->entry)) {
+			status = QDF_STATUS_E_FAILURE;
+			break;
+		}
+
+		cur_node = next_node;
+		next_node = NULL;
+	}
+
+mem_free:
+	if (scan_list)
+		wlan_scan_purge_results(scan_list);
+	util_scan_free_cache_entry(cur_entry);
+	return status;
+}
+
+QDF_STATUS lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
+					   struct pe_session *session_entry,
+					   tpSirProbeRespBeacon rcvd_probe_resp,
+					   uint8_t *probe_rsp,
+					   uint32_t probe_rsp_len, int32_t rssi)
 {
 	struct element_info link_probe_rsp = {0};
 	struct qdf_mac_addr sta_link_addr;
@@ -4301,6 +4376,17 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
 				goto end;
 			}
 		}
+		/*
+		 * If the partner link's AKM not matching current candidate
+		 * remove the partner links for this association.
+		 */
+		status = lim_check_partner_link_for_cmn_akm(session_entry);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			pe_debug("Non overlapping partner link AKM %d",
+				 status);
+			lim_clear_ml_partner_info(session_entry);
+			goto end;
+		}
 	} else if (session_entry->lim_join_req->is_ml_probe_req_sent &&
 		   !rcvd_probe_resp->mlo_ie.mlo_ie_present) {
 		status =
@@ -4309,8 +4395,7 @@ lim_gen_link_specific_probe_rsp(struct mac_context *mac_ctx,
 		if (QDF_IS_STATUS_ERROR(status))
 			lim_clear_ml_partner_info(session_entry);
 
-		status = QDF_STATUS_E_FAILURE;
-		return status;
+		return QDF_STATUS_E_FAILURE;
 	} else {
 		return status;
 	}

+ 7 - 1
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -56,6 +56,7 @@
 #include "son_api.h"
 #include "wlan_t2lm_api.h"
 #include "wlan_epcs_api.h"
+#include <wlan_mlo_mgr_sta.h>
 #include "wlan_mlo_mgr_public_structs.h"
 
 #define SA_QUERY_REQ_MIN_LEN \
@@ -1558,6 +1559,11 @@ static void lim_process_addba_req(struct mac_context *mac_ctx, uint8_t *rx_pkt_i
 	bool eht_cap = false;
 	uint8_t extd_buff_size = 0;
 
+	if (mlo_is_any_link_disconnecting(session->vdev)) {
+		pe_err("Ignore ADDBA, vdev is in not in conncted state");
+		return;
+	}
+
 	mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
 	body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
 	frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);

+ 148 - 11
core/mac/src/pe/lim/lim_process_assoc_rsp_frame.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -47,6 +47,8 @@
 #include "wlan_mlme_ucfg_api.h"
 #include "wlan_connectivity_logging.h"
 #include <lim_mlo.h>
+#include <utils_mlo.h>
+#include <wlan_cm_roam_api.h>
 #include "parser_api.h"
 #include "wlan_twt_cfg_ext_api.h"
 #include "wlan_mlo_mgr_roam.h"
@@ -1088,6 +1090,120 @@ void lim_send_join_fail_on_vdev(struct mac_context *mac_ctx,
 			session_entry);
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+static QDF_STATUS
+lim_gen_link_specific_probe_resp_from_assoc_resp(uint8_t *rx_pkt_info,
+						 uint32_t frame_len,
+						 struct pe_session *session)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct bss_description *bss;
+	struct scan_cache_entry *scan_entry;
+	struct mlo_partner_info *lim_partner_info;
+	struct partner_link_info *scan_partner_info;
+	struct mlo_link_info *link_info;
+	uint8_t link_id, idx, idx2;
+	struct qdf_mac_addr link_addr;
+	struct element_info link_probe_rsp, probe_rsp;
+	uint8_t *frame = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
+	int8_t rssi = WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info);
+
+	if (!session->lim_join_req) {
+		pe_debug("Session join req invalid");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	bss = &session->lim_join_req->bssDescription;
+	lim_partner_info = &session->lim_join_req->partner_info;
+
+	/*
+	 * For link VDEV no need to generate again, as during assoc VDEv
+	 * it is already generated.
+	 */
+	if (!bss->mbssid_info.profile_num ||
+	    !lim_partner_info->num_partner_links ||
+	    wlan_vdev_mlme_is_mlo_link_vdev(session->vdev)) {
+		return QDF_STATUS_SUCCESS;
+	}
+
+	link_probe_rsp.ptr = qdf_mem_malloc(MAX_MGMT_MPDU_LEN);
+	if (!link_probe_rsp.ptr) {
+		pe_err("mallloc failed for %u bytes", MAX_MGMT_MPDU_LEN);
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	scan_entry = wlan_cm_get_curr_candidate_entry(session->vdev,
+						      session->cm_id);
+	if (!scan_entry) {
+		pe_err("Curr scan entry NULL");
+		qdf_mem_free(link_probe_rsp.ptr);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	probe_rsp.ptr =
+		util_scan_entry_frame_ptr(scan_entry) + WLAN_MAC_HDR_LEN_3A;
+	probe_rsp.len =
+		util_scan_entry_frame_len(scan_entry) - WLAN_MAC_HDR_LEN_3A;
+
+	qdf_mem_copy(&link_addr, session->self_mac_addr, QDF_MAC_ADDR_SIZE);
+
+	/*
+	 * For each partner entry, check if the corresponding partner link
+	 * is found or not to generate probe resp for the missing link.
+	 */
+	for (idx2 = 0; idx2 < lim_partner_info->num_partner_links; idx2++) {
+		link_info = &lim_partner_info->partner_link_info[idx2];
+		for (idx = 0; idx < scan_entry->ml_info.num_links; idx++) {
+			scan_partner_info = &scan_entry->ml_info.link_info[idx];
+			if (!scan_partner_info->is_scan_entry_not_found)
+				continue;
+
+			if (link_info->link_id != scan_partner_info->link_id)
+				continue;
+
+			link_id = link_info->link_id;
+			link_probe_rsp.len = 0;
+			status = util_gen_link_probe_rsp_from_assoc_rsp(frame,
+									frame_len,
+									link_id,
+									link_addr,
+									link_probe_rsp.ptr,
+									(qdf_size_t)MAX_MGMT_MPDU_LEN,
+									(qdf_size_t *)&link_probe_rsp.len,
+									probe_rsp.ptr,
+									probe_rsp.len);
+
+			if (QDF_IS_STATUS_ERROR(status))
+				goto mem_free;
+
+			status = lim_add_bcn_probe(session->vdev,
+						   link_probe_rsp.ptr,
+						   link_probe_rsp.len,
+						   link_info->chan_freq, rssi);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				pe_debug("Scan entry add failed for %d",
+					 link_id);
+				goto mem_free;
+			}
+		}
+	}
+
+mem_free:
+	qdf_mem_free(link_probe_rsp.ptr);
+	util_scan_free_cache_entry(scan_entry);
+
+	return status;
+}
+#else /* WLAN_FEATURE_11BE_MLO */
+static inline QDF_STATUS
+lim_gen_link_specific_probe_resp_from_assoc_resp(uint8_t *rx_pkt_info,
+						 uint32_t frame_len,
+						 struct pe_session *session)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_FEATURE_11BE_MLO */
+
 /**
  * lim_process_assoc_rsp_frame() - Processes assoc response
  * @mac_ctx: Pointer to Global MAC structure
@@ -1263,6 +1379,16 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
 		return;
 	}
 
+	if (subtype != LIM_REASSOC) {
+		aid = assoc_rsp->aid & 0x3FFF;
+		wlan_connectivity_mgmt_event(mac_ctx->psoc,
+					     (struct wlan_frame_hdr *)hdr,
+					     session_entry->vdev_id,
+					     assoc_rsp->status_code, 0, rssi,
+					     0, 0, 0, aid,
+					     WLAN_ASSOC_RSP);
+	}
+
 	if (lim_is_session_eht_capable(session_entry)) {
 		uint8_t ies_offset;
 
@@ -1473,16 +1599,6 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
 			      (assoc_rsp->status_code ? QDF_STATUS_E_FAILURE :
 			       QDF_STATUS_SUCCESS), assoc_rsp->status_code);
 
-	if (subtype != LIM_REASSOC) {
-		aid = assoc_rsp->aid & 0x3FFF;
-		wlan_connectivity_mgmt_event(mac_ctx->psoc,
-					     (struct wlan_frame_hdr *)hdr,
-					     session_entry->vdev_id,
-					     assoc_rsp->status_code, 0, rssi,
-					     0, 0, 0, aid,
-					     WLAN_ASSOC_RSP);
-	}
-
 	ap_nss = lim_get_nss_supported_by_ap(&assoc_rsp->VHTCaps,
 					     &assoc_rsp->HTCaps,
 					     &assoc_rsp->he_cap);
@@ -1744,6 +1860,27 @@ lim_process_assoc_rsp_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
 			      QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS);
 #endif
 	lim_update_stads_ext_cap(mac_ctx, session_entry, assoc_rsp, sta_ds);
+
+	/* Try to generate link probe resp from assoc resp for MBSSID AP
+	 * as ML probe is not sent for MBSSID AP.
+	 *
+	 * Any failure during partner link probe resp generation, treat
+	 * it as connect failure and send deauth to AP.
+	 */
+	status = lim_gen_link_specific_probe_resp_from_assoc_resp(rx_pkt_info,
+								  frame_body_len,
+								  session_entry);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		assoc_cnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE;
+		assoc_cnf.protStatusCode = STATUS_UNSPECIFIED_FAILURE;
+		/* Send advisory Disassociation frame to AP */
+		lim_send_disassoc_mgmt_frame(mac_ctx,
+					     REASON_UNSPEC_FAILURE,
+					     hdr->sa, session_entry,
+					     false);
+		goto assocReject;
+	}
+
 	/* Update the BSS Entry, this entry was added during preassoc. */
 	if (QDF_STATUS_SUCCESS ==
 	    lim_sta_send_add_bss(mac_ctx, assoc_rsp, beacon,

+ 3 - 1
core/mac/src/pe/lim/lim_process_cfg_updates.c

@@ -1,5 +1,7 @@
 /*
  * Copyright (c) 2012-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2024 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
@@ -129,7 +131,7 @@ void lim_handle_param_update(struct mac_context *mac, eUpdateIEsType cfgId)
 
 		if (status != QDF_STATUS_SUCCESS)
 			pe_err("Failed lim_post_msg_api %u", status);
-			break;
+		break;
 	}
 	default:
 		break;

+ 64 - 33
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1043,6 +1043,64 @@ static void lim_handle_unknown_a2_index_frames(struct mac_context *mac_ctx,
 	return;
 }
 
+static bool
+lim_is_ignore_btm_frame(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id,
+			tSirMacFrameCtl fc, uint8_t *body, uint16_t frm_len)
+{
+	bool is_sta_roam_disabled_by_p2p, is_mbo_wo_pmf;
+	uint8_t action_id, category, token = 0;
+	tpSirMacActionFrameHdr action_hdr;
+	enum wlan_diag_btm_block_reason reason;
+
+	/*
+	 * Drop BTM frame received on STA interface if concurrent
+	 * P2P connection is active and p2p_disable_roam ini is
+	 * enabled. This will help to avoid scan triggered by
+	 * userspace after processing the BTM frame from AP so the
+	 * audio glitches are not seen in P2P connection.
+	 */
+	is_sta_roam_disabled_by_p2p = cfg_p2p_is_roam_config_disabled(psoc) &&
+		(policy_mgr_mode_specific_connection_count(psoc,
+							   PM_P2P_CLIENT_MODE,
+							   NULL) ||
+		 policy_mgr_mode_specific_connection_count(psoc,
+							   PM_P2P_GO_MODE,
+							   NULL));
+
+	is_mbo_wo_pmf = wlan_cm_is_mbo_ap_without_pmf(psoc, vdev_id);
+	if (!is_sta_roam_disabled_by_p2p && !is_mbo_wo_pmf)
+		return false;
+
+	action_hdr = (tpSirMacActionFrameHdr)body;
+
+	if (frm_len < sizeof(*action_hdr) || !action_hdr ||
+	    fc.type != SIR_MAC_MGMT_FRAME || fc.subType != SIR_MAC_MGMT_ACTION)
+		return false;
+
+	action_id = action_hdr->actionID;
+	category = action_hdr->category;
+	if (category == ACTION_CATEGORY_WNM &&
+	    (action_id == WNM_BSS_TM_QUERY ||
+	     action_id == WNM_BSS_TM_REQUEST ||
+	     action_id == WNM_BSS_TM_RESPONSE)) {
+		if (frm_len >= sizeof(*action_hdr) + 1)
+			token = *(body + sizeof(*action_hdr));
+		if (is_mbo_wo_pmf) {
+			pe_debug("Drop the BTM frame as it's received from MBO AP without PMF, vdev %d",
+				 vdev_id);
+			reason = WLAN_DIAG_BTM_BLOCK_MBO_WO_PMF;
+		} else {
+			pe_debug("Drop the BTM frame as p2p session is active, vdev %d",
+				 vdev_id);
+			reason = WLAN_DIAG_BTM_BLOCK_UNSUPPORTED_P2P_CONC;
+		}
+		wlan_cm_roam_btm_block_event(vdev_id, token, reason);
+		return true;
+	}
+
+	return false;
+}
+
 /**
  * lim_check_mgmt_registered_frames() - This function handles registered
  *                                      management frames.
@@ -1069,15 +1127,13 @@ lim_check_mgmt_registered_frames(struct mac_context *mac_ctx, uint8_t *buff_desc
 	uint16_t frm_len;
 	uint8_t type, sub_type;
 	bool match = false;
-	tpSirMacActionFrameHdr action_hdr;
-	uint8_t actionID, category, vdev_id = WLAN_INVALID_VDEV_ID;
+	uint8_t vdev_id = WLAN_INVALID_VDEV_ID;
 	QDF_STATUS qdf_status;
 
 	hdr = WMA_GET_RX_MAC_HEADER(buff_desc);
 	fc = hdr->fc;
 	frm_type = (fc.type << 2) | (fc.subType << 4);
 	body = WMA_GET_RX_MPDU_DATA(buff_desc);
-	action_hdr = (tpSirMacActionFrameHdr)body;
 	frm_len = WMA_GET_RX_PAYLOAD_LEN(buff_desc);
 
 	qdf_mutex_acquire(&mac_ctx->lim.lim_frame_register_lock);
@@ -1122,36 +1178,11 @@ lim_check_mgmt_registered_frames(struct mac_context *mac_ctx, uint8_t *buff_desc
 	if (match) {
 		pe_debug("rcvd frame match with registered frame params");
 
-		/*
-		 * Drop BTM frame received on STA interface if concurrent
-		 * P2P connection is active and p2p_disable_roam ini is
-		 * enabled. This will help to avoid scan triggered by
-		 * userspace after processing the BTM frame from AP so the
-		 * audio glitches are not seen in P2P connection.
-		 */
 		if (session_entry && LIM_IS_STA_ROLE(session_entry) &&
-		    ((cfg_p2p_is_roam_config_disabled(mac_ctx->psoc) &&
-		      (policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
-						PM_P2P_CLIENT_MODE, NULL) ||
-		       policy_mgr_mode_specific_connection_count(mac_ctx->psoc,
-						PM_P2P_GO_MODE, NULL))) ||
-		     wlan_cm_is_mbo_ap_without_pmf(mac_ctx->psoc,
-						   session_entry->vdev_id))) {
-			if (frm_len >= sizeof(*action_hdr) && action_hdr &&
-			    fc.type == SIR_MAC_MGMT_FRAME &&
-			    fc.subType == SIR_MAC_MGMT_ACTION) {
-				actionID = action_hdr->actionID;
-				category = action_hdr->category;
-				if (category == ACTION_CATEGORY_WNM &&
-				    (actionID == WNM_BSS_TM_QUERY ||
-				     actionID == WNM_BSS_TM_REQUEST ||
-				     actionID == WNM_BSS_TM_RESPONSE)) {
-					pe_debug("Drop the BTM frame as p2p session is active or rcvd from MBO AP without PMF, vdev %d",
-						 session_entry->vdev_id);
-					return match;
-				}
-			}
-		}
+		    lim_is_ignore_btm_frame(mac_ctx->psoc,
+					    session_entry->vdev_id, fc, body,
+					    frm_len))
+			return match;
 
 		/*
 		 * Some frames like GAS_INITIAL_REQ are registered with

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -309,6 +309,7 @@ void lim_process_mlm_join_cnf(struct mac_context *mac_ctx,
 
 	wlan_connectivity_sta_info_event(mac_ctx->psoc, session_entry->vdev_id,
 					 false);
+	wlan_connectivity_connecting_event(session_entry->vdev, NULL);
 
 	session_entry->join_probe_cnt = 0;
 	if (session_entry->limSmeState != eLIM_SME_WT_JOIN_STATE) {

+ 5 - 6
core/mac/src/pe/lim/lim_process_sme_req_messages.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -2098,7 +2098,7 @@ lim_get_bss_11be_mode_allowed(struct mac_context *mac_ctx,
 		is_eht_allowed =
 			wlan_cm_is_eht_allowed_for_current_security(
 					wlan_pdev_get_psoc(mac_ctx->pdev),
-					scan_entry);
+					scan_entry, false);
 		util_scan_free_cache_entry(scan_entry);
 		if (!is_eht_allowed) {
 			pe_debug("Downgrade to 11ax mode due to AP security validation failure");
@@ -9168,10 +9168,9 @@ bool lim_process_sme_req_messages(struct mac_context *mac,
 		break;
 
 	case eWNI_SME_ASSOC_CNF:
-		if (pMsg->type == eWNI_SME_ASSOC_CNF)
-			pe_debug("Received ASSOC_CNF message");
-			__lim_process_sme_assoc_cnf_new(mac, pMsg->type,
-							msg_buf);
+		pe_debug("Received ASSOC_CNF message");
+		__lim_process_sme_assoc_cnf_new(mac, pMsg->type,
+						msg_buf);
 		break;
 
 	case eWNI_SME_ADDTS_REQ:

+ 88 - 15
core/mac/src/pe/lim/lim_send_management_frames.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -5804,12 +5804,12 @@ lim_send_radio_measure_report_action_frame(struct mac_context *mac,
 						 pe_session);
 	}
 
-	pe_nofl_info("TX: type:%d seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report:%d peer:"QDF_MAC_ADDR_FMT,
-		     frm->MeasurementReport[0].type,
-		     (pMacHdr->seqControl.seqNumHi << HIGH_SEQ_NUM_OFFSET |
-		     pMacHdr->seqControl.seqNumLo),
-		     dialog_token, frm->num_MeasurementReport,
-		     is_last_report, num_report, QDF_MAC_ADDR_REF(peer));
+	pe_nofl_rl_info("TX: type:%d seq_no:%d dialog_token:%d no. of APs:%d is_last_rpt:%d num_report:%d peer:"QDF_MAC_ADDR_FMT,
+			frm->MeasurementReport[0].type,
+			(pMacHdr->seqControl.seqNumHi << HIGH_SEQ_NUM_OFFSET |
+			pMacHdr->seqControl.seqNumLo),
+			dialog_token, frm->num_MeasurementReport,
+			is_last_report, num_report, QDF_MAC_ADDR_REF(peer));
 
 	if (!wlan_reg_is_24ghz_ch_freq(pe_session->curr_op_freq) ||
 	    pe_session->opmode == QDF_P2P_CLIENT_MODE ||
@@ -5825,8 +5825,8 @@ lim_send_radio_measure_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_nofl_err("TX: [802.11 RRM] Send FAILED! err_status [%d]",
-			    qdf_status);
+		pe_nofl_rl_err("TX: [802.11 RRM] Send FAILED! err_status [%d]",
+			       qdf_status);
 		status_code = QDF_STATUS_E_FAILURE;
 		/* Pkt will be freed up by the callback */
 	}
@@ -6915,9 +6915,79 @@ lim_mgmt_t2lm_rsp_tx_complete(void *context, qdf_nbuf_t buf,
 					      rsp.DialogToken.token,
 					      rsp.Status.status,
 					      qdf_tx_complete,
-					      mgmt_params->chanfreq,
+					      (qdf_freq_t)mgmt_params->chanfreq,
 					      false,
-					      WLAN_CONN_DIAG_MLO_T2LM_RESP_EVENT);
+					      WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT);
+out:
+	qdf_nbuf_free(buf);
+
+	return status;
+}
+
+static QDF_STATUS
+lim_mgmt_t2lm_req_tx_complete(void *context, qdf_nbuf_t buf,
+			      uint32_t tx_status, void *params)
+{
+	struct mac_context *mac_ctx = (struct mac_context *)context;
+	struct pe_session *pe_session;
+	struct wlan_frame_hdr *mac_hdr;
+	struct wmi_mgmt_params *mgmt_params;
+	tDot11ft2lm_neg_req req = {0};
+	enum qdf_dp_tx_rx_status qdf_tx_complete;
+	uint32_t extract_status;
+	uint8_t *frame_ptr;
+	uint8_t ff_offset;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	if (!params) {
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	frame_ptr = qdf_nbuf_data(buf);
+	mac_hdr = (struct wlan_frame_hdr *)frame_ptr;
+
+	ff_offset = sizeof(*mac_hdr);
+	if (wlan_crypto_is_data_protected(frame_ptr))
+		ff_offset += IEEE80211_CCMP_MICLEN;
+
+	if (qdf_nbuf_len(buf) < (ff_offset + sizeof(struct action_frm_hdr))) {
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	mgmt_params = params;
+	pe_session = pe_find_session_by_vdev_id(mac_ctx, mgmt_params->vdev_id);
+	if (!pe_session || pe_session->opmode != QDF_STA_MODE) {
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	if (tx_status == WMI_MGMT_TX_COMP_TYPE_COMPLETE_OK)
+		qdf_tx_complete = QDF_TX_RX_STATUS_OK;
+	else if (tx_status  == WMI_MGMT_TX_COMP_TYPE_DISCARD)
+		qdf_tx_complete = QDF_TX_RX_STATUS_FW_DISCARD;
+	else
+		qdf_tx_complete = QDF_TX_RX_STATUS_NO_ACK;
+
+	extract_status =
+		dot11f_unpack_t2lm_neg_req(mac_ctx,
+					   frame_ptr + ff_offset,
+					   sizeof(req), &req, false);
+	if (DOT11F_FAILED(extract_status)) {
+		pe_err("Failed to unpack T2LM negotiation request (0x%08x)",
+		       extract_status);
+		status = QDF_STATUS_E_FAILURE;
+		goto out;
+	}
+
+	wlan_connectivity_t2lm_req_resp_event(pe_session->vdev,
+					      req.DialogToken.token,
+					      false,
+					      qdf_tx_complete,
+					      (qdf_freq_t)mgmt_params->chanfreq,
+					      false,
+					      WLAN_CONN_DIAG_MLO_T2LM_REQ_EVENT);
 out:
 	qdf_nbuf_free(buf);
 
@@ -7163,10 +7233,13 @@ lim_send_t2lm_action_req_frame(struct wlan_objmgr_vdev *vdev,
 
 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_MGMT,
 			 session->peSessionId, mgmt_hdr->fc.subType));
-	qdf_status = wma_tx_frame(mac_ctx, pkt_ptr, (uint16_t)num_bytes,
-				  TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
-				  lim_tx_complete, frame_ptr, tx_flag,
-				  vdev_id, 0, RATEID_DEFAULT, 0);
+	qdf_status = wma_tx_frameWithTxComplete(
+			mac_ctx, pkt_ptr, (uint16_t)num_bytes,
+			 TXRX_FRM_802_11_MGMT, ANI_TXDIR_TODS, 7,
+			 lim_tx_complete, frame_ptr,
+			 lim_mgmt_t2lm_req_tx_complete, tx_flag,
+			 vdev_id, 0, session->curr_op_freq,
+			 RATEID_DEFAULT, 0, 0);
 	MTRACE(qdf_trace(QDF_MODULE_ID_PE, TRACE_CODE_TX_COMPLETE,
 			 session->peSessionId, qdf_status));
 	if (qdf_status != QDF_STATUS_SUCCESS) {

+ 16 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -9016,6 +9016,21 @@ void lim_log_eht_op(struct mac_context *mac, tDot11fIEeht_op *eht_ops,
 			   eht_ops, sizeof(tDot11fIEeht_op));
 }
 
+static void
+lim_revise_eht_caps(struct mac_context *mac, tDot11fIEeht_cap *eht_cap)
+{
+	uint32_t country_max_allowed_bw;
+
+	country_max_allowed_bw = wlan_reg_get_country_max_allowed_bw(mac->pdev);
+	if (!country_max_allowed_bw) {
+		pe_debug("Failed to get country_max_allowed_bw");
+		return;
+	}
+
+	if (country_max_allowed_bw < BW_320_MHZ)
+		eht_cap->support_320mhz_6ghz = 0;
+}
+
 void lim_set_eht_caps(struct mac_context *mac,
 		      uint8_t *ie_start, uint32_t num_bytes, uint8_t band,
 		      uint8_t vdev_id)
@@ -9035,6 +9050,7 @@ void lim_set_eht_caps(struct mac_context *mac,
 		is_band_2g = true;
 
 	populate_dot11f_eht_caps_by_band(mac, is_band_2g, &dot11_cap, NULL);
+	lim_revise_eht_caps(mac, &dot11_cap);
 	populate_dot11f_he_caps_by_band(mac, is_band_2g, &dot11_he_cap,
 					NULL);
 	lim_log_eht_cap(mac, &dot11_cap);

+ 21 - 33
core/mac/src/pe/rrm/rrm_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -1240,18 +1240,18 @@ rrm_process_beacon_report_req(struct mac_context *mac,
 
 	measDuration = pBeaconReq->measurement_request.Beacon.meas_duration;
 
-	pe_nofl_info("RX: [802.11 BCN_RPT] seq:%d SSID:" QDF_SSID_FMT " BSSID:" QDF_MAC_ADDR_FMT " Token:%d op_class:%d ch:%d meas_mode:%d meas_duration:%d max_meas_dur: %d",
-		     mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
-		     QDF_SSID_REF(
+	pe_nofl_rl_info("RX: [802.11 BCN_RPT] seq:%d SSID:" QDF_SSID_FMT " BSSID:" QDF_MAC_ADDR_FMT " Token:%d op_class:%d ch:%d meas_mode:%d meas_duration:%d max_meas_dur: %d",
+			mac->rrm.rrmPEContext.prev_rrm_report_seq_num,
+			QDF_SSID_REF(
 			pBeaconReq->measurement_request.Beacon.SSID.num_ssid,
 			pBeaconReq->measurement_request.Beacon.SSID.ssid),
-		     QDF_MAC_ADDR_REF(
+			QDF_MAC_ADDR_REF(
 			pBeaconReq->measurement_request.Beacon.BSSID),
-		     pBeaconReq->measurement_token,
-		     pBeaconReq->measurement_request.Beacon.regClass,
-		     pBeaconReq->measurement_request.Beacon.channel,
-		     pBeaconReq->measurement_request.Beacon.meas_mode,
-		     measDuration, maxMeasduration);
+			pBeaconReq->measurement_token,
+			pBeaconReq->measurement_request.Beacon.regClass,
+			pBeaconReq->measurement_request.Beacon.channel,
+			pBeaconReq->measurement_request.Beacon.meas_mode,
+			measDuration, maxMeasduration);
 
 	req_mode = (pBeaconReq->parallel << 0) | (pBeaconReq->enable << 1) |
 		   (pBeaconReq->request << 2) | (pBeaconReq->report << 3) |
@@ -2061,8 +2061,8 @@ rrm_process_channel_load_req(struct mac_context *mac,
 {
 	struct scheduler_msg msg = {0};
 	struct ch_load_ind *load_ind;
-	struct bw_ind_element bw_ind;
-	struct wide_bw_chan_switch wide_bw;
+	struct bw_ind_element bw_ind = {0};
+	struct wide_bw_chan_switch wide_bw = {0};
 	struct rrm_reporting rrm_report;
 	uint8_t op_class, channel;
 	uint16_t randomization_intv, meas_duration, max_meas_duration;
@@ -2110,7 +2110,10 @@ rrm_process_channel_load_req(struct mac_context *mac,
 			pe_debug("Dropping req: invalid is_bw_ind_element IE");
 			return eRRM_REFUSED;
 		}
-	} else if (is_wide_bw_chan_switch) {
+	}
+
+	if (is_wide_bw_chan_switch) {
+		wide_bw.is_wide_bw_chan_switch = true;
 		wide_bw.channel_width = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_chan_width;
 		wide_bw.center_chan_freq0 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq0;
 		wide_bw.center_chan_freq1 = chan_load_req->measurement_request.channel_load.wide_bw_chan_switch.new_center_chan_freq1;
@@ -2118,12 +2121,10 @@ rrm_process_channel_load_req(struct mac_context *mac,
 			 wide_bw.channel_width, wide_bw.center_chan_freq0,
 			 wide_bw.center_chan_freq1);
 		if (wide_bw.channel_width < CH_WIDTH_20MHZ ||
-		    bw_ind.channel_width >= CH_WIDTH_320MHZ) {
+		    wide_bw.channel_width >= CH_WIDTH_320MHZ) {
 			pe_debug("Dropping req: invalid wide_bw IE");
 			return eRRM_REFUSED;
 		}
-	} else {
-		pe_debug("IE(s) are NULL in channel load request");
 	}
 
 	op_class = chan_load_req->measurement_request.channel_load.op_class;
@@ -2198,24 +2199,11 @@ rrm_process_channel_load_req(struct mac_context *mac,
 	load_ind->meas_duration = meas_duration;
 	curr_req->token = chan_load_req->measurement_token;
 
-	if (is_wide_bw_chan_switch) {
-		load_ind->wide_bw.is_wide_bw_chan_switch = true;
-		load_ind->wide_bw.channel_width = wide_bw.channel_width;
-		load_ind->wide_bw.center_chan_freq0 = wide_bw.center_chan_freq0;
-		load_ind->wide_bw.center_chan_freq1 = wide_bw.center_chan_freq1;
-	} else {
-		load_ind->wide_bw.channel_width = CH_WIDTH_INVALID;
-	}
+	if (is_wide_bw_chan_switch)
+		load_ind->wide_bw = wide_bw;
 
-	if (bw_ind.is_bw_ind_element) {
-		load_ind->bw_ind.is_bw_ind_element = true;
-		load_ind->bw_ind.channel_width = bw_ind.channel_width;
-		load_ind->bw_ind.ccfi0 = bw_ind.ccfi0;
-		load_ind->bw_ind.ccfi1 = bw_ind.ccfi1;
-		load_ind->bw_ind.center_freq = bw_ind.center_freq;
-	} else {
-		load_ind->bw_ind.is_bw_ind_element = false;
-	}
+	if (is_bw_ind)
+		load_ind->bw_ind = bw_ind;
 
 	/* Send request to SME. */
 	msg.type = eWNI_SME_CHAN_LOAD_REQ_IND;

+ 3 - 4
core/sme/src/common/sme_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -3306,8 +3306,7 @@ QDF_STATUS sme_get_network_params(struct mac_context *mac,
 		csr_translate_to_wni_cfg_dot11_mode(mac, dot11_mode);
 
 	dot11_cfg->nw_type =
-		csr_convert_mode_to_nw_type(dot11_cfg->dot11_mode,
-					    dot11_cfg->p_band);
+		csr_convert_mode_to_nw_type(dot11_mode, dot11_cfg->p_band);
 
 	/* If INI is enabled, use the rates from hostapd */
 	if (!cds_is_sub_20_mhz_enabled() && chan_switch_hostapd_rate_enabled &&
@@ -12669,7 +12668,7 @@ uint32_t sme_get_wni_dot11_mode(mac_handle_t mac_handle)
  *
  * Return: QDF_STATUS_SUCCESS on success, non-zero error code on failure.
  */
-QDF_STATUS sme_create_mon_session(mac_handle_t mac_handle, tSirMacAddr bss_id,
+QDF_STATUS sme_create_mon_session(mac_handle_t mac_handle, uint8_t *bss_id,
 				  uint8_t vdev_id)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;

+ 26 - 23
core/sme/src/rrm/sme_rrm.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 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
@@ -1171,7 +1171,7 @@ static QDF_STATUS sme_rrm_fill_scan_channels(struct mac_context *mac,
 	if (sme_rrm_context->channelList.numOfChannels == 0) {
 		qdf_mem_free(sme_rrm_context->channelList.freq_list);
 		sme_rrm_context->channelList.freq_list = NULL;
-		sme_err("No channels populated with requested operation class and current country, Hence abort the rrm operation");
+		sme_err_rl("No channels populated with requested operation class and current country, Hence abort the rrm operation");
 		return QDF_STATUS_E_FAILURE;
 	}
 
@@ -1230,13 +1230,7 @@ sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
 
 	bw_ind = &sme_rrm_ctx->chan_load_req_info.bw_ind;
 	wide_bw = &sme_rrm_ctx->chan_load_req_info.wide_bw;
-
-	if (bw_ind->is_bw_ind_element) {
-		chan_width = bw_ind->channel_width;
-		cen320_freq = bw_ind->center_freq;
-	} else if (wide_bw->is_wide_bw_chan_switch){
-		chan_width = wide_bw->channel_width;
-	} else {
+	if (!bw_ind->is_bw_ind_element && !wide_bw->is_wide_bw_chan_switch) {
 		if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev,
 					      sme_rrm_ctx->regClass))
 			c_space =
@@ -1274,6 +1268,14 @@ sme_rrm_fill_freq_list_for_channel_load(struct mac_context *mac_ctx,
 			sme_err("invalid chan_space: %d", c_space);
 			return QDF_STATUS_E_FAILURE;
 		}
+	} else {
+		if (bw_ind->is_bw_ind_element) {
+			chan_width = bw_ind->channel_width;
+			cen320_freq = bw_ind->center_freq;
+		}
+
+		if (wide_bw->is_wide_bw_chan_switch)
+			chan_width = wide_bw->channel_width;
 	}
 
 	sme_rrm_ctx->chan_load_req_info.req_chan_width = chan_width;
@@ -1390,6 +1392,7 @@ static QDF_STATUS sme_rrm_process_chan_load_req_ind(struct mac_context *mac,
 	struct ch_load_ind *chan_load;
 	tpRrmSMEContext sme_rrm_ctx;
 	tpRrmPEContext rrm_ctx;
+	struct channel_load_req_info *req_info;
 
 	chan_load = (struct ch_load_ind *)msg_buf;
 	sme_rrm_ctx = &mac->rrm.rrmSmeContext[chan_load->measurement_idx];
@@ -1406,27 +1409,27 @@ static QDF_STATUS sme_rrm_process_chan_load_req_ind(struct mac_context *mac,
 		     (uint8_t *)&chan_load->meas_duration,
 		     SIR_ESE_MAX_MEAS_IE_REQS);
 	sme_rrm_ctx->measurement_type = RRM_CHANNEL_LOAD;
-	sme_rrm_ctx->chan_load_req_info.channel = chan_load->channel;
-	sme_rrm_ctx->chan_load_req_info.req_freq = chan_load->req_freq;
+	req_info = &sme_rrm_ctx->chan_load_req_info;
+	req_info->channel = chan_load->channel;
+	req_info->req_freq = chan_load->req_freq;
 
-	qdf_mem_copy(&sme_rrm_ctx->chan_load_req_info.bw_ind,
-			&chan_load->bw_ind,
-			sizeof(sme_rrm_ctx->chan_load_req_info.bw_ind));
-	qdf_mem_copy(&sme_rrm_ctx->chan_load_req_info.wide_bw,
-			&chan_load->wide_bw,
-			sizeof(sme_rrm_ctx->chan_load_req_info.wide_bw));
+	qdf_mem_copy(&req_info->bw_ind, &chan_load->bw_ind,
+		     sizeof(req_info->bw_ind));
+	qdf_mem_copy(&req_info->wide_bw, &chan_load->wide_bw,
+		     sizeof(req_info->wide_bw));
 
-	sme_debug("idx:%d, token: %d randnIntvl: %d meas_duration %d, rrm_ctx dur %d reg_class: %d, type: %d, channel: %d, freq:%d, [bw_ind cw:%d, ccfs0:%d], [wide_bw cw:%d]",
+	sme_debug("idx:%d, token: %d randnIntvl: %d meas_duration %d, rrm_ctx dur %d reg_class: %d, type: %d, channel: %d, freq: %d, [bw_ind present: %d, cw: %d, ccfs0: %d], [wide_bw present: %d, cw: %d]",
 		  chan_load->measurement_idx, sme_rrm_ctx->token,
 		  sme_rrm_ctx->randnIntvl,
 		  chan_load->meas_duration,
 		  sme_rrm_ctx->duration[0], sme_rrm_ctx->regClass,
 		  sme_rrm_ctx->measurement_type,
-		  sme_rrm_ctx->chan_load_req_info.channel,
-		  sme_rrm_ctx->chan_load_req_info.req_freq,
-		  sme_rrm_ctx->chan_load_req_info.bw_ind.channel_width,
-		  sme_rrm_ctx->chan_load_req_info.bw_ind.center_freq,
-		  sme_rrm_ctx->chan_load_req_info.wide_bw.channel_width);
+		  req_info->channel, req_info->req_freq,
+		  req_info->bw_ind.is_bw_ind_element,
+		  req_info->bw_ind.channel_width,
+		  req_info->bw_ind.center_freq,
+		  req_info->wide_bw.is_wide_bw_chan_switch,
+		  req_info->wide_bw.channel_width);
 
 	return sme_rrm_issue_chan_load_measurement_scan(mac,
 						chan_load->measurement_idx);

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -5067,7 +5067,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 	}
 
 	if (cdp_peer_state_get(soc, params->smesessionId,
-			       params->bssId) == OL_TXRX_PEER_STATE_DISC) {
+			       params->bssId, true) == OL_TXRX_PEER_STATE_DISC) {
 		/*
 		 * This is the case for reassociation.
 		 * peer state update and peer_assoc is required since it

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

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1357,6 +1357,7 @@ static void wma_set_mlo_capability(tp_wma_handle wma,
 			link_id_bitmap = 1 << params->link_id;
 			ml_nlink_set_curr_force_inactive_state(
 					psoc, vdev, link_id_bitmap, LINK_ADD);
+			ml_nlink_init_concurrency_link_request(psoc, vdev);
 		}
 		wma_debug("assoc_link %d" QDF_MAC_ADDR_FMT ", force inactive %d link id %d",
 			  req->mlo_params.mlo_assoc_link,

+ 5 - 4
os_if/cp_stats/src/wlan_cfg80211_mc_cp_stats.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2011-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 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
@@ -1861,7 +1861,8 @@ void infra_cp_stats_bmiss_response_cb(struct infra_cp_stats_event *ev,
 
 struct infra_cp_stats_event *
 wlan_cfg80211_mc_bmiss_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
-					  uint8_t *bmiss_peer_mac, int *errno)
+					  uint8_t mac[QDF_MAC_ADDR_SIZE],
+					  int *errno)
 {
 	void *cookie;
 	int idx = 0;
@@ -1935,7 +1936,7 @@ wlan_cfg80211_mc_bmiss_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
 	info.num_mac_addr_list = MAX_TWT_STAT_MAC_ADDR_ENTRIES;
 	info.num_pdev_ids = 0;
 
-	qdf_mem_copy(&info.peer_mac_addr[0], bmiss_peer_mac, QDF_MAC_ADDR_SIZE);
+	qdf_mem_copy(&info.peer_mac_addr[0], mac, QDF_MAC_ADDR_SIZE);
 	status = ucfg_infra_cp_stats_register_resp_cb(wlan_vdev_get_psoc(vdev),
 						      &info);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -1987,7 +1988,7 @@ wlan_cfg80211_mc_bmiss_get_infra_cp_stats(struct wlan_objmgr_vdev *vdev,
 	out->bmiss_infra_cp_stats->cons_bmiss_stats.num_bcn_hist_lost =
 			bmiss_event->cons_bmiss_stats.num_bcn_hist_lost;
 
-	qdf_mem_copy(&out->bmiss_infra_cp_stats->peer_macaddr, bmiss_peer_mac,
+	qdf_mem_copy(&out->bmiss_infra_cp_stats->peer_macaddr, mac,
 		     QDF_MAC_ADDR_SIZE);
 	osif_request_put(request);
 	status = ucfg_infra_cp_stats_deregister_resp_cb(