Ver Fonte

Merge b6d1057c2a518b87f39178d90fe583c461024b93 on remote branch

Change-Id: Id2060c080ec2596bcb0f5f52e50dcbb1e552694b
Linux Build Service Account há 9 meses atrás
pai
commit
b8d0aa4793
59 ficheiros alterados com 985 adições e 314 exclusões
  1. 1 1
      components/cmn_services/interface_mgr/src/wlan_if_mgr_roam.c
  2. 4 0
      components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c
  3. 5 3
      components/dp/core/inc/wlan_dp_priv.h
  4. 39 8
      components/dp/core/src/wlan_dp_fisa_rx.c
  5. 5 1
      components/dp/core/src/wlan_dp_main.c
  6. 4 5
      components/dp/dispatcher/inc/wlan_dp_api.h
  7. 15 2
      components/dp/dispatcher/src/wlan_dp_api.c
  8. 11 0
      components/dp/dispatcher/src/wlan_dp_ucfg_api.c
  9. 28 1
      components/mlme/core/inc/wlan_mlme_main.h
  10. 3 2
      components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.h
  11. 65 0
      components/mlme/core/src/wlan_mlme_main.c
  12. 32 2
      components/mlme/core/src/wlan_mlme_vdev_mgr_interface.c
  13. 17 0
      components/mlme/dispatcher/inc/wlan_mlme_api.h
  14. 12 0
      components/mlme/dispatcher/inc/wlan_mlme_ucfg_api.h
  15. 39 2
      components/mlme/dispatcher/src/wlan_mlme_api.c
  16. 32 2
      components/p2p/core/src/wlan_p2p_off_chan_tx.c
  17. 23 1
      components/p2p/core/src/wlan_p2p_off_chan_tx.h
  18. 11 1
      components/p2p/dispatcher/inc/wlan_p2p_api.h
  19. 9 1
      components/p2p/dispatcher/src/wlan_p2p_api.c
  20. 42 8
      components/pre_cac/core/src/wlan_pre_cac_main.c
  21. 4 2
      components/pre_cac/core/src/wlan_pre_cac_main.h
  22. 6 3
      components/pre_cac/dispatcher/inc/wlan_pre_cac_ucfg_api.h
  23. 5 3
      components/pre_cac/dispatcher/src/wlan_pre_cac_ucfg_api.c
  24. 2 0
      components/tdls/core/src/wlan_tdls_mgmt.c
  25. 21 6
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c
  26. 6 5
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c
  27. 8 8
      components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload_event.c
  28. 1 1
      components/umac/mlme/connection_mgr/core/src/wlan_cm_vdev_connect.c
  29. 12 1
      core/hdd/inc/wlan_hdd_main.h
  30. 167 15
      core/hdd/src/wlan_hdd_cfg80211.c
  31. 4 6
      core/hdd/src/wlan_hdd_cm_connect.c
  32. 7 2
      core/hdd/src/wlan_hdd_cm_disconnect.c
  33. 4 1
      core/hdd/src/wlan_hdd_hostapd.c
  34. 2 3
      core/hdd/src/wlan_hdd_main.c
  35. 8 12
      core/hdd/src/wlan_hdd_p2p.c
  36. 15 3
      core/hdd/src/wlan_hdd_pre_cac.c
  37. 4 2
      core/hdd/src/wlan_hdd_stats.c
  38. 2 2
      core/mac/inc/qwlan_version.h
  39. 2 0
      core/mac/inc/sir_api.h
  40. 3 2
      core/mac/src/pe/lim/lim_assoc_utils.c
  41. 13 9
      core/mac/src/pe/lim/lim_process_action_frame.c
  42. 1 0
      core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c
  43. 5 4
      core/mac/src/pe/lim/lim_process_sme_req_messages.c
  44. 2 2
      core/mac/src/pe/lim/lim_session.c
  45. 1 1
      core/mac/src/pe/lim/lim_utils.c
  46. 2 1
      core/mac/src/pe/rrm/rrm_api.c
  47. 4 1
      core/mac/src/sys/legacy/src/utils/src/parser_api.c
  48. 5 0
      core/sap/src/sap_fsm.c
  49. 1 0
      core/sap/src/sap_module.c
  50. 5 1
      core/sme/inc/csr_api.h
  51. 2 1
      core/sme/inc/csr_internal.h
  52. 26 4
      core/sme/src/common/sme_api.c
  53. 187 139
      core/sme/src/csr/csr_api_roam.c
  54. 15 14
      core/sme/src/csr/csr_inside_api.h
  55. 17 17
      core/wma/src/wma_dev_if.c
  56. 1 1
      core/wma/src/wma_features.c
  57. 2 0
      core/wma/src/wma_mgmt.c
  58. 3 1
      core/wma/src/wma_power.c
  59. 13 1
      os_if/dp/src/os_if_dp_txrx.c

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

@@ -801,7 +801,7 @@ static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc,
 				    struct validate_bss_data *candidate_info)
 {
 	struct scan_cache_entry *scan_entry = candidate_info->scan_entry;
-	struct action_oui_search_attr attr;
+	struct action_oui_search_attr attr = {0};
 	int8_t i, allowed_partner_links = 0;
 	uint8_t mlo_support_link_num;
 

+ 4 - 0
components/cmn_services/policy_mgr/src/wlan_policy_mgr_get_set_utils.c

@@ -11287,6 +11287,10 @@ bool policy_mgr_is_sap_allowed_on_dfs_freq(struct wlan_objmgr_pdev *pdev,
 	sta_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
 							 vdev_id_list,
 							 PM_STA_MODE);
+
+	if (sta_cnt >= MAX_NUMBER_OF_CONC_CONNECTIONS)
+		return false;
+
 	gc_cnt = policy_mgr_get_mode_specific_conn_info(psoc, NULL,
 							&vdev_id_list[sta_cnt],
 							PM_P2P_CLIENT_MODE);

+ 5 - 3
components/dp/core/inc/wlan_dp_priv.h

@@ -415,6 +415,7 @@ struct fisa_pkt_hist {
  * @rx_flow_tuple_info: RX tuple information
  * @napi_id: NAPI ID (REO ID) on which the flow is being received
  * @vdev: VDEV handle corresponding to the FLOW
+ * @vdev_id: DP vdev id
  * @dp_intf: DP interface handle corresponding to the flow
  * @bytes_aggregated: Number of bytes currently aggregated
  * @flush_count: Number of Flow flushes done
@@ -459,6 +460,7 @@ struct dp_fisa_rx_sw_ft {
 	struct cdp_rx_flow_tuple_info rx_flow_tuple_info;
 	uint8_t napi_id;
 	struct dp_vdev *vdev;
+	uint8_t vdev_id;
 	struct wlan_dp_intf *dp_intf;
 	uint64_t bytes_aggregated;
 	uint32_t flush_count;
@@ -721,9 +723,9 @@ 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;
+	uint8_t destroyed;
+	uint8_t cdp_vdev_registered;
+	uint8_t	cdp_vdev_deleted;
 	TAILQ_ENTRY(wlan_dp_link) inactive_list_elem;
 };
 

+ 39 - 8
components/dp/core/src/wlan_dp_fisa_rx.c

@@ -459,6 +459,7 @@ static void dp_rx_fisa_update_sw_ft_entry(struct dp_fisa_rx_sw_ft *sw_ft_entry,
 {
 	sw_ft_entry->flow_hash = flow_hash;
 	sw_ft_entry->flow_id = flow_id;
+	sw_ft_entry->vdev_id = vdev->vdev_id;
 	sw_ft_entry->vdev = vdev;
 	sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 	sw_ft_entry->dp_ctx = dp_ctx;
@@ -590,6 +591,7 @@ dp_rx_fisa_add_ft_entry(struct dp_vdev *vdev,
 		if (is_same_flow(&sw_ft_entry->rx_flow_tuple_info,
 				 &rx_flow_tuple_info)) {
 			sw_ft_entry->vdev = vdev;
+			sw_ft_entry->vdev_id = vdev->vdev_id;
 			sw_ft_entry->dp_intf =
 					dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 			dp_fisa_debug("It is same flow fse entry idx %d",
@@ -1131,6 +1133,7 @@ dp_fisa_rx_get_sw_ft_entry(struct dp_rx_fst *fisa_hdl, qdf_nbuf_t nbuf,
 
 	if (!fisa_hdl->flow_deletion_supported) {
 		sw_ft_entry->vdev = vdev;
+		sw_ft_entry->vdev_id = vdev->vdev_id;
 		sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 		return sw_ft_entry;
 	}
@@ -1145,6 +1148,7 @@ dp_fisa_rx_get_sw_ft_entry(struct dp_rx_fst *fisa_hdl, qdf_nbuf_t nbuf,
 		return NULL;
 
 	sw_ft_entry->vdev = vdev;
+	sw_ft_entry->vdev_id = vdev->vdev_id;
 	sw_ft_entry->dp_intf = dp_fisa_rx_get_dp_intf_for_vdev(vdev);
 	return sw_ft_entry;
 }
@@ -1478,6 +1482,7 @@ dp_fisa_rx_get_flow_flush_vdev_ref(ol_txrx_soc_handle cdp_soc,
 				   struct dp_fisa_rx_sw_ft *fisa_flow)
 {
 	struct dp_vdev *fisa_flow_head_skb_vdev;
+	struct dp_vdev *fisa_flow_vdev;
 	uint8_t vdev_id;
 
 	vdev_id = QDF_NBUF_CB_RX_VDEV_ID(fisa_flow->head_skb);
@@ -1492,21 +1497,30 @@ get_new_vdev_ref:
 	}
 
 	if (qdf_unlikely(fisa_flow_head_skb_vdev != fisa_flow->vdev)) {
+		if (qdf_unlikely(fisa_flow_head_skb_vdev->vdev_id ==
+				 fisa_flow->vdev_id))
+			goto fisa_flow_vdev_fail;
+
+		fisa_flow_vdev = dp_vdev_get_ref_by_id(
+						cdp_soc_t_to_dp_soc(cdp_soc),
+						fisa_flow->vdev_id,
+						DP_MOD_ID_RX);
+		if (qdf_unlikely(!fisa_flow_vdev))
+			goto fisa_flow_vdev_fail;
+
+		if (qdf_unlikely(fisa_flow_vdev != fisa_flow->vdev))
+			goto fisa_flow_vdev_mismatch;
+
 		/*
 		 * vdev_id may mismatch in case of MLO link switch.
 		 * Check if the vdevs belong to same MLD,
 		 * if yes, then submit the flow else drop the packets.
 		 */
 		if (qdf_unlikely(qdf_mem_cmp(
-				fisa_flow->vdev->mld_mac_addr.raw,
+				fisa_flow_vdev->mld_mac_addr.raw,
 				fisa_flow_head_skb_vdev->mld_mac_addr.raw,
 				QDF_MAC_ADDR_SIZE) != 0)) {
-			qdf_nbuf_free(fisa_flow->head_skb);
-			dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
-					     fisa_flow_head_skb_vdev,
-					     DP_MOD_ID_RX);
-			fisa_flow_head_skb_vdev = NULL;
-			goto out;
+			goto fisa_flow_vdev_mismatch;
 		} else {
 			fisa_flow->same_mld_vdev_mismatch++;
 			/* Continue with aggregation */
@@ -1515,15 +1529,32 @@ get_new_vdev_ref:
 			dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
 					     fisa_flow_head_skb_vdev,
 					     DP_MOD_ID_RX);
+
 			/*
 			 * Update vdev_id and let it loop to find this
 			 * vdev by ref.
 			 */
-			vdev_id = fisa_flow->vdev->vdev_id;
+			vdev_id = fisa_flow_vdev->vdev_id;
+			dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+					     fisa_flow_vdev,
+					     DP_MOD_ID_RX);
 			goto get_new_vdev_ref;
 		}
+	} else {
+		goto out;
 	}
 
+fisa_flow_vdev_mismatch:
+	dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+			     fisa_flow_vdev,
+			     DP_MOD_ID_RX);
+
+fisa_flow_vdev_fail:
+	qdf_nbuf_free(fisa_flow->head_skb);
+	dp_vdev_unref_delete(cdp_soc_t_to_dp_soc(cdp_soc),
+			     fisa_flow_head_skb_vdev,
+			     DP_MOD_ID_RX);
+	fisa_flow_head_skb_vdev = NULL;
 out:
 	return fisa_flow_head_skb_vdev;
 }

+ 5 - 1
components/dp/core/src/wlan_dp_main.c

@@ -1202,6 +1202,8 @@ dp_vdev_obj_create_notification(struct wlan_objmgr_vdev *vdev, void *arg)
 
 	/* Update Parent interface details */
 	dp_link->magic = WLAN_DP_LINK_MAGIC;
+	dp_link->destroyed = 0;
+	dp_link->cdp_vdev_deleted = 0;
 	dp_link->dp_intf = dp_intf;
 	qdf_spin_lock_bh(&dp_intf->dp_link_list_lock);
 	qdf_list_insert_front(&dp_intf->dp_link_list, &dp_link->node);
@@ -2031,8 +2033,10 @@ void wlan_dp_link_cdp_vdev_delete_notification(void *context)
 	uint8_t found = 0;
 
 	/* dp_link will not be freed before this point. */
-	if (!dp_link)
+	if (!dp_link) {
+		dp_info("dp_link is null");
 		return;
+	}
 
 	dp_info("dp_link %pK id %d", dp_link, dp_link->link_id);
 	dp_intf = dp_link->dp_intf;

+ 4 - 5
components/dp/dispatcher/inc/wlan_dp_api.h

@@ -76,17 +76,16 @@ void wlan_dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support);
 
 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
 /**
- * wlan_dp_is_local_pkt_capture_enabled() - Get local packet capture config
+ * wlan_dp_is_local_pkt_capture_active() - Get local packet capture config
  * @psoc: pointer to psoc object
  *
- * Return: true if local packet capture is enabled from ini
- *         false otherwise
+ * Return: true if local packet capture is active, false otherwise
  */
 bool
-wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc);
+wlan_dp_is_local_pkt_capture_active(struct wlan_objmgr_psoc *psoc);
 #else
 static inline bool
-wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc)
+wlan_dp_is_local_pkt_capture_active(struct wlan_objmgr_psoc *psoc)
 {
 	return false;
 }

+ 15 - 2
components/dp/dispatcher/src/wlan_dp_api.c

@@ -21,6 +21,7 @@
 #include "wlan_dp_main.h"
 #include "wlan_dp_api.h"
 #include <wlan_dp_fisa_rx.h>
+#include <cdp_txrx_ctrl.h>
 
 void wlan_dp_update_peer_map_unmap_version(uint8_t *version)
 {
@@ -53,11 +54,23 @@ void wlan_dp_set_fisa_dynamic_aggr_size_support(bool dynamic_aggr_size_support)
 }
 
 #ifdef WLAN_FEATURE_LOCAL_PKT_CAPTURE
