qcacld-3.0: Add IPA WDI Unified API support

Support for WDI2 in the Unified IPA WDI APIs.

Change-Id: Ife42a6a96ce80070de51f994e29ded252b3dd980
CRs-Fixed: 2183498
diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c
index 48c67d6..2481ef5 100644
--- a/core/hdd/src/wlan_hdd_ipa.c
+++ b/core/hdd/src/wlan_hdd_ipa.c
@@ -35,7 +35,11 @@
 #ifdef IPA_OFFLOAD
 
 /* Include Files */
+#ifdef CONFIG_IPA_WDI_UNIFIED_API
+#include <qdf_ipa_wdi3.h>
+#else
 #include <qdf_ipa.h>
+#endif
 #include <wlan_hdd_includes.h>
 #include <wlan_hdd_ipa.h>
 
@@ -78,6 +82,8 @@
 #define HDD_IPA_UC_STA_ENABLE_MASK         BIT(6)
 #define HDD_IPA_REAL_TIME_DEBUGGING        BIT(8)
 
+#define HDD_IPA_MAX_BANDWIDTH              800
+
 #define HDD_IPA_MAX_PENDING_EVENT_COUNT    20
 
 #define IPA_WLAN_RX_SOFTIRQ_THRESH 16
@@ -471,6 +477,9 @@
 	struct completion ipa_uc_set_quota_comp;
 #endif
 	struct completion ipa_resource_comp;
+
+	uint32_t wdi_version;
+	bool is_smmu_enabled;	/* IPA caps returned from ipa_wdi_init */
 };
 
 #define HDD_IPA_WLAN_FRAG_HEADER        sizeof(struct frag_header)
@@ -547,8 +556,9 @@
 static void hdd_ipa_uc_proc_pending_event(struct hdd_ipa_priv *hdd_ipa,
 					  bool is_loading);
 
