mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
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
This commit is contained in:
parent
c744104a4e
commit
6834d321d8
12 changed files with 265 additions and 117 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
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(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;
|
||||
int errno;
|
||||
|
||||
err = hif_pci_bus_suspend(scn);
|
||||
if (err)
|
||||
goto exit_with_error;
|
||||
errno = hif_bus_suspend(hif_ctx);
|
||||
if (errno) {
|
||||
HIF_ERROR("%s: failed bus suspend: %d", __func__, errno);
|
||||
return errno;
|
||||
}
|
||||
|
||||
/*
|
||||
* normal 3-stage suspend from CNSS disables irqs before calling
|
||||
* noirq stage
|
||||
*/
|
||||
disable_irq(sc->pdev->irq);
|
||||
|
||||
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:
|
||||
enable_irq(sc->pdev->irq);
|
||||
err = hif_pci_bus_resume(scn);
|
||||
QDF_BUG(err == 0);
|
||||
bus_resume_noirq:
|
||||
QDF_BUG(!hif_bus_resume_noirq(hif_ctx));
|
||||
|
||||
irq_enable:
|
||||
QDF_BUG(!hif_apps_irqs_enable(hif_ctx));
|
||||
|
||||
bus_resume:
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue