Forráskód Böngészése

qcacmn: Add support for mlo groups in mlo setup and teardown

Add support for mlo groups in mlo soc/link setup and teardown
sequence participating in mlo.

Change-Id: I2b431b0ee1e5816b92ad183b52ad2998eb5bb46c
CRs-Fixed: 3343170
Surya Prakash Raajen 2 éve
szülő
commit
0fdd53b791

+ 3 - 0
target_if/core/inc/target_if.h

@@ -268,6 +268,8 @@ struct tgt_info {
  * @cfr_support_enable: CFR support enable
  * @set_pktlog_checksum: Set the pktlog checksum from FW ready event to pl_dev
  * @csa_switch_count_status: CSA event handler
+ * @mlo_capable: Checks if the SoC is MLO capable
+ * @mlo_get_group_id: Get the MLO group id of the SoC
  * @mlo_setup_done_event: MLO setup sequence complete event handler
  */
 struct target_ops {
@@ -334,6 +336,7 @@ struct target_ops {
 	void (*ema_init)(struct wlan_objmgr_pdev *pdev);
 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
 	bool (*mlo_capable)(struct wlan_objmgr_psoc *psoc);
+	uint8_t (*mlo_get_group_id)(struct wlan_objmgr_psoc *psoc);
 	void (*mlo_setup_done_event)(struct wlan_objmgr_psoc *psoc);
 #endif
 };

+ 52 - 5
target_if/init_deinit/src/init_event_handler.c

@@ -724,16 +724,44 @@ static bool init_deinit_mlo_capable(struct wlan_objmgr_psoc *psoc)
 	return false;
 }
 
+static bool init_deinit_mlo_get_group_id(struct wlan_objmgr_psoc *psoc,
+					 uint8_t *grp_id)
+{
+	struct target_psoc_info *tgt_hdl;
+
+	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
+	if (!tgt_hdl) {
+		target_if_err("target_psoc_info is null");
+		return false;
+	}
+
+	if ((tgt_hdl->tif_ops) &&
+	    (tgt_hdl->tif_ops->mlo_get_group_id)) {
+		*grp_id = tgt_hdl->tif_ops->mlo_get_group_id(psoc);
+		return true;
+	}
+
+	return false;
+}
+
 static void init_deinit_mlo_update_soc_ready(struct wlan_objmgr_psoc *psoc)
 {
-	if (init_deinit_mlo_capable(psoc))
-		mlo_setup_update_soc_ready(psoc);
+	uint8_t grp_id = 0;
+
+	if (init_deinit_mlo_capable(psoc)) {
+		if (!init_deinit_mlo_get_group_id(psoc, &grp_id)) {
+			target_if_err("Invalid MLD group id");
+			return;
+		}
+		mlo_setup_update_soc_ready(psoc, grp_id);
+	}
 }
 
 static void init_deinit_send_ml_link_ready(struct wlan_objmgr_psoc *psoc,
 					   void *object, void *arg)
 {
 	struct wlan_objmgr_pdev *pdev = object;
+	uint8_t grp_id = 0;
 
 	if (!init_deinit_mlo_capable(psoc))
 		return;
@@ -741,7 +769,10 @@ static void init_deinit_send_ml_link_ready(struct wlan_objmgr_psoc *psoc,
 	qdf_assert_always(psoc);
 	qdf_assert_always(pdev);
 
-	mlo_setup_link_ready(pdev);
+	if (!init_deinit_mlo_get_group_id(psoc, &grp_id))
+		qdf_assert_always(grp_id);
+
+	mlo_setup_link_ready(pdev, grp_id);
 }
 
 static void init_deinit_mlo_update_pdev_ready(struct wlan_objmgr_psoc *psoc,
@@ -1043,6 +1074,7 @@ static int init_deinit_mlo_setup_comp_event_handler(ol_scn_t scn_handle,
 	struct target_psoc_info *tgt_hdl;
 	struct wmi_unified *wmi_handle;
 	struct wmi_mlo_setup_complete_params params;
+	uint8_t grp_id = 0;
 
 	if (!scn_handle) {
 		target_if_err("scn handle NULL");
@@ -1050,16 +1082,24 @@ static int init_deinit_mlo_setup_comp_event_handler(ol_scn_t scn_handle,
 	}
 
 	psoc = target_if_get_psoc_from_scn_hdl(scn_handle);
+
 	if (!psoc) {
 		target_if_err("psoc is null");
 		return -EINVAL;
 	}
 
+	if (!init_deinit_mlo_get_group_id(psoc, &grp_id)) {
+		target_if_err("Invalid MLD group id");
+		return -EINVAL;
+	}
+
 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
+
 	if (!tgt_hdl) {
 		target_if_err("target_psoc_info is null");
 		return -EINVAL;
 	}
+
 	wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl);
 
 	if (wmi_extract_mlo_setup_cmpl_event(wmi_handle, event, &params) !=
@@ -1068,8 +1108,9 @@ static int init_deinit_mlo_setup_comp_event_handler(ol_scn_t scn_handle,
 
 	pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id,
 					  WLAN_INIT_DEINIT_ID);
+
 	if (pdev) {
-		mlo_link_setup_complete(pdev);
+		mlo_link_setup_complete(pdev, grp_id);
 		wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID);
 	}
 
@@ -1087,6 +1128,7 @@ static int init_deinit_mlo_teardown_comp_event_handler(ol_scn_t scn_handle,
 	struct target_psoc_info *tgt_hdl;
 	struct wmi_unified *wmi_handle;
 	struct wmi_mlo_teardown_cmpl_params params;
+	uint8_t grp_id = 0;
 
 	if (!scn_handle) {
 		target_if_err("scn handle NULL");
@@ -1099,6 +1141,11 @@ static int init_deinit_mlo_teardown_comp_event_handler(ol_scn_t scn_handle,
 		return -EINVAL;
 	}
 
+	if (!init_deinit_mlo_get_group_id(psoc, &grp_id)) {
+		target_if_err("Invalid MLD group id");
+		return -EINVAL;
+	}
+
 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
 	if (!tgt_hdl) {
 		target_if_err("target_psoc_info is null");
@@ -1113,7 +1160,7 @@ static int init_deinit_mlo_teardown_comp_event_handler(ol_scn_t scn_handle,
 	pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id,
 					  WLAN_INIT_DEINIT_ID);
 	if (pdev) {
-		mlo_link_teardown_complete(pdev);
+		mlo_link_teardown_complete(pdev, grp_id);
 		wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID);
 	}
 

+ 1 - 1
target_if/mgmt_txrx/src/target_if_mgmt_txrx_rx_reo.c

@@ -28,7 +28,7 @@
 #include <target_if_mgmt_txrx_rx_reo.h>
 #include <wlan_lmac_if_api.h>
 #include <init_deinit_lmac.h>
-
+#include <wlan_mlo_mgr_setup.h>
 /**
  * target_if_mgmt_rx_reo_fw_consumed_event_handler() - WMI event handler to
  * process MGMT Rx FW consumed event handler

+ 25 - 9
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_rx_reo.c

@@ -25,6 +25,7 @@
 #include "wlan_mgmt_txrx_main_i.h"
 #include <qdf_util.h>
 #include <wlan_mlo_mgr_cmn.h>
+#include <wlan_mlo_mgr_setup.h>
 
 static struct mgmt_rx_reo_context *g_rx_reo_ctx;
 
@@ -170,6 +171,7 @@ mgmt_rx_reo_validate_mlo_link_info(struct wlan_objmgr_psoc *psoc)
 	uint16_t valid_link_bitmap;
 	int8_t num_active_links_shmem;
 	int8_t num_active_links;
+	uint8_t grp_id = 0;
 	QDF_STATUS status;
 
 	if (!psoc) {
@@ -188,7 +190,12 @@ mgmt_rx_reo_validate_mlo_link_info(struct wlan_objmgr_psoc *psoc)
 	}
 	qdf_assert_always(num_active_links_shmem > 0);
 
-	num_active_links = wlan_mlo_get_num_active_links();
+	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
+		mgmt_rx_reo_err("Failed to get valid MLO Group id");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	num_active_links = wlan_mlo_get_num_active_links(grp_id);
 	qdf_assert_always(num_active_links > 0);
 
 	qdf_assert_always(num_active_links_shmem == num_active_links);
@@ -201,7 +208,7 @@ mgmt_rx_reo_validate_mlo_link_info(struct wlan_objmgr_psoc *psoc)
 	}
 	qdf_assert_always(valid_link_bitmap_shmem != 0);
 
-	valid_link_bitmap = wlan_mlo_get_valid_link_bitmap();
+	valid_link_bitmap = wlan_mlo_get_valid_link_bitmap(grp_id);
 	qdf_assert_always(valid_link_bitmap_shmem != 0);
 
 	qdf_assert_always(valid_link_bitmap_shmem == valid_link_bitmap);
@@ -212,11 +219,13 @@ mgmt_rx_reo_validate_mlo_link_info(struct wlan_objmgr_psoc *psoc)
 #ifndef WLAN_MGMT_RX_REO_SIM_SUPPORT
 /**
  * mgmt_rx_reo_is_valid_link() - Check whether the given HW link is valid
+ * @link_id: Link id to be checked
+ * @grp_id: MLO Group id which it belongs to
  *
  * Return: true if @link_id is a valid link else false
  */
 static bool
-mgmt_rx_reo_is_valid_link(uint8_t link_id)
+mgmt_rx_reo_is_valid_link(uint8_t link_id, uint8_t grp_id)
 {
 	uint16_t valid_hw_link_bitmap;
 
@@ -225,7 +234,7 @@ mgmt_rx_reo_is_valid_link(uint8_t link_id)
 		return false;
 	}
 
-	valid_hw_link_bitmap = wlan_mlo_get_valid_link_bitmap();
+	valid_hw_link_bitmap = wlan_mlo_get_valid_link_bitmap(grp_id);
 	qdf_assert_always(valid_hw_link_bitmap);
 
 	return (valid_hw_link_bitmap & (1 << link_id));
@@ -235,18 +244,21 @@ mgmt_rx_reo_is_valid_link(uint8_t link_id)
  * mgmt_rx_reo_get_num_mlo_links() - Get number of MLO HW links active in the
  * system
  * @reo_context: Pointer to reo context object
+ * @grp_id: MLO group id which it belongs to
  *
  * Return: On success returns number of active MLO HW links. On failure
  * returns WLAN_MLO_INVALID_NUM_LINKS.
  */
 static int8_t
-mgmt_rx_reo_get_num_mlo_links(struct mgmt_rx_reo_context *reo_context) {
+mgmt_rx_reo_get_num_mlo_links(struct mgmt_rx_reo_context *reo_context,
+			      uint8_t grp_id)
+{
 	if (!reo_context) {
 		mgmt_rx_reo_err("Mgmt reo context is null");
 		return WLAN_MLO_INVALID_NUM_LINKS;
 	}
 
-	return wlan_mlo_get_num_active_links();
+	return wlan_mlo_get_num_active_links(grp_id);
 }
 
 static QDF_STATUS
@@ -356,7 +368,9 @@ mgmt_rx_reo_sim_get_num_mlo_links(struct mgmt_rx_reo_sim_context *sim_context)
  * returns WLAN_MLO_INVALID_NUM_LINKS.
  */
 static int8_t
-mgmt_rx_reo_get_num_mlo_links(struct mgmt_rx_reo_context *reo_context) {
+mgmt_rx_reo_get_num_mlo_links(struct mgmt_rx_reo_context *reo_context,
+			      uint8_t grp_id)
+{
 	if (!reo_context) {
 		mgmt_rx_reo_err("Mgmt reo context is null");
 		return WLAN_MLO_INVALID_NUM_LINKS;
@@ -987,6 +1001,7 @@ wlan_mgmt_rx_reo_algo_calculate_wait_count(
 {
 	QDF_STATUS status;
 	uint8_t link;
+	int8_t grp_id;
 	int8_t in_frame_link;
 	int frames_pending, delta_fwd_host;
 	uint8_t snapshot_id;
@@ -1026,9 +1041,10 @@ wlan_mgmt_rx_reo_algo_calculate_wait_count(
 
 	/* Get the MLO link ID of incoming frame */
 	in_frame_link = wlan_get_mlo_link_id_from_pdev(in_frame_pdev);
+	grp_id = wlan_get_mlo_grp_id_from_pdev(in_frame_pdev);
 	qdf_assert_always(in_frame_link >= 0);
 	qdf_assert_always(in_frame_link < MAX_MLO_LINKS);
-	qdf_assert_always(mgmt_rx_reo_is_valid_link(in_frame_link));
+	qdf_assert_always(mgmt_rx_reo_is_valid_link(in_frame_link, grp_id));
 
 	in_frame_rx_reo_pdev_ctx =
 			wlan_mgmt_rx_reo_get_priv_object(in_frame_pdev);
@@ -1042,7 +1058,7 @@ wlan_mgmt_rx_reo_algo_calculate_wait_count(
 	/* Iterate over all the valid MLO links */
 	for (link = 0; link < MAX_MLO_LINKS; link++) {
 		/* No need wait for any frames on an invalid link */
-		if (!mgmt_rx_reo_is_valid_link(link)) {
+		if (!mgmt_rx_reo_is_valid_link(link, grp_id)) {
 			frames_pending = 0;
 			goto update_pending_frames;
 		}

+ 11 - 0
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_rx_reo_utils_api.h

@@ -41,6 +41,17 @@ struct mgmt_txrx_priv_pdev_context;
 int8_t
 wlan_get_mlo_link_id_from_pdev(struct wlan_objmgr_pdev *pdev);
 
+/**
+ * wlan_get_mlo_grp_id_from_pdev() - Helper API to get the MLO Group id
+ * from the pdev object.
+ * @pdev: Pointer to pdev object
+ *
+ * Return: On success returns the MLO Group id corresponding to the pdev
+ * object. On failure returns -1.
+ */
+int8_t
+wlan_get_mlo_grp_id_from_pdev(struct wlan_objmgr_pdev *pdev);
+
 /**
  * wlan_get_pdev_from_mlo_link_id() - Helper API to get the pdev
  * object from the link id.

+ 17 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_rx_reo_utils_api.c

@@ -27,6 +27,7 @@
 #include <wlan_mgmt_txrx_tgt_api.h>
 #include<wlan_mgmt_txrx_rx_reo_tgt_api.h>
 #include <wlan_mlo_mgr_cmn.h>
+#include <wlan_mlo_mgr_setup.h>
 
 QDF_STATUS
 wlan_mgmt_rx_reo_deinit(void)
@@ -83,6 +84,22 @@ wlan_get_mlo_link_id_from_pdev(struct wlan_objmgr_pdev *pdev)
 
 qdf_export_symbol(wlan_get_mlo_link_id_from_pdev);
 
+int8_t
+wlan_get_mlo_grp_id_from_pdev(struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_objmgr_psoc *psoc = wlan_pdev_get_psoc(pdev);
+	uint8_t grp_id;
+
+	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
+		mgmt_rx_reo_err("Failed to get valid MLO Group id");
+		return -EINVAL;
+	}
+
+	return grp_id;
+}
+
+qdf_export_symbol(wlan_get_mlo_grp_id_from_pdev);
+
 /**
  * wlan_get_pdev_from_mlo_link_id() - Helper API to get the pdev
  * object from the MLO HW link id.

+ 9 - 6
umac/mlo_mgr/inc/wlan_mlo_mgr_cmn.h

@@ -304,27 +304,30 @@ void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev,
 /**
  * wlan_mlo_get_max_num_links() - Get the maximum number of MLO links
  * possible in the system
+ * @grp_id: Id of the required MLO Group
  *
  * Return: Maximum number of MLO links in the system
  */
-int8_t wlan_mlo_get_max_num_links(void);
+int8_t wlan_mlo_get_max_num_links(uint8_t grp_id);
 
 /**
  * wlan_mlo_get_num_active_links() - Get the number of active MLO links
  * in the system
+ * @grp_id: Id of the required MLO Group
  *
  * Return: Number of active MLO links in the system
  */
-int8_t wlan_mlo_get_num_active_links(void);
+int8_t wlan_mlo_get_num_active_links(uint8_t grp_id);
 
 /**
  * wlan_mlo_get_valid_link_bitmap() - Get the bitmap indicating the valid
  * MLO links in the system. If bit position i is set, link with id i is
  * valid.
+ * @grp_id: Id of the required MLO Group
  *
  * Return: Valid link bitmap
  */
-uint16_t wlan_mlo_get_valid_link_bitmap(void);
+uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id);
 
 /**
  * wlan_mlo_get_pdev_hw_link_id() - Get hw_link_id of pdev
@@ -363,19 +366,19 @@ wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,
 
 #else
 static inline int8_t
-wlan_mlo_get_max_num_links(void)
+wlan_mlo_get_max_num_links(uint8_t grp_id)
 {
 	return WLAN_MLO_INVALID_NUM_LINKS;
 }
 
 static inline int8_t
-wlan_mlo_get_num_active_links(void)
+wlan_mlo_get_num_active_links(uint8_t grp_id)
 {
 	return WLAN_MLO_INVALID_NUM_LINKS;
 }
 
 static inline uint16_t
-wlan_mlo_get_valid_link_bitmap(void)
+wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)
 {
 	return 0;
 }

+ 36 - 11
umac/mlo_mgr/inc/wlan_mlo_mgr_public_structs.h

@@ -69,13 +69,18 @@ struct wlan_t2lm_context;
 #define PER_STA_PROF_MAC_ADDR_START 4
 
 #ifdef WLAN_MLO_MULTI_CHIP
-/*
+
+#ifndef WLAN_MAX_MLO_GROUPS
+#define WLAN_MAX_MLO_GROUPS 2
+#endif
+
+/**
  * enum MLO_LINK_STATE – MLO link state enums
- * @MLO_LINK_SETUP_INIT - MLO link SETUP exchange not yet done
- * @MLO_LINK_SETUP_DONE - MLO link SETUP exchange started
- * @MLO_LINK_READY - MLO link SETUP done and READY sent
- * @MLO_LINK_TEARDOWN - MLO teardown done.
- * @MLO_LINK_UNINITIALIZED - MLO link in blank state
+ * @MLO_LINK_SETUP_INIT: MLO link SETUP exchange not yet done
+ * @MLO_LINK_SETUP_DONE: MLO link SETUP exchange started
+ * @MLO_LINK_READY: MLO link SETUP done and READY sent
+ * @MLO_LINK_TEARDOWN: MLO teardown done.
+ * @MLO_LINK_UNINITIALIZED: MLO link in blank state
  */
 enum MLO_LINK_STATE {
 	MLO_LINK_SETUP_INIT,
@@ -85,6 +90,19 @@ enum MLO_LINK_STATE {
 	MLO_LINK_UNINITIALIZED,
 };
 
+/**
+ * enum MLO_SOC_LIST – MLO SOC LIST
+ * @WLAN_MLO_GROUP_DEFAULT_SOC_LIST:  All MLO SoCs that are part of this MLO
+ *                                    group, (inclusive of both setup sequence
+ *                                    completed, not yet completed)
+ * @WLAN_MLO_GROUP_CURRENT_SOC_LIST:  Current MLO SoCs that are probed for which
+ *                                    the setup sequence has been completed
+ */
+enum MLO_SOC_LIST {
+	WLAN_MLO_GROUP_DEFAULT_SOC_LIST,
+	WLAN_MLO_GROUP_CURRENT_SOC_LIST,
+};
+
 /**
  * struct mlo_setup_info: MLO setup status per link
  * @ml_grp_id: Unique id for ML grouping of Pdevs/links
@@ -92,8 +110,10 @@ enum MLO_LINK_STATE {
  * @num_soc: Number of soc ready or probed
  * @tot_links: Total links in ML group
  * @num_links: Number of links probed in ML group
- * @pdev_list[MAX_MLO_LINKS]: pdev pointers belonging to this group
- * @soc_list[MAX_MLO_CHIPS]: psoc pointers belonging to this group
+ * @pdev_list: current pdev pointers belonging to this group
+ * @soc_list: current psoc pointers belonging to this group
+ * @soc_list: Actual psoc pointers part of this group
+ * @soc_id_list: list of soc ids part of this mlo group
  * @state[MAX_MLO_LINKS]: MLO link state
  * @valid_link_bitmap: valid MLO link bitmap
  * @state_lock: lock to protect access to link state
@@ -109,7 +129,9 @@ struct mlo_setup_info {
 	uint8_t tot_links;
 	uint8_t num_links;
 	struct wlan_objmgr_pdev *pdev_list[MAX_MLO_LINKS];
+	struct wlan_objmgr_psoc *curr_soc_list[MAX_MLO_CHIPS];
 	struct wlan_objmgr_psoc *soc_list[MAX_MLO_CHIPS];
+	uint8_t soc_id_list[MAX_MLO_CHIPS];
 	enum MLO_LINK_STATE state[MAX_MLO_LINKS];
 	uint16_t valid_link_bitmap;
 	qdf_spinlock_t state_lock;
@@ -121,13 +143,14 @@ struct mlo_setup_info {
  * struct mlo_state_params: MLO state params for pdev iteration
  * @link_state_fail: Flag to check when pdev not in expected state
  * @check_state: State on against which pdev is to be expected
+ * @grp_id: Id of the required MLO Group
  */
 struct mlo_state_params {
 	bool link_state_fail;
 	enum MLO_LINK_STATE check_state;
+	uint8_t grp_id;
 };
 
-#define MAX_MLO_GROUP 1
 #endif
 
 /*
@@ -138,7 +161,8 @@ struct mlo_state_params {
  * @context: Array of MLO device context
  * @mlo_peer_id_bmap: bitmap to allocate MLO Peer ID
  * @max_mlo_peer_id: Max MLO Peer ID
- * @info: MLO setup info
+ * @info: Pointer to MLO setup_info of all groups
+ * @total_grp: Total number of MLO groups
  * @mlme_ops: MLO MLME callback function pointers
  * @msgq_ctx: Context switch mgr
  * @mlo_is_force_primary_umac: Force Primary UMAC enable
@@ -158,7 +182,8 @@ struct mlo_mgr_context {
 	qdf_bitmap(mlo_peer_id_bmap, MAX_MLO_PEER_ID);
 	uint16_t max_mlo_peer_id;
 #ifdef WLAN_MLO_MULTI_CHIP
-	struct mlo_setup_info setup_info;
+	struct mlo_setup_info *setup_info;
+	uint8_t total_grp;
 #endif
 	struct mlo_mlme_ext_ops *mlme_ops;
 	struct ctxt_switch_mgr *msgq_ctx;

+ 60 - 12
umac/mlo_mgr/inc/wlan_mlo_mgr_setup.h

@@ -20,12 +20,14 @@
 #ifndef _WLAN_MLO_MGR_SETUP_H_
 #define _WLAN_MLO_MGR_SETUP_H_
 #ifdef WLAN_MLO_MULTI_CHIP
+
 /**
  * mlo_setup_init() - API to init setup info events
+ * @total_grp: Total number of MLO groups
  *
  * Return: None
  */
-void mlo_setup_init(void);
+void mlo_setup_init(uint8_t total_grp);
 
 /**
  * mlo_setup_deinit() - API to deinit setup info events
@@ -37,96 +39,140 @@ void mlo_setup_deinit(void);
 /**
  * mlo_is_ml_soc() - API to check if psoc belongs to ML group
  * @psoc: Soc to be checked.
+ * @grp_id: ID of the required mlo group
  *
  * Return: true if psoc found in ml soc_list, or else return false
  */
-bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc);
+bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc, uint8_t grp_id);
 
 /**
  * mlo_get_soc_list() - API to get the list of SOCs participating in MLO
  * @soc_list: list where ML participating SOCs need to be populated
+ * @grp_id: ID of the required mlo group
+ * @tot_socs: Total number of socs, for which soc list is allocated
+ * @curr: Flag to get the current psoc list or actual psoc list
+ *
+ * Return: None
+ */
+void mlo_get_soc_list(struct wlan_objmgr_psoc **soc_list, uint8_t grp_id,
+		      uint8_t tot_socs, enum MLO_SOC_LIST curr);
+
+/**
+ * mlo_setup_update_soc_id_list() - API to update the list of SOCs ids
+ *                                  participating in that MLO group
+ * @grp_id: ID of the required mlo group
+ * @soc_list: soc ids part of that MLO group
  *
  * Return: None
  */
-void mlo_get_soc_list(struct wlan_objmgr_psoc **soc_list);
+void mlo_setup_update_soc_id_list(uint8_t grp_id, uint8_t *soc_id_list);
+
+/**
+ * mlo_psoc_get_grp_id() - API to get the MLO group id of the SoC
+ * @psoc: Required psoc pointer
+ * @grp_id: MLO Group id will be stored in here
+ *
+ * Return: bool: if valid group id true, else false
+ */
+bool mlo_psoc_get_grp_id(struct wlan_objmgr_psoc *psoc, uint8_t *grp_id);
 
 /**
  * mlo_cleanup_asserted_soc_setup_info() - API to cleanup the mlo setup info of
  * asserted soc
  * @psoc: Soc to be cleaned up
+ * @grp_id: ID of the required mlo group
  *
  * Return: None
  */
-void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc);
+void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc,
+					 uint8_t grp_id);
 
 /**
  * mlo_setup_update_total_socs() - API to update total socs for mlo
+ * @grp_id: ID of the required mlo group
  * @tot_socs: Total socs
  *
  * Return: None.
  */
-void mlo_setup_update_total_socs(uint8_t tot_socs);
+void mlo_setup_update_total_socs(uint8_t grp_id, uint8_t tot_socs);
+
+/**
+ * mlo_setup_get_total_socs() - API to get total socs for mlo group
+ * @grp_id: ID of the required mlo group
+ *
+ * Return: uint8_t, Number of total socs
+ */
+uint8_t mlo_setup_get_total_socs(uint8_t grp_id);
 
 /**
  * mlo_setup_update_num_links() - API to update num links in soc for mlo
  * @soc_id: soc object of SoC corresponding to num_link
+ * @grp_id: ID of the required mlo group
  * @num_links: Number of links in that soc
  *
  * Return: None.
  */
 void mlo_setup_update_num_links(struct wlan_objmgr_psoc *psoc,
+				uint8_t grp_id,
 				uint8_t num_links);
 
 /**
  * mlo_setup_update_soc_ready() - API to notify when FW init done
  * @psoc: soc object of SoC ready
+ * @grp_id: ID of the required mlo group
  *
  * Return: None.
  */
-void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc);
+void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc, uint8_t grp_id);
 
 /**
  * mlo_setup_link_ready() - API to notify link ready
  * @pdev: Pointer to pdev object
+ * @grp_id: ID of the required mlo group
  *
  * Return: None.
  */
-void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev);
+void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev, uint8_t grp_id);
 
 /**
  * mlo_link_setup_complete() - API to notify setup complete
  * @pdev: Pointer to pdev object
+ * @grp_id: ID of the required mlo group
  *
  * Return: None.
  */
-void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev);
+void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id);
 
 /**
  * mlo_link_teardown_complete() - API to notify teardown complete
  * @pdev: Pointer to pdev object
+ * @grp_id: ID of the required mlo group
  *
  * Return: None.
  */
-void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev);
+void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id);
 
 /**
  * mlo_setup_update_soc_down() - API to check and clear all links and bring
  *                               back to initial state for the particular soc
  *
- * @pdev: Pointer to pdev object
+ * @psoc: Pointer to psoc object
+ * @grp_id: ID of the required mlo group
  *
  * Return: None.
  */
-void mlo_setup_update_soc_down(struct wlan_objmgr_psoc *psoc);
+void mlo_setup_update_soc_down(struct wlan_objmgr_psoc *psoc, uint8_t grp_id);
 
 /**
  * mlo_link_teardown_link() - API to trigger teardown
  * @psoc: Pointer to psoc object
+ * @grp_id: ID of the required mlo group
  * @reason: Reason code for MLO tear down
  *
  * Return: QDF_STATUS - success / failure.
  */
 QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
+				  uint8_t grp_id,
 				  uint32_t reason);
 
 /**
@@ -145,14 +191,16 @@ bool mlo_vdevs_check_single_soc(struct wlan_objmgr_vdev **wlan_vdev_list,
  *                              are on the same expected state.
  *
  * @psoc: Pointer to psoc object
+ * @grp_id: ID of the required mlo group
  * @state: Expected link state to be verified
  *
  * Return: QDF_STATUS: QDF_STATUS_SUCCESS if all belongs to same state
  */
 QDF_STATUS mlo_check_all_pdev_state(struct wlan_objmgr_psoc *psoc,
+				    uint8_t grp_id,
 				    enum MLO_LINK_STATE state);
 #else
-static inline void mlo_setup_init(void)
+static inline void mlo_setup_init(uint8_t total_grp)
 {
 }
 

+ 26 - 6
umac/mlo_mgr/src/wlan_mlo_mgr_cmn.c

@@ -301,7 +301,7 @@ uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev,
 }
 
 #ifdef WLAN_MLO_MULTI_CHIP
-int8_t wlan_mlo_get_max_num_links(void)
+int8_t wlan_mlo_get_max_num_links(uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx;
 
@@ -309,21 +309,35 @@ int8_t wlan_mlo_get_max_num_links(void)
 	if (!mlo_ctx)
 		return WLAN_MLO_INVALID_NUM_LINKS;
 
-	return mlo_ctx->setup_info.tot_socs * WLAN_MAX_MLO_LINKS_PER_SOC;
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return WLAN_MLO_INVALID_NUM_LINKS;
+	}
+
+	return (mlo_ctx->setup_info[grp_id].tot_socs *
+		WLAN_MAX_MLO_LINKS_PER_SOC);
 }
 
-int8_t wlan_mlo_get_num_active_links(void)
+int8_t wlan_mlo_get_num_active_links(uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx;
 
 	mlo_ctx = wlan_objmgr_get_mlo_ctx();
+
 	if (!mlo_ctx)
 		return WLAN_MLO_INVALID_NUM_LINKS;
 
-	return mlo_ctx->setup_info.tot_links;
+	if (grp_id >= mlo_ctx->total_grp) {
+		qdf_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return WLAN_MLO_INVALID_NUM_LINKS;
+	}
+
+	return mlo_ctx->setup_info[grp_id].tot_links;
 }
 
-uint16_t wlan_mlo_get_valid_link_bitmap(void)
+uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx;
 
@@ -331,7 +345,13 @@ uint16_t wlan_mlo_get_valid_link_bitmap(void)
 	if (!mlo_ctx)
 		return 0;
 
-	return mlo_ctx->setup_info.valid_link_bitmap;
+	if (grp_id >= mlo_ctx->total_grp) {
+		qdf_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return 0;
+	}
+
+	return mlo_ctx->setup_info[grp_id].valid_link_bitmap;
 }
 
 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev)