-#if ((defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)) || \
-	defined(IPA_CLIENT_IS_MHI_CONS))
+static int hdd_ipa_uc_enable_pipes(struct hdd_ipa_priv *hdd_ipa);
+static int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa);
+
 /**
  * hdd_ipa_uc_loaded_uc_cb() - IPA UC loaded event callback
  * @priv_ctxt: hdd ipa local context
@@ -641,53 +651,6 @@
 }
 
 /**
- * hdd_ipa_uc_register_uc_ready() - Register UC ready callback function to IPA
- * @hdd_ipa: HDD IPA local context
- *
- * Register IPA UC ready callback function to IPA kernel driver
- * Even IPA UC loaded later than WLAN kernel driver, WLAN kernel driver will
- * open WDI pipe after WLAN driver loading finished
- *
- * Return: 0 Success
- *         -EPERM Registration fail
- */
-static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
-{
-	qdf_ipa_wdi_uc_ready_params_t uc_ready_param;
-	int ret = 0;
-
-	hdd_ipa->uc_loaded = false;
-	QDF_IPA_UC_READY_PARAMS_PRIV(&uc_ready_param) = (void *)hdd_ipa;
-	QDF_IPA_UC_READY_PARAMS_NOTIFY(&uc_ready_param) =
-		hdd_ipa_uc_loaded_uc_cb;
-	if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			"UC Ready CB register fail");
-		return -EPERM;
-	}
-	if (false != QDF_IPA_UC_READY_PARAMS_IS_UC_READY(&uc_ready_param)) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
-		hdd_ipa->uc_loaded = true;
-	} else {
-		ret = hdd_ipa_uc_send_wdi_control_msg(false);
-	}
-
-	return ret;
-}
-#else
-static int hdd_ipa_uc_register_uc_ready(struct hdd_ipa_priv *hdd_ipa)
-{
-	hdd_ipa->uc_loaded = true;
-	return 0;
-}
-
-static int hdd_ipa_uc_send_wdi_control_msg(bool ctrl)
-{
-	return 0;
-}
-#endif
-
-/**
  * hdd_ipa_is_enabled() - Is IPA enabled?
  * @hdd_ctx: Global HDD context
  *
@@ -792,6 +755,891 @@
 					 HDD_IPA_RM_ENABLE_MASK);
 }
 
+#ifdef FEATURE_METERING
+/**
+ * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
+ * IPA calls to get WLAN stats or set quota limit.
+ * @priv: pointer to private data registered with IPA (we register a
+ *»       pointer to the global IPA context)
+ * @evt: the IPA event which triggered the callback
+ * @data: data associated with the event
+ *
+ * Return: None
+ */
+static void __hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
+					    void *data)
+{
+	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
+	struct hdd_adapter *adapter = NULL;
+	qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats;
+	qdf_ipa_set_wifi_quota_t *ipa_set_quota;
+	int ret = 0;
+
+	if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
+		return;
+
+	adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
+
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "event=%d", evt);
+
+	switch (evt) {
+	case IPA_GET_WDI_SAP_STATS:
+		/* fill-up ipa_get_wdi_sap_stats structure after getting
+		 * ipa_uc_fw_stats from FW
+		 */
+		wdi_sap_stats = data;
+
+		if (!adapter) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+				    "IPA uC share stats failed - no adapter");
+			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) =
+				0;
+			return;
+		}
+
+		INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
+		hdd_ipa_uc_sharing_stats_request(
+			adapter,
+			QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats));
+		ret = wait_for_completion_timeout(
+			&hdd_ipa->ipa_uc_sharing_stats_comp,
+			msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
+		if (!ret) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+				    "IPA uC share stats request timed out");
+			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
+				= 0;
+		} else {
+			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
+				= 1;
+
+			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
+			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats)
+				= hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
+			HDD_IPA_DP_LOG(
+				QDF_TRACE_LEVEL_DEBUG,
+				"%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
+				"IPA_GET_WDI_SAP_STATS",
+				QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(
+					wdi_sap_stats),
+				QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(
+					wdi_sap_stats));
+		}
+		break;
+	case IPA_SET_WIFI_QUOTA:
+		/* get ipa_set_wifi_quota structure from IPA and pass to FW
+		 * through quota_exceeded field in ipa_uc_fw_stats
+		 */
+		ipa_set_quota = data;
+
+		if (!adapter) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+				    "IPA uC set quota failed - no adapter");
+			ipa_set_quota->set_valid = 0;
+			return;
+		}
+
+		INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
+		hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
+				     ipa_set_quota->quota_bytes);
+
+		ret = wait_for_completion_timeout(
+				&hdd_ipa->ipa_uc_set_quota_comp,
+				msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
+		if (!ret) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+				    "IPA uC set quota request timed out");
+			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	= 0;
+		} else {
+			QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) =
+				((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
+				  << 32) | hdd_ipa->ipa_quota_rsp.quota_lo;
+			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	=
+				hdd_ipa->ipa_quota_rsp.success;
+		}
+
+		HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
+			       ipa_set_quota->quota_bytes,
+			       ipa_set_quota->set_valid);
+		break;
+	}
+}
+
+/**
+ * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
+ * IPA calls to get WLAN stats or set quota limit.
+ * @priv: pointer to private data registered with IPA (we register a
+ *        pointer to the global IPA context)
+ * @evt: the IPA event which triggered the callback
+ * @data: data associated with the event
+ *
+ * Return: None
+ */
+static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
+					  void *data)
+{
+	cds_ssr_protect(__func__);
+	__hdd_ipa_wdi_meter_notifier_cb(evt, data);
+	cds_ssr_unprotect(__func__);
+}
+
+static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
+{
+	init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
+	init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
+}
+#else /* FEATURE_METERING */
+static void hdd_ipa_wdi_meter_notifier_cb(void)
+{
+}
+
+static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
+{
+}
+#endif /* FEATURE_METERING */
+
+#ifdef CONFIG_IPA_WDI_UNIFIED_API
+
+/*
+ * TODO: Get WDI version through FW capabilities
+ */
+#ifdef CONFIG_LITHIUM
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+	hdd_ipa->wdi_version = IPA_WDI_3;
+}
+#elif defined(QCA_WIFI_3_0)
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+	hdd_ipa->wdi_version = IPA_WDI_2;
+}
+#else
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+	hdd_ipa->wdi_version = IPA_WDI_1;
+}
+#endif
+
+static inline bool hdd_ipa_wdi_is_smmu_enabled(struct hdd_ipa_priv *hdd_ipa,
+					qdf_device_t osdev)
+{
+	/* TODO: Need to check if SMMU is supported on cld_3.2 */
+	/* return hdd_ipa->is_smmu_enabled && qdf_mem_smmu_s1_enabled(osdev); */
+	return 0;
+}
+
+static inline QDF_STATUS hdd_ipa_wdi_setup(struct hdd_ipa_priv *hdd_ipa)
+{
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
+	struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
+	qdf_ipa_sys_connect_params_t sys_in[HDD_IPA_MAX_IFACE];
+	int i;
+
+	for (i = 0; i < HDD_IPA_MAX_IFACE; i++)
+		memcpy(&sys_in[i],
+		       &hdd_ipa->sys_pipe[i].ipa_sys_params,
+		       sizeof(qdf_ipa_sys_connect_params_t));
+
+	return cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
+			       hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
+			       hdd_ipa_wdi_meter_notifier_cb,
+			       hdd_ctx->config->IpaDescSize,
+			       hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
+			       &hdd_ipa->tx_pipe_handle,
+			       &hdd_ipa->rx_pipe_handle,
+			       hdd_ipa_wdi_is_smmu_enabled(hdd_ipa, osdev),
+			       sys_in);
+}
+
+#ifdef FEATURE_METERING
+static inline void hdd_ipa_wdi_init_metering(struct hdd_ipa_priv *ipa_ctxt, void *in)
+{
+	qdf_ipa_wdi_init_in_params_t *wdi3_in;
+
+	wdi3_in = (qdf_ipa_wdi_init_in_params_t *)in;
+	QDF_IPA_WDI_INIT_IN_PARAMS_WDI_NOTIFY(wdi3_in) =
+				hdd_ipa_wdi_meter_notifier_cb;
+}
+#else
+static inline void hdd_ipa_wdi_init_metering(struct hdd_ipa_priv *ipa_ctxt, void *in)
+{
+}
+#endif
+
+static inline int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa)
+{
+	qdf_ipa_wdi_init_in_params_t in;
+	qdf_ipa_wdi_init_out_params_t out;
+	int ret;
+
+	hdd_ipa->uc_loaded = false;
+
+	QDF_IPA_WDI_INIT_IN_PARAMS_WDI_VERSION(&in) = hdd_ipa->wdi_version;
+	QDF_IPA_WDI_INIT_IN_PARAMS_NOTIFY(&in) = hdd_ipa_uc_loaded_uc_cb;
+	QDF_IPA_WDI_INIT_IN_PARAMS_PRIV(&in) = (void *)hdd_ipa;
+	hdd_ipa_wdi_init_metering(hdd_ipa, (void *)&in);
+
+	ret = qdf_ipa_wdi_init(&in, &out);
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "ipa_wdi_init failed with ret=%d", ret);
+		return -EPERM;
+	}
+
+	if (QDF_IPA_WDI_INIT_OUT_PARAMS_IS_UC_READY(&out)) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "IPA uC READY");
+		hdd_ipa->uc_loaded = true;
+		hdd_ipa->is_smmu_enabled =
+			QDF_IPA_WDI_INIT_OUT_PARAMS_IS_SMMU_ENABLED(&out);
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "is_smmu_enabled=%d",
+			    hdd_ipa->is_smmu_enabled);
+	} else {
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+static inline int hdd_ipa_wdi_cleanup(void)
+{
+	int ret;
+
+	ret = qdf_ipa_wdi_cleanup();
+	if (ret)
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "ipa_wdi_cleanup failed ret=%d", ret);
+	return ret;
+}
+
+static inline int hdd_ipa_wdi_setup_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+					     struct ipa_sys_connect_params *sys,
+					     uint32_t *handle)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_teardown_sys_pipe(struct hdd_ipa_priv *hdd_ipa,
+						uint32_t handle)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_request_resource(
+			struct hdd_ipa_priv *hdd_ipa,
+			enum ipa_rm_resource_name res_name)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_release_resource(
+			struct hdd_ipa_priv *hdd_ipa,
+			enum ipa_rm_resource_name res_name)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_setup_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_destroy_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_request(struct hdd_ipa_priv *hdd_ipa)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
+{
+	return 0;
+}
+
+static inline int hdd_ipa_wdi_rm_notify_completion(
+			enum ipa_rm_event event,
+			enum ipa_rm_resource_name resource_name)
+{
+	return 0;
+}
+
+#else /* CONFIG_IPA_WDI_UNIFIED_API */
+
+static inline void hdd_ipa_wdi_get_wdi_version(struct hdd_ipa_priv *hdd_ipa)
+{
+}
+
+static inline int hdd_ipa_wdi_is_smmu_enabled(struct hdd_ipa_priv *hdd_ipa,
+				       qdf_device_t osdev)
+{
+	/* TODO: Need to check if SMMU is supported on cld_3.2 */
+	/* return qdf_mem_smmu_s1_enabled(osdev); */
+	return 0;
+}
+
+static inline QDF_STATUS hdd_ipa_wdi_setup(struct hdd_ipa_priv *hdd_ipa)
+{
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
+	void *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
+	struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
+
+	return cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
+			       hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
+			       hdd_ipa_wdi_meter_notifier_cb,
+			       hdd_ctx->config->IpaDescSize,
+			       hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
+			       &hdd_ipa->tx_pipe_handle,
+			       &hdd_ipa->rx_pipe_handle);
+}
+
+static inline int hdd_ipa_wdi_init(struct hdd_ipa_priv *hdd_ipa)
+{
+	struct ipa_wdi_uc_ready_params uc_ready_param;
+	int ret = 0;
+
+	hdd_ipa->uc_loaded = false;
+	uc_ready_param.priv = (void *)hdd_ipa;
+	uc_ready_param.notify = hdd_ipa_uc_loaded_uc_cb;
+	if (ipa_uc_reg_rdyCB(&uc_ready_param)) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "UC Ready CB register fail");
+		return -EPERM;
+	}
+
+	if (true == uc_ready_param.is_uC_ready) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "UC Ready");
+		hdd_ipa->uc_loaded = true;
+	} else {
+		ret = -EACCES;
+	}
+
+	return ret;
+}
+
+static inline int hdd_ipa_wdi_cleanup(void)
+{
+	int ret;
+
+	ret = ipa_uc_dereg_rdyCB();
+	if (ret)
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "UC Ready CB deregister fail");
+	return ret;
+}
+
+static inline int hdd_ipa_wdi_setup_sys_pipe(
+		struct hdd_ipa_priv *hdd_ipa,
+		struct ipa_sys_connect_params *sys, uint32_t *handle)
+{
+	return qdf_ipa_setup_sys_pipe(sys, handle);
+}
+
+static inline int hdd_ipa_wdi_teardown_sys_pipe(
+		struct hdd_ipa_priv *hdd_ipa,
+		uint32_t handle)
+{
+	return qdf_ipa_teardown_sys_pipe(handle);
+}
+
+static inline int hdd_ipa_wdi_rm_request_resource(
+		struct hdd_ipa_priv *hdd_ipa,
+		enum ipa_rm_resource_name res_name)
+{
+	return qdf_ipa_rm_request_resource(res_name);
+}
+
+static inline int hdd_ipa_wdi_rm_release_resource(
+		struct hdd_ipa_priv *hdd_ipa,
+		enum ipa_rm_resource_name res_name)
+{
+	return qdf_ipa_rm_release_resource(res_name);
+}
+
+/**
+ * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
+ * @work: struct work_struct
+ * @work_handler: work_handler
+ *
+ * Return: none
+ */
+static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
+					work_func_t work_handler)
+{
+	INIT_WORK(work, work_handler);
+}
+
+/**
+ * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
+ * @work: scheduled work
+ *
+ * When IPA resources are released in hdd_ipa_wdi_rm_try_release() we do
+ * not want to immediately release the wake lock since the system
+ * would then potentially try to suspend when there is a healthy data
+ * rate.  Deferred work is scheduled and this function handles the
+ * work.  When this function is called, if the IPA resource is still
+ * released then we release the wake lock.
+ *
+ * Return: None
+ */
+static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
+{
+	struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
+						    struct hdd_ipa_priv,
+						    wake_lock_work);
+
+	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+
+	if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
+		goto end;
+
+	hdd_ipa->wake_lock_released = true;
+	qdf_wake_lock_release(&hdd_ipa->wake_lock,
+			      WIFI_POWER_EVENT_WAKELOCK_IPA);
+
+end:
+	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+}
+
+/**
+ * hdd_ipa_wdi_rm_request() - Request resource from IPA
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 on success, negative errno on error
+ */
+static int hdd_ipa_wdi_rm_request(struct hdd_ipa_priv *hdd_ipa)
+{
+	int ret = 0;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return 0;
+
+	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+
+	switch (hdd_ipa->rm_state) {
+	case HDD_IPA_RM_GRANTED:
+		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+		return 0;
+	case HDD_IPA_RM_GRANT_PENDING:
+		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+		return -EINPROGRESS;
+	case HDD_IPA_RM_RELEASED:
+		hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
+		break;
+	}
+
+	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+	ret = qdf_ipa_rm_inactivity_timer_request_resource(
+			IPA_RM_RESOURCE_WLAN_PROD);
+
+	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+	if (ret == 0) {
+		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+		hdd_ipa->stats.num_rm_grant_imm++;
+	}
+
+	cancel_delayed_work(&hdd_ipa->wake_lock_work);
+	if (hdd_ipa->wake_lock_released) {
+		qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
+				      WIFI_POWER_EVENT_WAKELOCK_IPA);
+		hdd_ipa->wake_lock_released = false;
+	}
+	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+	return ret;
+}
+
+/**
+ * hdd_ipa_wdi_rm_try_release() - Attempt to release IPA resource
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 if resources released, negative errno otherwise
+ */
+static int hdd_ipa_wdi_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
+{
+	int ret = 0;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return 0;
+
+	if (atomic_read(&hdd_ipa->tx_ref_cnt))
+		return -EAGAIN;
+
+	qdf_spin_lock_bh(&hdd_ipa->pm_lock);
+
+	if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
+		qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
+		return -EAGAIN;
+	}
+	qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
+
+	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+	switch (hdd_ipa->rm_state) {
+	case HDD_IPA_RM_GRANTED:
+		break;
+	case HDD_IPA_RM_GRANT_PENDING:
+		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+		return -EINPROGRESS;
+	case HDD_IPA_RM_RELEASED:
+		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+		return 0;
+	}
+
+	/* IPA driver returns immediately so set the state here to avoid any
+	 * race condition.
+	 */
+	hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
+	hdd_ipa->stats.num_rm_release++;
+	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+	ret = qdf_ipa_rm_inactivity_timer_release_resource(
+				IPA_RM_RESOURCE_WLAN_PROD);
+
+	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+	if (unlikely(ret != 0)) {
+		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+		WARN_ON(1);
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
+			"ipa_rm_inactivity_timer_release_resource returnied fail");
+	}
+
+	/*
+	 * If wake_lock is released immediately, kernel would try to suspend
+	 * immediately as well, Just avoid ping-pong between suspend-resume
+	 * while there is healthy amount of data transfer going on by
+	 * releasing the wake_lock after some delay.
+	 */
+	schedule_delayed_work(&hdd_ipa->wake_lock_work,
+			      msecs_to_jiffies
+				      (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
+
+	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+
+	return ret;
+}
+
+/**
+ * hdd_ipa_rm_notify() - IPA resource manager notifier callback
+ * @user_data: user data registered with IPA
+ * @event: the IPA resource manager event that occurred
+ * @data: the data associated with the event
+ *
+ * Return: None
+ */
+static void hdd_ipa_rm_notify(void *user_data, enum ipa_rm_event event,
+			      unsigned long data)
+{
+	struct hdd_ipa_priv *hdd_ipa = user_data;
+
+	if (unlikely(!hdd_ipa))
+		return;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return;
+
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
+
+	switch (event) {
+	case IPA_RM_RESOURCE_GRANTED:
+		if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
+			/* RM Notification comes with ISR context
+			 * it should be serialized into work queue to avoid
+			 * ISR sleep problem
+			 */
+			hdd_ipa->uc_rm_work.event = event;
+			schedule_work(&hdd_ipa->uc_rm_work.work);
+			break;
+		}
+		qdf_spin_lock_bh(&hdd_ipa->rm_lock);
+		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
+		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
+		hdd_ipa->stats.num_rm_grant++;
+		break;
+
+	case IPA_RM_RESOURCE_RELEASED:
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
+		hdd_ipa->resource_unloading = false;
+		break;
+
+	default:
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
+		break;
+	}
+}
+
+/**
+ * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
+ *
+ * Callback function registered with IPA that is called when IPA wants
+ * to release the WLAN consumer resource
+ *
+ * Return: 0 if the request is granted, negative errno otherwise
+ */
+static int hdd_ipa_rm_cons_release(void)
+{
+	return 0;
+}
+
+/**
+ * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
+ *
+ * Callback function registered with IPA that is called when IPA wants
+ * to access the WLAN consumer resource
+ *
+ * Return: 0 if the request is granted, negative errno otherwise
+ */
+static int hdd_ipa_rm_cons_request(void)
+{
+	int ret = 0;
+
+	if (ghdd_ipa->resource_loading) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+			    "IPA resource loading in progress");
+		ghdd_ipa->pending_cons_req = true;
+		ret = -EINPROGRESS;
+	} else if (ghdd_ipa->resource_unloading) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
+			    "IPA resource unloading in progress");
+		ghdd_ipa->pending_cons_req = true;
+		ret = -EPERM;
+	}
+
+	return ret;
+}
+
+/**
+ * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
+ * @context: User context registered with TL (the IPA Global context is
+ *	registered
+ * @rxpkt: Packet containing the notification
+ * @staid: ID of the station associated with the packet
+ *
+ * Return: None
+ */
+static void
+hdd_ipa_uc_rm_notify_handler(void *context, enum ipa_rm_event event)
+{
+	struct hdd_ipa_priv *hdd_ipa = context;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	/*
+	 * When SSR is going on or driver is unloading, just return.
+	 */
+	status = wlan_hdd_validate_context(hdd_ipa->hdd_ctx);
+	if (status)
+		return;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return;
+
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d", event);
+
+	switch (event) {
+	case IPA_RM_RESOURCE_GRANTED:
+		/* Differed RM Granted */
+		qdf_mutex_acquire(&hdd_ipa->ipa_lock);
+		if ((false == hdd_ipa->resource_unloading) &&
+			(!hdd_ipa->activated_fw_pipe)) {
+			hdd_ipa_uc_enable_pipes(hdd_ipa);
+		}
+		qdf_mutex_release(&hdd_ipa->ipa_lock);
+		break;
+
+	case IPA_RM_RESOURCE_RELEASED:
+		/* Differed RM Released */
+		hdd_ipa->resource_unloading = false;
+		break;
+
+	default:
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "invalid event code %d",  event);
+		break;
+	}
+}
+
+/**
+ * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
+ * @hdd_ipa: Global HDD IPA context
+ * @event: IPA resource manager event to be deferred
+ *
+ * This function is called when a resource manager event is received
+ * from firmware in interrupt context.  This function will defer the
+ * handling to the OL RX thread
+ *
+ * Return: None
+ */
+static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
+{
+	enum ipa_rm_event event;
+	struct uc_rm_work_struct *uc_rm_work = container_of(work,
+			struct uc_rm_work_struct, work);
+	struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
+			struct hdd_ipa_priv, uc_rm_work);
+
+	cds_ssr_protect(__func__);
+	event = uc_rm_work->event;
+	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "posted event %d",  event);
+
+	hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
+	cds_ssr_unprotect(__func__);
+}
+
+/**
+ * hdd_ipa_wdi_setup_rm() - Setup IPA resource management
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Return: 0 on success, negative errno on error
+ */
+static int hdd_ipa_wdi_setup_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+	struct ipa_rm_create_params create_params = { 0 };
+	int ret;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return 0;
+
+	hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
+				hdd_ipa_uc_rm_notify_defer);
+	memset(&create_params, 0, sizeof(create_params));
+	create_params.name = IPA_RM_RESOURCE_WLAN_PROD;
+	create_params.reg_params.user_data = hdd_ipa;
+	create_params.reg_params.notify_cb = hdd_ipa_rm_notify;
+	create_params.floor_voltage = IPA_VOLTAGE_SVS;
+
+	ret = qdf_ipa_rm_create_resource(&create_params);
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "Create RM resource failed: %d", ret);
+		goto setup_rm_fail;
+	}
+
+	memset(&create_params, 0, sizeof(create_params));
+	create_params.name = IPA_RM_RESOURCE_WLAN_CONS;
+	create_params.request_resource = hdd_ipa_rm_cons_request;
+	create_params.release_resource = hdd_ipa_rm_cons_release;
+	create_params.floor_voltage = IPA_VOLTAGE_SVS;
+
+	ret = qdf_ipa_rm_create_resource(&create_params);
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "Create RM CONS resource failed: %d", ret);
+		goto delete_prod;
+	}
+
+	ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+			      IPA_RM_RESOURCE_APPS_CONS);
+
+	ret = qdf_ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
+					   HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
+			    ret);
+		goto timer_init_failed;
+	}
+
+	/* Set the lowest bandwidth to start with */
+	ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
+
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "Set perf level failed: %d", ret);
+		goto set_perf_failed;
+	}
+
+	qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
+	INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
+			  hdd_ipa_wake_lock_timer_func);
+	qdf_spinlock_create(&hdd_ipa->rm_lock);
+	hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
+	hdd_ipa->wake_lock_released = true;
+	atomic_set(&hdd_ipa->tx_ref_cnt, 0);
+
+	return ret;
+
+set_perf_failed:
+	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
+
+timer_init_failed:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+
+delete_prod:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+
+setup_rm_fail:
+	return ret;
+}
+
+/**
+ * hdd_ipa_wdi_destroy_rm() - Destroy IPA resources
+ * @hdd_ipa: Global HDD IPA context
+ *
+ * Destroys all resources associated with the IPA resource manager
+ *
+ * Return: None
+ */
+static void hdd_ipa_wdi_destroy_rm(struct hdd_ipa_priv *hdd_ipa)
+{
+	int ret;
+
+	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
+		return;
+
+	cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
+	qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
+	cancel_work_sync(&hdd_ipa->uc_rm_work.work);
+	qdf_spinlock_destroy(&hdd_ipa->rm_lock);
+
+	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
+
+	ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+	if (ret)
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "RM PROD resource delete failed %d", ret);
+
+	ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+	if (ret)
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "RM CONS resource delete failed %d", ret);
+}
+
+static int hdd_ipa_wdi_rm_notify_completion(enum ipa_rm_event event,
+		enum ipa_rm_resource_name resource_name)
+{
+	return qdf_ipa_rm_notify_completion(event, resource_name);
+}
+#endif /* CONFIG_IPA_WDI_UNIFIED_API */
+
 /**
  * hdd_ipa_uc_rt_debug_host_fill - fill rt debug buffer
  * @ctext: pointer to hdd context.
@@ -832,7 +1680,7 @@
 	qdf_mutex_release(&hdd_ipa->rt_debug_lock);
 
 	qdf_mc_timer_start(&hdd_ipa->rt_debug_fill_timer,
-		HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
+			   HDD_IPA_UC_RT_DEBUG_FILL_INTERVAL);
 }
 
 /**
@@ -861,14 +1709,14 @@
 
 	if (!hdd_ipa_is_rt_debugging_enabled(hdd_ctx)) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
-			"IPA RT debug is not enabled");
+			    "IPA RT debug is not enabled");
 		return;
 	}
 
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
-		"========= WLAN-IPA DEBUG BUF DUMP ==========\n");
+		    "========= WLAN-IPA DEBUG BUF DUMP ==========\n");
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
-		"     TM     :   EXEP   :   DROP   :   NETS   :   FWOK   :   TXFD   :   DSTR   :   DSCD\n");
+		    "     TM     :   EXEP   :   DROP   :   NETS   :   FWOK   :   TXFD   :   DSTR   :   DSCD\n");
 
 	qdf_mutex_acquire(&hdd_ipa->rt_debug_lock);
 	for (dump_count = 0;
@@ -878,16 +1726,16 @@
 			HDD_IPA_UC_RT_DEBUG_BUF_COUNT;
 		dump_info = &hdd_ipa->rt_bug_buffer[dump_index];
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
-			"%12llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n",
-			dump_info->time, dump_info->ipa_excep_count,
-			dump_info->rx_drop_count, dump_info->net_sent_count,
-			dump_info->tx_fwd_ok_count, dump_info->tx_fwd_count,
-			dump_info->rx_destructor_call,
-			dump_info->rx_discard_count);
+			    "%12llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu:%10llu\n",
+			    dump_info->time, dump_info->ipa_excep_count,
+			    dump_info->rx_drop_count, dump_info->net_sent_count,
+			    dump_info->tx_fwd_ok_count, dump_info->tx_fwd_count,
+			    dump_info->rx_destructor_call,
+			    dump_info->rx_discard_count);
 	}
 	qdf_mutex_release(&hdd_ipa->rt_debug_lock);
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO,
-		"======= WLAN-IPA DEBUG BUF DUMP END ========\n");
+		    "======= WLAN-IPA DEBUG BUF DUMP END ========\n");
 }
 
 /**
@@ -1899,7 +2747,7 @@
 	result = cdp_ipa_enable_pipes(soc, (struct cdp_pdev *)pdev);
 	if (result) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-				"Enable PIPE fail, code %d", result);
+				"Enable IPA WDI PIPE failed: ret=%d", result);
 		goto end;
 	}
 
@@ -1945,7 +2793,7 @@
 	result = cdp_ipa_disable_pipes(soc, (struct cdp_pdev *)pdev);
 	if (result) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-				"Disable WDI PIPE fail, code %d", result);
+				"Disable IPA WDI PIPE failed: ret=%d", result);
 		goto end;
 	}
 
@@ -1977,13 +2825,14 @@
 	 * PROD resource may return sync or async manners
 	 */
 	if (hdd_ipa_is_rm_enabled(hdd_ctx)) {
-		if (!ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
+		if (!hdd_ipa_wdi_rm_request_resource(
+			hdd_ipa, IPA_RM_RESOURCE_WLAN_PROD)) {
 			/* RM PROD request sync return
 			 * enable pipe immediately
 			 */
 			if (hdd_ipa_uc_enable_pipes(hdd_ipa)) {
 				HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"IPA WDI Pipe activation failed");
+					    "IPA WDI Pipe activation failed");
 				hdd_ipa->resource_loading = false;
 				return -EBUSY;
 			}
@@ -2036,86 +2885,6 @@
 }
 
 /**
- * hdd_ipa_uc_rm_notify_handler() - IPA uC resource notification handler
- * @context: User context registered with TL (the IPA Global context is
- *	registered
- * @rxpkt: Packet containing the notification
- * @staid: ID of the station associated with the packet
- *
- * Return: None
- */
-static void
-hdd_ipa_uc_rm_notify_handler(void *context, qdf_ipa_rm_event_t event)
-{
-	struct hdd_ipa_priv *hdd_ipa = context;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	struct hdd_context *hdd_ctx = hdd_ipa->hdd_ctx;
-
-	/*
-	 * When SSR is going on or driver is unloading, just return.
-	 */
-	status = wlan_hdd_validate_context(hdd_ctx);
-	if (status)
-		return;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ctx))
-		return;
-
-	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "event code %d",
-		     event);
-
-	switch (event) {
-	case IPA_RM_RESOURCE_GRANTED:
-		/* Differed RM Granted */
-		qdf_mutex_acquire(&hdd_ipa->ipa_lock);
-		if ((false == hdd_ipa->resource_unloading) &&
-			(!hdd_ipa->activated_fw_pipe)) {
-			hdd_ipa_uc_enable_pipes(hdd_ipa);
-		}
-		qdf_mutex_release(&hdd_ipa->ipa_lock);
-		break;
-
-	case IPA_RM_RESOURCE_RELEASED:
-		/* Differed RM Released */
-		hdd_ipa->resource_unloading = false;
-		break;
-
-	default:
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "invalid event code %d",  event);
-		break;
-	}
-}
-
-/**
- * hdd_ipa_uc_rm_notify_defer() - Defer IPA uC notification
- * @hdd_ipa: Global HDD IPA context
- * @event: IPA resource manager event to be deferred
- *
- * This function is called when a resource manager event is received
- * from firmware in interrupt context.  This function will defer the
- * handling to the OL RX thread
- *
- * Return: None
- */
-static void hdd_ipa_uc_rm_notify_defer(struct work_struct *work)
-{
-	qdf_ipa_rm_event_t event;
-	struct uc_rm_work_struct *uc_rm_work = container_of(work,
-			struct uc_rm_work_struct, work);
-	struct hdd_ipa_priv *hdd_ipa = container_of(uc_rm_work,
-			struct hdd_ipa_priv, uc_rm_work);
-
-	cds_ssr_protect(__func__);
-	event = uc_rm_work->event;
-	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG,
-		"posted event %d",  event);
-
-	hdd_ipa_uc_rm_notify_handler(hdd_ipa, event);
-	cds_ssr_unprotect(__func__);
-}
-
-/**
  * hdd_ipa_uc_loaded_handler() - Process IPA uC loaded indication
  * @hdd_ipa: hdd ipa local context
  *
@@ -2139,13 +2908,7 @@
 	hdd_ctx = hdd_ipa->hdd_ctx;
 
 	/* Connect pipe */
