瀏覽代碼

qcacmn: Code change in IPA component for 2x_pdev

2x_pdev changes are included mainly related to IPA
init for second pdev/radio and pipe enablement for
second pdev/radio, code changes can support n number
of radio for IPA, add support for new IPA API's.

Change-Id: Iac67e05e0f0098bdc24626fdbe59b89d768154cd
Devender Kumar 3 年之前
父節點
當前提交
3d525ae1ce

+ 3 - 2
ipa/core/inc/wlan_ipa_core.h

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -770,7 +770,8 @@ static inline void wlan_ipa_mcc_work_handler(void *data)
 QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 			     uint8_t session_id,
 			     uint8_t session_id,
 			     enum wlan_ipa_wlan_event ipa_event_type,
 			     enum wlan_ipa_wlan_event ipa_event_type,
-			     uint8_t *mac_addr, bool is_2g_iface);
+			     uint8_t *mac_addr, bool is_2g_iface,
+			     struct wlan_ipa_priv *ipa_obj);
 
 
 /**
 /**
  * wlan_ipa_uc_smmu_map() - Map / Unmap DMA buffer to IPA UC
  * wlan_ipa_uc_smmu_map() - Map / Unmap DMA buffer to IPA UC

+ 4 - 1
ipa/core/inc/wlan_ipa_main.h

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -31,6 +31,9 @@
 #include <wlan_ipa_public_struct.h>
 #include <wlan_ipa_public_struct.h>
 #include <wlan_ipa_priv.h>
 #include <wlan_ipa_priv.h>
 
 
+/* Declare a variable for IPA instancess added based on pdev */
+extern uint8_t g_instances_added;
+#define IPA_INVALID_HDL 0xFF
 #define ipa_fatal(params...) \
 #define ipa_fatal(params...) \
 	QDF_TRACE_FATAL(QDF_MODULE_ID_IPA, params)
 	QDF_TRACE_FATAL(QDF_MODULE_ID_IPA, params)
 #define ipa_err(params...) \
 #define ipa_err(params...) \

+ 5 - 0
ipa/core/inc/wlan_ipa_priv.h

@@ -516,11 +516,13 @@ struct uc_rm_work_struct {
  * @work: uC OP work
  * @work: uC OP work
  * @msg: OP message
  * @msg: OP message
  * @osdev: poiner to qdf net device, used by osif_psoc_sync_trans_start_wait
  * @osdev: poiner to qdf net device, used by osif_psoc_sync_trans_start_wait
+ * @ipa_priv_bp: back pointer to ipa_obj
  */
  */
 struct uc_op_work_struct {
 struct uc_op_work_struct {
 	qdf_work_t work;
 	qdf_work_t work;
 	struct op_msg_type *msg;
 	struct op_msg_type *msg;
 	qdf_device_t osdev;
 	qdf_device_t osdev;
+	struct wlan_ipa_priv *ipa_priv_bp;
 };
 };
 
 
 /**
 /**
@@ -734,6 +736,9 @@ struct wlan_ipa_priv {
 	qdf_atomic_t stats_quota;
 	qdf_atomic_t stats_quota;
 	uint8_t curr_bw_level;
 	uint8_t curr_bw_level;
 	qdf_atomic_t deinit_in_prog;
 	qdf_atomic_t deinit_in_prog;
+	uint8_t instance_id;
+	bool handle_initialized;
+	qdf_ipa_wdi_hdl_t hdl;
 };
 };
 
 
 #define WLAN_IPA_WLAN_FRAG_HEADER        sizeof(struct frag_header)
 #define WLAN_IPA_WLAN_FRAG_HEADER        sizeof(struct frag_header)

+ 86 - 38
ipa/core/src/wlan_ipa_core.c

@@ -37,6 +37,8 @@
 #include <qal_vbus_dev.h>
 #include <qal_vbus_dev.h>
 
 
 #define IPA_SPS_DESC_SIZE 8
 #define IPA_SPS_DESC_SIZE 8
+#define IPA_DEFAULT_HDL 0
+
 static struct wlan_ipa_priv *gp_ipa;
 static struct wlan_ipa_priv *gp_ipa;
 static void wlan_ipa_set_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx);
 static void wlan_ipa_set_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx);
 static void wlan_ipa_reset_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx);
 static void wlan_ipa_reset_pending_tx_timer(struct wlan_ipa_priv *ipa_ctx);
@@ -542,7 +544,7 @@ wlan_ipa_wdi_setup(struct wlan_ipa_priv *ipa_ctx,
 				   &ipa_ctx->tx_pipe_handle,
 				   &ipa_ctx->tx_pipe_handle,
 				   &ipa_ctx->rx_pipe_handle,
 				   &ipa_ctx->rx_pipe_handle,
 				   wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
 				   wlan_ipa_wdi_is_smmu_enabled(ipa_ctx, osdev),
-				   sys_in, ipa_ctx->over_gsi);
+				   sys_in, ipa_ctx->over_gsi, ipa_ctx->hdl);
 
 
 	qdf_mem_free(sys_in);
 	qdf_mem_free(sys_in);
 
 
@@ -590,6 +592,7 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
 	QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
 	QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = ipa_ctx->wdi_version;
 	QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
 	QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = wlan_ipa_uc_loaded_uc_cb;
 	QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
 	QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = ipa_ctx;
+	QDF_IPA_WDI_INIT_IN_PARAMS_INSTANCE_ID(&in) = ipa_ctx->instance_id;
 	wlan_ipa_wdi_init_metering(ipa_ctx, &in);
 	wlan_ipa_wdi_init_metering(ipa_ctx, &in);
 
 
 	ret = qdf_ipa_wdi_init(&in, &out);
 	ret = qdf_ipa_wdi_init(&in, &out);
@@ -602,8 +605,10 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
 		QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
 		QDF_IPA_WDI_INIT_OUT_PARAMS_IS_OVER_GSI(&out);
 	ipa_ctx->is_smmu_enabled =
 	ipa_ctx->is_smmu_enabled =
 		QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
 		QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
-	ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d",
-		 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled);
+	ipa_ctx->hdl = QDF_IPA_WDI_INIT_OUT_PARAMS_HANDLE(&out);
+
+	ipa_info("ipa_over_gsi: %d, is_smmu_enabled: %d, handle: %d",
+		 ipa_ctx->over_gsi, ipa_ctx->is_smmu_enabled, ipa_ctx->hdl);
 
 
 	if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
 	if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
 		ipa_debug("IPA uC READY");
 		ipa_debug("IPA uC READY");
@@ -616,11 +621,11 @@ static inline QDF_STATUS wlan_ipa_wdi_init(struct wlan_ipa_priv *ipa_ctx)
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 
-static inline int wlan_ipa_wdi_cleanup(void)
+static inline int wlan_ipa_wdi_cleanup(qdf_ipa_wdi_hdl_t hdl)
 {
 {
 	int ret;
 	int ret;
 
 
-	ret = qdf_ipa_wdi_cleanup();
+	ret = qdf_ipa_wdi_cleanup(hdl);
 	if (ret)
 	if (ret)
 		ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
 		ipa_info("ipa_wdi_cleanup failed ret=%d", ret);
 	return ret;
 	return ret;
@@ -697,11 +702,18 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
 		ipa_info("No buffers to map/unmap");
 		ipa_info("No buffers to map/unmap");
 		return 0;
 		return 0;
 	}
 	}
-
+	/**
+	 * This API will compile for prelithium chipset
+	 * where we have only one soc so passing default
+	 * handle to IPA which is 0.
+	 */
 	if (map)
 	if (map)
-		return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
+		return qdf_ipa_wdi_create_smmu_mapping(IPA_DEFAULT_HDL,
+						       num_buf, buf_arr);
 	else
 	else
-		return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
+		return qdf_ipa_wdi_release_smmu_mapping(IPA_DEFAULT_HDL,
+							num_buf, buf_arr);
+	return 0;
 }
 }
 
 
 #ifdef MDM_PLATFORM
 #ifdef MDM_PLATFORM
