From 7d797709071b33bea03c9880502ce4ff28fe570a Mon Sep 17 00:00:00 2001 From: Vevek Venkatesan Date: Tue, 25 May 2021 00:26:09 +0530 Subject: [PATCH] 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 --- dp/wifi3.0/dp_main.c | 1 + hif/inc/hif.h | 8 ++++++++ hif/src/dispatcher/ahb_api.h | 3 ++- hif/src/dispatcher/dummy.c | 10 ++++++++++ hif/src/dispatcher/dummy.h | 1 + hif/src/dispatcher/ipci_api.h | 8 ++++++++ hif/src/dispatcher/multibus.c | 6 ++++++ hif/src/dispatcher/multibus.h | 2 ++ hif/src/dispatcher/multibus_ahb.c | 3 ++- hif/src/dispatcher/multibus_ipci.c | 1 + hif/src/dispatcher/multibus_pci.c | 2 ++ hif/src/dispatcher/pci_api.h | 3 ++- hif/src/hif_exec.c | 15 +++++++++++++++ hif/src/hif_exec.h | 3 ++- hif/src/ipcie/if_ipci.c | 2 +- hif/src/pcie/if_pci.c | 2 +- 16 files changed, 64 insertions(+), 6 deletions(-) diff --git a/dp/wifi3.0/dp_main.c b/dp/wifi3.0/dp_main.c index 550de8fe70..08c121aa7c 100644 --- a/dp/wifi3.0/dp_main.c +++ b/dp/wifi3.0/dp_main.c @@ -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"); } diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 3fc12f9ba6..1be6704830 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -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. diff --git a/hif/src/dispatcher/ahb_api.h b/hif/src/dispatcher/ahb_api.h index 87e64d3494..312536965c 100644 --- a/hif/src/dispatcher/ahb_api.h +++ b/hif/src/dispatcher/ahb_api.h @@ -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); diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index 69c33c3498..98e22953d1 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -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 diff --git a/hif/src/dispatcher/dummy.h b/hif/src/dispatcher/dummy.h index 698a624660..1827868cfb 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -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); diff --git a/hif/src/dispatcher/ipci_api.h b/hif/src/dispatcher/ipci_api.h index 5a2d19e53e..d305b1d12a 100644 --- a/hif/src/dispatcher/ipci_api.h +++ b/hif/src/dispatcher/ipci_api.h @@ -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 diff --git a/hif/src/dispatcher/multibus.c b/hif/src/dispatcher/multibus.c index 9a8cf010ee..06e70f01d3 100644 --- a/hif/src/dispatcher/multibus.c +++ b/hif/src/dispatcher/multibus.c @@ -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); diff --git a/hif/src/dispatcher/multibus.h b/hif/src/dispatcher/multibus.h index 737cd33eb3..6dec956533 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -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); diff --git a/hif/src/dispatcher/multibus_ahb.c b/hif/src/dispatcher/multibus_ahb.c index ae6535b0a4..ccd2260676 100644 --- a/hif/src/dispatcher/multibus_ahb.c +++ b/hif/src/dispatcher/multibus_ahb.c @@ -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; diff --git a/hif/src/dispatcher/multibus_ipci.c b/hif/src/dispatcher/multibus_ipci.c index feb50ba099..e59e6c0ffe 100644 --- a/hif/src/dispatcher/multibus_ipci.c +++ b/hif/src/dispatcher/multibus_ipci.c @@ -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 = diff --git a/hif/src/dispatcher/multibus_pci.c b/hif/src/dispatcher/multibus_pci.c index bedaacd5b6..c231e5ec1a 100644 --- a/hif/src/dispatcher/multibus_pci.c +++ b/hif/src/dispatcher/multibus_pci.c @@ -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; diff --git a/hif/src/dispatcher/pci_api.h b/hif/src/dispatcher/pci_api.h index f1760e96e6..63781f8339 100644 --- a/hif/src/dispatcher/pci_api.h +++ b/hif/src/dispatcher/pci_api.h @@ -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 diff --git a/hif/src/hif_exec.c b/hif/src/hif_exec.c index a85e2ea0a0..51b4f75178 100644 --- a/hif/src/hif_exec.c +++ b/hif/src/hif_exec.c @@ -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 diff --git a/hif/src/hif_exec.h b/hif/src/hif_exec.h index 8135c1a7da..530477d884 100644 --- a/hif/src/hif_exec.h +++ b/hif/src/hif_exec.h @@ -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, diff --git a/hif/src/ipcie/if_ipci.c b/hif/src/ipcie/if_ipci.c index a5a08518e3..7eff3c012f 100644 --- a/hif/src/ipcie/if_ipci.c +++ b/hif/src/ipcie/if_ipci.c @@ -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); diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c index 4b218b3098..58ce5dd92f 100644 --- a/hif/src/pcie/if_pci.c +++ b/hif/src/pcie/if_pci.c @@ -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);