+ 54 - 5
umac/mlo_mgr/src/wlan_mlo_mgr_main.c

@@ -77,7 +77,6 @@ static void mlo_global_ctx_init(void)
 	ml_aid_lock_create(mlo_mgr_ctx);
 	mlo_mgr_ctx->mlo_is_force_primary_umac = 0;
 	mlo_msgq_init();
-	mlo_setup_init();
 }
 
 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc)
@@ -376,13 +375,19 @@ static inline
 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
 			       struct wlan_objmgr_vdev *vdev)
 {
-	struct wlan_objmgr_pdev *pdev = NULL;
-	struct wlan_objmgr_psoc *psoc = NULL;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_psoc *psoc;
+	uint8_t grp_id = 0;
 
 	pdev = wlan_vdev_get_pdev(vdev);
 
 	psoc = wlan_pdev_get_psoc(ref_pdev);
-	if (mlo_check_all_pdev_state(psoc, MLO_LINK_SETUP_DONE)) {
+	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
+		mlo_err("Unable to get the MLO Group ID for the vdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) {
 		mlo_err("Pdev link is not in ready state, initial link setup failed");
 		return QDF_STATUS_E_FAILURE;
 	}
@@ -395,6 +400,27 @@ QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
 	return QDF_STATUS_SUCCESS;
 }
 
+static inline
+QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
+				 struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_objmgr_psoc *psoc;
+	uint8_t grp_id = 0;
+
+	psoc = wlan_vdev_get_psoc(vdev);
+	if (!mlo_psoc_get_grp_id(psoc, &grp_id)) {
+		mlo_err("Unable to get mlo group id");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	if (grp_id != ref_id) {
+		mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 static inline
 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev,
 				struct wlan_objmgr_vdev *vdev)
@@ -422,6 +448,13 @@ QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev,
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+static inline
+QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id,
+				 struct wlan_objmgr_vdev *vdev)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif
 
 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
@@ -429,7 +462,9 @@ QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
 				       enum QDF_OPMODE opmode)
 {
 	uint32_t id = 0;
-	struct wlan_objmgr_vdev *vdev = NULL;
+	uint8_t ref_id = 0;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_psoc *psoc;
 
 	if (!ml_dev)
 		return QDF_STATUS_E_FAILURE;
@@ -437,6 +472,15 @@ QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
 	if (!pdev)
 		return QDF_STATUS_E_FAILURE;
 
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc)
+		return QDF_STATUS_E_FAILURE;
+
+	if (!mlo_psoc_get_grp_id(psoc, &ref_id)) {
+		mlo_err("Unable to get mlo group id");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	mlo_dev_lock_acquire(ml_dev);
 	while (id < WLAN_UMAC_MLO_MAX_VDEVS) {
 		vdev = ml_dev->wlan_vdev_list[id];
@@ -453,6 +497,11 @@ QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev,
 				mlo_dev_lock_release(ml_dev);
 				return QDF_STATUS_E_FAILURE;
 			}
+
+			if (wlan_mlo_check_grp_id(ref_id, vdev)) {
+				mlo_dev_lock_release(ml_dev);
+				return QDF_STATUS_E_FAILURE;
+			}
 		}
 		id++;
 	}