@@ -945,9 +957,12 @@ int wlan_ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
 	}
 	}
 
 
 	if (map)
 	if (map)
-		return qdf_ipa_wdi_create_smmu_mapping(num_buf, buf_arr);
+		return qdf_ipa_wdi_create_smmu_mapping(IPA_DEFAULT_HDL,
+						       num_buf, buf_arr);
 	else
 	else
-		return qdf_ipa_wdi_release_smmu_mapping(num_buf, buf_arr);
+		return qdf_ipa_wdi_release_smmu_mapping(IPA_DEFAULT_HDL,
+							num_buf, buf_arr);
+	return 0;
 }
 }
 
 
 static enum wlan_ipa_forward_type
 static enum wlan_ipa_forward_type
@@ -976,10 +991,14 @@ wlan_ipa_rx_intrabss_fwd(struct wlan_ipa_priv *ipa_ctx,
 static int wlan_ipa_send_sta_eapol_to_nw(qdf_nbuf_t skb,
 static int wlan_ipa_send_sta_eapol_to_nw(qdf_nbuf_t skb,
 					 struct wlan_objmgr_pdev *pdev)
 					 struct wlan_objmgr_pdev *pdev)
 {
 {
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_ctx;
 	struct ethhdr *eh;
 	struct ethhdr *eh;
 	struct wlan_objmgr_vdev *vdev = NULL;
 	struct wlan_objmgr_vdev *vdev = NULL;
 
 
+	ipa_ctx = ipa_pdev_get_priv_obj(pdev);
+	if (!ipa_ctx)
+		return -EINVAL;
+
 	eh = (struct ethhdr *)qdf_nbuf_data(skb);
 	eh = (struct ethhdr *)qdf_nbuf_data(skb);
 	vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(
 	vdev = wlan_objmgr_get_vdev_by_macaddr_from_pdev(
 				pdev, eh->h_dest, WLAN_IPA_ID);
 				pdev, eh->h_dest, WLAN_IPA_ID);
@@ -1019,7 +1038,9 @@ static void
 wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
 wlan_ipa_send_skb_to_network(qdf_nbuf_t skb,
 			     struct wlan_ipa_iface_context *iface_ctx)
 			     struct wlan_ipa_iface_context *iface_ctx)
 {
 {
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_ctx;
+
+	ipa_ctx = iface_ctx->ipa_ctx;
 
 
 	if (!iface_ctx->dev) {
 	if (!iface_ctx->dev) {
 		ipa_debug_rl("Invalid interface");
 		ipa_debug_rl("Invalid interface");
@@ -1513,7 +1534,8 @@ QDF_STATUS wlan_ipa_uc_enable_pipes(struct wlan_ipa_priv *ipa_ctx)
 
 
 	if (qdf_atomic_read(&ipa_ctx->pipes_disabled)) {
 	if (qdf_atomic_read(&ipa_ctx->pipes_disabled)) {
 		result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
 		result = cdp_ipa_enable_pipes(ipa_ctx->dp_soc,
-					      ipa_ctx->dp_pdev_id);
+					      ipa_ctx->dp_pdev_id,
+					      ipa_ctx->hdl);
 		if (result) {
 		if (result) {
 			ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
 			ipa_err("Enable IPA WDI PIPE failed: ret=%d", result);
 			qdf_status = QDF_STATUS_E_FAILURE;
 			qdf_status = QDF_STATUS_E_FAILURE;
@@ -1573,7 +1595,8 @@ wlan_ipa_uc_disable_pipes(struct wlan_ipa_priv *ipa_ctx, bool force_disable)
 			wlan_ipa_set_pending_tx_timer(ipa_ctx);
 			wlan_ipa_set_pending_tx_timer(ipa_ctx);
 		} else {
 		} else {
 			qdf_status = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
 			qdf_status = cdp_ipa_disable_pipes(ipa_ctx->dp_soc,
-							   ipa_ctx->dp_pdev_id);
+							   ipa_ctx->dp_pdev_id,
+							   ipa_ctx->hdl);
 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
 			if (QDF_IS_STATUS_ERROR(qdf_status)) {
 				ipa_err("Disable IPA WDI PIPE failed: ret=%u",
 				ipa_err("Disable IPA WDI PIPE failed: ret=%u",
 					qdf_status);
 					qdf_status);
@@ -1715,7 +1738,8 @@ static void wlan_ipa_cleanup_iface(struct wlan_ipa_iface_context *iface_context,
 
 
 	if (cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
 	if (cdp_ipa_cleanup_iface(ipa_ctx->dp_soc,
 				  iface_context->dev->name,
 				  iface_context->dev->name,
-				  wlan_ipa_is_ipv6_enabled(ipa_ctx->config))) {
+				  wlan_ipa_is_ipv6_enabled(ipa_ctx->config),
+				  ipa_ctx->hdl)) {
 		ipa_err("ipa_cleanup_iface failed");
 		ipa_err("ipa_cleanup_iface failed");
 	}
 	}
 
 
@@ -1944,7 +1968,8 @@ static QDF_STATUS wlan_ipa_setup_iface(struct wlan_ipa_priv *ipa_ctx,
 				     iface_context->cons_client,
 				     iface_context->cons_client,
 				     wlan_ipa_set_session_id(session_id,
 				     wlan_ipa_set_session_id(session_id,
 							     is_2g_iface),
 							     is_2g_iface),
-				     wlan_ipa_is_ipv6_enabled(ipa_ctx->config));
+				     wlan_ipa_is_ipv6_enabled(ipa_ctx->config),
+				     ipa_ctx->hdl);
 	if (status != QDF_STATUS_SUCCESS)
 	if (status != QDF_STATUS_SUCCESS)
 		goto end;
 		goto end;
 
 
@@ -2450,9 +2475,10 @@ wlan_ipa_save_bssid_iface_ctx(struct wlan_ipa_priv *ipa_ctx, uint8_t iface_id,
 static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 				      uint8_t session_id,
 				      uint8_t session_id,
 				      qdf_ipa_wlan_event type,
 				      qdf_ipa_wlan_event type,
-				      uint8_t *mac_addr, bool is_2g_iface)
+				      uint8_t *mac_addr, bool is_2g_iface,
+				      struct wlan_ipa_priv *ipa_obj)
 {
 {
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_ctx;
 	struct wlan_ipa_iface_context *iface_ctx = NULL;
 	struct wlan_ipa_iface_context *iface_ctx = NULL;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_wlan_msg_t *msg;
 	qdf_ipa_wlan_msg_t *msg;
@@ -2470,6 +2496,7 @@ static QDF_STATUS __wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 	if (type >= QDF_IPA_WLAN_EVENT_MAX)
 	if (type >= QDF_IPA_WLAN_EVENT_MAX)
 		return QDF_STATUS_E_INVAL;
 		return QDF_STATUS_E_INVAL;
 
 
+	ipa_ctx = ipa_obj;
 	if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
 	if (wlan_ipa_uc_is_enabled(ipa_ctx->config) &&
 	    !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
 	    !wlan_ipa_uc_sta_is_enabled(ipa_ctx->config) &&
 	    (device_mode != QDF_SAP_MODE)) {
 	    (device_mode != QDF_SAP_MODE)) {
@@ -3174,7 +3201,8 @@ static uint8_t wlan_ipa_device_mode_switch(uint8_t device_mode)
 QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 		      uint8_t session_id,
 		      uint8_t session_id,
 		      enum wlan_ipa_wlan_event ipa_event_type,
 		      enum wlan_ipa_wlan_event ipa_event_type,
-		      uint8_t *mac_addr, bool is_2g_iface)
+		      uint8_t *mac_addr, bool is_2g_iface,
+		      struct wlan_ipa_priv *ipa_obj)
 {
 {
 	qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
 	qdf_ipa_wlan_event type = wlan_host_to_ipa_wlan_event(ipa_event_type);
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
@@ -3186,7 +3214,7 @@ QDF_STATUS wlan_ipa_wlan_evt(qdf_netdev_t net_dev, uint8_t device_mode,
 	    (device_mode == QDF_SAP_MODE))
 	    (device_mode == QDF_SAP_MODE))
 		status  = __wlan_ipa_wlan_evt(net_dev, device_mode,
 		status  = __wlan_ipa_wlan_evt(net_dev, device_mode,
 					      session_id, type, mac_addr,
 					      session_id, type, mac_addr,
-					      is_2g_iface);
+					      is_2g_iface, ipa_obj);
 
 
 	return status;
 	return status;
 }
 }
@@ -3226,7 +3254,7 @@ wlan_ipa_uc_proc_pending_event(struct wlan_ipa_priv *ipa_ctx, bool is_loading)
 					   pending_event->session_id,
 					   pending_event->session_id,
 					   pending_event->type,
 					   pending_event->type,
 					   pending_event->mac_addr,
 					   pending_event->mac_addr,
-					   pending_event->is_2g_iface);
+					   pending_event->is_2g_iface, ipa_ctx);
 		}
 		}
 
 
 		if (vdev)
 		if (vdev)
@@ -3427,7 +3455,8 @@ static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
  *
  *
  * Return: QDF_STATUS
  * Return: QDF_STATUS
  */
  */
-static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
+static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(struct wlan_ipa_priv *ipa_ctx,
+						   bool ctrl)
 {
 {
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
@@ -3438,9 +3467,10 @@ static inline uint8_t wlan_ipa_get_rx_ipa_client(struct wlan_ipa_priv *ipa_ctx)
 	return IPA_CLIENT_WLAN1_PROD;
 	return IPA_CLIENT_WLAN1_PROD;
 }
 }
 
 
-static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
+static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(struct wlan_ipa_priv *ipa_ctx,
+						   bool ctrl)
 {
 {
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_obj = ipa_ctx;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_wlan_msg_t *ipa_msg;
 	qdf_ipa_wlan_msg_t *ipa_msg;
 	int ret = 0;
 	int ret = 0;
@@ -3453,10 +3483,10 @@ static QDF_STATUS wlan_ipa_uc_send_wdi_control_msg(bool ctrl)
 
 
 	if (ctrl) {
 	if (ctrl) {
 		QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
 		QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_ENABLE);
-		ipa_ctx->stats.event[QDF_WDI_ENABLE]++;
+		ipa_obj->stats.event[QDF_WDI_ENABLE]++;
 	} else {
 	} else {
 		QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
 		QDF_IPA_SET_META_MSG_TYPE(&meta, QDF_WDI_DISABLE);
-		ipa_ctx->stats.event[QDF_WDI_DISABLE]++;
+		ipa_obj->stats.event[QDF_WDI_DISABLE]++;
 	}
 	}
 
 
 	ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
 	ipa_debug("ipa_send_msg(Evt:%d)", QDF_IPA_MSG_META_MSG_TYPE(&meta));
@@ -3729,7 +3759,7 @@ QDF_STATUS wlan_ipa_setup(struct wlan_ipa_priv *ipa_ctx,
 						ipa_ctx);
 						ipa_ctx);
 			}
 			}
 		} else if (status == QDF_STATUS_E_BUSY) {
 		} else if (status == QDF_STATUS_E_BUSY) {
-			ret = wlan_ipa_uc_send_wdi_control_msg(false);
+			ret = wlan_ipa_uc_send_wdi_control_msg(ipa_ctx, false);
 			if (ret) {
 			if (ret) {
 				ipa_err("IPA WDI msg send failed: ret=%d", ret);
 				ipa_err("IPA WDI msg send failed: ret=%d", ret);
 				goto ipa_wdi_destroy;
 				goto ipa_wdi_destroy;
@@ -3835,7 +3865,7 @@ QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
 	}
 	}
 
 
 	if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
 	if (wlan_ipa_uc_is_enabled(ipa_ctx->config)) {
-		wlan_ipa_wdi_cleanup();
+		wlan_ipa_wdi_cleanup(ipa_ctx->hdl);
 		qdf_mutex_destroy(&ipa_ctx->event_lock);
 		qdf_mutex_destroy(&ipa_ctx->event_lock);
 		qdf_mutex_destroy(&ipa_ctx->ipa_lock);
 		qdf_mutex_destroy(&ipa_ctx->ipa_lock);
 		qdf_list_destroy(&ipa_ctx->pending_event);
 		qdf_list_destroy(&ipa_ctx->pending_event);
@@ -3844,6 +3874,15 @@ QDF_STATUS wlan_ipa_cleanup(struct wlan_ipa_priv *ipa_ctx)
 
 
 	gp_ipa = NULL;
 	gp_ipa = NULL;
 
 
+	/* Acquire lock */
+	ipa_init_deinit_lock();
+	if (g_instances_added)
+		g_instances_added--;
+	/* Unlock */
+	ipa_init_deinit_unlock();
+
+	ipa_ctx->handle_initialized = false;
+
 	return QDF_STATUS_SUCCESS;
 	return QDF_STATUS_SUCCESS;
 }
 }
 
 