-bool wlan_dp_is_local_pkt_capture_enabled(struct wlan_objmgr_psoc *psoc)
+bool wlan_dp_is_local_pkt_capture_active(struct wlan_objmgr_psoc *psoc)
 {
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	union cdp_config_param_t param;
+	QDF_STATUS status;
 
-	return cdp_cfg_get(soc, cfg_dp_local_pkt_capture);
+	status = cdp_txrx_get_psoc_param(soc, CDP_MONITOR_FLAG, &param);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		dp_err("Unable to fetch monitor flags.");
+		return false;
+	}
+
+	if (cdp_cfg_get(soc, cfg_dp_local_pkt_capture) &&
+	    !(QDF_MONITOR_FLAG_OTHER_BSS & param.cdp_monitor_flag))
+		return true;
+
+	return false;
 }
 #endif
 

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

@@ -1213,6 +1213,9 @@ QDF_STATUS ucfg_dp_sta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	}
 
 	dp_link->cdp_vdev_registered = 1;
+	dp_link->cdp_vdev_deleted = 0;
+	dp_link->destroyed = 0;
+
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1267,6 +1270,8 @@ QDF_STATUS ucfg_dp_tdlsta_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	}
 
 	dp_link->cdp_vdev_registered = 1;
+	dp_link->cdp_vdev_deleted = 0;
+	dp_link->destroyed = 0;
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1301,6 +1306,8 @@ QDF_STATUS ucfg_dp_ocb_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 	}
 
 	dp_link->cdp_vdev_registered = 1;
+	dp_link->cdp_vdev_deleted = 0;
+	dp_link->destroyed = 0;
 	dp_intf->txrx_ops = txrx_ops;
 
 	qdf_copy_macaddr(&dp_link->conn_info.peer_macaddr,
@@ -1333,6 +1340,8 @@ QDF_STATUS ucfg_dp_mon_register_txrx_ops(struct wlan_objmgr_vdev *vdev)
 			  &txrx_ops);
 
 	dp_link->cdp_vdev_registered = 1;
+	dp_link->cdp_vdev_deleted = 0;
+	dp_link->destroyed = 0;
 	dp_intf->txrx_ops = txrx_ops;
 
 	return QDF_STATUS_SUCCESS;
@@ -1380,6 +1389,8 @@ QDF_STATUS ucfg_dp_softap_register_txrx_ops(struct wlan_objmgr_vdev *vdev,
 	}
 
 	dp_link->cdp_vdev_registered = 1;
+	dp_link->cdp_vdev_deleted = 0;
+	dp_link->destroyed = 0;
 	dp_intf->txrx_ops = *txrx_ops;
 	dp_intf->sap_tx_block_mask &= ~DP_TX_FN_CLR;
 

+ 28 - 1
components/mlme/core/inc/wlan_mlme_main.h

@@ -100,6 +100,18 @@ enum wmm_user_mode {
 
 };
 
+/**
+ * struct peer_mac_addresses -Peer MAC address info
+ * @mac: Provided peer MAC address
+ * @peer_mac: Peer MAC address
+ * @peer_mld: Peer MLD address
+ */
+struct peer_mac_addresses {
+	struct qdf_mac_addr mac;
+	struct qdf_mac_addr peer_mac;
+	struct qdf_mac_addr peer_mld;
+};
+
 struct pwr_channel_info {
 	uint32_t first_freq;
 	uint8_t num_chan;
@@ -827,7 +839,7 @@ struct enhance_roam_info {
  *				operation on bss color collision detection
  * @bss_color_change_runtime_lock: runtime lock to complete bss color change
  * @disconnect_runtime_lock: runtime lock to complete disconnection
- * @best_6g_power_type: best 6g power type
+ * @keep_alive_period: KEEPALIVE period in seconds
  */
 struct mlme_legacy_priv {
 	bool chan_switch_in_progress;
@@ -900,6 +912,7 @@ struct mlme_legacy_priv {
 	qdf_runtime_lock_t bss_color_change_runtime_lock;
 	qdf_runtime_lock_t disconnect_runtime_lock;
 	enum reg_6g_ap_type best_6g_power_type;
+	uint16_t keep_alive_period;
 };
 
 /**
@@ -2006,4 +2019,18 @@ uint8_t wlan_mlme_get_sap_psd_for_20mhz(struct wlan_objmgr_vdev *vdev);
  */
 QDF_STATUS wlan_mlme_set_sap_psd_for_20mhz(struct wlan_objmgr_vdev *vdev,
 					   uint8_t psd_power);
+
+/**
+ * wlan_find_peer_and_get_mac_and_mld_addr() - This API find peer from the peer
+ * list and cache peer MAC and MLD address in the peer_mac_info.
+ * @psoc: PSOC object
+ * @peer_mac_info: Peer MAC address info
+ *
+ * Return: None
+ */
+QDF_STATUS
+wlan_find_peer_and_get_mac_and_mld_addr(
+				struct wlan_objmgr_psoc *psoc,
+				struct peer_mac_addresses *peer_mac_info);
+
 #endif

+ 3 - 2
components/mlme/core/inc/wlan_mlme_vdev_mgr_interface.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
@@ -316,12 +316,13 @@ mlme_set_cac_required(struct wlan_objmgr_vdev *vdev, bool val);
  * mlme_set_mbssid_info() - save mbssid info
  * @vdev: vdev pointer
  * @mbssid_info: mbssid info
+ * @freq: current operating frequency
  *
  * Return: QDF_STATUS
  */
 QDF_STATUS
 mlme_set_mbssid_info(struct wlan_objmgr_vdev *vdev,
-		     struct scan_mbssid_info *mbssid_info);
+		     struct scan_mbssid_info *mbssid_info, qdf_freq_t freq);
 
 /**
  * mlme_get_mbssid_info() - get mbssid info

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

@@ -5755,3 +5755,68 @@ wlan_mlme_set_sap_psd_for_20mhz(struct wlan_objmgr_vdev *vdev,
 	mlme_priv->mlme_ap.psd_20mhz = psd_power;
 	return QDF_STATUS_SUCCESS;
 }
+
+/**
+ * wlan_peer_find_mld_peer_n_get_mac_info() - This API will find MLD peer from
+ * peer list.
+ * @psoc: Pointer to psoc object
+ * @obj: Pointer to peer object
+ * @args: Pointer to void * argument
+ *
+ * Return: void
+ */
+static void
+wlan_peer_find_mld_peer_n_get_mac_info(struct wlan_objmgr_psoc *psoc,
+				       void *obj, void *args)
+{
+	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
+	struct peer_mac_addresses *peer_mac_info =
+				(struct peer_mac_addresses *)args;
+	uint8_t *mld_mac, *peer_mac, *given_mac;
+
+	mld_mac = wlan_peer_mlme_get_mldaddr(peer);
+	peer_mac = wlan_peer_get_macaddr(peer);
+	given_mac = peer_mac_info->mac.bytes;
+
+	if (!mld_mac || WLAN_ADDR_EQ(mld_mac, given_mac) != QDF_STATUS_SUCCESS)
+		return;
+	qdf_copy_macaddr(&peer_mac_info->peer_mac,
+			 (struct qdf_mac_addr *)peer_mac);
+	qdf_copy_macaddr(&peer_mac_info->peer_mld,
+			 (struct qdf_mac_addr *)mld_mac);
+}
+
+QDF_STATUS wlan_find_peer_and_get_mac_and_mld_addr(
+				struct wlan_objmgr_psoc *psoc,
+				struct peer_mac_addresses *peer_mac_info)
+{
+	struct wlan_objmgr_peer *peer;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	peer = wlan_objmgr_get_peer_by_mac(psoc, peer_mac_info->mac.bytes,
+					   WLAN_LEGACY_MAC_ID);
+	if (peer) {
+		qdf_copy_macaddr(
+			&peer_mac_info->peer_mac,
+			(struct qdf_mac_addr *)wlan_peer_get_macaddr(peer));
+		if (wlan_peer_mlme_get_mldaddr(peer))
+			qdf_copy_macaddr(
+				&peer_mac_info->peer_mld,
+				(struct qdf_mac_addr *)
+				wlan_peer_mlme_get_mldaddr(peer));
+		wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_MAC_ID);
+		return status;
+	}
+
+	/* if not found with mac address try finding using MLD address */
+	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
+				     wlan_peer_find_mld_peer_n_get_mac_info,
+				     peer_mac_info, 0, WLAN_LEGACY_MAC_ID);
+	if (qdf_is_macaddr_zero(&peer_mac_info->peer_mac)) {
+		mlme_err("peer is null for mac:" QDF_MAC_ADDR_FMT,
+			 QDF_MAC_ADDR_REF(peer_mac_info->mac.bytes));
+		return QDF_STATUS_E_EXISTS;
+	}
+
+	return status;
+}

+ 32 - 2
components/mlme/core/src/wlan_mlme_vdev_mgr_interface.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
@@ -1349,10 +1349,13 @@ bool mlme_get_cac_required(struct wlan_objmgr_vdev *vdev)
 }
 
 QDF_STATUS mlme_set_mbssid_info(struct wlan_objmgr_vdev *vdev,
-				struct scan_mbssid_info *mbssid_info)
+				struct scan_mbssid_info *mbssid_info,
+				qdf_freq_t freq)
 {
 	struct vdev_mlme_obj *vdev_mlme;
 	struct vdev_mlme_mbss_11ax *mbss_11ax;
+	struct qdf_mac_addr bssid;
+	struct qdf_mac_addr bcast_addr = QDF_MAC_ADDR_BCAST_INIT;
 
 	vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev);
 	if (!vdev_mlme) {
@@ -1368,6 +1371,33 @@ QDF_STATUS mlme_set_mbssid_info(struct wlan_objmgr_vdev *vdev,
 	qdf_mem_copy(mbss_11ax->non_trans_bssid,
 		     mbssid_info->non_trans_bssid, QDF_MAC_ADDR_SIZE);
 
+	qdf_mem_copy(&bssid.bytes, vdev_mlme->mgmt.generic.bssid,
+		     QDF_MAC_ADDR_SIZE);
+
+	/*
+	 * Consider the case of 5 GHz + non-tx 6 GHz MLO candidate.
+	 * The scan entry might be generated from a ML-probe, which doesn't have
+	 * the MBSSID info for the non-tx partner link. In this case, host has
+	 * to identify if this link is MBSS or not. This is essential to receive
+	 * traffic over this link.
+	 *
+	 * The below logic looks into the rnr db for the 6 GHz bssid and
+	 * determines if the bssid is non-tx profile from the bss parameter
+	 * saved by its neighbor. If this is a non-tx bssid, but trans_bssid
+	 * info is not available from the scan entry, then set transmitted bssid
+	 * to bcast address. Upon sending this bcast tx bssid to firmware, the
+	 * firmware would auto-detect the tx bssid from the upcoming beacons
+	 * and tunes the interface to proper bssid.
+	 *
+	 * Note: Always send bcast mac in trans_bssid if the host is unable
+	 * to determine if a given BSS is part of an MBSS.
+	 */
+	if (freq != INVALID_CHANNEL_NUM && !mbss_11ax->profile_idx &&
+	    qdf_is_macaddr_zero((struct qdf_mac_addr *)&mbss_11ax->trans_bssid) &&
+	    util_is_bssid_non_tx(wlan_vdev_get_psoc(vdev), &bssid, freq))
+		qdf_mem_copy(mbss_11ax->trans_bssid,
+			     bcast_addr.bytes, QDF_MAC_ADDR_SIZE);
+
 	return QDF_STATUS_SUCCESS;
 }
 

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

@@ -4985,4 +4985,21 @@ wlan_mlme_send_csa_event_status_ind(struct wlan_objmgr_vdev *vdev,
 QDF_STATUS
 wlan_mlme_is_hs_20_btm_offload_disabled(struct wlan_objmgr_psoc *psoc,
 					bool *val);
+/**
+ * wlan_mlme_set_keepalive_period() - Save keep alive period
+ * @vdev: VDEV object
+ * @keep_alive_period: Keep alive period
+ *
+ * Return: None
+ */
+void wlan_mlme_set_keepalive_period(struct wlan_objmgr_vdev *vdev,
+				    uint16_t keep_alive_period);
+
+/**
+ * wlan_mlme_get_keepalive_period() - Get keep alive period
+ * @vdev: VDEV object
+ *
+ * Return: Keep alive period.
+ */
+uint16_t wlan_mlme_get_keepalive_period(struct wlan_objmgr_vdev *vdev);
 #endif /* _WLAN_MLME_API_H_ */

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

@@ -5436,4 +5436,16 @@ ucfg_mlme_assemble_rate_code(uint8_t preamble, uint8_t nss, uint8_t rate)
 {
 	return wlan_mlme_assemble_rate_code(preamble, nss, rate);
 }
+
+/**
+ * ucfg_mlme_get_keepalive_period() - Get keep alive period
+ * @vdev: VDEV object
+ *
+ * Return: Keep alive period.
+ */
+static inline
+uint16_t ucfg_mlme_get_keepalive_period(struct wlan_objmgr_vdev *vdev)
+{
+	return wlan_mlme_get_keepalive_period(vdev);
+}
 #endif /* _WLAN_MLME_UCFG_API_H_ */

+ 39 - 2
components/mlme/dispatcher/src/wlan_mlme_api.c

@@ -1411,13 +1411,23 @@ bool wlan_mlme_get_epcs_capability(struct wlan_objmgr_psoc *psoc)
 void wlan_mlme_set_epcs_capability(struct wlan_objmgr_psoc *psoc, bool flag)
 {
 	struct wlan_mlme_psoc_ext_obj *mlme_obj = mlme_get_psoc_ext_obj(psoc);
+	struct mac_context *mac_ctx = cds_get_context(QDF_MODULE_ID_PE);
 
-	if (!mlme_obj)
+	if (!mlme_obj || !mac_ctx)
 		return;
 
 	mlme_debug("set mlme epcs capability from %d to %d",
 		   mlme_obj->cfg.sta.epcs_capability, flag);
 	mlme_obj->cfg.sta.epcs_capability = flag;
+	if (flag) {
+		mlme_obj->cfg.eht_caps.dot11_eht_cap.epcs_pri_access = 1;
+		mac_ctx->eht_cap_2g.epcs_pri_access = 1;
+		mac_ctx->eht_cap_5g.epcs_pri_access = 1;
+	} else {
+		mlme_obj->cfg.eht_caps.dot11_eht_cap.epcs_pri_access = 0;
+		mac_ctx->eht_cap_2g.epcs_pri_access = 0;
+		mac_ctx->eht_cap_5g.epcs_pri_access = 0;
+	}
 }
 
 bool wlan_mlme_get_eht_disable_punct_in_us_lpi(struct wlan_objmgr_psoc *psoc)
@@ -5265,7 +5275,8 @@ void wlan_mlme_update_sae_single_pmk(struct wlan_objmgr_vdev *vdev,
 		return;
 	}
 
-	if (keymgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE))
+	if (QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+	    QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))
 		is_sae_connection = true;
 
 	mlme_legacy_debug("SAE_SPMK: single_pmk_ap:%d, is_sae_connection:%d, pmk_len:%d",
@@ -8395,3 +8406,29 @@ wlan_mlme_is_hs_20_btm_offload_disabled(struct wlan_objmgr_psoc *psoc,
 	return QDF_STATUS_SUCCESS;
 }
 
+void wlan_mlme_set_keepalive_period(struct wlan_objmgr_vdev *vdev,
+				    uint16_t keep_alive_period)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_err("vdev legacy private object is NULL");
+		return;
+	}
+
+	mlme_priv->keep_alive_period = keep_alive_period;
+}
+
+uint16_t wlan_mlme_get_keepalive_period(struct wlan_objmgr_vdev *vdev)
+{
+	struct mlme_legacy_priv *mlme_priv;
+
+	mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
+	if (!mlme_priv) {
+		mlme_err("vdev legacy private object is NULL");
+		return 0;
+	}
+
+	return mlme_priv->keep_alive_period;
+}