+ 520 - 144
umac/mlo_mgr/src/wlan_mlo_mgr_setup.c

@@ -25,16 +25,97 @@
 #include <wlan_mgmt_txrx_rx_reo_utils_api.h>
 
 #ifdef WLAN_MLO_MULTI_CHIP
-bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc)
+static inline
+bool mlo_psoc_get_index_id(struct wlan_objmgr_psoc *psoc,
+			   uint8_t grp_id,
+			   uint8_t *index,
+			   bool teardown)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
-	uint8_t chip_idx;
+	uint8_t id;
+
+	if (!mlo_ctx)
+		return false;
+
+	if (!psoc)
+		return false;
+
+	if (!index)
+		return false;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return false;
+	}
+
+	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
+		if (mlo_ctx->setup_info[grp_id].curr_soc_list[id] == psoc) {
+			*index = id;
+			return true;
+		}
+
+	if (teardown)
+		return false;
+
+	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
+		if (!mlo_ctx->setup_info[grp_id].curr_soc_list[id]) {
+			*index = id;
+			return true;
+		}
+
+	return false;
+}
+
+bool mlo_psoc_get_grp_id(struct wlan_objmgr_psoc *psoc, uint8_t *ret_id)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t grp_id;
+	uint8_t tot_socs;
+	uint8_t id;
 
 	if (!mlo_ctx)
 		return false;
 
