Răsfoiți Sursa

qcacmn: Fix IRQ disable for unit-test suspend on PCIe

pld_disable_irq is a no-op for PCI devices, causing unit-test resume
to fail in some cases. Define new IRQ disable/enable API's in HIF for
unit-test suspend/resume to use.

Change-Id: Ib3e6007025e791c867463c7d9f64512628c4ca0b
CRs-Fixed: 2023978
Dustin Brown 8 ani în urmă
părinte
comite
6834d321d8

+ 44 - 0
hif/inc/hif.h

@@ -722,6 +722,50 @@ int hif_bus_suspend(struct hif_opaque_softc *);
 int hif_bus_resume_noirq(struct hif_opaque_softc *);
 int hif_bus_suspend_noirq(struct hif_opaque_softc *);
 
+/**
+ * hif_apps_irqs_enable() - Enables all irqs from the APPS side
+ * @hif_ctx: an opaque HIF handle to use
+ *
+ * As opposed to the standard hif_irq_enable, this function always applies to
+ * the APPS side kernel interrupt handling.
+ *
+ * Return: errno
+ */
+int hif_apps_irqs_enable(struct hif_opaque_softc *hif_ctx);
+
+/**
+ * hif_apps_irqs_disable() - Disables all irqs from the APPS side
+ * @hif_ctx: an opaque HIF handle to use
+ *
+ * As opposed to the standard hif_irq_disable, this function always applies to
+ * the APPS side kernel interrupt handling.
+ *
+ * Return: errno
+ */
+int hif_apps_irqs_disable(struct hif_opaque_softc *hif_ctx);
+
+/**
+ * hif_apps_wake_irq_enable() - Enables the wake irq from the APPS side
+ * @hif_ctx: an opaque HIF handle to use
+ *
+ * As opposed to the standard hif_irq_enable, this function always applies to
+ * the APPS side kernel interrupt handling.
+ *
+ * Return: errno
+ */
+int hif_apps_wake_irq_enable(struct hif_opaque_softc *hif_ctx);
+
+/**
+ * hif_apps_wake_irq_disable() - Disables the wake irq from the APPS side
+ * @hif_ctx: an opaque HIF handle to use
+ *
+ * As opposed to the standard hif_irq_disable, this function always applies to
+ * the APPS side kernel interrupt handling.
+ *
+ * Return: errno
+ */
+int hif_apps_wake_irq_disable(struct hif_opaque_softc *hif_ctx);
+
 #ifdef FEATURE_RUNTIME_PM
 int hif_pre_runtime_suspend(struct hif_opaque_softc *hif_ctx);
 void hif_pre_runtime_resume(struct hif_opaque_softc *hif_ctx);

+ 10 - 1
hif/src/ce/ce_internal.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -495,4 +495,13 @@ static inline void ce_t2h_msg_ce_cleanup(struct CE_handle *ce_hdl)
 
 /* Additional internal-only ce_send flags */
 #define CE_SEND_FLAG_GATHER             0x00010000      /* Use Gather */
+
+/**
+ * hif_get_wake_ce_id() - gets the copy engine id used for waking up
+ * @scn: The hif context to use
+ * @ce_id: a pointer where the copy engine Id should be populated
+ *
+ * Return: errno
+ */
+int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id);
 #endif /* __COPY_ENGINE_INTERNAL_H__ */

+ 20 - 0
hif/src/ce/ce_main.c

@@ -3177,3 +3177,23 @@ void hif_wlan_disable(struct hif_softc *scn)
 	pld_wlan_disable(scn->qdf_dev->dev, mode);
 }
 
+int hif_get_wake_ce_id(struct hif_softc *scn, uint8_t *ce_id)
+{
+	QDF_STATUS status;
+	uint8_t ul_pipe, dl_pipe;
+	int ul_is_polled, dl_is_polled;
+
+	/* DL pipe for HTC_CTRL_RSVD_SVC should map to the wake CE */
+	status = hif_map_service_to_pipe(GET_HIF_OPAQUE_HDL(scn),
+					 HTC_CTRL_RSVD_SVC,
+					 &ul_pipe, &dl_pipe,
+					 &ul_is_polled, &dl_is_polled);
+	if (status) {
+		HIF_ERROR("%s: failed to map pipe: %d", __func__, status);
+		return qdf_status_to_os_return(status);
+	}
+
+	*ce_id = dl_pipe;
+
+	return 0;
+}