+ 32 - 2
components/p2p/core/src/wlan_p2p_off_chan_tx.c

@@ -809,8 +809,8 @@ static void p2p_init_frame_info(struct p2p_frame_info *frame_info)
  *
  * Return: QDF_STATUS_SUCCESS - in case of success
  */
-static QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length,
-	struct p2p_frame_info *frame_info)
+QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length,
+			      struct p2p_frame_info *frame_info)
 {
 	uint8_t type;
 	uint8_t sub_type;
@@ -897,6 +897,22 @@ static QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length,
 	return QDF_STATUS_SUCCESS;
 }
 
+bool p2p_is_action_frame_of_p2p_type(uint8_t *data_buf, uint32_t length)
+{
+	struct p2p_frame_info frame_info = {0};
+	QDF_STATUS status;
+
+	status = p2p_get_frame_info(data_buf, length, &frame_info);
+	if (QDF_IS_STATUS_ERROR(status))
+		return false;
+
+	if (frame_info.public_action_type != P2P_PUBLIC_ACTION_NOT_SUPPORT ||
+	    frame_info.action_type != P2P_ACTION_NOT_SUPPORT)
+		return true;
+
+	return false;
+}
+
 #ifdef WLAN_FEATURE_P2P_DEBUG
 /**
  * p2p_tx_update_connection_status() - Update P2P connection status
@@ -3420,6 +3436,10 @@ QDF_STATUS p2p_process_mgmt_tx_ack_cnf(
 	return QDF_STATUS_SUCCESS;
 }
 
+#define P2P_IS_SOCIAL_CHANNEL(center_freq)	\
+	(((center_freq) == 2412) || ((center_freq) == 2437) || \
+		((center_freq) == 2462))
+
 QDF_STATUS p2p_process_rx_mgmt(
 	struct p2p_rx_mgmt_event *rx_mgmt_event)
 {
@@ -3467,6 +3487,16 @@ QDF_STATUS p2p_process_rx_mgmt(
 			p2p_debug("p2p frame, extend roc accordingly");
 			p2p_extend_roc_timer(p2p_soc_obj, &frame_info);
 		}
+
+		if (frame_info.public_action_type ==
+		    P2P_PUBLIC_ACTION_NEG_REQ &&
+		    wlan_reg_is_24ghz_ch_freq(rx_mgmt->rx_freq) &&
+		    !P2P_IS_SOCIAL_CHANNEL(rx_mgmt->rx_freq)) {
+			p2p_debug("Drop P2P Negotiation Req due to non-Social channel: %d",
+				  rx_mgmt->rx_freq);
+			qdf_mem_free(rx_mgmt);
+			return QDF_STATUS_SUCCESS;
+		}
 	}
 
 	if (rx_mgmt->frm_type == MGMT_ACTION_CATEGORY_VENDOR_SPECIFIC)

+ 23 - 1
components/p2p/core/src/wlan_p2p_off_chan_tx.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2019, 2021 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
@@ -197,6 +197,28 @@ struct tx_action_context {
 	qdf_nbuf_t nbuf;
 };
 
+/**
+ * p2p_get_frame_info() - get frame information from packet
+ * @data_buf:          data buffer address
+ * @length:            buffer length
+ * @frame_info:        frame information
+ *
+ * This function gets frame information from packet.
+ *
+ * Return: QDF_STATUS_SUCCESS - in case of success
+ */
+QDF_STATUS p2p_get_frame_info(uint8_t *data_buf, uint32_t length,
+			      struct p2p_frame_info *frame_info);
+
+/**
+ * p2p_is_action_frame_of_p2p_type() - Given action frame is p2p type or not
+ * @data_buf: data buffer address
+ * @length: buffer length
+ *
+ * Return: bool
+ */
+bool p2p_is_action_frame_of_p2p_type(uint8_t *data_buf, uint32_t length);
+
 /**
  * p2p_rand_mac_tx_done() - process random mac mgmt tx done
  * @soc: soc

+ 11 - 1
components/p2p/dispatcher/inc/wlan_p2p_api.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-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
@@ -63,6 +63,16 @@ QDF_STATUS wlan_p2p_cleanup_roc_by_vdev(struct wlan_objmgr_vdev *vdev,
  */
 QDF_STATUS wlan_p2p_status_connect(struct wlan_objmgr_vdev *vdev);
 
+/**
+ * wlan_p2p_is_action_frame_of_p2p_type() - Given action frame is p2p type or
+ * not
+ * @data_buf: data buffer address
+ * @length: buffer length
+ *
+ * Return: bool
+ */
+bool wlan_p2p_is_action_frame_of_p2p_type(uint8_t *data_buf, uint32_t length);
+
 /**
  * wlan_p2p_abort_scan() - Abort on going scan on p2p interfaces
  * @pdev: pdev object

+ 9 - 1
components/p2p/dispatcher/src/wlan_p2p_api.c

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-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
@@ -28,6 +28,7 @@
 #include "../../core/src/wlan_p2p_roc.h"
 #include <cds_utils.h>
 #include "wlan_scan_api.h"
+#include "../../core/src/wlan_p2p_off_chan_tx.h"
 
 bool wlan_p2p_check_oui_and_force_1x1(uint8_t *assoc_ie, uint32_t assoc_ie_len)
 {
@@ -76,6 +77,13 @@ QDF_STATUS wlan_p2p_status_connect(struct wlan_objmgr_vdev *vdev)
 	return p2p_status_connect(vdev);
 }
 
+bool
+wlan_p2p_is_action_frame_of_p2p_type(uint8_t *data_buf,
+				     uint32_t length)
+{
+	return p2p_is_action_frame_of_p2p_type(data_buf, length);
+}
+
 #ifdef WLAN_FEATURE_P2P_P2P_STA
 QDF_STATUS
 wlan_p2p_check_and_force_scc_go_plus_go(struct wlan_objmgr_psoc *psoc,

+ 42 - 8
components/pre_cac/core/src/wlan_pre_cac_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 above
@@ -284,7 +284,8 @@ void pre_cac_get_vdev_id(struct wlan_objmgr_psoc *psoc,
 
 int pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 				  uint32_t chan_freq,
-				  uint32_t *pre_cac_chan_freq)
+				  uint32_t *pre_cac_chan_freq,
+				  enum phy_ch_width cac_ch_width)
 {
 	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
 	uint32_t len = CFG_VALID_CHANNEL_LIST_LEN;
@@ -293,6 +294,8 @@ int pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 	uint32_t weight_len = 0;
 	QDF_STATUS status;
 	uint32_t i;
+	bool is_ch_dfs = false;
+	struct ch_params ch_params;
 
 	pre_cac_stop(psoc);
 
@@ -320,33 +323,64 @@ int pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 							 freq_list, &len,
 							 pcl_weights,
 							 weight_len);
+try_next_bw:
 		for (i = 0; i < len; i++) {
-			if (wlan_reg_is_dfs_for_freq(pdev,
-						     freq_list[i])) {
+			is_ch_dfs = false;
+			qdf_mem_zero(&ch_params, sizeof(ch_params));
+			ch_params.ch_width = cac_ch_width;
+			wlan_reg_set_create_punc_bitmap(&ch_params, true);
+			if (wlan_reg_is_5ghz_ch_freq(freq_list[i]) &&
+			    wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
+					pdev, freq_list[i], &ch_params,
+				REG_CURRENT_PWR_MODE) == CHANNEL_STATE_DFS)
+				is_ch_dfs = true;
+
+			if (is_ch_dfs) {
 				*pre_cac_chan_freq = freq_list[i];
 				break;
 			}
 		}
 
+		if (*pre_cac_chan_freq == 0 &&
+		    cac_ch_width != CH_WIDTH_20MHZ &&
+		    wlan_get_next_lower_bandwidth(cac_ch_width)
+						!= CH_WIDTH_INVALID) {
+			cac_ch_width =
+				wlan_get_next_lower_bandwidth(cac_ch_width);
+			pre_cac_debug("try next bw %d", cac_ch_width);
+			goto try_next_bw;
+		}
+
 		if (*pre_cac_chan_freq == 0) {
 			pre_cac_err("unable to find outdoor channel");
 			return -EINVAL;
 		}
 	} else {
+		qdf_mem_zero(&ch_params, sizeof(ch_params));
+		ch_params.ch_width = cac_ch_width;
+		wlan_reg_set_create_punc_bitmap(&ch_params, true);
+		if (wlan_reg_is_5ghz_ch_freq(chan_freq) &&
+		    wlan_reg_get_5g_bonded_channel_state_for_pwrmode(
+				pdev, chan_freq, &ch_params,
+				REG_CURRENT_PWR_MODE) == CHANNEL_STATE_DFS)
+			is_ch_dfs = true;
+
 		/* Only when driver selects a channel, check is done for
 		 * unnsafe and NOL channels. When user provides a fixed channel
 		 * the user is expected to take care of this.
 		 */
 		if (!wlan_mlme_is_channel_valid(psoc, chan_freq) ||
-		    !wlan_reg_is_dfs_for_freq(pdev, chan_freq)) {
-			pre_cac_err("Invalid channel for pre cac:%d",
-				    chan_freq);
+		    !is_ch_dfs) {
+			pre_cac_err("Invalid channel for pre cac:%d dfs %d",
+				    chan_freq, is_ch_dfs);
 			return -EINVAL;
 		}
 		*pre_cac_chan_freq = chan_freq;
 	}
 
-	pre_cac_debug("selected pre cac channel:%d", *pre_cac_chan_freq);
+	pre_cac_debug("selected pre cac channel:%d bw %d", *pre_cac_chan_freq,
+		      cac_ch_width);
+
 	return 0;
 }
 

+ 4 - 2
components/pre_cac/core/src/wlan_pre_cac_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 above
@@ -233,6 +233,7 @@ void pre_cac_clear_work(struct wlan_objmgr_psoc *psoc);
  * @pdev: pdev object manager
  * @chan_freq: Channel frequency requested by userspace
  * @pre_cac_chan_freq: Pointer to the pre CAC channel frequency storage
+ * @cac_ch_width: bandwidth of channel frequency pre_cac_chan_freq
  *
  * Validates the channel provided by userspace. If user provided channel 0,
  * a valid outdoor channel must be selected from the regulatory channel.
@@ -241,7 +242,8 @@ void pre_cac_clear_work(struct wlan_objmgr_psoc *psoc);
  */
 int pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 				  uint32_t chan_freq,
-				  uint32_t *pre_cac_chan_freq);
+				  uint32_t *pre_cac_chan_freq,
+				  enum phy_ch_width cac_ch_width);
 
 /**
  * pre_cac_set_status() - Set pre cac status

+ 6 - 3
components/pre_cac/dispatcher/inc/wlan_pre_cac_ucfg_api.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 above
@@ -77,6 +77,7 @@ bool ucfg_pre_cac_is_active(struct wlan_objmgr_psoc *psoc);
  * @pdev: pdev object manager
  * @chan_freq: Channel frequency requested by userspace
  * @pre_cac_chan_freq: Pointer to the pre CAC channel frequency storage
+ * @cac_ch_width: bandwidth of channel frequency pre_cac_chan_freq
  *
  * Validates the channel provided by userspace. If user provided channel 0,
  * a valid outdoor channel must be selected from the regulatory channel.
@@ -85,7 +86,8 @@ bool ucfg_pre_cac_is_active(struct wlan_objmgr_psoc *psoc);
  */
 int ucfg_pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 				       uint32_t chan_freq,
