qcacmn: add hif_grp_irq_deconfigure bus_ops to free ext grp IRQs

As per current design, in failure path of hdd_wlan_start_modules,
mem_free of hif_ext_group is done (in cds_dp_close) before
free_irq (in hdd_hif_close), during next hdd_wlan_start_modules,
request_irq adds new handler entry to the list in irq_desc, this
leads to a crash on accessing older stale entry from irq handler,
so adding a bus_ops hif_grp_irq_deconfigure to free ext grp IRQs.

Change-Id: I4d0a2bee1fabee388cea8a85226fae641165a8d5
CRs-Fixed: 2949400
This commit is contained in:
Vevek Venkatesan
2021-05-25 00:26:09 +05:30
committed by Madan Koyyalamudi
parent e914459b55
commit 7d79770907
16 changed files with 64 additions and 6 deletions

View File

@@ -2853,6 +2853,7 @@ static void dp_soc_interrupt_detach(struct cdp_soc_t *txrx_soc)
if (soc->intr_mode == DP_INTR_POLL) {
qdf_timer_free(&soc->int_timer);
} else {
hif_deconfigure_ext_group_interrupts(soc->hif_handle);
hif_deregister_exec_group(soc->hif_handle, "dp_intr");
}

View File

@@ -1494,6 +1494,14 @@ int32_t hif_get_int_ctx_irq_num(struct hif_opaque_softc *softc,
*/
QDF_STATUS hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx);
/**
* hif_deconfigure_ext_group_interrupts() - Deconfigure ext group intrrupts
* @hif_ctx: hif opaque context
*
* Return: None
*/
void hif_deconfigure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx);
/**
* hif_register_ext_group() - API to register external group
* interrupt handler.

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2018,2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2013-2018,2020-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -50,6 +50,7 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc);
int hif_ahb_configure_irq_by_ceid(struct hif_softc *sc, int ce_id);
int hif_ahb_configure_grp_irq(struct hif_softc *scn,
struct hif_exec_context *hif_ext_grp);
void hif_ahb_deconfigure_grp_irq(struct hif_softc *scn);
bool hif_ahb_needs_bmi(struct hif_softc *scn);
void hif_ahb_display_stats(struct hif_softc *scn);
void hif_ahb_clear_stats(struct hif_softc *scn);

View File

@@ -262,6 +262,16 @@ int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc,
return 0;
}
/**
* hif_dummy_grp_irq_deconfigure - dummy call
* hif_sc: hif context
*
* Return: none
*/
void hif_dummy_grp_irq_deconfigure(struct hif_softc *hif_sc)
{
}
/**
* hif_dummy_dump_registers - dummy call
* hif_sc: hif context

View File

@@ -44,6 +44,7 @@ void hif_dummy_grp_irq_enable(struct hif_softc *hif_sc, uint32_t grp_id);
void hif_dummy_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id);
int hif_dummy_grp_irq_configure(struct hif_softc *hif_sc,
struct hif_exec_context *exec);
void hif_dummy_grp_irq_deconfigure(struct hif_softc *hif_sc);
int hif_dummy_dump_registers(struct hif_softc *hif_sc);
void hif_dummy_dump_target_memory(struct hif_softc *hif_sc, void *ramdump_base,
uint32_t address, uint32_t size);

View File

@@ -205,6 +205,14 @@ int hif_ipci_configure_grp_irq(
struct hif_softc *scn,
struct hif_exec_context *exec);
/**
* hif_ipci_deconfigure_grp_irq() - deconfigure HW block irq
* @scn: hif context
*
* Return: None
*/
void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn);
/**
* hif_ipci_display_stats() - display stats
* @hif_ctx: hif context

View File

@@ -58,6 +58,7 @@ static void hif_initialize_default_ops(struct hif_softc *hif_sc)
bus_ops->hif_bus_late_resume = &hif_dummy_bus_resume;
bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq;
bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure;
bus_ops->hif_grp_irq_deconfigure = &hif_dummy_grp_irq_deconfigure;
bus_ops->hif_config_irq_affinity =
&hif_dummy_config_irq_affinity;
bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
@@ -346,6 +347,11 @@ int hif_grp_irq_configure(struct hif_softc *hif_sc,
return hif_sc->bus_ops.hif_grp_irq_configure(hif_sc, hif_exec);
}
void hif_grp_irq_deconfigure(struct hif_softc *hif_sc)
{
hif_sc->bus_ops.hif_grp_irq_deconfigure(hif_sc);
}
int hif_dump_registers(struct hif_opaque_softc *hif_hdl)
{
struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);

View File

@@ -65,6 +65,7 @@ struct hif_bus_ops {
void (*hif_irq_enable)(struct hif_softc *hif_sc, int ce_id);
int (*hif_grp_irq_configure)(struct hif_softc *hif_sc,
struct hif_exec_context *exec);
void (*hif_grp_irq_deconfigure)(struct hif_softc *hif_sc);
int (*hif_dump_registers)(struct hif_softc *hif_sc);
void (*hif_dump_target_memory)(struct hif_softc *hif_sc,
void *ramdump_base,
@@ -234,6 +235,7 @@ static inline int hif_sdio_get_context_size(void)
int hif_grp_irq_configure(struct hif_softc *hif_sc,
struct hif_exec_context *hif_exec);
void hif_grp_irq_deconfigure(struct hif_softc *hif_sc);
#ifdef HIF_USB
QDF_STATUS hif_initialize_usb_ops(struct hif_bus_ops *bus_ops);
int hif_usb_get_context_size(void);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018,2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2018,2020-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -69,6 +69,7 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops)
bus_ops->hif_disable_power_management =
&hif_dummy_disable_power_management;
bus_ops->hif_grp_irq_configure = &hif_ahb_configure_grp_irq;
bus_ops->hif_grp_irq_deconfigure = &hif_ahb_deconfigure_grp_irq;
bus_ops->hif_addr_in_boundary = &hif_dummy_addr_in_boundary;
bus_ops->hif_needs_bmi = &hif_ahb_needs_bmi;
bus_ops->hif_display_stats = &hif_ahb_display_stats;

View File

@@ -71,6 +71,7 @@ QDF_STATUS hif_initialize_ipci_ops(struct hif_softc *hif_sc)
bus_ops->hif_disable_power_management =
&hif_ipci_disable_power_management;
bus_ops->hif_grp_irq_configure = &hif_ipci_configure_grp_irq;
bus_ops->hif_grp_irq_deconfigure = &hif_ipci_deconfigure_grp_irq;
bus_ops->hif_display_stats =
&hif_ipci_display_stats;
bus_ops->hif_clear_stats =

View File

@@ -81,6 +81,7 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc)
bus_ops->hif_disable_power_management =
&hif_pci_disable_power_management;
bus_ops->hif_grp_irq_configure = &hif_pci_configure_grp_irq;
bus_ops->hif_grp_irq_deconfigure = &hif_pci_deconfigure_grp_irq;
bus_ops->hif_display_stats =
&hif_pci_display_stats;
bus_ops->hif_clear_stats =
@@ -113,6 +114,7 @@ QDF_STATUS hif_update_irq_ops_with_pci(struct hif_softc *hif_sc)
struct hif_bus_ops *bus_ops = &hif_sc->bus_ops;
bus_ops->hif_grp_irq_configure = &hif_pci_configure_grp_irq;
bus_ops->hif_grp_irq_deconfigure = &hif_pci_deconfigure_grp_irq;
bus_ops->hif_nointrs = &hif_pci_nointrs;
bus_ops->hif_irq_disable = &hif_pci_irq_disable;
bus_ops->hif_irq_enable = &hif_pci_irq_enable;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -52,6 +52,7 @@ void hif_pci_enable_power_management(struct hif_softc *hif_ctx,
void hif_pci_disable_power_management(struct hif_softc *hif_ctx);
int hif_pci_configure_grp_irq(struct hif_softc *scn,
struct hif_exec_context *exec);
void hif_pci_deconfigure_grp_irq(struct hif_softc *scn);
/**
* hif_pci_reg_read32() - Read register in 32bits

View File

@@ -835,6 +835,21 @@ QDF_STATUS hif_configure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx)
qdf_export_symbol(hif_configure_ext_group_interrupts);
void hif_deconfigure_ext_group_interrupts(struct hif_opaque_softc *hif_ctx)
{
struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
if (!scn || !scn->ext_grp_irq_configured) {
hif_err("scn(%pk) is NULL or grp irq not configured", scn);
return;
}
hif_grp_irq_deconfigure(scn);
scn->ext_grp_irq_configured = false;
}
qdf_export_symbol(hif_deconfigure_ext_group_interrupts);
#ifdef WLAN_SUSPEND_RESUME_TEST
/**
* hif_check_and_trigger_ut_resume() - check if unit-test command was used to

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
* Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -153,6 +153,7 @@ void hif_exec_destroy(struct hif_exec_context *ctx);
int hif_grp_irq_configure(struct hif_softc *scn,
struct hif_exec_context *hif_exec);
void hif_grp_irq_deconfigure(struct hif_softc *scn);
irqreturn_t hif_ext_group_interrupt_handler(int irq, void *context);
struct hif_exec_context *hif_exec_get_ctx(struct hif_opaque_softc *hif,

View File

@@ -225,7 +225,7 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
*
* Return: none
*/
static void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn)
void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn)
{
int i, j, irq;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);

View File

@@ -2098,7 +2098,7 @@ static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
return ret;
}
static void hif_pci_deconfigure_grp_irq(struct hif_softc *scn)
void hif_pci_deconfigure_grp_irq(struct hif_softc *scn)
{
int i, j, irq;
struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);