@@ -3969,7 +4008,7 @@ static void wlan_ipa_uc_loaded_handler(struct wlan_ipa_priv *ipa_ctx)
 	return;
 	return;
 
 
 smmu_map_fail:
 smmu_map_fail:
-	qdf_ipa_wdi_disconn_pipes();
+	qdf_ipa_wdi_disconn_pipes(ipa_ctx->hdl);
 
 
 connect_pipe_fail:
 connect_pipe_fail:
 	if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
 	if (wlan_ipa_uc_sta_is_enabled(ipa_ctx->config)) {
@@ -4014,7 +4053,7 @@ static void wlan_ipa_uc_op_cb(struct op_msg_type *op_msg,
 			qdf_event_set(&ipa_ctx->ipa_resource_comp);
 			qdf_event_set(&ipa_ctx->ipa_resource_comp);
 			if (ipa_ctx->wdi_enabled == false) {
 			if (ipa_ctx->wdi_enabled == false) {
 				ipa_ctx->wdi_enabled = true;
 				ipa_ctx->wdi_enabled = true;
-				if (wlan_ipa_uc_send_wdi_control_msg(true) == 0)
+				if (wlan_ipa_uc_send_wdi_control_msg(ipa_ctx, true) == 0)
 					wlan_ipa_send_mcc_scc_msg(ipa_ctx,
 					wlan_ipa_send_mcc_scc_msg(ipa_ctx,
 							ipa_ctx->mcc_mode);
 							ipa_ctx->mcc_mode);
 			}
 			}
@@ -4103,7 +4142,7 @@ static void __wlan_ipa_uc_fw_op_event_handler(void *data)
 	struct op_msg_type *msg;
 	struct op_msg_type *msg;
 	struct uc_op_work_struct *uc_op_work =
 	struct uc_op_work_struct *uc_op_work =
 				(struct uc_op_work_struct *)data;
 				(struct uc_op_work_struct *)data;
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_ctx = uc_op_work->ipa_priv_bp;
 
 
 	msg = uc_op_work->msg;
 	msg = uc_op_work->msg;
 	uc_op_work->msg = NULL;
 	uc_op_work->msg = NULL;
@@ -4198,6 +4237,7 @@ QDF_STATUS wlan_ipa_uc_ol_init(struct wlan_ipa_priv *ipa_ctx,
 	for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
 	for (i = 0; i < WLAN_IPA_UC_OPCODE_MAX; i++) {
 		ipa_ctx->uc_op_work[i].osdev = osdev;
 		ipa_ctx->uc_op_work[i].osdev = osdev;
 		ipa_ctx->uc_op_work[i].msg = NULL;
 		ipa_ctx->uc_op_work[i].msg = NULL;
+		ipa_ctx->uc_op_work[i].ipa_priv_bp = ipa_ctx;
 		qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
 		qdf_create_work(0, &ipa_ctx->uc_op_work[i].work,
 				wlan_ipa_uc_fw_op_event_handler,
 				wlan_ipa_uc_fw_op_event_handler,
 				&ipa_ctx->uc_op_work[i]);
 				&ipa_ctx->uc_op_work[i]);
@@ -4288,7 +4328,7 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
 		status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
 		status = cdp_ipa_cleanup(ipa_ctx->dp_soc,
 					 ipa_ctx->dp_pdev_id,
 					 ipa_ctx->dp_pdev_id,
 					 ipa_ctx->tx_pipe_handle,
 					 ipa_ctx->tx_pipe_handle,
-					 ipa_ctx->rx_pipe_handle);
+					 ipa_ctx->rx_pipe_handle, ipa_ctx->hdl);
 		if (status)
 		if (status)
 			ipa_err("Failure to cleanup IPA pipes (status=%d)",
 			ipa_err("Failure to cleanup IPA pipes (status=%d)",
 				status);
 				status);
@@ -4314,12 +4354,18 @@ QDF_STATUS wlan_ipa_uc_ol_deinit(struct wlan_ipa_priv *ipa_ctx)
  */
  */
 static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
 static QDF_STATUS wlan_ipa_uc_send_evt(qdf_netdev_t net_dev,
 				       qdf_ipa_wlan_event type,
 				       qdf_ipa_wlan_event type,
-				       uint8_t *mac_addr)
+				       uint8_t *mac_addr,
+				       struct wlan_ipa_priv *ipa_priv)
 {
 {
-	struct wlan_ipa_priv *ipa_ctx = gp_ipa;
+	struct wlan_ipa_priv *ipa_ctx;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_msg_meta_t meta;
 	qdf_ipa_wlan_msg_t *msg;
 	qdf_ipa_wlan_msg_t *msg;
 
 
+	if (!ipa_priv)
+		return QDF_STATUS_E_INVAL;
+
+	ipa_ctx = ipa_priv;
+
 	QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
 	QDF_IPA_MSG_META_MSG_LEN(&meta) = sizeof(qdf_ipa_wlan_msg_t);
 	msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
 	msg = qdf_mem_malloc(QDF_IPA_MSG_META_MSG_LEN(&meta));
 	if (!msg)
 	if (!msg)
@@ -4357,7 +4403,7 @@ void wlan_ipa_uc_cleanup_sta(struct wlan_ipa_priv *ipa_ctx,
 		if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE &&
 		if (iface_ctx && iface_ctx->device_mode == QDF_STA_MODE &&
 		    iface_ctx->dev && iface_ctx->dev == net_dev) {
 		    iface_ctx->dev && iface_ctx->dev == net_dev) {
 			wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
 			wlan_ipa_uc_send_evt(net_dev, QDF_IPA_STA_DISCONNECT,
-					     net_dev->dev_addr);
+					     net_dev->dev_addr, ipa_ctx);
 			wlan_ipa_cleanup_iface(iface_ctx, NULL);
 			wlan_ipa_cleanup_iface(iface_ctx, NULL);
 		}
 		}
 	}
 	}