-				       uint32_t *pre_cac_chan_freq);
+				       uint32_t *pre_cac_chan_freq,
+				       enum phy_ch_width cac_ch_width);
 
 #if defined(FEATURE_SAP_COND_CHAN_SWITCH)
 /**
@@ -226,7 +228,8 @@ ucfg_pre_cac_is_active(struct wlan_objmgr_psoc *psoc)
 static inline int
 ucfg_pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 				   uint32_t chan_freq,
-				   uint32_t *pre_cac_chan_freq)
+				   uint32_t *pre_cac_chan_freq,
+				   enum phy_ch_width cac_ch_width)
 {
 	return 0;
 }

+ 5 - 3
components/pre_cac/dispatcher/src/wlan_pre_cac_ucfg_api.c

@@ -1,5 +1,5 @@
 /*
- * 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 above
@@ -73,10 +73,12 @@ void ucfg_pre_cac_get_vdev_id(struct wlan_objmgr_psoc *psoc,
 
 int ucfg_pre_cac_validate_and_get_freq(struct wlan_objmgr_pdev *pdev,
 				       uint32_t chan_freq,
-				       uint32_t *pre_cac_chan_freq)
+				       uint32_t *pre_cac_chan_freq,
+				       enum phy_ch_width cac_ch_width)
 {
 	return pre_cac_validate_and_get_freq(pdev, chan_freq,
-					     pre_cac_chan_freq);
+					     pre_cac_chan_freq,
+					     cac_ch_width);
 }
 
 #if defined(FEATURE_SAP_COND_CHAN_SWITCH)

+ 2 - 0
components/tdls/core/src/wlan_tdls_mgmt.c

@@ -556,6 +556,8 @@ static QDF_STATUS tdls_process_rx_mgmt(
 				return QDF_STATUS_SUCCESS;
 			} else if (status == QDF_STATUS_SUCCESS) {
 				vdev = tdls_process_mlo_choice_tdls_vdev(vdev);
+				if (!vdev)
+					return QDF_STATUS_SUCCESS;
 				tdls_vdev =
 				     wlan_objmgr_vdev_get_comp_private_obj(vdev,
 							   WLAN_UMAC_COMP_TDLS);

+ 21 - 6
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_fw_sync.c

@@ -184,11 +184,18 @@ cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev,
 	struct qdf_mac_addr connected_bssid;
 	uint8_t vdev_id;
 	struct wlan_objmgr_psoc *psoc;
+	uint8_t good_rssi_cfg;
+	struct psoc_mlme_obj *mlme_psoc_obj;
+	struct scoring_cfg *score_config;
 
 	pdev = wlan_vdev_get_pdev(vdev);
 	vdev_id = wlan_vdev_get_id(vdev);
 	psoc = wlan_pdev_get_psoc(pdev);
 
+	mlme_psoc_obj = wlan_psoc_mlme_get_cmpt_obj(psoc);
+	if (!mlme_psoc_obj)
+		return QDF_STATUS_E_INVAL;
+
 	if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) {
 		if (!MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc,
 					sync_ind->roamed_vdev_id))
@@ -219,12 +226,16 @@ cm_fw_roam_sync_start_ind(struct wlan_objmgr_vdev *vdev,
 	if (IS_ROAM_REASON_STA_KICKOUT(sync_ind->roam_reason)) {
 		struct reject_ap_info ap_info;
 
-		qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
-		ap_info.bssid = connected_bssid;
-		ap_info.reject_ap_type = DRIVER_AVOID_TYPE;
-		ap_info.reject_reason = REASON_STA_KICKOUT;
-		ap_info.source = ADDED_BY_DRIVER;
-		wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
+		score_config = &mlme_psoc_obj->psoc_cfg.score_config;
+		good_rssi_cfg = score_config->rssi_score.good_rssi_threshold;
+		if (good_rssi_cfg > sync_ind->rssi) {
+			qdf_mem_zero(&ap_info, sizeof(struct reject_ap_info));
+			ap_info.bssid = connected_bssid;
+			ap_info.reject_ap_type = DRIVER_AVOID_TYPE;
+			ap_info.reject_reason = REASON_STA_KICKOUT;
+			ap_info.source = ADDED_BY_DRIVER;
+			wlan_dlm_add_bssid_to_reject_list(pdev, &ap_info);
+		}
 	}
 
 	cm_update_scan_mlme_on_roam(vdev, &connected_bssid,
@@ -780,7 +791,9 @@ static QDF_STATUS cm_process_roam_keys(struct wlan_objmgr_vdev *vdev,
 
 	if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED ||
 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) ||
 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_OWE) ||
+	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE_EXT_KEY) ||
 	    QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) {
 		struct wlan_crypto_pmksa *pmkid_cache, *pmksa;
 
@@ -899,6 +912,8 @@ static QDF_STATUS cm_process_roam_keys(struct wlan_objmgr_vdev *vdev,
 					     roaming_info->pmk,
 					     roaming_info->pmk_len);
 				pmkid_cache->pmk_len = roaming_info->pmk_len;
+			} else {
+				mlme_debug("PMK not received from fw");
 			}
 
 			wlan_cm_set_psk_pmk(pdev, vdev_id,

+ 6 - 5
components/umac/mlme/connection_mgr/core/src/wlan_cm_roam_offload.c

@@ -4341,13 +4341,13 @@ cm_roam_switch_to_init(struct wlan_objmgr_pdev *pdev,
 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
 						    WLAN_MLME_NB_ID);
 	if (!vdev) {
-		mlme_err("CM_RSO: vdev is null");
+		mlme_err("CM_RSO: vdev:%d is null", vdev_id);
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (cm_is_vdev_disconnecting(vdev) ||
-	    cm_is_vdev_disconnected(vdev)) {
-		mlme_debug("CM_RSO: RSO Init received in disconnected state");
+	if (!cm_is_vdev_connected(vdev)) {
+		mlme_debug("CM_RSO: vdev:%d RSO Init received in non-connected state",
+			   vdev_id);
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_NB_ID);
 		return QDF_STATUS_E_INVAL;
 	}
@@ -5626,7 +5626,8 @@ cm_store_sae_single_pmk_to_global_cache(struct wlan_objmgr_psoc *psoc,
 	wlan_cm_roam_cfg_get_value(psoc, vdev_id,
 				   IS_SINGLE_PMK, &src_cfg);
 	if (!src_cfg.bool_value ||
-	    !QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE))
+	    !(QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+	      QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)))
 		return;
 	/*
 	 * Mark the AP as single PMK capable in Crypto Table

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

@@ -530,7 +530,6 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev,
 	uint8_t vdev_id;
 
 	sync_ind = (struct roam_offload_synch_ind *)event;
-
 	if (!sync_ind) {
 		mlme_err("Roam Sync ind ptr is NULL");
 		return QDF_STATUS_E_NULL_VALUE;
@@ -554,8 +553,7 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev,
 
 	wlan_roam_debug_log(sync_ind->roamed_vdev_id, DEBUG_ROAM_SYNCH_IND,
 			    DEBUG_INVALID_PEER_ID, sync_ind->bssid.bytes, NULL,
-			    0,
-			    0);
+			    0, 0);
 	DPTRACE(qdf_dp_trace_record_event(QDF_DP_TRACE_EVENT_RECORD,
 					  sync_ind->roamed_vdev_id,
 					  QDF_TRACE_DEFAULT_PDEV_ID,
@@ -570,8 +568,8 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev,
 		goto err;
 	}
 
-	if (!QDF_IS_STATUS_SUCCESS(cm_fw_roam_sync_start_ind(vdev,
-							     sync_ind))) {
+	status = cm_fw_roam_sync_start_ind(vdev, sync_ind);
+	if (QDF_IS_STATUS_ERROR(status)) {
 		mlme_err("LFR3: vdev:%d CSR Roam synch cb failed", vdev_id);
 		wlan_cm_free_roam_synch_frame_ind(rso_cfg);
 		goto err;
@@ -587,6 +585,7 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev,
 		} else {
 			mlme_err("LFR3: MLO: vdev:%d Invalid link Beacon Length",
 				 vdev_id);
+			status = QDF_STATUS_E_FAILURE;
 			goto err;
 		}
 	} else if (sync_ind->beacon_probe_resp_length >
@@ -612,12 +611,13 @@ QDF_STATUS cm_roam_sync_event_handler_cb(struct wlan_objmgr_vdev *vdev,
 			(QDF_IEEE80211_3ADDR_HDR_LEN + MAC_B_PR_SSID_OFFSET);
 
 	} else {
-		mlme_err("LFR3: vdev:%d Invalid Beacon Length", vdev_id);
+		mlme_err("LFR3: vdev:%d Invalid Beacon Length:%d", vdev_id,
+			 sync_ind->beacon_probe_resp_length);
+		status = QDF_STATUS_E_FAILURE;
 		goto err;
 	}
 
-	if (QDF_IS_STATUS_ERROR(cm_roam_pe_sync_callback(sync_ind,
-							 vdev_id,
+	if (QDF_IS_STATUS_ERROR(cm_roam_pe_sync_callback(sync_ind, vdev_id,
 							 ie_len))) {
 		mlme_err("LFR3: vdev:%d PE roam synch cb failed", vdev_id);
 		status = QDF_STATUS_E_BUSY;

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

@@ -1059,7 +1059,7 @@ QDF_STATUS cm_connect_start_ind(struct wlan_objmgr_vdev *vdev,
 		return QDF_STATUS_E_INVAL;
 	}
 
-	if (!wlan_dp_is_local_pkt_capture_enabled(psoc) &&
+	if (!wlan_dp_is_local_pkt_capture_active(psoc) &&
 	    policy_mgr_is_sta_mon_concurrency(psoc))
 		return QDF_STATUS_E_NOSUPPORT;
 

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

@@ -5093,6 +5093,7 @@ bool wlan_hdd_is_session_type_monitor(uint8_t session_type);
  * @name: name of the interface
  * @rtnl_held: True if RTNL lock is held
  * @name_assign_type: the name of assign type of the netdev
+ * @is_rx_mon: if monitor mode is getting enabled
  *
  * Return: 0 - on success
  *         err code - on failure
@@ -5100,7 +5101,8 @@ bool wlan_hdd_is_session_type_monitor(uint8_t session_type);
 int wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
 			       struct hdd_adapter **adapter,
 			       const char *name, bool rtnl_held,
-			       unsigned char name_assign_type);
+			       unsigned char name_assign_type,
+			       bool is_rx_mon);
 
 #ifdef CONFIG_WLAN_DEBUG_CRASH_INJECT
 /**
@@ -5552,4 +5554,13 @@ hdd_lpc_is_work_scheduled(struct hdd_context *hdd_ctx)
 }
 #endif
 
+/**
+ * hdd_allow_new_intf() - Allow new intf created or not
+ * @hdd_ctx: hdd context
+ * @mode: qdf opmode of new interface
+ *
+ * Return: true if allowed, otherwise false
+ */
+bool hdd_allow_new_intf(struct hdd_context *hdd_ctx,
+			enum QDF_OPMODE mode);
 #endif /* end #if !defined(WLAN_HDD_MAIN_H) */

+ 167 - 15
core/hdd/src/wlan_hdd_cfg80211.c

@@ -8384,7 +8384,7 @@ void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
 	vendor_event = wlan_cfg80211_vendor_event_alloc(
 			hdd_ctx->wiphy, &link_info->adapter->wdev, len,
 			QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG_INDEX,
-			GFP_KERNEL);
+			qdf_mem_malloc_flags());
 
 	if (!vendor_event) {
 		hdd_err("wlan_cfg80211_vendor_event_alloc failed vdev id %d, data len %d",
@@ -8409,7 +8409,7 @@ void hdd_cfr_data_send_nl_event(uint8_t vdev_id, uint32_t pid,
 			hdd_err_rl("nlhdr is null");
 	}
 
-	wlan_cfg80211_vendor_event(vendor_event, GFP_ATOMIC);
+	wlan_cfg80211_vendor_event(vendor_event, qdf_mem_malloc_flags());
 }
 #endif
 
@@ -11800,6 +11800,67 @@ void wlan_hdd_save_sta_keep_alive_interval(struct hdd_adapter *adapter,
 	adapter->keep_alive_interval = keep_alive_interval;
 }
 
+#ifdef WLAN_FEATURE_11BE_MLO
+/**
+ * hdd_ml_vdev_set_sta_keep_alive_interval() - Set STA KEEPALIVE interval for
+ *                                             all connected ml vdev
+ * @vdev: Pointer to vdev
+ * @hdd_ctx: Pointer to hdd context
+ * @keep_alive_interval: KEEPALIVE interval
+ *
+ * Return: 0 on success, negative on failure
+ */
+static int hdd_ml_vdev_set_sta_keep_alive_interval(
+						struct wlan_objmgr_vdev *vdev,
+						struct hdd_context *hdd_ctx,
+						uint16_t keep_alive_interval)
+{
+	struct wlan_objmgr_vdev *ml_vdev;
+	uint8_t ml_vdev_id;
+	struct wlan_mlo_dev_context *mlo_dev_ctx;
+	struct wlan_hdd_link_info *link_info;
+	int status, i;
+
+	mlo_dev_ctx = vdev->mlo_dev_ctx;
+	if (!mlo_dev_ctx) {
+		hdd_err("MLO dev context null");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS ; i++) {
+		ml_vdev = mlo_dev_ctx->wlan_vdev_list[i];
+		if (!ml_vdev)
+			continue;
+
+		ml_vdev_id = ml_vdev->vdev_objmgr.vdev_id;
+		link_info = hdd_get_link_info_by_vdev(hdd_ctx, ml_vdev_id);
+		if (!link_info)
+			continue;
+
+		if (!hdd_is_vdev_in_conn_state(link_info)) {
+			hdd_debug("Vdev (id %d) not in connected/started state",
+				  link_info->vdev_id);
+			continue;
+		}
+
+		status = hdd_vdev_send_sta_keep_alive_interval(link_info,
+							hdd_ctx,
+							keep_alive_interval);
+		if (status)
+			return status;
+	}
+
+	return 0;
+}
+#else
+static inline int hdd_ml_vdev_set_sta_keep_alive_interval(
+						struct wlan_objmgr_vdev *vdev,
+						struct hdd_context *hdd_ctx,
+						uint16_t keep_alive_interval)
+{
+	return -EINVAL;
+}
+#endif
 /**
  * hdd_vdev_set_sta_keep_alive_interval() - Set sta keep alive interval
  * @link_info: Link info pointer.
@@ -11815,6 +11876,7 @@ static int hdd_vdev_set_sta_keep_alive_interval(
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	enum QDF_OPMODE device_mode = link_info->adapter->device_mode;
 	uint16_t keep_alive_interval;
+	struct wlan_objmgr_vdev *vdev = link_info->vdev;
 
 	keep_alive_interval = nla_get_u16(attr);
 	if (keep_alive_interval > STA_KEEPALIVE_INTERVAL_MAX ||
@@ -11824,24 +11886,28 @@ static int hdd_vdev_set_sta_keep_alive_interval(
 		return -EINVAL;
 	}
 
-	hdd_debug("sta keep alive interval = %u", keep_alive_interval);
-
 	if (device_mode != QDF_STA_MODE) {
 		hdd_debug("This command is not supported for %s device mode",
 			  device_mode_to_string(device_mode));
 		return -EINVAL;
 	}
 
+	hdd_debug("sta keep alive interval = %u", keep_alive_interval);
+	wlan_hdd_save_sta_keep_alive_interval(adapter, keep_alive_interval);
+
 	if (!hdd_is_vdev_in_conn_state(link_info)) {
-		hdd_debug("Vdev (id %d) not in connected/started state, cannot accept command",
+		hdd_debug("Vdev (id %d) not in connected/started state, configure KEEPALIVE interval after connection",
 			  link_info->vdev_id);
-		return -EINVAL;
+		return 0;
 	}
 
-	wlan_hdd_save_sta_keep_alive_interval(adapter, keep_alive_interval);
+	if (!wlan_vdev_mlme_is_mlo_vdev(vdev))
+		return hdd_vdev_send_sta_keep_alive_interval(link_info,
+							hdd_ctx,
+							keep_alive_interval);
 
-	return hdd_vdev_send_sta_keep_alive_interval(link_info, hdd_ctx,
-						     keep_alive_interval);
+	return hdd_ml_vdev_set_sta_keep_alive_interval(vdev, hdd_ctx,
+						       keep_alive_interval);
 }
 
 #ifdef WLAN_FEATURE_11BE_MLO
@@ -13255,6 +13321,58 @@ static int hdd_get_optimized_power_config(struct wlan_hdd_link_info *link_info,
 	return 0;
 }
 
+/**
+ * hdd_get_sta_keepalive_interval() - Get keep alive interval
+ * @link_info: Link info pointer in HDD adapter
+ * @skb: sk buffer to hold nl80211 attributes
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+static int hdd_get_sta_keepalive_interval(struct wlan_hdd_link_info *link_info,
+					  struct sk_buff *skb,
+					  const struct nlattr *attr)
+{
+	struct hdd_adapter *adapter = link_info->adapter;
+	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	enum QDF_OPMODE device_mode = adapter->device_mode;
+	uint32_t keep_alive_interval;
+	struct wlan_objmgr_vdev *vdev;
+
+	if (device_mode != QDF_STA_MODE) {
+		hdd_debug("This command is not supported for %s device mode",
+			  device_mode_to_string(device_mode));
+		return -EINVAL;
+	}
+
+	if (!hdd_is_vdev_in_conn_state(link_info)) {
+		if (adapter->keep_alive_interval)
+			keep_alive_interval = adapter->keep_alive_interval;
+		else
+			ucfg_mlme_get_sta_keep_alive_period(
+							hdd_ctx->psoc,
+							&keep_alive_interval);
+	} else {
+		vdev = hdd_objmgr_get_vdev_by_user(link_info, WLAN_OSIF_CM_ID);
+		if (!vdev) {
+			hdd_err("vdev is NULL");
+			return -EINVAL;
+		}
+
+		keep_alive_interval = ucfg_mlme_get_keepalive_period(vdev);
+		hdd_objmgr_put_vdev_by_user(vdev, WLAN_OSIF_CM_ID);
+	}
+
+	hdd_debug("STA KEEPALIVE interval = %d", keep_alive_interval);
+	if (nla_put_u16(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL,
+			keep_alive_interval)) {
+		hdd_err("nla_put failure");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /**
  * typedef config_getter_fn - get configuration handler
  * @link_info: Link info pointer in HDD adapter
@@ -13342,6 +13460,9 @@ static const struct config_getters config_getters[] = {
 	 {QCA_WLAN_VENDOR_ATTR_CONFIG_MLO_LINKS,
 	 WLAN_MAX_ML_BSS_LINKS * sizeof(uint8_t) * 2,
 	 hdd_get_mlo_max_band_info},
+	 {QCA_WLAN_VENDOR_ATTR_CONFIG_KEEP_ALIVE_INTERVAL,
+	  sizeof(uint16_t),
+	  hdd_get_sta_keepalive_interval},
 };
 
 /**
@@ -29350,7 +29471,8 @@ static int __wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					       struct net_device *dev,
 					       const u8 *buf, size_t len,
 					       const u8 *src, const u8 *dest,
-						__be16 proto, bool unencrypted)
+						__be16 proto, bool unencrypted,
+						int link_id)
 {
 	qdf_nbuf_t nbuf;
 	struct ethhdr *ehdr;
@@ -29392,7 +29514,8 @@ static int _wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					      struct net_device *dev,
 					      const u8 *buf, size_t len,
 					      const u8 *src, const u8 *dest,
-					      __be16 proto, bool unencrypted)
+					      __be16 proto, bool unencrypted,
+					      int link_id)
 {
 	int errno;
 	struct osif_vdev_sync *vdev_sync;
@@ -29402,14 +29525,15 @@ static int _wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 		return errno;
 
 	errno = __wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len, src,
-						    dest, proto, unencrypted);
+						    dest, proto, unencrypted,
+						    link_id);
 
 	osif_vdev_sync_op_stop(vdev_sync);
 
 	return errno;
 }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 0, 0) || \
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41) || \
 	defined(CFG80211_TX_CONTROL_PORT_LINK_SUPPORT))
 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					     struct net_device *dev,
@@ -29418,28 +29542,54 @@ static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					     const u8 *dest, const __be16 proto,
 					     bool unencrypted, int link_id,
 					     u64 *cookie)
+{
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
+						  adapter->mac_addr.bytes,
+						  dest, proto, unencrypted,
+						  link_id);
+}
 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					     struct net_device *dev,
 					     const u8 *buf, size_t len,
 					     const u8 *dest, __be16 proto,
 					     bool unencrypted, u64 *cookie)
+{
+	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+
+	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
+						  adapter->mac_addr.bytes,
+						  dest, proto, unencrypted, -1);
+}
 #else
 static int wlan_hdd_cfg80211_tx_control_port(struct wiphy *wiphy,
 					     struct net_device *dev,
 					     const u8 *buf, size_t len,
 					     const u8 *dest, __be16 proto,
 					     bool unencrypted)
-#endif
 {
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 
 	return _wlan_hdd_cfg80211_tx_control_port(wiphy, dev, buf, len,
 						  adapter->mac_addr.bytes,
-						  dest, proto, unencrypted);
+						  dest, proto, unencrypted, -1);
 }
+#endif
 
 #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41))
+bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
+				       u8 *ta_addr,
+				       struct sk_buff *skb,
+				       bool unencrypted)
+{
+	return cfg80211_rx_control_port(dev, skb, unencrypted, -1);
+}
+
+#else
 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
 				       u8 *ta_addr,
 				       struct sk_buff *skb,
@@ -29447,6 +29597,8 @@ bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
 {
 	return cfg80211_rx_control_port(dev, ta_addr, skb, unencrypted);
 }
+#endif
+
 #else
 bool wlan_hdd_cfg80211_rx_control_port(struct net_device *dev,
 				       u8 *ta_addr,

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

@@ -1795,15 +1795,13 @@ hdd_cm_connect_success_pre_user_update(struct wlan_objmgr_vdev *vdev,
 		link_info->vdev_id, QDF_TRACE_DEFAULT_PDEV_ID,
 		QDF_PROTO_TYPE_MGMT, QDF_PROTO_MGMT_ASSOC));
 
-	if (is_roam) {
+	if (is_roam)
 		ucfg_dp_nud_indicate_roam(vdev);
+	 /* hdd_objmgr_set_peer_mlme_auth_state */
 
-		if (adapter->keep_alive_interval)
-			hdd_vdev_send_sta_keep_alive_interval(link_info,
-						hdd_ctx,
+	if (adapter->keep_alive_interval)
+		hdd_vdev_send_sta_keep_alive_interval(link_info, hdd_ctx,
 						adapter->keep_alive_interval);
-	}
-	 /* hdd_objmgr_set_peer_mlme_auth_state */
 }
 
 static void

+ 7 - 2
core/hdd/src/wlan_hdd_cm_disconnect.c

@@ -188,7 +188,10 @@ hdd_reset_sta_keep_alive_interval(struct wlan_hdd_link_info *link_info,
 		return;
 	}
 
-	wlan_hdd_save_sta_keep_alive_interval(link_info->adapter, 0);
+	if (!wlan_vdev_mlme_get_is_mlo_link(hdd_ctx->psoc,
+					    link_info->vdev_id))
+		wlan_hdd_save_sta_keep_alive_interval(link_info->adapter, 0);
+
 	ucfg_mlme_get_sta_keep_alive_period(hdd_ctx->psoc,
 					    &keep_alive_interval);
 	hdd_vdev_send_sta_keep_alive_interval(link_info, hdd_ctx,
@@ -280,7 +283,9 @@ __hdd_cm_disconnect_handler_post_user_update(struct wlan_hdd_link_info *link_inf
 
 	ucfg_dp_nud_reset_tracking(vdev);
 	hdd_reset_limit_off_chan(adapter);
-	hdd_reset_sta_keep_alive_interval(link_info, hdd_ctx);
+
+	if (!is_link_switch)
+		hdd_reset_sta_keep_alive_interval(link_info, hdd_ctx);
 
 	hdd_cm_print_bss_info(sta_ctx);
 }

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

@@ -525,6 +525,9 @@ static int __hdd_hostapd_open(struct net_device *dev)
 		return ret;
 	}
 