-	status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
-			       hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
-			       hdd_ipa_wdi_meter_notifier_cb,
-			       hdd_ctx->config->IpaDescSize,
-			       hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
-			       &hdd_ipa->tx_pipe_handle,
-			       &hdd_ipa->rx_pipe_handle);
+	status = hdd_ipa_wdi_setup(hdd_ipa);
 	if (status) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 			    "Failure to setup IPA pipes (status=%d)",
@@ -2698,7 +3461,7 @@
 			}
 			hdd_ipa_uc_proc_pending_event(hdd_ipa, true);
 			if (hdd_ipa->pending_cons_req)
-				ipa_rm_notify_completion(
+				hdd_ipa_wdi_rm_notify_completion(
 						IPA_RM_RESOURCE_GRANTED,
 						IPA_RM_RESOURCE_WLAN_CONS);
 			hdd_ipa->pending_cons_req = false;
@@ -2725,8 +3488,8 @@
 			hdd_ipa->resource_unloading = false;
 			complete(&hdd_ipa->ipa_resource_comp);
 			if (hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-				ipa_rm_release_resource(
-					IPA_RM_RESOURCE_WLAN_PROD);
+				hdd_ipa_wdi_rm_release_resource(
+					hdd_ipa, IPA_RM_RESOURCE_WLAN_PROD);
 			hdd_ipa_uc_proc_pending_event(hdd_ipa, false);
 			hdd_ipa->pending_cons_req = false;
 		}
@@ -2933,174 +3696,6 @@
 	INIT_WORK(work, work_handler);
 }
 