@@ -4376,7 +4422,7 @@ QDF_STATUS wlan_ipa_uc_disconnect_ap(struct wlan_ipa_priv *ipa_ctx,
 	iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
 	iface_ctx = wlan_ipa_get_iface(ipa_ctx, QDF_SAP_MODE);
 	if (iface_ctx)
 	if (iface_ctx)
 		status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
 		status = wlan_ipa_uc_send_evt(net_dev, QDF_IPA_AP_DISCONNECT,
-					      net_dev->dev_addr);
+					      net_dev->dev_addr, ipa_ctx);
 	else
 	else
 		return QDF_STATUS_E_INVAL;
 		return QDF_STATUS_E_INVAL;
 
 
@@ -4413,11 +4459,13 @@ void wlan_ipa_uc_ssr_cleanup(struct wlan_ipa_priv *ipa_ctx)
 			if (iface->device_mode == QDF_SAP_MODE)
 			if (iface->device_mode == QDF_SAP_MODE)
 				wlan_ipa_uc_send_evt(iface->dev,
 				wlan_ipa_uc_send_evt(iface->dev,
 						     QDF_IPA_AP_DISCONNECT,
 						     QDF_IPA_AP_DISCONNECT,
-						     iface->dev->dev_addr);
+						     iface->dev->dev_addr,
+						     ipa_ctx);
 			else if (iface->device_mode == QDF_STA_MODE)
 			else if (iface->device_mode == QDF_STA_MODE)
 				wlan_ipa_uc_send_evt(iface->dev,
 				wlan_ipa_uc_send_evt(iface->dev,
 						     QDF_IPA_STA_DISCONNECT,
 						     QDF_IPA_STA_DISCONNECT,
-						     iface->dev->dev_addr);
+						     iface->dev->dev_addr,
+						     ipa_ctx);
 			wlan_ipa_cleanup_iface(iface, NULL);
 			wlan_ipa_cleanup_iface(iface, NULL);
 		}
 		}
 	}
 	}