+	if (!hdd_allow_new_intf(hdd_ctx, adapter->device_mode))
+		return -EOPNOTSUPP;
+
 	ret = hdd_start_adapter(adapter, true);
 	if (ret) {
 		hdd_err("Error Initializing the AP mode: %d", ret);
@@ -1897,7 +1900,7 @@ hdd_hostapd_update_beacon_country_ie(struct hdd_adapter *adapter)
 	struct hdd_station_info *sta_info, *tmp = NULL;
 	struct hdd_context *hdd_ctx;
 	struct hdd_ap_ctx *ap_ctx;
-	struct action_oui_search_attr attr;
+	struct action_oui_search_attr attr = {0};
 	QDF_STATUS status;
 	bool found = false;
 

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

@@ -21766,7 +21766,7 @@ int
 wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
 			   struct hdd_adapter **adapter,
 			   const char *name, bool rtnl_held,
-			   unsigned char name_assign_type)
+			   unsigned char name_assign_type, bool is_rx_mon)
 {
 	struct hdd_adapter *sta_adapter;
 	struct hdd_adapter *mon_adapter;
@@ -21790,8 +21790,7 @@ wlan_hdd_add_monitor_check(struct hdd_context *hdd_ctx,
 		return -EINVAL;
 	}
 
-	if (!ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc) &&
-	    ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc)) {
+	if (is_rx_mon) {
 		num_open_session = policy_mgr_mode_specific_connection_count(
 						hdd_ctx->psoc,
 						PM_STA_MODE,

+ 8 - 12
core/hdd/src/wlan_hdd_p2p.c

@@ -642,15 +642,8 @@ int hdd_set_p2p_ps(struct net_device *dev, void *msgData)
 	return wlan_hdd_set_power_save(adapter, &noa);
 }
 
-/**
- * hdd_allow_new_intf() - Allow new intf created or not
- * @hdd_ctx: hdd context
- * @mode: qdf opmode of new interface
- *
- * Return: true if allowed, otherwise false
- */
-static bool hdd_allow_new_intf(struct hdd_context *hdd_ctx,
-			       enum QDF_OPMODE mode)
+bool hdd_allow_new_intf(struct hdd_context *hdd_ctx,
+			enum QDF_OPMODE mode)
 {
 	struct hdd_adapter *adapter = NULL;
 	struct hdd_adapter *next_adapter = NULL;
@@ -779,6 +772,8 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 
 	adapter = NULL;
 	if (type == NL80211_IFTYPE_MONITOR) {
+		bool is_rx_mon = QDF_MONITOR_FLAG_OTHER_BSS & *flags;
+
 		/*
 		 * if QDF_MONITOR_FLAG_OTHER_BSS bit is set in monitor flags
 		 * driver will assume current mode as STA + Monitor Mode.
@@ -787,14 +782,15 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
 		 * reject the request.
 		 **/
 		if ((ucfg_dp_is_local_pkt_capture_enabled(hdd_ctx->psoc) &&
-		     !(QDF_MONITOR_FLAG_OTHER_BSS & *flags)) ||
+		     !is_rx_mon) ||
 		    (ucfg_mlme_is_sta_mon_conc_supported(hdd_ctx->psoc) &&
-		     (QDF_MONITOR_FLAG_OTHER_BSS & *flags)) ||
+		     is_rx_mon) ||
 		    ucfg_pkt_capture_get_mode(hdd_ctx->psoc) !=
 						PACKET_CAPTURE_MODE_DISABLE) {
 			ret = wlan_hdd_add_monitor_check(hdd_ctx,
 							 &adapter, name, true,
-							 name_assign_type);
+							 name_assign_type,
+							 is_rx_mon);
 			if (ret)
 				return ERR_PTR(-EINVAL);
 

+ 15 - 3
core/hdd/src/wlan_hdd_pre_cac.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 above
@@ -267,10 +267,22 @@ static int __wlan_hdd_request_pre_cac(struct hdd_context *hdd_ctx,
 		return -EINVAL;
 	}
 
-	hdd_debug("channel: %d", chan_freq);
+	cac_ch_width = wlansap_get_max_bw_by_phymode(hdd_ap_ctx->sap_context);
+	if (cac_ch_width > DEFAULT_PRE_CAC_BANDWIDTH)
+		cac_ch_width = DEFAULT_PRE_CAC_BANDWIDTH;
+	if (chan_freq) {
+		qdf_mem_zero(&chandef, sizeof(struct cfg80211_chan_def));
+		if (wlan_set_def_pre_cac_chan(hdd_ctx, chan_freq, &chandef,
+					      &channel_type, &cac_ch_width)) {
+			hdd_err("failed to set pre_cac channel %d", chan_freq);
+			return -EINVAL;
+		}
+	}
+	hdd_debug("channel: %d bw: %d", chan_freq, cac_ch_width);
 
 	ret = ucfg_pre_cac_validate_and_get_freq(hdd_ctx->pdev, chan_freq,
-						 &pre_cac_chan_freq);
+						 &pre_cac_chan_freq,
+						 cac_ch_width);
 	if (ret != 0) {
 		hdd_err("can't validate pre-cac channel");
 		goto release_intf_addr_and_return_failure;

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

@@ -523,8 +523,8 @@ hdd_get_link_info_by_bssid(struct hdd_context *hdd_ctx, const uint8_t *bssid)
 	return NULL;
 }
 
-#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
 #define WLAN_INVALID_RSSI_VALUE -128
+#if defined(WLAN_FEATURE_11BE_MLO) && defined(CFG80211_11BE_BASIC)
 /**
  * wlan_hdd_is_per_link_stats_supported - Check if FW supports per link stats
  * @hdd_ctx: Pointer to hdd context
@@ -7618,7 +7618,9 @@ static int wlan_hdd_update_rate_info(struct wlan_hdd_link_info *link_info,
 		return -EINVAL;
 	}
 
-	if (!ucfg_mlme_stats_is_link_speed_report_actual(hdd_ctx->psoc)) {
+	if (sinfo->signal == WLAN_INVALID_RSSI_VALUE) {
+		hdd_debug("don't fill tx rx rate for inactive link");
+	} else if (!ucfg_mlme_stats_is_link_speed_report_actual(hdd_ctx->psoc)) {
 		bool tx_rate_calc, rx_rate_calc;
 		uint8_t tx_nss_max, rx_nss_max;
 

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

@@ -32,9 +32,9 @@
 #define QWLAN_VERSION_MAJOR            5
 #define QWLAN_VERSION_MINOR            2
 #define QWLAN_VERSION_PATCH            1
-#define QWLAN_VERSION_EXTRA            ""
+#define QWLAN_VERSION_EXTRA            "X"
 #define QWLAN_VERSION_BUILD            90
 
-#define QWLAN_VERSIONSTR               "5.2.1.90"
+#define QWLAN_VERSIONSTR               "5.2.1.90X"
 
 #endif /* QWLAN_VERSION_H */

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

@@ -1191,6 +1191,7 @@ struct disassoc_ind {
 	tSirResultCodes status_code;
 	struct qdf_mac_addr bssid;
 	struct qdf_mac_addr peer_macaddr;
+	struct qdf_mac_addr peer_mld_addr;
 	uint16_t staId;
 	uint32_t reasonCode;
 	bool from_ap;
@@ -1262,6 +1263,7 @@ struct deauth_ind {
 	tSirResultCodes status_code;
 	struct qdf_mac_addr bssid;      /* AP BSSID */
 	struct qdf_mac_addr peer_macaddr;
+	struct qdf_mac_addr peer_mld_addr;
 
 	uint16_t staId;
 	uint32_t reasonCode;

+ 3 - 2
core/mac/src/pe/lim/lim_assoc_utils.c

@@ -2858,7 +2858,8 @@ static void lim_set_mbssid_info(struct pe_session *pe_session)
 		mbssid_info =
 			&pe_session->pLimReAssocReq->bssDescription.mbssid_info;
 
-	mlme_set_mbssid_info(pe_session->vdev, mbssid_info);
+	mlme_set_mbssid_info(pe_session->vdev, mbssid_info,
+			     pe_session->curr_op_freq);
 }
 
 /**
@@ -3689,7 +3690,7 @@ lim_limit_bw_for_iot_ap(struct mac_context *mac_ctx,
 			struct pe_session *session,
 			struct bss_description *bss_desc)
 {
-	struct action_oui_search_attr vendor_ap_search_attr;
+	struct action_oui_search_attr vendor_ap_search_attr = {0};
 	uint16_t ie_len;
 
 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);

+ 13 - 9
core/mac/src/pe/lim/lim_process_action_frame.c

@@ -58,6 +58,7 @@
 #include "wlan_epcs_api.h"
 #include <wlan_mlo_mgr_sta.h>
 #include "wlan_mlo_mgr_public_structs.h"
+#include "wlan_p2p_api.h"
 
 #define SA_QUERY_REQ_MIN_LEN \
 (DOT11F_FF_CATEGORY_LEN + DOT11F_FF_ACTION_LEN + DOT11F_FF_TRANSACTIONID_LEN)
@@ -2294,11 +2295,9 @@ void lim_process_action_frame_no_session(struct mac_context *mac, uint8_t *pBd)
 	tpSirMacMgmtHdr mac_hdr = WMA_GET_RX_MAC_HEADER(pBd);
 	uint32_t frame_len = WMA_GET_RX_PAYLOAD_LEN(pBd);
 	uint8_t *pBody = WMA_GET_RX_MPDU_DATA(pBd);
-	uint8_t dpp_oui[] = { 0x50, 0x6F, 0x9A, 0x1A };
 	tpSirMacActionFrameHdr action_hdr = (tpSirMacActionFrameHdr) pBody;
 	tpSirMacVendorSpecificPublicActionFrameHdr vendor_specific;
 
-
 	pe_debug("Received an action frame category: %d action_id: %d",
 		 action_hdr->category, (action_hdr->category ==
 		 ACTION_CATEGORY_PUBLIC || action_hdr->category ==
@@ -2325,13 +2324,18 @@ void lim_process_action_frame_no_session(struct mac_context *mac, uint8_t *pBd)
 				return;
 			}
 
-			/* Check if it is a DPP public action frame */
-			if (qdf_mem_cmp(vendor_specific->Oui, dpp_oui, 4)) {
-				pe_debug("public action frame (Vendor specific) OUI: %x %x %x %x",
-					 vendor_specific->Oui[0],
-					 vendor_specific->Oui[1],
-					 vendor_specific->Oui[2],
-					 vendor_specific->Oui[3]);
+			pe_debug("public action frame (Vendor specific) OUI: %x %x %x %x",
+				 vendor_specific->Oui[0],
+				 vendor_specific->Oui[1],
+				 vendor_specific->Oui[2],
+				 vendor_specific->Oui[3]);
+
+			/* Drop P2P frames as they are handled by P2P module */
+			if (wlan_p2p_is_action_frame_of_p2p_type(
+						(uint8_t *)mac_hdr,
+						WMA_GET_RX_MPDU_LEN(pBd))) {
+				pe_debug("Drop P2P public action frame as already handled in p2p module");
+				return;
 			}
 		}
 

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

@@ -3165,6 +3165,7 @@ static void lim_process_switch_channel_join_req(
 	 * and wait for the probe response/ beacon to post JOIN CNF
 	 */
 	if (nontx_bss_id) {
+		pe_debug("Skip sending join probe for MBSS candidate");
 		session_entry->limMlmState = eLIM_MLM_JOINED_STATE;
 		join_cnf.sessionId = session_entry->peSessionId;
 		join_cnf.resultCode = eSIR_SME_SUCCESS;

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

@@ -1792,7 +1792,7 @@ static void lim_check_oui_and_update_session(struct mac_context *mac_ctx,
 					     struct pe_session *session,
 					     tDot11fBeaconIEs *ie_struct)
 {
-	struct action_oui_search_attr vendor_ap_search_attr;
+	struct action_oui_search_attr vendor_ap_search_attr = {0};
 	uint16_t ie_len;
 	bool follow_ap_edca;
 	struct bss_description *bss_desc =
@@ -2884,7 +2884,8 @@ lim_update_sae_single_pmk_ap_cap(struct mac_context *mac,
 	akm = wlan_crypto_get_param(session->vdev,
 				    WLAN_CRYPTO_PARAM_KEY_MGMT);
 
-	if (QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) &&
+	if ((QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+	     QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY)) &&
 	    mac->mlme_cfg->lfr.sae_single_pmk_feature_enabled)
 		wlan_mlme_set_sae_single_pmk_bss_cap(mac->psoc,
 			session->vdev_id,
@@ -3155,7 +3156,7 @@ bool lim_enable_cts_to_self_for_exempted_iot_ap(
 				       uint8_t *ie_ptr,
 				       uint16_t ie_len)
 {
-	struct action_oui_search_attr vendor_ap_search_attr;
+	struct action_oui_search_attr vendor_ap_search_attr = {0};
 
 	vendor_ap_search_attr.ie_data = ie_ptr;
 	vendor_ap_search_attr.ie_length = ie_len;
@@ -3186,7 +3187,7 @@ lim_disable_bformee_for_iot_ap(struct mac_context *mac_ctx,
 			       struct pe_session *session,
 			       struct bss_description *bss_desc)
 {
-	struct action_oui_search_attr vendor_ap_search_attr;
+	struct action_oui_search_attr vendor_ap_search_attr = {0};
 	uint16_t ie_len;
 
 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);

+ 2 - 2
core/mac/src/pe/lim/lim_session.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
@@ -829,7 +829,7 @@ static void lim_clear_mbssid_info(struct wlan_objmgr_vdev *vdev)
 {
 	struct scan_mbssid_info mbssid_info = {0};
 
-	mlme_set_mbssid_info(vdev, &mbssid_info);
+	mlme_set_mbssid_info(vdev, &mbssid_info, INVALID_CHANNEL_NUM);
 }
 
 /**

+ 1 - 1
core/mac/src/pe/lim/lim_utils.c

@@ -7132,7 +7132,7 @@ void lim_intersect_sta_he_caps(struct mac_context *mac_ctx,
 static bool
 lim_is_vendor_htc_he_ap(struct bss_description *bss_desc)
 {
-	struct action_oui_search_attr vendor_ap_search_attr;
+	struct action_oui_search_attr vendor_ap_search_attr = {0};
 	uint16_t ie_len;
 
 	ie_len = wlan_get_ielen_from_bss_description(bss_desc);

+ 2 - 1
core/mac/src/pe/rrm/rrm_api.c

@@ -1625,7 +1625,8 @@ rrm_fill_beacon_ies(struct mac_context *mac, uint8_t *pIes,
 		i = 0;
 		do {
 			if (((!eids) || (*pBcnIes == eids[i])) ||
-				((*pBcnIes == eid) && *(pBcnIes + 2) == extn_eids[i])) {
+			    ((*pBcnIes == eid) &&
+			     (extn_eids && *(pBcnIes + 2) == extn_eids[i]))) {
 				if (((*pNumIes) + len) < pIesMaxSize) {
 						qdf_mem_copy(pIes, pBcnIes, len);
 						pIes += len;

+ 4 - 1
core/mac/src/sys/legacy/src/utils/src/parser_api.c

@@ -12831,7 +12831,10 @@ QDF_STATUS populate_dot11f_assoc_req_mlo_ie(struct mac_context *mac_ctx,
 						WLAN_EXTN_ELEMID_HE_6G_CAP;
 		}
 		populate_dot11f_eht_caps_by_band(mac_ctx, is_2g, &eht_caps,
-						 pe_session);
+						 NULL);
+		if (!WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_freq))
+			eht_caps.support_320mhz_6ghz = 0;
+
 		if ((eht_caps.present && frm->eht_cap.present &&
 		     qdf_mem_cmp(&eht_caps, &frm->eht_cap, sizeof(eht_caps))) ||
 		     (eht_caps.present && !frm->eht_cap.present) ||

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

@@ -190,6 +190,11 @@ sap_is_chan_change_needed(struct sap_context *sap_ctx)
 	QDF_STATUS status;
 	struct mac_context *mac_ctx;
 
+	if (!sap_phymode_is_eht(sap_ctx->phyMode)) {
+		sap_debug("phy mode: 0x%x", sap_ctx->phyMode);
+		return true;
+	}
+
 	mac_ctx = sap_get_mac_context();
 	if (!mac_ctx) {
 		sap_err("Invalid MAC context");

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

@@ -1327,6 +1327,7 @@ wlansap_5g_original_bw_validate(
 	enum phy_ch_width ch_width)
 {
 	if (sap_context->csa_reason != CSA_REASON_USER_INITIATED &&
+	    sap_context->csa_reason != CSA_REASON_PRE_CAC_SUCCESS &&
 	    WLAN_REG_IS_5GHZ_CH_FREQ(chan_freq) &&
 	    ch_width >= CH_WIDTH_160MHZ &&
 	    sap_context->ch_width_orig < CH_WIDTH_160MHZ)

+ 5 - 1
core/sme/inc/csr_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
@@ -35,6 +35,9 @@
 
 #define CSR_INVALID_SCANRESULT_HANDLE       (NULL)
 
+/* Length to print MAC 12 char + 5 ":" + 2 space + mld string */
+#define MAC_ADDR_DUMP_LEN 26
+
 enum csr_akm_type {
 	/* never used */
 	eCSR_AUTH_TYPE_NONE,
@@ -748,6 +751,7 @@ typedef struct tagCsrEseBeaconReq {
 
 struct csr_del_sta_params {
 	struct qdf_mac_addr peerMacAddr;
+	struct qdf_mac_addr peer_mld_addr;
 	uint16_t reason_code;
 	uint8_t subtype;
 };

+ 2 - 1
core/sme/inc/csr_internal.h

@@ -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
@@ -118,6 +118,7 @@ struct csr_channel {
 struct roam_cmd {
 	enum csr_roam_reason roamReason;
 	tSirMacAddr peerMac;
+	struct qdf_mac_addr peer_mld_addr;
 	enum wlan_reason_code reason;
 };
 

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

@@ -564,28 +564,50 @@ static void sme_dump_peer_disconnect_timeout_info(tSmeCmd *sme_cmd)
 {
 	struct wmstatus_changecmd *wms_cmd;
 	struct qdf_mac_addr peer_macaddr = QDF_MAC_ADDR_ZERO_INIT;
+	struct qdf_mac_addr peer_mld_addr = QDF_MAC_ADDR_ZERO_INIT;
+	char mld_log_str[MAC_ADDR_DUMP_LEN] = {0};
 
 	if (sme_cmd->command == eSmeCommandRoam &&
 	    (sme_cmd->u.roamCmd.roamReason == eCsrForcedDisassocSta ||
 	    sme_cmd->u.roamCmd.roamReason == eCsrForcedDeauthSta)) {
 		qdf_mem_copy(peer_macaddr.bytes, sme_cmd->u.roamCmd.peerMac,
 			     QDF_MAC_ADDR_SIZE);
+		if (!qdf_is_macaddr_zero(&sme_cmd->u.roamCmd.peer_mld_addr))
+			qdf_copy_macaddr(&peer_mld_addr,
+					 &sme_cmd->u.roamCmd.peer_mld_addr);
 	} else if (sme_cmd->command == eSmeCommandWmStatusChange) {
 		wms_cmd = &sme_cmd->u.wmStatusChangeCmd;
-		if (wms_cmd->Type == eCsrDisassociated)
+		if (wms_cmd->Type == eCsrDisassociated) {
 			qdf_copy_macaddr(
 				&peer_macaddr,
 				&wms_cmd->u.DisassocIndMsg.peer_macaddr);
-		else if (wms_cmd->Type == eCsrDeauthenticated)
+			if (!qdf_is_macaddr_zero(
+				&wms_cmd->u.DisassocIndMsg.peer_mld_addr))
+				qdf_copy_macaddr(
+					&peer_mld_addr,
+					&wms_cmd->u.DisassocIndMsg.peer_mld_addr);
+		} else if (wms_cmd->Type == eCsrDeauthenticated) {
 			qdf_copy_macaddr(
 				&peer_macaddr,
 				&wms_cmd->u.DeauthIndMsg.peer_macaddr);
+			if (!qdf_is_macaddr_zero(
+				&wms_cmd->u.DeauthIndMsg.peer_mld_addr))
+				qdf_copy_macaddr(
+					&peer_mld_addr,
+					&wms_cmd->u.DeauthIndMsg.peer_mld_addr);
+		}
 	}
 
+	if (!qdf_is_macaddr_zero(&peer_mld_addr))
+		qdf_scnprintf(mld_log_str, MAC_ADDR_DUMP_LEN,
+			      " mld: " QDF_MAC_ADDR_FMT,
+			      QDF_MAC_ADDR_REF(peer_mld_addr.bytes));
+
 	if (!qdf_is_macaddr_zero(&peer_macaddr))
-		sme_err("vdev %d cmd %d timeout for peer " QDF_MAC_ADDR_FMT,
+		sme_err("vdev %d cmd %d timeout for peer " QDF_MAC_ADDR_FMT "%s",
 			sme_cmd->vdev_id, sme_cmd->command,
-			QDF_MAC_ADDR_REF(peer_macaddr.bytes));
+			QDF_MAC_ADDR_REF(peer_macaddr.bytes), mld_log_str);
+
 }
 
 QDF_STATUS sme_ser_cmd_callback(struct wlan_serialization_command *cmd,

+ 187 - 139
core/sme/src/csr/csr_api_roam.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
@@ -2311,14 +2311,19 @@ QDF_STATUS csr_roam_call_callback(struct mac_context *mac, uint32_t sessionId,
 }
 
 static bool csr_peer_mac_match_cmd(tSmeCmd *sme_cmd,
-				   struct qdf_mac_addr peer_macaddr,
+				   struct qdf_mac_addr *peer_macaddr,
+				   struct qdf_mac_addr *peer_mld_addr,
 				   uint8_t vdev_id)
 {
 	if (sme_cmd->command == eSmeCommandRoam &&
 	    (sme_cmd->u.roamCmd.roamReason == eCsrForcedDisassocSta ||
 	     sme_cmd->u.roamCmd.roamReason == eCsrForcedDeauthSta) &&
-	    !qdf_mem_cmp(peer_macaddr.bytes, sme_cmd->u.roamCmd.peerMac,
-			 QDF_MAC_ADDR_SIZE))
+	     (qdf_is_macaddr_equal(
+			peer_macaddr,
+			(struct qdf_mac_addr *)sme_cmd->u.roamCmd.peerMac) ||
+	      (!qdf_is_macaddr_zero(peer_mld_addr) &&
+	       qdf_is_macaddr_equal(peer_mld_addr,
+				    &sme_cmd->u.roamCmd.peer_mld_addr))))
 		return true;
 
 	if (sme_cmd->command == eSmeCommandWmStatusChange) {
@@ -2326,15 +2331,23 @@ static bool csr_peer_mac_match_cmd(tSmeCmd *sme_cmd,
 
 		wms_cmd = &sme_cmd->u.wmStatusChangeCmd;
 		if (wms_cmd->Type == eCsrDisassociated &&
-		    !qdf_mem_cmp(peer_macaddr.bytes,
-				 wms_cmd->u.DisassocIndMsg.peer_macaddr.bytes,
-				 QDF_MAC_ADDR_SIZE))
+		    (qdf_is_macaddr_equal(
+				peer_macaddr,
+				&wms_cmd->u.DisassocIndMsg.peer_macaddr) ||
+		     (!qdf_is_macaddr_zero(peer_mld_addr) &&
+		      qdf_is_macaddr_equal(
+				peer_mld_addr,
+				&wms_cmd->u.DisassocIndMsg.peer_mld_addr))))
 			return true;
 
 		if (wms_cmd->Type == eCsrDeauthenticated &&
-		    !qdf_mem_cmp(peer_macaddr.bytes,
-				 wms_cmd->u.DeauthIndMsg.peer_macaddr.bytes,
-				 QDF_MAC_ADDR_SIZE))
+		    (qdf_is_macaddr_equal(
+				peer_macaddr,
+				&wms_cmd->u.DeauthIndMsg.peer_macaddr) ||
+		     (!qdf_is_macaddr_zero(peer_mld_addr) &&
+		      qdf_is_macaddr_equal(
+				peer_mld_addr,
+				&wms_cmd->u.DeauthIndMsg.peer_mld_addr))))
 			return true;
 	}
 
@@ -2344,7 +2357,8 @@ static bool csr_peer_mac_match_cmd(tSmeCmd *sme_cmd,
 static bool
 csr_is_deauth_disassoc_in_pending_q(struct mac_context *mac_ctx,
 				    uint8_t vdev_id,
-				    struct qdf_mac_addr peer_macaddr)
+				    struct qdf_mac_addr *peer_macaddr,
+				    struct qdf_mac_addr *peer_mld_addr)
 {
 	tListElem *entry = NULL;
 	tSmeCmd *sme_cmd;
@@ -2353,7 +2367,8 @@ csr_is_deauth_disassoc_in_pending_q(struct mac_context *mac_ctx,
 	while (entry) {
 		sme_cmd = GET_BASE_ADDR(entry, tSmeCmd, Link);
 		if ((sme_cmd->vdev_id == vdev_id) &&
-		    csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
+		    csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
+					   peer_mld_addr, vdev_id))
 			return true;
 		entry = csr_nonscan_pending_ll_next(mac_ctx, entry,
 						    LL_ACCESS_NOLOCK);
@@ -2365,20 +2380,23 @@ csr_is_deauth_disassoc_in_pending_q(struct mac_context *mac_ctx,
 static bool
 csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
 				   uint8_t vdev_id,
-				   struct qdf_mac_addr peer_macaddr)
+				   struct qdf_mac_addr *peer_macaddr,
+				   struct qdf_mac_addr *peer_mld_addr)
 {
 	tSmeCmd *sme_cmd;
 
 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
 						WLAN_SER_CMD_FORCE_DEAUTH_STA);
 
-	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
+	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
+					      peer_mld_addr, vdev_id))
 		return true;
 
 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
 					WLAN_SER_CMD_FORCE_DISASSOC_STA);
 
-	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
+	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
+					      peer_mld_addr, vdev_id))
 		return true;
 
 	/*
@@ -2387,7 +2405,8 @@ csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
 	 */
 	sme_cmd = wlan_serialization_get_active_cmd(mac_ctx->psoc, vdev_id,
 						WLAN_SER_CMD_WM_STATUS_CHANGE);
-	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr, vdev_id))
+	if (sme_cmd && csr_peer_mac_match_cmd(sme_cmd, peer_macaddr,
+					      peer_mld_addr, vdev_id))
 		return true;
 
 	return false;
@@ -2398,7 +2417,8 @@ csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
  *  disassoc is already in progress.
  * @mac_ctx: Global MAC context
  * @vdev_id: vdev id
- * @peer_macaddr: Peer MAC address
+ * @peer_macaddr: Peer MAC address to check
+ * @peer_mld_addr: peer MLD address to check
  *
  * Return: True if deauth/disassoc indication can be dropped
  *  else false
@@ -2406,111 +2426,136 @@ csr_is_deauth_disassoc_in_active_q(struct mac_context *mac_ctx,
 static bool
 csr_is_deauth_disassoc_already_active(struct mac_context *mac_ctx,
 				      uint8_t vdev_id,
-				      struct qdf_mac_addr peer_macaddr)
+				      struct qdf_mac_addr *peer_macaddr,
+				      struct qdf_mac_addr *peer_mld_addr)
 {
-	bool ret = csr_is_deauth_disassoc_in_pending_q(mac_ctx,
-						      vdev_id,
-						      peer_macaddr);
+	char mld_log_str[MAC_ADDR_DUMP_LEN] = {0};
+
+	bool ret = csr_is_deauth_disassoc_in_pending_q(
+					mac_ctx, vdev_id, peer_macaddr,
+					peer_mld_addr);
 	if (!ret)
 		/**
 		 * commands are not found in pending queue, check in active
 		 * queue as well
 		 */
-		ret = csr_is_deauth_disassoc_in_active_q(mac_ctx,
-							  vdev_id,
-							  peer_macaddr);
+		ret = csr_is_deauth_disassoc_in_active_q(
+					mac_ctx, vdev_id,
+					peer_macaddr, peer_mld_addr);
 
-	if (ret)
-		sme_debug("Deauth/Disassoc already in progress for "QDF_MAC_ADDR_FMT,
-			  QDF_MAC_ADDR_REF(peer_macaddr.bytes));
+	if (ret) {
+		if (!qdf_is_macaddr_zero((struct qdf_mac_addr *)&peer_mld_addr))
+			qdf_scnprintf(mld_log_str, MAC_ADDR_DUMP_LEN,
+				      " mld: " QDF_MAC_ADDR_FMT,
+				      QDF_MAC_ADDR_REF(peer_mld_addr->bytes));
+		sme_debug("Deauth/Disassoc already in progress for " QDF_MAC_ADDR_FMT "%s",
+			  QDF_MAC_ADDR_REF(peer_macaddr->bytes), mld_log_str);
+	}
 
 	return ret;
 }
 
-/**
- * csr_roam_issue_disassociate_sta_cmd() - disassociate a associated station
- * @sessionId:     Session Id for Soft AP
- * @p_del_sta_params: Pointer to parameters of the station to disassoc
- *
- * CSR function that HDD calls to delete a associated station
+/*
+ * csr_is_deauth_disassoc_cmd_active() - Function to check if deauth or
+ *  disassoc is already in progress.
+ * @mac_ctx: Global MAC context
+ * @vdev_id: vdev ID
+ * @macaddr: mac address provided (mld/link/mac for the peer to check)
+ * @peer_mac: found peer mac
+ * @peer_mld_mac: found peer mld if ML connection
  *
- * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_* on error
+ * Return: True if deauth/disassoc indication can be dropped else false
  */
-QDF_STATUS csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
-					       uint32_t sessionId,
-					       struct csr_del_sta_params
-					       *p_del_sta_params)
+static bool
+csr_is_deauth_disassoc_cmd_active(struct mac_context *mac_ctx,
+				  uint8_t vdev_id, struct qdf_mac_addr macaddr,
+				  struct qdf_mac_addr *peer_mac,
+				  struct qdf_mac_addr *peer_mld_mac)
+{
+	struct peer_mac_addresses peer_mac_info;
+
+	qdf_mem_zero(&peer_mac_info, sizeof(struct peer_mac_addresses));
+	qdf_copy_macaddr(&peer_mac_info.mac, &macaddr);
+	wlan_find_peer_and_get_mac_and_mld_addr(mac_ctx->psoc, &peer_mac_info);
+	if (csr_is_deauth_disassoc_already_active(mac_ctx, vdev_id,
+						  &peer_mac_info.peer_mac,
+						  &peer_mac_info.peer_mld))
+		return true;
 
+	if (peer_mac && peer_mld_mac) {
+		if (!qdf_is_macaddr_equal(&macaddr, &peer_mac_info.peer_mac))
+			sme_debug("Vdev %d, given mac " QDF_MAC_ADDR_FMT " found peer mac " QDF_MAC_ADDR_FMT,
+				  vdev_id, QDF_MAC_ADDR_REF(macaddr.bytes),
+				  QDF_MAC_ADDR_REF(peer_mac_info.peer_mac.bytes));
+		qdf_copy_macaddr(peer_mac, &peer_mac_info.peer_mac);
+		qdf_copy_macaddr(peer_mld_mac, &peer_mac_info.peer_mld);
+	}
+
+	return false;
+}
+
+static QDF_STATUS
+csr_roam_issue_discon_sta_roam_cmd(struct mac_context *mac,
+				   uint8_t vdev_id,
+				   enum csr_roam_reason discon_reason,
+				   struct csr_del_sta_params *del_sta_params)
 {
+	tSmeCmd *cmd;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	tSmeCmd *pCommand;
+	struct qdf_mac_addr peer_mac = QDF_MAC_ADDR_ZERO_INIT;
+	struct qdf_mac_addr peer_mld_mac = QDF_MAC_ADDR_ZERO_INIT;
 
-	do {
-		if (csr_is_deauth_disassoc_already_active(mac, sessionId,
-					      p_del_sta_params->peerMacAddr))
-			break;
-		pCommand = csr_get_command_buffer(mac);
-		if (!pCommand) {
-			sme_err("fail to get command buffer");
-			status = QDF_STATUS_E_RESOURCES;
-			break;
-		}
-		pCommand->command = eSmeCommandRoam;
-		pCommand->vdev_id = (uint8_t) sessionId;
-		pCommand->u.roamCmd.roamReason = eCsrForcedDisassocSta;
-		qdf_mem_copy(pCommand->u.roamCmd.peerMac,
-				p_del_sta_params->peerMacAddr.bytes,
-				sizeof(pCommand->u.roamCmd.peerMac));
-		pCommand->u.roamCmd.reason = p_del_sta_params->reason_code;
+	if (csr_is_deauth_disassoc_cmd_active(mac, vdev_id,
+					      del_sta_params->peerMacAddr,
+					      &peer_mac, &peer_mld_mac))
+		return status;
 
-		status = csr_queue_sme_command(mac, pCommand, false);
-		if (!QDF_IS_STATUS_SUCCESS(status))
-			sme_err("fail to send message status: %d", status);
-	} while (0);
+	cmd = csr_get_command_buffer(mac);
+	if (!cmd) {
+		sme_err("Vdev %d " QDF_MAC_ADDR_FMT " fails to get command buffer for reason %d",
+			vdev_id,
+			QDF_MAC_ADDR_REF(del_sta_params->peerMacAddr.bytes),
+			discon_reason);
+		return QDF_STATUS_E_RESOURCES;
+	}
+
+	cmd->command = eSmeCommandRoam;
+	cmd->vdev_id = vdev_id;
+	cmd->u.roamCmd.roamReason = discon_reason;
+	qdf_copy_macaddr((struct qdf_mac_addr *)&cmd->u.roamCmd.peerMac,
+			 &peer_mac);
+	qdf_copy_macaddr(&cmd->u.roamCmd.peer_mld_addr, &peer_mld_mac);
+	cmd->u.roamCmd.reason = del_sta_params->reason_code;
+
+	status = csr_queue_sme_command(mac, cmd, false);
+	if (QDF_IS_STATUS_ERROR(status))
+		sme_err("Vdev %d " QDF_MAC_ADDR_FMT " fails to get send message status: %d",
+			vdev_id,
+			QDF_MAC_ADDR_REF(del_sta_params->peerMacAddr.bytes),
+			status);
 
 	return status;
 }
 
-/**
- * csr_roam_issue_deauthSta() - delete a associated station
- * @sessionId:     Session Id for Soft AP
- * @pDelStaParams: Pointer to parameters of the station to deauthenticate
- *
- * CSR function that HDD calls to delete a associated station
- *
- * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_** on error
- */
-QDF_STATUS csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
-		uint32_t sessionId,
-		struct csr_del_sta_params *pDelStaParams)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	tSmeCmd *pCommand;
-
-	do {
-		if (csr_is_deauth_disassoc_already_active(mac, sessionId,
-					      pDelStaParams->peerMacAddr))
-			break;
-		pCommand = csr_get_command_buffer(mac);
-		if (!pCommand) {
-			sme_err("fail to get command buffer");
-			status = QDF_STATUS_E_RESOURCES;
-			break;
-		}
-		pCommand->command = eSmeCommandRoam;
-		pCommand->vdev_id = (uint8_t) sessionId;
-		pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta;
-		qdf_mem_copy(pCommand->u.roamCmd.peerMac,
-			     pDelStaParams->peerMacAddr.bytes,
-			     sizeof(tSirMacAddr));
-		pCommand->u.roamCmd.reason = pDelStaParams->reason_code;
+QDF_STATUS
+csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
+				    uint8_t vdev_id,
+				    struct csr_del_sta_params *del_sta_params)
 
-		status = csr_queue_sme_command(mac, pCommand, false);
-		if (!QDF_IS_STATUS_SUCCESS(status))
-			sme_err("fail to send message status: %d", status);
-	} while (0);
+{
+	return csr_roam_issue_discon_sta_roam_cmd(mac, vdev_id,
+						  eCsrForcedDisassocSta,
+						  del_sta_params);
+}
 
-	return status;
+QDF_STATUS
+csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
+			      uint8_t vdev_id,
+			      struct csr_del_sta_params *del_sta_params)
+{
+	return csr_roam_issue_discon_sta_roam_cmd(mac, vdev_id,
+						  eCsrForcedDeauthSta,
+						  del_sta_params);
 }
 
 /**
@@ -4081,50 +4126,47 @@ static void
 csr_roam_chk_lnk_disassoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 {
 	struct csr_roam_session *session;
-	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
-	struct disassoc_ind *pDisassocInd;
+	uint8_t vdev_id = WLAN_UMAC_VDEV_ID_MAX;
+	struct disassoc_ind *disassoc_ind;
 
 	/*
 	 * Check if AP dis-associated us because of MIC failure. If so,
 	 * then we need to take action immediately and not wait till the
 	 * the WmStatusChange requests is pushed and processed
 	 */