-#ifdef FEATURE_METERING
-/**
- * __hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
- * IPA calls to get WLAN stats or set quota limit.
- * @priv: pointer to private data registered with IPA (we register a
- *»       pointer to the global IPA context)
- * @evt: the IPA event which triggered the callback
- * @data: data associated with the event
- *
- * Return: None
- */
-static void __hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
-					  void *data)
-{
-	struct hdd_ipa_priv *hdd_ipa = ghdd_ipa;
-	struct hdd_adapter *adapter = NULL;
-	qdf_ipa_get_wdi_sap_stats_t *wdi_sap_stats;
-	qdf_ipa_set_wifi_quota_t *ipa_set_quota;
-	int ret = 0;
-
-	if (wlan_hdd_validate_context(hdd_ipa->hdd_ctx))
-		return;
-
-	adapter = hdd_get_adapter(hdd_ipa->hdd_ctx, QDF_STA_MODE);
-
-	HDD_IPA_LOG(QDF_TRACE_LEVEL_INFO, "event=%d", evt);
-
-	switch (evt) {
-	case IPA_GET_WDI_SAP_STATS:
-		/* fill-up ipa_get_wdi_sap_stats structure after getting
-		 * ipa_uc_fw_stats from FW
-		 */
-		wdi_sap_stats = data;
-
-		if (!adapter) {
-			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-				"IPA uC share stats failed - no adapter");
-			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats) =
-				0;
-			return;
-		}
-
-		INIT_COMPLETION(hdd_ipa->ipa_uc_sharing_stats_comp);
-		hdd_ipa_uc_sharing_stats_request(adapter,
-			QDF_IPA_GET_WDI_SAP_STATS_RESET_STATS(wdi_sap_stats));
-		ret = wait_for_completion_timeout(
-			&hdd_ipa->ipa_uc_sharing_stats_comp,
-			msecs_to_jiffies(IPA_UC_SHARING_STATES_WAIT_TIME));
-		if (!ret) {
-			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"IPA uC share stats request timed out");
-			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
-				= 0;
-		} else {
-			QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(wdi_sap_stats)
-				= 1;
-
-			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv4_rx_packets;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv4_rx_bytes;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv6_rx_packets;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv6_rx_bytes;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv4_tx_packets;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv4_tx_bytes;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv6_tx_packets;
-			QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(wdi_sap_stats)
-				= hdd_ipa->ipa_sharing_stats.ipv6_tx_bytes;
-			HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG,
-				"%s:%d,%llu,%llu,%llu,%llu,%llu,%llu,%llu,%llu",
-				"IPA_GET_WDI_SAP_STATS",
-				QDF_IPA_GET_WDI_SAP_STATS_STATS_VALID(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_PACKETS(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV4_RX_BYTES(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_PACKETS(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV6_RX_BYTES(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_PACKETS(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV4_TX_BYTES(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_PACKETS(
-					wdi_sap_stats),
-				QDF_IPA_GET_WDI_SAP_STATS_IPV6_TX_BYTES(
-					wdi_sap_stats));
-		}
-		break;
-	case IPA_SET_WIFI_QUOTA:
-		/* get ipa_set_wifi_quota structure from IPA and pass to FW
-		 * through quota_exceeded field in ipa_uc_fw_stats
-		 */
-		ipa_set_quota = data;
-
-		if (!adapter) {
-			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-				"IPA uC set quota failed - no adapter");
-			ipa_set_quota->set_valid = 0;
-			return;
-		}
-
-		INIT_COMPLETION(hdd_ipa->ipa_uc_set_quota_comp);
-		hdd_ipa_uc_set_quota(adapter, ipa_set_quota->set_quota,
-				     ipa_set_quota->quota_bytes);
-
-		ret = wait_for_completion_timeout(
-				&hdd_ipa->ipa_uc_set_quota_comp,
-				msecs_to_jiffies(IPA_UC_SET_QUOTA_WAIT_TIME));
-		if (!ret) {
-			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"IPA uC set quota request timed out");
-			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	= 0;
-		} else {
-			QDF_IPA_SET_WIFI_QUOTA_BYTES(ipa_set_quota) =
-				((uint64_t)(hdd_ipa->ipa_quota_rsp.quota_hi)
-				  <<32)|hdd_ipa->ipa_quota_rsp.quota_lo;
-			QDF_IPA_SET_WIFI_QUOTA_SET_VALID(ipa_set_quota)	=
-				hdd_ipa->ipa_quota_rsp.success;
-		}
-
-		HDD_IPA_DP_LOG(QDF_TRACE_LEVEL_DEBUG, "SET_QUOTA: %llu, %d",
-			       ipa_set_quota->quota_bytes,
-			       ipa_set_quota->set_valid);
-		break;
-	}
-}
-
-/**
- * hdd_ipa_wdi_meter_notifier_cb() - WLAN to IPA callback handler.
- * IPA calls to get WLAN stats or set quota limit.
- * @priv: pointer to private data registered with IPA (we register a
- *        pointer to the global IPA context)
- * @evt: the IPA event which triggered the callback
- * @data: data associated with the event
- *
- * Return: None
- */
-static void hdd_ipa_wdi_meter_notifier_cb(qdf_ipa_wdi_meter_evt_type_t evt,
-					  void *data)
-{
-	cds_ssr_protect(__func__);
-	__hdd_ipa_wdi_meter_notifier_cb(evt, data);
-	cds_ssr_unprotect(__func__);
-}
-
-static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
-{
-	init_completion(&ipa_ctxt->ipa_uc_sharing_stats_comp);
-	init_completion(&ipa_ctxt->ipa_uc_set_quota_comp);
-}
-#else
-static void hdd_ipa_wdi_meter_notifier_cb(void)
-{
-}
-
-static void hdd_ipa_init_metering(struct hdd_ipa_priv *ipa_ctxt)
-{
-}
-#endif
-
 /**
  * hdd_ipa_uc_ol_init() - Initialize IPA uC offload
  * @hdd_ctx: Global HDD context
@@ -3147,13 +3742,7 @@
 	}
 
 	if (true == hdd_ipa->uc_loaded) {
-		status = cdp_ipa_setup(soc, (struct cdp_pdev *)pdev,
-				       hdd_ipa_i2w_cb, hdd_ipa_w2i_cb,
-				       hdd_ipa_wdi_meter_notifier_cb,
-				       hdd_ctx->config->IpaDescSize,
-				       hdd_ipa, hdd_ipa_is_rm_enabled(hdd_ctx),
-				       &hdd_ipa->tx_pipe_handle,
-				       &hdd_ipa->rx_pipe_handle);
+		status = hdd_ipa_wdi_setup(hdd_ipa);
 		if (status) {
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 				    "Failure to setup IPA pipes (status=%d)",
@@ -3606,245 +4195,6 @@
 }
 
 /**
- * hdd_ipa_wake_lock_timer_func() - Wake lock work handler
- * @work: scheduled work
- *
- * When IPA resources are released in hdd_ipa_rm_try_release() we do
- * not want to immediately release the wake lock since the system
- * would then potentially try to suspend when there is a healthy data
- * rate.  Deferred work is scheduled and this function handles the
- * work.  When this function is called, if the IPA resource is still
- * released then we release the wake lock.
- *
- * Return: None
- */
-static void hdd_ipa_wake_lock_timer_func(struct work_struct *work)
-{
-	struct hdd_ipa_priv *hdd_ipa = container_of(to_delayed_work(work),
-						    struct hdd_ipa_priv,
-						    wake_lock_work);
-
-	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-
-	if (hdd_ipa->rm_state != HDD_IPA_RM_RELEASED)
-		goto end;
-
-	hdd_ipa->wake_lock_released = true;
-	qdf_wake_lock_release(&hdd_ipa->wake_lock,
-			      WIFI_POWER_EVENT_WAKELOCK_IPA);
-
-end:
-	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-}
-
-/**
- * hdd_ipa_rm_request() - Request resource from IPA
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 on success, negative errno on error
- */
-static int hdd_ipa_rm_request(struct hdd_ipa_priv *hdd_ipa)
-{
-	int ret = 0;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-		return 0;
-
-	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-
-	switch (hdd_ipa->rm_state) {
-	case HDD_IPA_RM_GRANTED:
-		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-		return 0;
-	case HDD_IPA_RM_GRANT_PENDING:
-		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-		return -EINPROGRESS;
-	case HDD_IPA_RM_RELEASED:
-		hdd_ipa->rm_state = HDD_IPA_RM_GRANT_PENDING;
-		break;
-	}
-
-	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
-	ret = qdf_ipa_rm_inactivity_timer_request_resource(
-			IPA_RM_RESOURCE_WLAN_PROD);
-
-	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-	if (ret == 0) {
-		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
-		hdd_ipa->stats.num_rm_grant_imm++;
-	}
-
-	cancel_delayed_work(&hdd_ipa->wake_lock_work);
-	if (hdd_ipa->wake_lock_released) {
-		qdf_wake_lock_acquire(&hdd_ipa->wake_lock,
-				      WIFI_POWER_EVENT_WAKELOCK_IPA);
-		hdd_ipa->wake_lock_released = false;
-	}
-	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
-	return ret;
-}
-
-/**
- * hdd_ipa_rm_try_release() - Attempt to release IPA resource
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 if resources released, negative errno otherwise
- */
-static int hdd_ipa_rm_try_release(struct hdd_ipa_priv *hdd_ipa)
-{
-	int ret = 0;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-		return 0;
-
-	if (atomic_read(&hdd_ipa->tx_ref_cnt))
-		return -EAGAIN;
-
-	qdf_spin_lock_bh(&hdd_ipa->pm_lock);
-
-	if (!qdf_nbuf_is_queue_empty(&hdd_ipa->pm_queue_head)) {
-		qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
-		return -EAGAIN;
-	}
-	qdf_spin_unlock_bh(&hdd_ipa->pm_lock);
-
-	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-	switch (hdd_ipa->rm_state) {
-	case HDD_IPA_RM_GRANTED:
-		break;
-	case HDD_IPA_RM_GRANT_PENDING:
-		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-		return -EINPROGRESS;
-	case HDD_IPA_RM_RELEASED:
-		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-		return 0;
-	}
-
-	/* IPA driver returns immediately so set the state here to avoid any
-	 * race condition.
-	 */
-	hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
-	hdd_ipa->stats.num_rm_release++;
-	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
-	ret = qdf_ipa_rm_inactivity_timer_release_resource(
-				IPA_RM_RESOURCE_WLAN_PROD);
-
-	qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-	if (unlikely(ret != 0)) {
-		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
-		WARN_ON(1);
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_WARN,
-			"ipa_rm_inactivity_timer_release_resource returnied fail");
-	}
-
-	/*
-	 * If wake_lock is released immediately, kernel would try to suspend
-	 * immediately as well, Just avoid ping-pong between suspend-resume
-	 * while there is healthy amount of data transfer going on by
-	 * releasing the wake_lock after some delay.
-	 */
-	schedule_delayed_work(&hdd_ipa->wake_lock_work,
-			      msecs_to_jiffies
-				      (HDD_IPA_RX_INACTIVITY_MSEC_DELAY));
-
-	qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-
-	return ret;
-}
-
-/**
- * hdd_ipa_rm_notify() - IPA resource manager notifier callback
- * @user_data: user data registered with IPA
- * @event: the IPA resource manager event that occurred
- * @data: the data associated with the event
- *
- * Return: None
- */
-static void hdd_ipa_rm_notify(void *user_data, qdf_ipa_rm_event_t event,
-			      unsigned long data)
-{
-	struct hdd_ipa_priv *hdd_ipa = user_data;
-
-	if (unlikely(!hdd_ipa))
-		return;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-		return;
-
-	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "Evt: %d", event);
-
-	switch (event) {
-	case IPA_RM_RESOURCE_GRANTED:
-		if (hdd_ipa_uc_is_enabled(hdd_ipa->hdd_ctx)) {
-			/* RM Notification comes with ISR context
-			 * it should be serialized into work queue to avoid
-			 * ISR sleep problem
-			 */
-			hdd_ipa->uc_rm_work.event = event;
-			schedule_work(&hdd_ipa->uc_rm_work.work);
-			break;
-		}
-		qdf_spin_lock_bh(&hdd_ipa->rm_lock);
-		hdd_ipa->rm_state = HDD_IPA_RM_GRANTED;
-		qdf_spin_unlock_bh(&hdd_ipa->rm_lock);
-		hdd_ipa->stats.num_rm_grant++;
-		break;
-
-	case IPA_RM_RESOURCE_RELEASED:
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "RM Release");
-		hdd_ipa->resource_unloading = false;
-		break;
-
-	default:
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Unknown RM Evt: %d", event);
-		break;
-	}
-}
-
-/**
- * hdd_ipa_rm_cons_release() - WLAN consumer resource release handler
- *
- * Callback function registered with IPA that is called when IPA wants
- * to release the WLAN consumer resource
- *
- * Return: 0 if the request is granted, negative errno otherwise
- */
-static int hdd_ipa_rm_cons_release(void)
-{
-	return 0;
-}
-
-/**
- * hdd_ipa_rm_cons_request() - WLAN consumer resource request handler
- *
- * Callback function registered with IPA that is called when IPA wants
- * to access the WLAN consumer resource
- *
- * Return: 0 if the request is granted, negative errno otherwise
- */
-static int hdd_ipa_rm_cons_request(void)
-{
-	int ret = 0;
-
-	if (ghdd_ipa->resource_loading) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
-			    "IPA resource loading in progress");
-		ghdd_ipa->pending_cons_req = true;
-		ret = -EINPROGRESS;
-	} else if (ghdd_ipa->resource_unloading) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_FATAL,
-				"IPA resource unloading in progress");
-		ghdd_ipa->pending_cons_req = true;
-		ret = -EPERM;
-	}
-
-	return ret;
-}
-
-/**
  * __hdd_ipa_set_perf_level() - Set IPA performance level
  * @hdd_ctx: Global HDD context
  * @tx_packets: Number of packets transmitted in the last sample period
@@ -3946,146 +4296,6 @@
 	return ret;
 }
 
-/**
- * hdd_ipa_init_uc_rm_work - init ipa uc resource manager work
- * @work: struct work_struct
- * @work_handler: work_handler
- *
- * Return: none
- */
-static void hdd_ipa_init_uc_rm_work(struct work_struct *work,
-					work_func_t work_handler)
-{
-	INIT_WORK(work, work_handler);
-}
-
-/**
- * hdd_ipa_setup_rm() - Setup IPA resource management
- * @hdd_ipa: Global HDD IPA context
- *
- * Return: 0 on success, negative errno on error
- */
-static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa)
-{
-	qdf_ipa_rm_create_params_t create_params = { 0 };
-	int ret;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-		return 0;
-
-	hdd_ipa_init_uc_rm_work(&hdd_ipa->uc_rm_work.work,
-		hdd_ipa_uc_rm_notify_defer);
-	memset(&create_params, 0, sizeof(create_params));
-	QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
-		 IPA_RM_RESOURCE_WLAN_PROD;
-	QDF_IPA_RM_CREATE_PARAMS_USER_DATA(&create_params) =
-		hdd_ipa;
-	QDF_IPA_RM_CREATE_PARAMS_NOTIFY_CB(&create_params) =
-		hdd_ipa_rm_notify;
-	QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
-		IPA_VOLTAGE_SVS;
-
-	ret = qdf_ipa_rm_create_resource(&create_params);
-	if (ret) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "Create RM resource failed: %d", ret);
-		goto setup_rm_fail;
-	}
-
-	memset(&create_params, 0, sizeof(create_params));
-	QDF_IPA_RM_CREATE_PARAMS_NAME(&create_params) =
-		IPA_RM_RESOURCE_WLAN_CONS;
-	QDF_IPA_RM_CREATE_PARAMS_REQUEST_RESOURCE(&create_params) =
-		hdd_ipa_rm_cons_request;
-	QDF_IPA_RM_CREATE_PARAMS_RELEASE_RESOURCE(&create_params) =
-		hdd_ipa_rm_cons_release;
-	QDF_IPA_RM_CREATE_PARAMS_FLOOR_VOLTAGE(&create_params) =
-		IPA_VOLTAGE_SVS;
-
-	ret = qdf_ipa_rm_create_resource(&create_params);
-	if (ret) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "Create RM CONS resource failed: %d", ret);
-		goto delete_prod;
-	}
-
-	ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
-			      IPA_RM_RESOURCE_APPS_CONS);
-
-	ret = qdf_ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WLAN_PROD,
-			HDD_IPA_RX_INACTIVITY_MSEC_DELAY);
-	if (ret) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Timer init failed: %d",
-			    ret);
-		goto timer_init_failed;
-	}
-
-	/* Set the lowest bandwidth to start with */
-	ret = hdd_ipa_set_perf_level(hdd_ipa->hdd_ctx, 0, 0);
-
-	if (ret) {
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "Set perf level failed: %d", ret);
-		goto set_perf_failed;
-	}
-
-	qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa");
-	INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work,
-			  hdd_ipa_wake_lock_timer_func);
-	qdf_spinlock_create(&hdd_ipa->rm_lock);
-	hdd_ipa->rm_state = HDD_IPA_RM_RELEASED;
-	hdd_ipa->wake_lock_released = true;
-	atomic_set(&hdd_ipa->tx_ref_cnt, 0);
-
-	return ret;
-
-set_perf_failed:
-	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
-
-timer_init_failed:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
-
-delete_prod:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
-
-setup_rm_fail:
-	return ret;
-}
-
-/**
- * hdd_ipa_destroy_rm_resource() - Destroy IPA resources
- * @hdd_ipa: Global HDD IPA context
- *
- * Destroys all resources associated with the IPA resource manager
- *
- * Return: None
- */
-static void hdd_ipa_destroy_rm_resource(struct hdd_ipa_priv *hdd_ipa)
-{
-	int ret;
-
-	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
-		return;
-
-	cancel_delayed_work_sync(&hdd_ipa->wake_lock_work);
-	qdf_wake_lock_destroy(&hdd_ipa->wake_lock);
-
-	cancel_work_sync(&hdd_ipa->uc_rm_work.work);
-	qdf_spinlock_destroy(&hdd_ipa->rm_lock);
-
-	ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WLAN_PROD);
-
-	ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
-	if (ret)
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "RM PROD resource delete failed %d", ret);
-
-	ret = qdf_ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
-	if (ret)
-		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-			    "RM CONS resource delete failed %d", ret);
-}
-
 #ifdef QCA_CONFIG_SMP
 static int hdd_ipa_aggregated_rx_ind(qdf_nbuf_t skb)
 {
@@ -4450,7 +4660,7 @@
 
 	atomic_dec(&hdd_ipa->tx_ref_cnt);
 
-	hdd_ipa_rm_try_release(hdd_ipa);
+	hdd_ipa_wdi_rm_try_release(hdd_ipa);
 }
 
 /**
@@ -4476,7 +4686,7 @@
 		ipa_free_skb(ipa_tx_desc);
 		iface_context->stats.num_tx_drop++;
 		qdf_spin_unlock_bh(&iface_context->interface_lock);
-		hdd_ipa_rm_try_release(hdd_ipa);
+		hdd_ipa_wdi_rm_try_release(hdd_ipa);
 		return;
 	}
 
@@ -4490,7 +4700,7 @@
 			ipa_free_skb(ipa_tx_desc);
 			qdf_spin_unlock_bh(&iface_context->interface_lock);
 			iface_context->stats.num_tx_cac_drop++;
-			hdd_ipa_rm_try_release(hdd_ipa);
+			hdd_ipa_wdi_rm_try_release(hdd_ipa);
 			return;
 		}
 	}
@@ -4530,7 +4740,7 @@
 		hdd_ipa->stats.num_tx_desc_error++;
 		qdf_spin_unlock_bh(&hdd_ipa->q_lock);
 		ipa_free_skb(ipa_tx_desc);
-		hdd_ipa_rm_try_release(hdd_ipa);
+		hdd_ipa_wdi_rm_try_release(hdd_ipa);
 		return;
 	}
 
@@ -4677,7 +4887,7 @@
 	 * workaround to request PROD resource while data is going over CONS
 	 * pipe to prevent the IPA hardware clockdown.
 	 */