-	for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++)
-		if (mlo_ctx->setup_info.soc_list[chip_idx] == psoc)
+	if (!psoc)
+		return false;
+
+	if (!ret_id)
+		return false;
+
+	for (grp_id = 0; grp_id < mlo_ctx->total_grp; grp_id++) {
+		tot_socs = mlo_ctx->setup_info[grp_id].tot_socs;
+		for (id = 0; id < tot_socs; id++)
+			if (mlo_ctx->setup_info[grp_id].soc_list[id] == psoc) {
+				*ret_id = grp_id;
+				return true;
+			}
+	}
+
+	return false;
+}
+
+qdf_export_symbol(mlo_psoc_get_grp_id);
+
+bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t id;
+
+	if (!mlo_ctx)
+		return false;
+
+	if (!psoc)
+		return false;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return false;
+	}
+
+	for (id = 0; id < mlo_ctx->setup_info[grp_id].tot_socs; id++)
+		if (mlo_ctx->setup_info[grp_id].curr_soc_list[id] == psoc)
 			return true;
 
 	return false;
@@ -42,49 +123,113 @@ bool mlo_is_ml_soc(struct wlan_objmgr_psoc *psoc)
 
 qdf_export_symbol(mlo_is_ml_soc);
 
-void mlo_get_soc_list(struct wlan_objmgr_psoc **soc_list)
+static void mlo_set_soc_list(uint8_t grp_id, struct wlan_objmgr_psoc *psoc)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
-	uint8_t chip_idx;
+	uint8_t idx;
 