+ 5 - 3
ipa/core/src/wlan_ipa_main.c

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -621,7 +621,8 @@ QDF_STATUS ipa_uc_ol_deinit(struct wlan_objmgr_pdev *pdev)
 
 
 	status = wlan_ipa_uc_ol_deinit(ipa_obj);
 	status = wlan_ipa_uc_ol_deinit(ipa_obj);
 	ipa_obj_cleanup(ipa_obj);
 	ipa_obj_cleanup(ipa_obj);
-	ipa_disable_register_cb();
+	if (!g_instances_added)
+		ipa_disable_register_cb();
 
 
 out:
 out:
 	ipa_init_deinit_unlock();
 	ipa_init_deinit_unlock();
@@ -667,7 +668,8 @@ QDF_STATUS ipa_wlan_evt(struct wlan_objmgr_pdev *pdev, qdf_netdev_t net_dev,
 	}
 	}
 
 
 	return wlan_ipa_wlan_evt(net_dev, device_mode, session_id,
 	return wlan_ipa_wlan_evt(net_dev, device_mode, session_id,
-				 ipa_event_type, mac_addr, is_2g_iface);
+				 ipa_event_type, mac_addr, is_2g_iface,
+				 ipa_obj);
 }
 }
 
 
 int ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)
 int ipa_uc_smmu_map(bool map, uint32_t num_buf, qdf_mem_info_t *buf_arr)