+ 8 - 13
hif/src/ce/ce_tasklet.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -335,25 +335,20 @@ static bool hif_interrupt_is_fake_apps_resume(struct hif_opaque_softc *hif_ctx,
 					      int ce_id)
 {
 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
-	uint8_t ul_pipe, dl_pipe;
-	int ul_is_polled, dl_is_polled;
-	QDF_STATUS status;
+	int errno;
+	uint8_t wake_ce_id;
 
 	if (!test_bit(HIF_FA_SUSPENDED_BIT, &scn->fake_apps_ctx.state))
 		return false;
 
-	/* ensure passed ce_id matches wake irq */
-	/* dl_pipe will be populated with the wake irq number */
-	status = hif_map_service_to_pipe(hif_ctx, HTC_CTRL_RSVD_SVC,
-					 &ul_pipe, &dl_pipe,
-					 &ul_is_polled, &dl_is_polled);
-
-	if (status) {
-		HIF_ERROR("%s: pipe_mapping failure", __func__);
+	/* ensure passed ce_id matches wake ce_id */
+	errno = hif_get_wake_ce_id(scn, &wake_ce_id);
+	if (errno) {
+		HIF_ERROR("%s: failed to get wake CE Id: %d", __func__, errno);
 		return false;
 	}
 
-	return ce_id == dl_pipe;
+	return ce_id == wake_ce_id;
 }
 
 /**

+ 82 - 0
hif/src/dispatcher/multibus.c

@@ -35,6 +35,8 @@
 #include "dummy.h"
 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB)
 #include "ce_main.h"
+#include "ce_api.h"
+#include "ce_internal.h"
 #endif
 #include "htc_services.h"
 #include "a_types.h"
@@ -412,3 +414,83 @@ int hif_bus_reset_resume(struct hif_opaque_softc *scn)
 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
 	return hif_sc->bus_ops.hif_bus_reset_resume(hif_sc);
 }
+
+int hif_apps_irqs_disable(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_softc *scn;
+	int i;
+
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn) {
+		QDF_BUG(0);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < scn->ce_count; ++i)
+		disable_irq(scn->bus_ops.hif_map_ce_to_irq(scn, i));
+
+	return 0;
+}
+
+int hif_apps_irqs_enable(struct hif_opaque_softc *hif_ctx)
+{
+	struct hif_softc *scn;
+	int i;
+
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn) {
+		QDF_BUG(0);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < scn->ce_count; ++i)
+		enable_irq(scn->bus_ops.hif_map_ce_to_irq(scn, i));
+
+	return 0;
+}
+
+int hif_apps_wake_irq_disable(struct hif_opaque_softc *hif_ctx)
+{
+	int errno;
+	struct hif_softc *scn;
+	uint8_t wake_ce_id;
+
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn) {
+		QDF_BUG(0);
+		return -EINVAL;
+	}
+
+	errno = hif_get_wake_ce_id(scn, &wake_ce_id);
+	if (errno) {
+		HIF_ERROR("%s: failed to get wake CE Id: %d", __func__, errno);
+		return errno;
+	}
+
+	disable_irq(scn->bus_ops.hif_map_ce_to_irq(scn, wake_ce_id));
+
+	return 0;
+}
+
+int hif_apps_wake_irq_enable(struct hif_opaque_softc *hif_ctx)
+{
+	int errno;
+	struct hif_softc *scn;
+	uint8_t wake_ce_id;
+
+	scn = HIF_GET_SOFTC(hif_ctx);
+	if (!scn) {
+		QDF_BUG(0);
+		return -EINVAL;
+	}
+
+	errno = hif_get_wake_ce_id(scn, &wake_ce_id);
+	if (errno) {
+		HIF_ERROR("%s: failed to get wake CE Id: %d", __func__, errno);
+		return errno;
+	}
+
+	enable_irq(scn->bus_ops.hif_map_ce_to_irq(scn, wake_ce_id));
+
+	return 0;
+}

+ 2 - 1
hif/src/dispatcher/multibus.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -81,6 +81,7 @@ struct hif_bus_ops {
 	void (*hif_set_bundle_mode) (struct hif_softc *hif_ctx, bool enabled,
 					int rx_bundle_cnt);
 	int (*hif_bus_reset_resume)(struct hif_softc *hif_ctx);
+	int (*hif_map_ce_to_irq)(struct hif_softc *hif_sc, int ce_id);
 };
 
 #ifdef HIF_SNOC

+ 4 - 1
hif/src/dispatcher/multibus_pci.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -90,6 +90,9 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
 	bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable;
 	bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable;
 
+	/* default to legacy mapping handler; override as needed */
+	bus_ops->hif_map_ce_to_irq = &hif_pci_legacy_map_ce_to_irq;
+
 	return QDF_STATUS_SUCCESS;
 }
 