-	if (!mlo_ctx) {
-		for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++)
-			soc_list[chip_idx] = NULL;
+	if (!mlo_ctx)
+		return;
+
+	if (!psoc)
+		return;
 
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
 		return;
 	}
 
-	for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++)
-		soc_list[chip_idx] = mlo_ctx->setup_info.soc_list[chip_idx];
+	for (idx = 0; idx < mlo_ctx->setup_info[grp_id].tot_socs; idx++) {
+		if (mlo_ctx->setup_info[grp_id].soc_id_list[idx] ==
+				psoc->soc_objmgr.psoc_id) {
+			mlo_ctx->setup_info[grp_id].soc_list[idx] = psoc;
+		}
+	}
+}
+
+void mlo_get_soc_list(struct wlan_objmgr_psoc **soc_list,
+		      uint8_t grp_id,
+		      uint8_t total_socs,
+		      enum MLO_SOC_LIST curr)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t chip_idx;
+
+	if (!mlo_ctx)
+		goto err_case;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		goto err_case;
+	}
+
+	if (total_socs != mlo_ctx->setup_info[grp_id].tot_socs) {
+		mlo_err("Mismatch in number of socs in the grp id %d, expected %d observed %d",
+			grp_id, total_socs,
+			mlo_ctx->setup_info[grp_id].tot_socs);
+		goto err_case;
+	}
+
+	if (curr == WLAN_MLO_GROUP_CURRENT_SOC_LIST) {
+		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
+			soc_list[chip_idx] =
+			mlo_ctx->setup_info[grp_id].curr_soc_list[chip_idx];
+	} else {
+		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
+			soc_list[chip_idx] =
+				mlo_ctx->setup_info[grp_id].soc_list[chip_idx];
+	}
+
+	return;
+
+err_case:
+		for (chip_idx = 0; chip_idx < total_socs; chip_idx++)
+			soc_list[chip_idx] = NULL;
+
+		return;
 }
 
 qdf_export_symbol(mlo_get_soc_list);
 
-void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc)
+void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc,
+					 uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 	uint8_t link_idx;
 	struct wlan_objmgr_pdev *pdev;
+	struct mlo_setup_info *setup_info;
 
 	if (!mlo_ctx)
 		return;
 
-	if (!mlo_ctx->setup_info.num_links)
+	if (!psoc)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	if (!setup_info->num_links)
 		return;
 
 	if (!psoc) {
-		qdf_info("NULL psoc");
+		mlo_info("NULL psoc");
 		return;
 	}
 
 	for (link_idx = 0; link_idx < MAX_MLO_LINKS; link_idx++) {
-		pdev = mlo_ctx->setup_info.pdev_list[link_idx];
+		pdev = setup_info->pdev_list[link_idx];
 		if (pdev) {
 			if (wlan_pdev_get_psoc(pdev) == psoc) {
-				mlo_ctx->setup_info.pdev_list[link_idx] = NULL;
-				mlo_ctx->setup_info.state[link_idx] =
-					MLO_LINK_TEARDOWN;
-				mlo_ctx->setup_info.num_links--;
+				setup_info->pdev_list[link_idx] = NULL;
+				setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
+				setup_info->num_links--;
 			}
 		}
 	}
@@ -92,20 +237,70 @@ void mlo_cleanup_asserted_soc_setup_info(struct wlan_objmgr_psoc *psoc)
 
 qdf_export_symbol(mlo_cleanup_asserted_soc_setup_info);
 
-void mlo_setup_update_total_socs(uint8_t tot_socs)
+void mlo_setup_update_soc_id_list(uint8_t grp_id, uint8_t *soc_id_list)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint32_t tot_socs;
+	uint32_t num_soc;
+	uint8_t *soc_list;
 
 	if (!mlo_ctx)
 		return;
 