+ 5 - 4
ipa/core/src/wlan_ipa_rm.c

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -47,7 +48,7 @@ QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx,
 			  ipa_ctx->curr_cons_bw, next_bw);
 			  ipa_ctx->curr_cons_bw, next_bw);
 		ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 		ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 					     QDF_IPA_CLIENT_WLAN1_CONS,
 					     QDF_IPA_CLIENT_WLAN1_CONS,
-					     next_bw);
+					     next_bw, ipa_ctx->hdl);
 		if (ret) {
 		if (ret) {
 			ipa_err("RM CONS set perf profile failed: %d", ret);
 			ipa_err("RM CONS set perf profile failed: %d", ret);
 
 
@@ -55,7 +56,7 @@ QDF_STATUS wlan_ipa_set_perf_level(struct wlan_ipa_priv *ipa_ctx,
 		}
 		}
 		ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 		ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 					     QDF_IPA_CLIENT_WLAN1_PROD,
 					     QDF_IPA_CLIENT_WLAN1_PROD,
-					     next_bw);
+					     next_bw, ipa_ctx->hdl);
 		if (ret) {
 		if (ret) {
 			ipa_err("RM PROD set perf profile failed: %d", ret);
 			ipa_err("RM PROD set perf profile failed: %d", ret);
 			return QDF_STATUS_E_FAILURE;
 			return QDF_STATUS_E_FAILURE;
@@ -80,7 +81,7 @@ QDF_STATUS wlan_ipa_init_perf_level(struct wlan_ipa_priv *ipa_ctx)
 
 
 	ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 	ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 				     QDF_IPA_CLIENT_WLAN1_CONS,
 				     QDF_IPA_CLIENT_WLAN1_CONS,
-				     WLAN_IPA_MAX_BANDWIDTH);
+				     WLAN_IPA_MAX_BANDWIDTH, ipa_ctx->hdl);
 	if (ret) {
 	if (ret) {
 		ipa_err("CONS set perf profile failed: %d", ret);
 		ipa_err("CONS set perf profile failed: %d", ret);
 		return QDF_STATUS_E_FAILURE;
 		return QDF_STATUS_E_FAILURE;
@@ -88,7 +89,7 @@ QDF_STATUS wlan_ipa_init_perf_level(struct wlan_ipa_priv *ipa_ctx)
 
 
 	ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 	ret = cdp_ipa_set_perf_level(ipa_ctx->dp_soc,
 				     QDF_IPA_CLIENT_WLAN1_PROD,
 				     QDF_IPA_CLIENT_WLAN1_PROD,
-				     WLAN_IPA_MAX_BANDWIDTH);
+				     WLAN_IPA_MAX_BANDWIDTH, ipa_ctx->hdl);
 	if (ret) {
 	if (ret) {
 		ipa_err("PROD set perf profile failed: %d", ret);
 		ipa_err("PROD set perf profile failed: %d", ret);
 		return QDF_STATUS_E_FAILURE;
 		return QDF_STATUS_E_FAILURE;

+ 5 - 0
ipa/core/src/wlan_ipa_stats.c

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -127,6 +128,10 @@ static void wlan_ipa_uc_rt_debug_handler(void *ctext)
 
 
 void wlan_ipa_uc_rt_debug_destructor(qdf_nbuf_t nbuff)
 void wlan_ipa_uc_rt_debug_destructor(qdf_nbuf_t nbuff)
 {
 {
+	/* Make change to get the ipa_ctx on per pdev basis
+	 * Currently storing the debug count only in global ipa_ctx
+	 * or to the last enumerated radio ipa_ctx
+	 */
 	struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context();
 	struct wlan_ipa_priv *ipa_ctx = wlan_ipa_get_obj_context();
 
 
 	if (!ipa_ctx) {
 	if (!ipa_ctx) {

+ 10 - 1
ipa/dispatcher/inc/wlan_ipa_obj_mgmt_api.h

@@ -1,5 +1,6 @@
 /*
 /*
  * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -69,6 +70,15 @@ static inline bool wlan_ipa_config_is_enabled(void)
 	return ipa_config_is_enabled();
 	return ipa_config_is_enabled();
 }
 }
 
 
+/**
+ * wlan_ipa_get_hdl() - Get ipa hdl set by IPA driver
+ * @psoc: void psoc object
+ * @pdev_id: pdev id
+ *
+ * Return: IPA handle
+ */
+qdf_ipa_wdi_hdl_t wlan_ipa_get_hdl(void *soc, uint8_t pdev_id);
+
 #else
 #else
 
 
 static inline QDF_STATUS ipa_init(void)
 static inline QDF_STATUS ipa_init(void)
@@ -95,7 +105,6 @@ static inline bool wlan_ipa_config_is_enabled(void)
 {
 {
 	return false;
 	return false;
 }
 }
-
 #endif /* IPA_OFFLOAD */
 #endif /* IPA_OFFLOAD */
 
 
 #endif /* _WLAN_IPA_OBJ_MGMT_H_ */
 #endif /* _WLAN_IPA_OBJ_MGMT_H_ */

+ 120 - 26
ipa/dispatcher/src/wlan_ipa_obj_mgmt_api.c

@@ -1,6 +1,6 @@
 /*
 /*
  * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved.
  * Copyright (c) 2018, 2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
  * any purpose with or without fee is hereby granted, provided that the
@@ -23,13 +23,19 @@
 #include "wlan_ipa_obj_mgmt_api.h"
 #include "wlan_ipa_obj_mgmt_api.h"
 #include "wlan_ipa_main.h"
 #include "wlan_ipa_main.h"
 #include "wlan_objmgr_global_obj.h"
 #include "wlan_objmgr_global_obj.h"
+#include <wlan_objmgr_global_obj_i.h>
 #include "target_if_ipa.h"
 #include "target_if_ipa.h"
 #include "wlan_ipa_ucfg_api.h"
 #include "wlan_ipa_ucfg_api.h"
 #include "qdf_platform.h"
 #include "qdf_platform.h"
 #include "qdf_module.h"
 #include "qdf_module.h"
 
 
+/* This is as per IPA capbility */
+#define MAX_INSTANCES_SUPPORTED 2
+
+uint8_t g_instances_added;
 static bool g_ipa_is_ready;
 static bool g_ipa_is_ready;
-static qdf_mutex_t g_init_deinit_lock;
+qdf_mutex_t g_init_deinit_lock;
+
 bool ipa_cb_is_ready(void)
 bool ipa_cb_is_ready(void)
 {
 {
 	return g_ipa_is_ready;
 	return g_ipa_is_ready;
@@ -136,17 +142,24 @@ ipa_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
 static void ipa_register_ready_cb(void *user_data)
 static void ipa_register_ready_cb(void *user_data)
 {
 {
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)user_data;
+	struct wlan_ipa_priv *ipa_obj;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_pdev *pdev;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_psoc *psoc;
 	qdf_device_t qdf_dev;
 	qdf_device_t qdf_dev;
+	qdf_ipa_wdi_capabilities_out_params_t out_param;
+	uint8_t obj_id;
+	uint8_t pdev_id;
+	uint8_t pdev_count;
+	uint8_t instances_supported = 0;
+	uint8_t instances_processed = 0;
 
 
 	if (!ipa_config_is_enabled()) {
 	if (!ipa_config_is_enabled()) {
 		ipa_info("IPA config is disabled");
 		ipa_info("IPA config is disabled");
 		return;
 		return;
 	}
 	}
-	if (!ipa_obj) {
-		ipa_err("IPA object is NULL");
+
+	if (!user_data) {
+		ipa_err("User_data object is NULL");
 		return;
 		return;
 	}
 	}
 
 
@@ -166,31 +179,77 @@ static void ipa_register_ready_cb(void *user_data)
 		ipa_err("Driver modules stop in-progress/done, releasing lock");
 		ipa_err("Driver modules stop in-progress/done, releasing lock");
 		goto out;
 		goto out;
 	}
 	}
-	pdev = ipa_priv_obj_get_pdev(ipa_obj);
-	psoc = wlan_pdev_get_psoc(pdev);
-	qdf_dev = wlan_psoc_get_qdf_dev(psoc);
-	if (!qdf_dev) {
-		ipa_err("QDF device context is NULL");
-		goto out;
-	}
 
 
 	g_ipa_is_ready = true;
 	g_ipa_is_ready = true;
 	ipa_info("IPA ready callback invoked: ipa_register_ready_cb");
 	ipa_info("IPA ready callback invoked: ipa_register_ready_cb");
-	status = ipa_obj_setup(ipa_obj);
-	if (QDF_IS_STATUS_ERROR(status)) {
-		ipa_err("Failed to setup ipa component");
-		wlan_objmgr_pdev_component_obj_detach(pdev,
-						      WLAN_UMAC_COMP_IPA,
-						      ipa_obj);
-		qdf_mem_free(ipa_obj);
-		ipa_disable_register_cb();
-		goto out;
-	}
-	if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) {
-		ipa_err("IPA ucfg_ipa_uc_ol_init failed");
-		goto out;
-	}
 
 
+	/* Make call to get num_instances supported by IPA */
+	qdf_ipa_wdi_get_capabilities(&out_param);
+	instances_supported =
+		QDF_IPA_WDI_CAPABILITIES_OUT_PARAMS_NUM_INSTANCES(&out_param);
+	ipa_info("Max instances supported by IPA is %d", instances_supported);
+
+	for (obj_id = 0; obj_id < WLAN_OBJMGR_MAX_DEVICES; obj_id++) {
+		/* Get Psoc from global umac obj */
+		psoc = g_umac_glb_obj->psoc[obj_id];
+		if (!psoc)
+			continue;
+
+		pdev_count = psoc->soc_objmgr.wlan_pdev_count;
+		for (pdev_id = 0; pdev_id < pdev_count &&
+		     instances_processed < instances_supported &&
+		     instances_processed < g_instances_added;
+		     pdev_id++, instances_processed++) {
+			pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id,
+							  WLAN_IPA_ID);
+
+			if (!pdev) {
+				qdf_err("Pdev is NULL for pdev_id[%d]", pdev_id);
+				continue;
+			}
+
+			/* Get IPA obj from pdev obj */
+			ipa_obj = ipa_pdev_get_priv_obj(pdev);
+
+			if (!ipa_obj) {
+				ipa_err("ipa_obj is NULL for pdev_id[%d]",
+					pdev_id);
+				wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+				continue;
+			}
+
+			if (ipa_obj->handle_initialized) {
+				ipa_info("ipa_obj hdl is true for pdev_id %d", pdev_id);
+				wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+				continue;
+			}
+			/* Update instace_id for current pdev */
+			ipa_obj->instance_id = instances_processed;
+			qdf_dev = wlan_psoc_get_qdf_dev(psoc);
+			if (!qdf_dev) {
+				ipa_err("QDF device context is NULL");
+				wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+				continue;
+			}
+
+			status = ipa_obj_setup(ipa_obj);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				ipa_err("Failed to setup ipa component");
+				wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_IPA,
+								      ipa_obj);
+				qdf_mem_free(ipa_obj);
+				wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+				continue;
+			}
+			if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) {
+				ipa_err("IPA ucfg_ipa_uc_ol_init failed");
+				wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+				continue;
+			}
+			ipa_obj->handle_initialized = true;
+			wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+		}
+	}
 out:
 out:
 	ipa_init_deinit_unlock();
 	ipa_init_deinit_unlock();
 }
 }
@@ -211,6 +270,13 @@ QDF_STATUS ipa_register_is_ipa_ready(struct wlan_objmgr_pdev *pdev)
 		return QDF_STATUS_E_FAILURE;
 		return QDF_STATUS_E_FAILURE;
 	}
 	}
 
 