+ 2 - 1
hif/src/dispatcher/multibus_snoc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -81,6 +81,7 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops)
 		&hif_snoc_clear_stats;
 	bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable;
 	bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable;
+	bus_ops->hif_map_ce_to_irq = &hif_snoc_map_ce_to_irq;
 
 	return QDF_STATUS_SUCCESS;
 }

+ 2 - 1
hif/src/dispatcher/pci_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -54,4 +54,5 @@ void hif_pci_enable_power_management(struct hif_softc *hif_ctx,
 void hif_pci_disable_power_management(struct hif_softc *hif_ctx);
 void hif_pci_display_stats(struct hif_softc *hif_ctx);
 void hif_pci_clear_stats(struct hif_softc *hif_ctx);
+int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id);
 #endif /* _PCI_API_H_ */

+ 2 - 1
hif/src/dispatcher/snoc_api.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -46,4 +46,5 @@ void hif_snoc_irq_enable(struct hif_softc *scn, int ce_id);
 int hif_snoc_dump_registers(struct hif_softc *scn);
 void hif_snoc_display_stats(struct hif_softc *hif_ctx);
 void hif_snoc_clear_stats(struct hif_softc *hif_ctx);
+int hif_snoc_map_ce_to_irq(struct hif_softc *scn, int ce_id);
 #endif /* _SNOC_API_H_ */

+ 85 - 98
hif/src/pcie/if_pci.c

@@ -2730,30 +2730,21 @@ void hif_pci_prevent_linkdown(struct hif_softc *scn, bool flag)
 }
 #endif
 