-	hdd_ipa_rm_request(hdd_ipa);
+	hdd_ipa_wdi_rm_request(hdd_ipa);
 
 	qdf_spin_lock_bh(&hdd_ipa->pm_lock);
 	/*
@@ -4913,8 +5123,9 @@
 		if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
 			ipa->keep_ipa_awake = 1;
 
-		ret = qdf_ipa_setup_sys_pipe(ipa,
-			&hdd_ipa->sys_pipe[i].conn_hdl);
+		ret = hdd_ipa_wdi_setup_sys_pipe(
+				hdd_ipa, ipa,
+				&hdd_ipa->sys_pipe[i].conn_hdl);
 		if (ret) {
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
 				    "Failed for pipe %d ret: %d", i, ret);
@@ -4978,11 +5189,11 @@
 	if (!hdd_ipa_is_rm_enabled(hdd_ipa->hdd_ctx))
 		ipa->keep_ipa_awake = 1;
 
-	ret = qdf_ipa_setup_sys_pipe(ipa,
+	ret = hdd_ipa_wdi_setup_sys_pipe(hdd_ipa, ipa,
 			&hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl);
 	if (ret) {
 		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-				"Failed for RX pipe: %d", ret);
+			    "Failed for RX pipe: %d", ret);
 		return ret;
 	}
 	hdd_ipa->sys_pipe[HDD_IPA_RX_PIPE].conn_hdl_valid = 1;
@@ -5040,8 +5251,8 @@
 
 	for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
 		if (hdd_ipa->sys_pipe[i].conn_hdl_valid)
-			qdf_ipa_teardown_sys_pipe(
-				hdd_ipa->sys_pipe[i].conn_hdl);
+			hdd_ipa_wdi_teardown_sys_pipe(
+				hdd_ipa, hdd_ipa->sys_pipe[i].conn_hdl);
 		qdf_mem_zero(&hdd_ipa->sys_pipe[i],
 			     sizeof(struct hdd_ipa_sys_pipe));
 	}
@@ -5064,8 +5275,8 @@
 
 	for (i = 0; i < HDD_IPA_MAX_SYSBAM_PIPE; i++) {
 		if (hdd_ipa->sys_pipe[i].conn_hdl_valid) {
-			ret = qdf_ipa_teardown_sys_pipe(
-				hdd_ipa->sys_pipe[i].conn_hdl);
+			ret = hdd_ipa_wdi_teardown_sys_pipe(
+				hdd_ipa, hdd_ipa->sys_pipe[i].conn_hdl);
 			if (ret)
 				HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR, "Failed: %d",
 					    ret);
@@ -5148,6 +5359,7 @@
 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 	struct ol_txrx_pdev_t *pdev = cds_get_context(QDF_MODULE_ID_TXRX);
 	void *tl_context = NULL;
+	uint8_t iface_id;
 	int i, ret = 0;
 
 	HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "enter");
@@ -5177,6 +5389,7 @@
 	adapter->ipa_context = iface_context;
 	iface_context->adapter = adapter;
 	iface_context->sta_id = sta_id;
+	iface_id = iface_context->iface_id;
 	tl_context = (void *)cdp_peer_get_vdev_by_sta_id(
 				soc, (struct cdp_pdev *)pdev, sta_id);
 	if (tl_context == NULL) {
@@ -5194,8 +5407,11 @@
 				  iface_context->cons_client,
 				  adapter->session_id,
 				  hdd_ipa_is_ipv6_enabled(hdd_ipa->hdd_ctx));
-	if (ret)
+	if (ret) {
+		HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+			    "IPA interface setup failed: ret=%d", ret);
 		goto end;
+	}
 
 	hdd_ipa->num_iface++;
 
@@ -5688,7 +5904,7 @@
 		memcpy(msg_ex->attribs[0].u.mac_addr, mac_addr,
 		       IPA_MAC_ADDR_SIZE);
 
-		ret = ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn);
+		ret = qdf_ipa_send_msg(&meta, msg_ex, hdd_ipa_msg_free_fn);
 
 		if (ret) {
 			HDD_IPA_LOG(QDF_TRACE_LEVEL_DEBUG, "%s: Evt: %d : %d",
@@ -5774,7 +5990,7 @@
 		    QDF_IPA_WLAN_MSG_NAME(msg),
 		    QDF_IPA_MSG_META_MSG_TYPE(&meta));
 
-	ret = ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
+	ret = qdf_ipa_send_msg(&meta, msg, hdd_ipa_msg_free_fn);
 
 	if (ret) {
 		hdd_err("%s: Evt: %d fail:%d",
@@ -5891,7 +6107,7 @@
 	int ret, i;
 	struct hdd_ipa_iface_context *iface_context = NULL;
 	struct ol_txrx_pdev_t *pdev = NULL;
-	qdf_ipa_rm_perf_profile_t profile;
+	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
 
 	if (!hdd_ipa_is_enabled(hdd_ctx))
 		return QDF_STATUS_SUCCESS;
@@ -5915,6 +6131,8 @@
 	hdd_ipa->hdd_ctx = hdd_ctx;
 	hdd_ipa->num_iface = 0;
 
+	hdd_ipa_wdi_get_wdi_version(hdd_ipa);
+
 	/* Create the interface context */
 	for (i = 0; i < HDD_IPA_MAX_IFACE; i++) {
 		iface_context = &hdd_ipa->iface_context[i];
@@ -5936,7 +6154,7 @@
 	qdf_mutex_create(&hdd_ipa->event_lock);
 	qdf_mutex_create(&hdd_ipa->ipa_lock);
 
-	ret = hdd_ipa_setup_rm(hdd_ipa);
+	ret = hdd_ipa_wdi_setup_rm(hdd_ipa);
 	if (ret)
 		goto fail_setup_rm;
 
@@ -5963,8 +6181,15 @@
 			if (ret)
 				goto fail_create_sys_pipe;
 		}