+	/* Acquire lock */
+	ipa_init_deinit_lock();
+	g_instances_added++;
+	ipa_info("No. of instances added for IPA is %d", g_instances_added);
+	/* Unlock */
+	ipa_init_deinit_unlock();
+
 	ret = qdf_ipa_register_ipa_ready_cb(ipa_register_ready_cb,
 	ret = qdf_ipa_register_ipa_ready_cb(ipa_register_ready_cb,
 					    (void *)ipa_obj);
 					    (void *)ipa_obj);
 	if (ret == -EEXIST) {
 	if (ret == -EEXIST) {
@@ -294,3 +360,31 @@ QDF_STATUS ipa_deinit(void)
 
 
 	return status;
 	return status;
 }
 }
+
+qdf_ipa_wdi_hdl_t wlan_ipa_get_hdl(void *soc, uint8_t pdev_id)
+{
+	struct wlan_objmgr_psoc *psoc = (struct wlan_objmgr_psoc *)soc;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ipa_priv *ipa_obj;
+	qdf_ipa_wdi_hdl_t hdl;
+
+	pdev = wlan_objmgr_get_pdev_by_id(psoc, pdev_id, WLAN_IPA_ID);
+
+	if (!pdev) {
+		ipa_err("Failed to get pdev handle");
+		return IPA_INVALID_HDL;
+	}
+
+	ipa_obj = ipa_pdev_get_priv_obj(pdev);
+	if (!ipa_obj) {
+		ipa_err("IPA object is NULL for pdev_id[%d]", pdev_id);
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+		return IPA_INVALID_HDL;
+	}
+	hdl = ipa_obj->hdl;
+
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_IPA_ID);
+	return hdl;
+}
+
+qdf_export_symbol(wlan_ipa_get_hdl);