-/**
- * hif_pci_bus_enable_wake_irq() - enable pci bus wake irq
- *
- * Configures the pci irq line as a wakeup source.
- *
- * Return: 0 for success and non-zero for failure
- */
-static int hif_pci_bus_enable_wake_irq(struct hif_softc *scn)
+static int hif_mark_wake_irq_wakeable(struct hif_softc *scn)
 {
-	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
+	int errno;
+	uint8_t ce_id;
 
-	if (!sc) {
-		HIF_ERROR("%s: sc is null", __func__);
-		return -EFAULT;
+	errno = hif_get_wake_ce_id(scn, &ce_id);
+	if (errno) {
+		HIF_ERROR("%s: failed to get wake CE Id: %d", __func__, errno);
+		return errno;
 	}
 
-	if (!sc->pdev) {
-		HIF_ERROR("%s: pdev is null", __func__);
-		return -EFAULT;
-	}
-
-	if (unlikely(enable_irq_wake(sc->pdev->irq))) {
-		HIF_ERROR("%s: Failed to enable wake IRQ", __func__);
-		return -EINVAL;
+	errno = enable_irq_wake(scn->bus_ops.hif_map_ce_to_irq(scn, ce_id));
+	if (errno) {
+		HIF_ERROR("%s: Failed to mark wake IRQ: %d", __func__, errno);
+		return errno;
 	}
 
 	return 0;
@@ -2768,11 +2759,19 @@ static int hif_pci_bus_enable_wake_irq(struct hif_softc *scn)
  */
 int hif_pci_bus_suspend(struct hif_softc *scn)
 {
+	/*
+	 * This is a workaround to a spurious wake interrupt issue. The
+	 * proper fix is being worked on, and this should be removed as
+	 * soon as possible.
+	 */
+	HIF_ERROR("%s: Pausing bus suspend for 200ms", __func__);
+	msleep(200);
+
 	if (hif_can_suspend_link(GET_HIF_OPAQUE_HDL(scn)))
 		return 0;
 
 	/* pci link is staying up; enable wake irq */
-	return hif_pci_bus_enable_wake_irq(scn);
+	return hif_mark_wake_irq_wakeable(scn);
 }
 
 /**
@@ -2814,30 +2813,21 @@ static int __hif_check_link_status(struct hif_softc *scn)
 	return -EACCES;
 }
 
-/**
- * hif_pci_bus_disable_wake_irq() - disable pci bus wake irq
- *
- * Deconfigures the pci irq line as a wakeup source.
- *
- * Return: 0 for success and non-zero for failure
- */
-static int hif_pci_bus_disable_wake_irq(struct hif_softc *scn)
+static int hif_unmark_wake_irq_wakeable(struct hif_softc *scn)
 {
-	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
-
-	if (!sc) {
-		HIF_ERROR("%s: sc is null", __func__);
-		return -EFAULT;
-	}
+	int errno;
+	uint8_t ce_id;
 
-	if (!sc->pdev) {
-		HIF_ERROR("%s: pdev is null", __func__);
-		return -EFAULT;
+	errno = hif_get_wake_ce_id(scn, &ce_id);
+	if (errno) {
+		HIF_ERROR("%s: failed to get wake CE Id: %d", __func__, errno);
+		return errno;
 	}
 
-	if (unlikely(disable_irq_wake(sc->pdev->irq))) {
-		HIF_ERROR("%s: Failed to disable wake IRQ", __func__);
-		return -EFAULT;
+	errno = disable_irq_wake(scn->bus_ops.hif_map_ce_to_irq(scn, ce_id));
+	if (errno) {
+		HIF_ERROR("%s: Failed to unmark wake IRQ: %d", __func__, errno);
+		return errno;
 	}
 
 	return 0;
@@ -2862,7 +2852,7 @@ int hif_pci_bus_resume(struct hif_softc *scn)
 		return 0;
 
 	/* pci link is up; disable wake irq */
-	return hif_pci_bus_disable_wake_irq(scn);
+	return hif_unmark_wake_irq_wakeable(scn);
 }
 
 /**
@@ -3093,30 +3083,39 @@ int hif_runtime_suspend(struct hif_opaque_softc *hif_ctx)
 {
 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
-	int err;
-
-	err = hif_pci_bus_suspend(scn);
-	if (err)
-		goto exit_with_error;
+	int errno;
 
-	/*
-	 * normal 3-stage suspend from CNSS disables irqs before calling
-	 * noirq stage
-	 */
-	disable_irq(sc->pdev->irq);
+	errno = hif_bus_suspend(hif_ctx);
+	if (errno) {
+		HIF_ERROR("%s: failed bus suspend: %d", __func__, errno);
+		return errno;
+	}
 
-	err = hif_pci_bus_suspend_noirq(scn);
-	if (err)
+	errno = hif_apps_irqs_disable(hif_ctx);
+	if (errno) {
+		HIF_ERROR("%s: failed disable irqs: %d", __func__, errno);
 		goto bus_resume;
+	}
+
+	errno = hif_bus_suspend_noirq(hif_ctx);
+	if (errno) {
+		HIF_ERROR("%s: failed bus suspend noirq: %d", __func__, errno);
+		goto irqs_enable;
+	}
+
+	/* link should always be down; skip enable wake irq */
 
 	return 0;
 
+bus_resume_noirq:
+	QDF_BUG(!hif_bus_resume_noirq(hif_ctx));
+
+irq_enable:
+	QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
+
 bus_resume:
-	enable_irq(sc->pdev->irq);
-	err = hif_pci_bus_resume(scn);
-	QDF_BUG(err == 0);
+	QDF_BUG(!hif_bus_resume(hif_ctx));
 
-exit_with_error:
 	return err;
 }
 
@@ -3154,7 +3153,6 @@ static void hif_fastpath_resume(struct hif_opaque_softc *hif_ctx)
 static void hif_fastpath_resume(struct hif_opaque_softc *hif_ctx) {}
 #endif
 
-
 /**
  * hif_runtime_resume() - do the bus resume part of a runtime resume
  *
@@ -3162,35 +3160,14 @@ static void hif_fastpath_resume(struct hif_opaque_softc *hif_ctx) {}
  */
 int hif_runtime_resume(struct hif_opaque_softc *hif_ctx)
 {
-	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
-	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
-	int err;
-
-	err = hif_pci_bus_resume_noirq(scn);
-	if (err)
-		goto exit_with_error;
-
-	/*
-	 * normal 3-stage resume from CNSS enables irqs after calling
-	 * noirq stage
-	 */
-	enable_irq(sc->pdev->irq);
-
-	err = hif_pci_bus_resume(scn);
-	if (err)
-		goto bus_suspend_noirq;
+	/* link should always be down; skip disable wake irq */
 
+	QDF_BUG(!hif_bus_resume_noirq(hif_ctx));
+	QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
+	QDF_BUG(!hif_bus_resume(hif_ctx));
 	hif_fastpath_resume(hif_ctx);
 
 	return 0;
-
-bus_suspend_noirq:
-	disable_irq(sc->pdev->irq);
-	err = hif_pci_bus_suspend_noirq(scn);
-	QDF_BUG(err == 0);
-
-exit_with_error:
-	return err;
 }
 #endif /* #ifdef FEATURE_RUNTIME_PM */
 
@@ -3580,6 +3557,13 @@ static irqreturn_t hif_ce_interrupt_handler(int irq, void *context)
 }
 extern const char *ce_name[];
 
+static int hif_ce_msi_map_ce_to_irq(struct hif_softc *scn, int ce_id)
+{
+	struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn);
+
+	return pci_scn->ce_msi_irq_num[ce_id];
+}
+
 /* hif_srng_msi_irq_disable() - disable the irq for msi
  * @hif_sc: hif context
  * @ce_id: which ce to disable copy complete interrupts for
@@ -3590,16 +3574,12 @@ extern const char *ce_name[];
  */
 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
 {
-	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(hif_sc);
-
-	disable_irq_nosync(pci_sc->ce_msi_irq_num[ce_id]);
+	disable_irq_nosync(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
 }
 
 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
 {
-	struct hif_pci_softc *pci_sc = HIF_GET_PCI_SOFTC(hif_sc);
-
-	enable_irq(pci_sc->ce_msi_irq_num[ce_id]);
+	enable_irq(hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
 }
 
 static void hif_ce_legacy_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
@@ -3625,17 +3605,15 @@ static int hif_ce_msi_configure_irq(struct hif_softc *scn)
 		return ret;
 
 	if (ce_srng_based(scn)) {
-		scn->bus_ops.hif_irq_disable =
-			&hif_ce_srng_msi_irq_disable;
-		scn->bus_ops.hif_irq_enable =
-			&hif_ce_srng_msi_irq_enable;
+		scn->bus_ops.hif_irq_disable = &hif_ce_srng_msi_irq_disable;
+		scn->bus_ops.hif_irq_enable = &hif_ce_srng_msi_irq_enable;
 	} else {
-		scn->bus_ops.hif_irq_disable =
-			&hif_ce_legacy_msi_irq_disable;
-		scn->bus_ops.hif_irq_enable =
-			&hif_ce_legacy_msi_irq_enable;
+		scn->bus_ops.hif_irq_disable = &hif_ce_legacy_msi_irq_disable;
+		scn->bus_ops.hif_irq_enable = &hif_ce_legacy_msi_irq_enable;
 	}
 
+	scn->bus_ops.hif_map_ce_to_irq = &hif_ce_msi_map_ce_to_irq;
+
 	/* needs to match the ce_id -> irq data mapping
 	 * used in the srng parameter configuration
 	 */
@@ -3955,6 +3933,7 @@ void hif_pci_irq_enable(struct hif_softc *scn, int ce_id)
 	/* check for missed firmware crash */
 	hif_fw_interrupt_handler(0, scn);
 }
+
 /**
  * hif_pci_irq_disable() - ce_irq_disable
  * @scn: hif_softc
@@ -4436,3 +4415,11 @@ void hif_runtime_lock_deinit(struct hif_opaque_softc *hif_ctx,
 	qdf_mem_free(context);
 }
 #endif /* FEATURE_RUNTIME_PM */
+
+int hif_pci_legacy_map_ce_to_irq(struct hif_softc *scn, int ce_id)
+{
+	struct hif_pci_softc *pci_scn = HIF_GET_PCI_SOFTC(scn);
+
+	/* legacy case only has one irq */
+	return pci_scn->irq;
+}

+ 4 - 0
hif/src/snoc/if_snoc.c

@@ -457,3 +457,7 @@ int hif_snoc_bus_suspend_noirq(struct hif_softc *scn)
 	return 0;
 }
 
+int hif_snoc_map_ce_to_irq(struct hif_softc *scn, int ce_id)
+{
+	return icnss_get_irq(ce_id);
+}