-	pDisassocInd = (struct disassoc_ind *)msg_ptr;
-	sessionId = pDisassocInd->vdev_id;
-	sme_debug("Disassoc Indication from MAC for vdev_id %d bssid " QDF_MAC_ADDR_FMT,
-		  pDisassocInd->vdev_id,
-		  QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes));
+	disassoc_ind = (struct disassoc_ind *)msg_ptr;
+	vdev_id = disassoc_ind->vdev_id;
 
-	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
+	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
 		sme_err("vdev:%d Invalid session. BSSID: " QDF_MAC_ADDR_FMT,
-			sessionId, QDF_MAC_ADDR_REF(pDisassocInd->bssid.bytes));
+			vdev_id, QDF_MAC_ADDR_REF(disassoc_ind->bssid.bytes));
 
 		return;
 	}
 
-	if (!csr_if_peer_present(mac_ctx, &pDisassocInd->bssid.bytes[0],
-				 &pDisassocInd->peer_macaddr.bytes[0]))
+	if (!csr_if_peer_present(mac_ctx, &disassoc_ind->bssid.bytes[0],
+				 &disassoc_ind->peer_macaddr.bytes[0]))
 		return;
 
-	if (csr_is_deauth_disassoc_already_active(mac_ctx, sessionId,
-	    pDisassocInd->peer_macaddr))
+	if (csr_is_deauth_disassoc_cmd_active(mac_ctx, vdev_id,
+					      disassoc_ind->peer_macaddr,
+					      &disassoc_ind->peer_macaddr,
+					      &disassoc_ind->peer_mld_addr))
 		return;
 