-	mlo_ctx->setup_info.tot_socs = tot_socs;
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	tot_socs = mlo_ctx->setup_info[grp_id].tot_socs;
+	soc_list = mlo_ctx->setup_info[grp_id].soc_id_list;
+
+	for (num_soc = 0; num_soc < tot_socs; num_soc++)
+		soc_list[num_soc] = soc_id_list[num_soc];
+}
+
+qdf_export_symbol(mlo_setup_update_soc_id_list);
+
+uint8_t mlo_setup_get_total_socs(uint8_t grp_id)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+
+	if (!mlo_ctx)
+		return 0;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return 0;
+	}
+
+	return mlo_ctx->setup_info[grp_id].tot_socs;
+}
+
+qdf_export_symbol(mlo_setup_get_total_socs);
+
+void mlo_setup_update_total_socs(uint8_t grp_id, uint8_t tot_socs)
+{
+	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+
+	if (!mlo_ctx)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	mlo_ctx->setup_info[grp_id].tot_socs = tot_socs;
+	mlo_ctx->setup_info[grp_id].ml_grp_id = grp_id;
 }
 
 qdf_export_symbol(mlo_setup_update_total_socs);
 
 static QDF_STATUS mlo_find_pdev_idx(struct wlan_objmgr_pdev *pdev,
-				    uint8_t *link_idx)
+				    uint8_t *link_idx, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 	uint8_t idx;
@@ -113,11 +308,20 @@ static QDF_STATUS mlo_find_pdev_idx(struct wlan_objmgr_pdev *pdev,
 	if (!mlo_ctx)
 		return QDF_STATUS_E_FAILURE;
 
+	if (!pdev)
+		return QDF_STATUS_E_FAILURE;
+
 	if (!link_idx)
 		return QDF_STATUS_E_FAILURE;
 
-	for (idx = 0; idx < mlo_ctx->setup_info.tot_links; idx++) {
-		if (mlo_ctx->setup_info.pdev_list[idx] == pdev) {
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	for (idx = 0; idx < mlo_ctx->setup_info[grp_id].tot_links; idx++) {
+		if (mlo_ctx->setup_info[grp_id].pdev_list[idx] == pdev) {
 			*link_idx = idx;
 			return QDF_STATUS_SUCCESS;
 		}
@@ -155,27 +359,39 @@ static void mlo_check_state(struct wlan_objmgr_psoc *psoc,
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 	struct mlo_state_params *params = (struct mlo_state_params *)args;
 
+	uint8_t grp_id = params->grp_id;
 	pdev = (struct wlan_objmgr_pdev *)obj;
 
 	if (!mlo_ctx)
 		return;
 
-	if (mlo_find_pdev_idx(pdev, &link_idx) != QDF_STATUS_SUCCESS) {
-		qdf_info("Failed to find pdev");
+	if (!psoc)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
+		mlo_info("Failed to find pdev");
 		return;
 	}
 
-	if (mlo_ctx->setup_info.state[link_idx] != params->check_state)
+	if (mlo_ctx->setup_info[grp_id].state[link_idx] != params->check_state)
 		params->link_state_fail = 1;
 }
 
 QDF_STATUS mlo_check_all_pdev_state(struct wlan_objmgr_psoc *psoc,
+				    uint8_t grp_id,
 				    enum MLO_LINK_STATE state)
 {
 	QDF_STATUS status = QDF_STATUS_E_INVAL;
 	struct mlo_state_params params = {0};
 
 	params.check_state = state;
+	params.grp_id = grp_id;
 
 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
 				     mlo_check_state, &params,
@@ -189,16 +405,34 @@ QDF_STATUS mlo_check_all_pdev_state(struct wlan_objmgr_psoc *psoc,
 	return status;
 }
 
-void mlo_setup_init(void)
+void mlo_setup_init(uint8_t total_grp)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
+	uint8_t id;
 
 	if (!mlo_ctx)
 		return;
 
-	if (qdf_event_create(&mlo_ctx->setup_info.event) !=
-						QDF_STATUS_SUCCESS) {
-		mlo_err("Unable to create teardown event");
+	if (!total_grp && total_grp > WLAN_MAX_MLO_GROUPS) {
+		mlo_err("Total number of groups (%d) is greater than MAX (%d), MLD Setup failed!!",
+			total_grp, WLAN_MAX_MLO_GROUPS);
+		return;
+	}
+
+	mlo_ctx->total_grp = total_grp;
+	setup_info = qdf_mem_malloc(sizeof(struct mlo_setup_info) *
+					      total_grp);
+
+	if (!setup_info)
+		return;
+
+	mlo_ctx->setup_info = setup_info;
+	mlo_ctx->setup_info[0].ml_grp_id = 0;
+	for (id = 0; id < total_grp; id++) {
+		if (qdf_event_create(&mlo_ctx->setup_info[id].event) !=
+							QDF_STATUS_SUCCESS)
+			mlo_err("Unable to create teardown event");
 	}
 }
 
@@ -207,111 +441,170 @@ qdf_export_symbol(mlo_setup_init);
 void mlo_setup_deinit(void)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	uint8_t id;
 
 	if (!mlo_ctx)
 		return;
 
-	qdf_event_destroy(&mlo_ctx->setup_info.event);
+	if (!mlo_ctx->setup_info)
+		return;
+
+	for (id = 0; id < mlo_ctx->total_grp; id++)
+		qdf_event_destroy(&mlo_ctx->setup_info[id].event);
+
+	qdf_mem_free(mlo_ctx->setup_info);
+	mlo_ctx->setup_info = NULL;
 }
 
 qdf_export_symbol(mlo_setup_deinit);
 
 void mlo_setup_update_num_links(struct wlan_objmgr_psoc *psoc,
-				uint8_t num_links)
+				uint8_t grp_id, uint8_t num_links)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 
 	if (!mlo_ctx)
 		return;
 
-	mlo_ctx->setup_info.tot_links += num_links;
+	if (!psoc)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	mlo_ctx->setup_info[grp_id].tot_links += num_links;
 }
 
 qdf_export_symbol(mlo_setup_update_num_links);
 
-void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc)
+void mlo_setup_update_soc_ready(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
-	uint8_t chip_idx, tot_socs = 0;
+	struct mlo_setup_info *setup_info;
+	uint8_t chip_idx, tot_socs;
 	struct cdp_mlo_ctxt *dp_mlo_ctxt;
 
-	if (!mlo_ctx || !mlo_ctx->setup_info.tot_socs)
+	if (!mlo_ctx)
 		return;
 
-	tot_socs = mlo_ctx->setup_info.tot_socs;
-	chip_idx = wlan_psoc_get_id(psoc);
+	if (!psoc)
+		return;
 
-	if (!(chip_idx < MAX_MLO_CHIPS)) {
-		qdf_err("Invalid chip index, SoC setup failed");
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	if (!setup_info->tot_socs)
+		return;
+
+	tot_socs = setup_info->tot_socs;
+	if (!mlo_psoc_get_index_id(psoc, grp_id, &chip_idx, 0))  {
+		mlo_err("Unable to fetch chip idx for psoc id %d grp id %d",
+			psoc->soc_objmgr.psoc_id,
+			grp_id);
+		return;
+	}
+
+	if (!(chip_idx < tot_socs)) {
+		mlo_err("Invalid chip index, SoC setup failed");
 		return;
 	}
 
-	mlo_ctx->setup_info.soc_list[chip_idx] = psoc;
-	mlo_ctx->setup_info.num_soc++;
-	qdf_debug("soc updated to mld list, id %d num soc %d",
-		  chip_idx, mlo_ctx->setup_info.num_soc);
+	setup_info->curr_soc_list[chip_idx] = psoc;
+	mlo_set_soc_list(grp_id, psoc);
+	setup_info->num_soc++;
 
-	if (mlo_ctx->setup_info.num_soc != mlo_ctx->setup_info.tot_socs)
+	mlo_debug("SoC updated to mld grp %d , chip idx %d num soc %d",
+		  grp_id, chip_idx, setup_info->num_soc);
+
+	if (setup_info->num_soc != tot_socs)
 		return;
+
 	dp_mlo_ctxt = cdp_mlo_ctxt_attach(wlan_psoc_get_dp_handle(psoc),
-					  (struct cdp_ctrl_mlo_mgr *)mlo_ctx);
-	wlan_objmgr_set_dp_mlo_ctx(dp_mlo_ctxt);
+			(struct cdp_ctrl_mlo_mgr *)mlo_ctx);
+	wlan_objmgr_set_dp_mlo_ctx(dp_mlo_ctxt, grp_id);
 
-	for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++) {
+	for (chip_idx = 0; chip_idx < tot_socs; chip_idx++) {
 		struct wlan_objmgr_psoc *tmp_soc =
-			mlo_ctx->setup_info.soc_list[chip_idx];
+			setup_info->curr_soc_list[chip_idx];
 		if (tmp_soc)
 			cdp_soc_mlo_soc_setup(wlan_psoc_get_dp_handle(tmp_soc),
-					      mlo_ctx->setup_info.dp_handle);
+					      setup_info->dp_handle);
 	}
 
 	cdp_mlo_setup_complete(wlan_psoc_get_dp_handle(psoc),
-			       mlo_ctx->setup_info.dp_handle);
+			       setup_info->dp_handle);
 }
 
 qdf_export_symbol(mlo_setup_update_soc_ready);
 