-		if (hdd_ipa_uc_register_uc_ready(hdd_ipa))
+
+		ret = hdd_ipa_wdi_init(hdd_ipa);
+		if (ret) {
+			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
+				    "IPA WDI init failed: ret=%d", ret);
+			if (ret == -EACCES)
+				ret = hdd_ipa_uc_send_wdi_control_msg(false);
 			goto fail_create_sys_pipe;
+		}
 	} else {
 		ret = hdd_ipa_setup_sys_pipe(hdd_ipa);
 		if (ret)
@@ -5973,19 +6198,18 @@
 
 	/* When IPA clock scaling is disabled, initialze maximum clock */
 	if (!hdd_ipa_is_clk_scaling_enabled(hdd_ctx)) {
-		profile.max_supported_bandwidth_mbps = 800;
 		hdd_debug("IPA clock scaling is disabled.");
 		hdd_debug("Set initial CONS/PROD perf: %d",
-			  profile.max_supported_bandwidth_mbps);
-		ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_CONS,
-					      &profile);
+			  HDD_IPA_MAX_BANDWIDTH);
+		ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_CONS,
+					     HDD_IPA_MAX_BANDWIDTH);
 		if (ret) {
 			hdd_err("RM CONS set perf profile failed: %d", ret);
 			goto fail_create_sys_pipe;
 		}
 