-	sme_nofl_info("disassoc from peer " QDF_MAC_ADDR_FMT
-		      "reason: %d status: %d vid %d",
-		      QDF_MAC_ADDR_REF(pDisassocInd->peer_macaddr.bytes),
-		      pDisassocInd->reasonCode,
-		      pDisassocInd->status_code, sessionId);
-	session = CSR_GET_SESSION(mac_ctx, sessionId);
+	session = CSR_GET_SESSION(mac_ctx, vdev_id);
 	if (!session) {
-		sme_err("session: %d not found", sessionId);
+		sme_err("vdev %d session not found", vdev_id);
 		return;
 	}
+	sme_debug("Vdev %d, peer " QDF_MAC_ADDR_FMT " reason: %d status: %d",
+		  vdev_id, QDF_MAC_ADDR_REF(disassoc_ind->peer_macaddr.bytes),
+		  disassoc_ind->reasonCode, disassoc_ind->status_code);
 	/* Update the disconnect stats */
 	session->disconnect_stats.disconnection_cnt++;
 	session->disconnect_stats.disassoc_by_peer++;
 
-	csr_roam_issue_wm_status_change(mac_ctx, sessionId,
+	csr_roam_issue_wm_status_change(mac_ctx, vdev_id,
 					eCsrDisassociated, msg_ptr);
 }
 
@@ -4132,36 +4174,40 @@ static void
 csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 {
 	struct csr_roam_session *session;
-	uint32_t sessionId = WLAN_UMAC_VDEV_ID_MAX;
-	struct deauth_ind *pDeauthInd;
+	uint8_t vdev_id = WLAN_UMAC_VDEV_ID_MAX;
+	struct deauth_ind *deauth_ind;
 
-	pDeauthInd = (struct deauth_ind *)msg_ptr;
-	sme_debug("DEAUTH Indication from MAC for vdev_id %d bssid "QDF_MAC_ADDR_FMT,
-		  pDeauthInd->vdev_id,
-		  QDF_MAC_ADDR_REF(pDeauthInd->bssid.bytes));
+	deauth_ind = (struct deauth_ind *)msg_ptr;
 
-	sessionId = pDeauthInd->vdev_id;
-	if (!CSR_IS_SESSION_VALID(mac_ctx, sessionId)) {
+	vdev_id = deauth_ind->vdev_id;
+	if (!CSR_IS_SESSION_VALID(mac_ctx, vdev_id)) {
 		sme_err("vdev %d: Invalid session BSSID: " QDF_MAC_ADDR_FMT,
-			pDeauthInd->vdev_id,
-			QDF_MAC_ADDR_REF(pDeauthInd->bssid.bytes));
+			deauth_ind->vdev_id,
+			QDF_MAC_ADDR_REF(deauth_ind->bssid.bytes));
 		return;
 	}
 
-	if (!csr_if_peer_present(mac_ctx, &pDeauthInd->bssid.bytes[0],
-				 &pDeauthInd->peer_macaddr.bytes[0]))
+	if (!csr_if_peer_present(mac_ctx, &deauth_ind->bssid.bytes[0],
+				 &deauth_ind->peer_macaddr.bytes[0]))
 		return;
 
-	if (csr_is_deauth_disassoc_already_active(mac_ctx, sessionId,
-	    pDeauthInd->peer_macaddr))
+	if (csr_is_deauth_disassoc_cmd_active(mac_ctx, vdev_id,
+					      deauth_ind->peer_macaddr,
+					      &deauth_ind->peer_macaddr,
+					      &deauth_ind->peer_mld_addr))
 		return;
-	session = CSR_GET_SESSION(mac_ctx, sessionId);
+
+	session = CSR_GET_SESSION(mac_ctx, vdev_id);
 	if (!session) {
-		sme_err("session %d not found", sessionId);
+		sme_err("vdev %d session not found", vdev_id);
 		return;
 	}
+	sme_debug("vdev %d bssid " QDF_MAC_ADDR_FMT " reason: %d status: %d",
+		  deauth_ind->vdev_id,
+		  QDF_MAC_ADDR_REF(deauth_ind->bssid.bytes),
+		  deauth_ind->reasonCode, deauth_ind->status_code);
 	/* Update the disconnect stats */
-	switch (pDeauthInd->reasonCode) {
+	switch (deauth_ind->reasonCode) {
 	case REASON_DISASSOC_DUE_TO_INACTIVITY:
 		session->disconnect_stats.disconnection_cnt++;
 		session->disconnect_stats.peer_kickout++;
@@ -4184,7 +4230,7 @@ csr_roam_chk_lnk_deauth_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
 		break;
 	}
 
-	csr_roam_issue_wm_status_change(mac_ctx, sessionId,
+	csr_roam_issue_wm_status_change(mac_ctx, vdev_id,
 					eCsrDeauthenticated,
 					msg_ptr);
 }
@@ -5050,7 +5096,8 @@ void csr_clear_sae_single_pmk(struct wlan_objmgr_psoc *psoc,
 		return;
 	}
 
-	if (!(keymgmt & (1 << WLAN_CRYPTO_KEY_MGMT_SAE))) {
+	if (!(QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE) ||
+	      QDF_HAS_PARAM(keymgmt, WLAN_CRYPTO_KEY_MGMT_SAE_EXT_KEY))) {
 		wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_SME_ID);
 		return;
 	}
@@ -5528,7 +5575,8 @@ static void csr_fill_connected_profile(struct mac_context *mac_ctx,
 
 	if (rsp->connect_rsp.is_reassoc ||
 	    csr_is_link_switch_in_progress(vdev))
-		mlme_set_mbssid_info(vdev, &cur_node->entry->mbssid_info);
+		mlme_set_mbssid_info(vdev, &cur_node->entry->mbssid_info,
+				     bss_desc->chan_freq);
 
 	if (bcn_ies->Country.present)
 		qdf_mem_copy(country_code, bcn_ies->Country.country,

+ 15 - 14
core/sme/src/csr/csr_inside_api.h

@@ -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
@@ -374,31 +374,32 @@ QDF_STATUS csr_roam_issue_stop_bss_cmd(struct mac_context *mac, uint8_t vdev_id,
 
 /**
  * csr_roam_issue_disassociate_sta_cmd() - disassociate a associated station
- * @mac:          Pointer to global structure for MAC
- * @sessionId:     Session Id for Soft AP
- * @p_del_sta_params: Pointer to parameters of the station to disassoc
+ * @mac: Pointer to global structure for MAC
+ * @vdev_id: vdev Id for Soft AP
+ * @del_sta_params: Pointer to parameters of the station to disassoc
  *
  * CSR function that HDD calls to issue a deauthenticate station command
  *
  * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_* on error
  */
-QDF_STATUS csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
-					       uint32_t sessionId,
-					       struct csr_del_sta_params
-					       *p_del_sta_params);
+QDF_STATUS
+csr_roam_issue_disassociate_sta_cmd(struct mac_context *mac,
+				    uint8_t vdev_id,
+				    struct csr_del_sta_params *del_sta_params);
 /**
  * csr_roam_issue_deauth_sta_cmd() - issue deauthenticate station command
- * @mac:          Pointer to global structure for MAC
- * @sessionId:     Session Id for Soft AP
- * @pDelStaParams: Pointer to parameters of the station to deauthenticate
+ * @mac: Pointer to global structure for MAC
+ * @vdev_id: vdev Id for Soft AP
+ * @del_sta_params: Pointer to parameters of the station to deauthenticate
  *
  * CSR function that HDD calls to issue a deauthenticate station command
  *
  * Return: QDF_STATUS_SUCCESS on success or another QDF_STATUS_** on error
  */
-QDF_STATUS csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
-		uint32_t sessionId,
-		struct csr_del_sta_params *pDelStaParams);
+QDF_STATUS
+csr_roam_issue_deauth_sta_cmd(struct mac_context *mac,
+			      uint8_t vdev_id,
+			      struct csr_del_sta_params *del_sta_params);
 
 /*
  * csr_send_chng_mcc_beacon_interval() -

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

@@ -555,7 +555,7 @@ static QDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle,
 	QDF_STATUS qdf_status;
 	uint8_t vdev_id = del_vdev_req->vdev_id;
 	struct wma_target_req *msg = NULL;
-	struct del_sta_self_rsp_params *sta_self_wmi_rsp;
+	struct del_sta_self_rsp_params *sta_self_wmi_rsp = NULL;
 
 	wma_debug("P2P Device: removing self peer "QDF_MAC_ADDR_FMT,
 		  QDF_MAC_ADDR_REF(del_vdev_req->self_mac_addr));
@@ -592,7 +592,8 @@ static QDF_STATUS wma_self_peer_remove(tp_wma_handle wma_handle,
 		wma_err("wma_remove_peer is failed");
 		wma_remove_req(wma_handle, vdev_id,
 			       WMA_DEL_P2P_SELF_STA_RSP_START);
-		qdf_mem_free(sta_self_wmi_rsp);
+		if (sta_self_wmi_rsp)
+			qdf_mem_free(sta_self_wmi_rsp);
 
 		goto error;
 	}
@@ -5347,7 +5348,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 				  WMA_VHT_PPS_DELIM_CRC_FAIL, 1);
 	if (wmi_service_enabled(wma->wmi_handle,
 				wmi_service_listen_interval_offload_support)) {
-		struct wlan_objmgr_vdev *vdev;
+		struct wlan_objmgr_vdev *vdev = NULL;
 		uint32_t moddtim;
 		bool is_connection_roaming_cfg_set = 0;
 
@@ -5385,10 +5386,16 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 			wma_debug("failed to send wmi_vdev_param_dyndtim_cnt");
 			goto out;
 		}
+
 		vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc,
 							params->smesessionId,
 							WLAN_LEGACY_WMA_ID);
-		if (!vdev || !ucfg_pmo_get_moddtim_user_enable(vdev)) {
+		if (!vdev) {
+			wma_debug("Invalid vdev");
+			goto out;
+		}
+
+		if (!ucfg_pmo_get_moddtim_user_enable(vdev)) {
 			moddtim = wma->staModDtim;
 			status = mlme_check_index_setparam(
 						setparam,
@@ -5397,15 +5404,9 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 						MAX_VDEV_STA_REQ_PARAMS);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				wma_debug("failed to send wmi_vdev_param_moddtim_cnt");
-				if (vdev)
-					wlan_objmgr_vdev_release_ref(vdev,
-							WLAN_LEGACY_WMA_ID);
-				goto out;
+				goto rel_ref;
 			}
-			if (vdev)
-				wlan_objmgr_vdev_release_ref(vdev,
-							    WLAN_LEGACY_WMA_ID);
-		} else if (vdev && ucfg_pmo_get_moddtim_user_enable(vdev) &&
+		} else if (ucfg_pmo_get_moddtim_user_enable(vdev) &&
 			   !ucfg_pmo_get_moddtim_user_active(vdev)) {
 			moddtim = ucfg_pmo_get_moddtim_user(vdev);
 			status = mlme_check_index_setparam(
@@ -5415,19 +5416,18 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params)
 						MAX_VDEV_STA_REQ_PARAMS);
 			if (QDF_IS_STATUS_ERROR(status)) {
 				wma_debug("failed to send wmi_vdev_param_moddtim_cnt");
-				wlan_objmgr_vdev_release_ref(vdev,
-							WLAN_LEGACY_WMA_ID);
-				goto out;
+				goto rel_ref;
 			}
-			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
 		}
 		status = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM,
 							params->smesessionId,
 							setparam, index);
 		if (QDF_IS_STATUS_ERROR(status)) {
 			wma_err("failed to send DTIM vdev setparams");
-			goto out;
 		}
+rel_ref:
+		if (vdev)
+			wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
 
 	} else {
 		wma_debug("listen interval offload is not set");

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

@@ -5833,7 +5833,7 @@ int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, uint32_t len)
 	tp_wma_handle wma = (tp_wma_handle)handle;
 	WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf;
 	wmi_chan_info_event_fixed_param *event;
-	struct scan_chan_info buf;
+	struct scan_chan_info buf = {0};
 	struct mac_context *mac = NULL;
 	struct channel_status *channel_status;
 	bool snr_monitor_enabled;

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

@@ -879,6 +879,8 @@ void wma_set_sta_keep_alive(tp_wma_handle wma, uint8_t vdev_id,
 			if (method == WMI_KEEP_ALIVE_NULL_PKT)
 				params.method = WMI_KEEP_ALIVE_MGMT_FRAME;
 		}
+
+		wlan_mlme_set_keepalive_period(intr->vdev, params.timeperiod);
 	}
 
 	if (hostv4addr)

+ 3 - 1
core/wma/src/wma_power.c

@@ -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
@@ -1724,6 +1724,8 @@ QDF_STATUS wma_enable_disable_imps(uint32_t pdev_id, uint32_t param_val)
 		wma_err("Unable to enable/disable:(%d) IMPS",
 			param_val);
 
+	wma->in_imps = !!param_val;
+
 	return status;
 }
 #endif /* FEATURE_TX_POWER */

+ 13 - 1
os_if/dp/src/os_if_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 above
@@ -546,6 +546,17 @@ osif_dp_register_arp_unsolicited_cbk(struct wlan_dp_psoc_callbacks *cb_obj)
 #endif
 
 #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41))
+static
+bool osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev, u8 *ta_addr,
+				      qdf_nbuf_t nbuf, bool unencrypted)
+{
+	return cfg80211_rx_control_port((struct net_device *)dev,
+					(struct sk_buff *)nbuf,
+					unencrypted, -1);
+}
+
+#else
 static
 bool osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev, u8 *ta_addr,
 				      qdf_nbuf_t nbuf, bool unencrypted)
@@ -554,6 +565,7 @@ bool osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev, u8 *ta_addr,
 					ta_addr, (struct sk_buff *)nbuf,
 					unencrypted);
 }
+#endif
 
 static void
 osif_dp_register_send_rx_pkt_over_nl(struct wlan_dp_psoc_callbacks *cb_obj)