-void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev)
+void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
 	uint8_t link_idx;
 	uint16_t link_id;
 
-	if (!mlo_ctx || !mlo_ctx->setup_info.tot_links)
+	if (!mlo_ctx)
+		return;
+
+	if (!pdev)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
 		return;
+	}
 
-	if (mlo_find_pdev_idx(pdev, &link_idx) == QDF_STATUS_SUCCESS) {
-		qdf_debug("pdev already part of list link idx %d", link_idx);
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	if (!setup_info->tot_links) {
+		mlo_err("Setup info total links %d for grp id %d",
+			setup_info->tot_links, grp_id);
 		return;
 	}
 
-	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
-		if (!mlo_ctx->setup_info.pdev_list[link_idx])
+	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) == QDF_STATUS_SUCCESS) {
+		mlo_debug("Pdev already part of list link idx %d", link_idx);
+		return;
+	}
+
+	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
+		if (!setup_info->pdev_list[link_idx])
 			break;
 
-	if (link_idx >= mlo_ctx->setup_info.tot_links) {
-		qdf_err("Exceeding max total mld links");
+	if (link_idx >= setup_info->tot_links) {
+		mlo_err("Exceeding max total mld links");
 		return;
 	}
 
-	mlo_ctx->setup_info.pdev_list[link_idx] = pdev;
-	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_SETUP_INIT;
-	mlo_ctx->setup_info.num_links++;
+	setup_info->pdev_list[link_idx] = pdev;
+	setup_info->state[link_idx] = MLO_LINK_SETUP_INIT;
+	setup_info->num_links++;
 
 	link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
 	if (link_id == INVALID_HW_LINK_ID) {
-		qdf_err("Invalid HW link id for the pdev");
+		mlo_err("Invalid HW link id for the pdev");
 		return;
 	}
-	mlo_ctx->setup_info.valid_link_bitmap |= (1 << link_id);
+	setup_info->valid_link_bitmap |= (1 << link_id);
 
-	qdf_debug("pdev updated to mld link %d num_links %d",
-		  link_idx, mlo_ctx->setup_info.num_links);
+	mlo_debug("Pdev updated to Grp id %d mld link %d num_links %d  hw link id %d Valid link bitmap %d",
+		  grp_id, link_idx, setup_info->num_links,
+		  link_id, setup_info->valid_link_bitmap);
 
 	qdf_assert_always(link_idx < MAX_MLO_LINKS);
 
-	if (mlo_ctx->setup_info.num_links == mlo_ctx->setup_info.tot_links &&
-	    mlo_ctx->setup_info.num_soc == mlo_ctx->setup_info.tot_socs) {
+	if (setup_info->num_links == setup_info->tot_links &&
+	    setup_info->num_soc == setup_info->tot_socs) {
 		struct wlan_objmgr_psoc *psoc;
 		struct wlan_lmac_if_tx_ops *tx_ops;
 		QDF_STATUS status;
@@ -325,50 +618,65 @@ void mlo_setup_link_ready(struct wlan_objmgr_pdev *pdev)
 			qdf_assert_always(0);
 		}
 
-		qdf_debug("Trigger MLO Setup request");
+		mlo_debug("Trigger MLO Setup request");
 		if (tx_ops && tx_ops->mops.target_if_mlo_setup_req) {
 			tx_ops->mops.target_if_mlo_setup_req(
-					mlo_ctx->setup_info.pdev_list,
-					mlo_ctx->setup_info.num_links,
-					mlo_ctx->setup_info.ml_grp_id);
+					setup_info->pdev_list,
+					setup_info->num_links,
+					grp_id);
 		}
 	}
 }
 
 qdf_export_symbol(mlo_setup_link_ready);
 
-void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev)
+void mlo_link_setup_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
 	uint8_t link_idx;
 
 	if (!mlo_ctx)
 		return;
 
-	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
-		if (mlo_ctx->setup_info.pdev_list[link_idx] == pdev) {
-			mlo_ctx->setup_info.state[link_idx] =
+	if (!pdev)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
+		if (setup_info->pdev_list[link_idx] == pdev) {
+			setup_info->state[link_idx] =
 							MLO_LINK_SETUP_DONE;
 			break;
 		}
 
-	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
-		if (mlo_ctx->setup_info.state[link_idx] == MLO_LINK_SETUP_DONE)
+	mlo_debug("Setup complete for pdev id %d mlo group %d",
+		  pdev->pdev_objmgr.wlan_pdev_id, grp_id);
+
+	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
+		if (setup_info->state[link_idx] == MLO_LINK_SETUP_DONE)
 			continue;
 		else
 			break;
 
-	if (link_idx == mlo_ctx->setup_info.tot_links) {
+	if (link_idx == setup_info->tot_links) {
 		struct wlan_objmgr_psoc *psoc;
 		struct wlan_lmac_if_tx_ops *tx_ops;
 
 		psoc = wlan_pdev_get_psoc(pdev);
 		tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
-		/* Trigger MLO ready */
+		mlo_debug("Trigger MLO ready");
 		if (tx_ops && tx_ops->mops.target_if_mlo_ready) {
 			tx_ops->mops.target_if_mlo_ready(
-					mlo_ctx->setup_info.pdev_list,
-					mlo_ctx->setup_info.num_links);
+					setup_info->pdev_list,
+					setup_info->num_links);
 		}
 	}
 }
@@ -381,75 +689,110 @@ static void mlo_setup_link_down(struct wlan_objmgr_psoc *psoc,
 	struct wlan_objmgr_pdev *pdev;
 	uint8_t link_idx;
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
 	uint16_t link_id;
+	uint8_t grp_id = *(uint8_t *)args;
+
+	if (!mlo_ctx)
+		return;
+
+	if (!psoc)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
 
 	pdev = (struct wlan_objmgr_pdev *)obj;
 
-	if (mlo_find_pdev_idx(pdev, &link_idx) != QDF_STATUS_SUCCESS) {
-		qdf_info("Failed to find pdev");
+	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
+		mlo_info("Failed to find pdev");
 		return;
 	}
 
-	mlo_ctx->setup_info.pdev_list[link_idx] = NULL;
-	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_UNINITIALIZED;
-	mlo_ctx->setup_info.num_links--;
+	setup_info->pdev_list[link_idx] = NULL;
+	setup_info->state[link_idx] = MLO_LINK_UNINITIALIZED;
+	setup_info->num_links--;
 
 	link_id = wlan_mlo_get_pdev_hw_link_id(pdev);
 	if (link_id == INVALID_HW_LINK_ID) {
-		qdf_err("Invalid HW link id for the pdev");
+		mlo_err("Invalid HW link id for the pdev");
 		return;
 	}
-	mlo_ctx->setup_info.valid_link_bitmap &= ~(1 << link_id);
+	setup_info->valid_link_bitmap &= ~(1 << link_id);
 
-	qdf_debug("link down link_idx %d num_links %d",
-		  link_idx, mlo_ctx->setup_info.num_links);
+	mlo_debug("Pdev link down grp_id %d link_idx %d num_links %d",
+		  grp_id, link_idx, setup_info->num_links);
 }
 
-void mlo_setup_update_soc_down(struct wlan_objmgr_psoc *psoc)
+void mlo_setup_update_soc_down(struct wlan_objmgr_psoc *psoc, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
 	uint8_t chip_idx;
 
 	if (!mlo_ctx)
 		return;
 
-	if (!mlo_ctx->setup_info.num_links) {
-		qdf_debug("Links are already down");
+	if (!psoc)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
 		return;
 	}
 
-	wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
-				     mlo_setup_link_down, NULL,
-				     0, WLAN_MLME_NB_ID);
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	if (setup_info->num_links) {
+		wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
+					     mlo_setup_link_down, &grp_id,
+					     0, WLAN_MLME_NB_ID);
+	}
 
-	chip_idx = wlan_psoc_get_id(psoc);
+	if (!mlo_psoc_get_index_id(psoc, grp_id, &chip_idx, 1)) {
+		mlo_err("Unable to fetch chip idx for psoc id %d grp id %d",
+			psoc->soc_objmgr.psoc_id,
+			grp_id);
+		return;
+	}
 
 	if (!(chip_idx < MAX_MLO_CHIPS)) {
-		qdf_err("Invalid chip index, SoC setup down failed");
+		mlo_err("Invalid chip index, SoC setup down failed");
 		return;
 	}
 