-		ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WLAN_PROD,
-					      &profile);
+		ret = cdp_ipa_set_perf_level(soc, IPA_RM_RESOURCE_WLAN_PROD,
+					     HDD_IPA_MAX_BANDWIDTH);
 		if (ret) {
 			hdd_err("RM PROD set perf profile failed: %d", ret);
 			goto fail_create_sys_pipe;
@@ -5998,7 +6222,7 @@
 	return QDF_STATUS_SUCCESS;
 
 fail_create_sys_pipe:
-	hdd_ipa_destroy_rm_resource(hdd_ipa);
+	hdd_ipa_wdi_destroy_rm(hdd_ipa);
 fail_setup_rm:
 	qdf_spinlock_destroy(&hdd_ipa->pm_lock);
 	qdf_mem_free(hdd_ipa);
@@ -6086,7 +6310,7 @@
 	if (hdd_ipa_uc_sta_is_enabled(hdd_ipa->hdd_ctx))
 		hdd_ipa_teardown_sys_pipe(hdd_ipa);
 
-	hdd_ipa_destroy_rm_resource(hdd_ipa);
+	hdd_ipa_wdi_destroy_rm(hdd_ipa);
 
 	__hdd_ipa_flush(hdd_ctx);
 
@@ -6100,9 +6324,7 @@
 	}
 
 	if (hdd_ipa_uc_is_enabled(hdd_ctx)) {
-		if (ipa_uc_dereg_rdyCB())
-			HDD_IPA_LOG(QDF_TRACE_LEVEL_ERROR,
-					"UC Ready CB deregister fail");
+		hdd_ipa_wdi_cleanup();
 		hdd_ipa_uc_rt_debug_deinit(hdd_ctx);
 		qdf_mutex_destroy(&hdd_ipa->event_lock);
 		qdf_mutex_destroy(&hdd_ipa->ipa_lock);