-	mlo_ctx->setup_info.soc_list[chip_idx] = NULL;
-	mlo_ctx->setup_info.num_soc--;
+	setup_info->curr_soc_list[chip_idx] = NULL;
+	setup_info->num_soc--;
 
-	qdf_debug("Soc down, num soc %d num links %d",
-		  mlo_ctx->setup_info.num_soc,
-		  mlo_ctx->setup_info.num_links);
+	mlo_debug("Soc down, mlo group %d num soc %d num links %d",
+		  grp_id, setup_info->num_soc,
+		  setup_info->num_links);
 }
 
 qdf_export_symbol(mlo_setup_update_soc_down);
 
 static void mlo_dp_ctxt_detach(struct wlan_objmgr_psoc *psoc,
+			       uint8_t grp_id,
 			       struct cdp_mlo_ctxt *dp_mlo_ctxt)
 {
-	wlan_objmgr_set_dp_mlo_ctx(NULL);
+	if (!psoc)
+		return;
+
+	wlan_objmgr_set_dp_mlo_ctx(NULL, grp_id);
 	if (dp_mlo_ctxt)
 		cdp_mlo_ctxt_detach(wlan_psoc_get_dp_handle(psoc), dp_mlo_ctxt);
 }
 
-void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev)
+void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev, uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
+	struct mlo_setup_info *setup_info;
 	uint8_t link_idx;
 	struct wlan_objmgr_psoc *soc;
 	uint8_t chip_idx;
@@ -458,114 +801,147 @@ void mlo_link_teardown_complete(struct wlan_objmgr_pdev *pdev)
 	if (!mlo_ctx)
 		return;
 
-	if (!mlo_ctx->setup_info.num_links) {
-		qdf_err("Delayed response ignore");
+	if (!pdev)
+		return;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	if (!setup_info->num_links) {
+		mlo_err("Delayed response ignore");
 		return;
 	}
 
-	if (mlo_find_pdev_idx(pdev, &link_idx) != QDF_STATUS_SUCCESS) {
-		qdf_info("Failed to find pdev");
+	if (mlo_find_pdev_idx(pdev, &link_idx, grp_id) != QDF_STATUS_SUCCESS) {
+		mlo_info("Failed to find pdev");
 		return;
 	}
 
-	qdf_debug("Teardown link idx = %d", link_idx);
-	mlo_ctx->setup_info.state[link_idx] = MLO_LINK_TEARDOWN;
+	mlo_debug("Teardown link idx = %d", link_idx);
+	setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
 
 	/* Waiting for teardown on other links */
-	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
-		if (mlo_ctx->setup_info.state[link_idx] != MLO_LINK_TEARDOWN)
+	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
+		if (setup_info->state[link_idx] != MLO_LINK_TEARDOWN)
 			return;
 
-	qdf_info("Teardown complete");
+	mlo_debug("Teardown complete");
 
-	for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++) {
-		soc = mlo_ctx->setup_info.soc_list[chip_idx];
+	for (chip_idx = 0; chip_idx < setup_info->tot_socs; chip_idx++) {
+		soc = setup_info->curr_soc_list[chip_idx];
 		if (soc) {
 			num_soc++;
 			cdp_soc_mlo_soc_teardown(wlan_psoc_get_dp_handle(soc),
-						 mlo_ctx->setup_info.dp_handle,
+						 setup_info->dp_handle,
 						 false);
-			if (num_soc == mlo_ctx->setup_info.tot_socs)
-				mlo_dp_ctxt_detach(soc,
-						 mlo_ctx->setup_info.dp_handle);
+			if (num_soc == setup_info->tot_socs)
+				mlo_dp_ctxt_detach(soc, grp_id,
+						   setup_info->dp_handle);
 		}
 	}
 
-	qdf_event_set(&mlo_ctx->setup_info.event);
+	qdf_event_set(&setup_info->event);
 }
 
 qdf_export_symbol(mlo_link_teardown_complete);
 
-static void mlo_force_teardown(void)
+static void mlo_force_teardown(uint8_t grp_id)
 {
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 	struct wlan_objmgr_psoc *soc;
-	uint8_t link_idx = 0;
+	struct mlo_setup_info *setup_info;
+	uint8_t link_idx;
 	uint8_t chip_idx;
 	uint8_t num_soc = 0;
 
 	if (!mlo_ctx)
 		return;
 
-	for (link_idx = 0; link_idx < mlo_ctx->setup_info.tot_links; link_idx++)
-		mlo_ctx->setup_info.state[link_idx] = MLO_LINK_TEARDOWN;
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return;
+	}
+
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	for (link_idx = 0; link_idx < setup_info->tot_links; link_idx++)
+		setup_info->state[link_idx] = MLO_LINK_TEARDOWN;
 
-	for (chip_idx = 0; chip_idx < MAX_MLO_CHIPS; chip_idx++) {
-		soc = mlo_ctx->setup_info.soc_list[chip_idx];
+	for (chip_idx = 0; chip_idx < setup_info->tot_socs; chip_idx++) {
+		soc = setup_info->curr_soc_list[chip_idx];
 		if (soc) {
 			num_soc++;
 			cdp_soc_mlo_soc_teardown(wlan_psoc_get_dp_handle(soc),
-						 mlo_ctx->setup_info.dp_handle,
+						 setup_info->dp_handle,
 						 true);
-			if (num_soc == mlo_ctx->setup_info.tot_socs)
-				mlo_dp_ctxt_detach(soc,
-						 mlo_ctx->setup_info.dp_handle);
+			if (num_soc == setup_info->tot_socs)
+				mlo_dp_ctxt_detach(soc, grp_id,
+						   setup_info->dp_handle);
 		}
 	}
 }
 
 #define MLO_MGR_TEARDOWN_TIMEOUT 3000
 QDF_STATUS mlo_link_teardown_link(struct wlan_objmgr_psoc *psoc,
+				  uint8_t grp_id,
 				  uint32_t reason)
 {
 	struct wlan_lmac_if_tx_ops *tx_ops;
 	QDF_STATUS status;
+	struct mlo_setup_info *setup_info;
 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
 
 	if (!mlo_ctx)
 		return QDF_STATUS_E_FAILURE;
 
-	qdf_debug("Teardown req with num_soc %d num_link %d",
-		  mlo_ctx->setup_info.num_soc,
-		  mlo_ctx->setup_info.num_links);
+	if (!psoc)
+		return QDF_STATUS_E_FAILURE;
+
+	if (grp_id >= mlo_ctx->total_grp) {
+		mlo_err("Invalid grp id %d, total no of groups %d",
+			grp_id, mlo_ctx->total_grp);
+		return QDF_STATUS_E_INVAL;
+	}
 
-	if (!mlo_ctx->setup_info.num_soc)
+	setup_info = &mlo_ctx->setup_info[grp_id];
+
+	mlo_debug("Teardown req with grp_id %d num_soc %d num_link %d",
+		  grp_id, setup_info->num_soc, setup_info->num_links);
+
+	if (!setup_info->num_soc)
 		return QDF_STATUS_SUCCESS;
 
-	if (!mlo_check_all_pdev_state(psoc, MLO_LINK_TEARDOWN))
+	if (!mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_TEARDOWN))
 		return QDF_STATUS_SUCCESS;
 
 	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
 	/* Trigger MLO teardown */
 	if (tx_ops && tx_ops->mops.target_if_mlo_teardown_req) {
 		tx_ops->mops.target_if_mlo_teardown_req(
-				mlo_ctx->setup_info.pdev_list,
-				mlo_ctx->setup_info.num_links,
+				setup_info->pdev_list,
+				setup_info->num_links,
 				reason);
 	}
 
 	if (reason == WMI_MLO_TEARDOWN_REASON_SSR) {
 		/* do not wait for teardown event completion here for SSR */
-		mlo_dp_ctxt_detach(psoc, mlo_ctx->setup_info.dp_handle);
+		mlo_dp_ctxt_detach(psoc, grp_id, setup_info->dp_handle);
 		return QDF_STATUS_SUCCESS;
 	}
 
 	status = qdf_wait_for_event_completion(
-			&mlo_ctx->setup_info.event,
+			&setup_info->event,
 			MLO_MGR_TEARDOWN_TIMEOUT);
+
 	if (status != QDF_STATUS_SUCCESS) {
-		qdf_info("Teardown timeout");
-		mlo_force_teardown();
+		qdf_debug("Teardown timeout");
+		mlo_force_teardown(grp_id);
 	}
 
 	return status;