From 31108f318c7200be0e403a209cc4cbc7ea230999 Mon Sep 17 00:00:00 2001 From: Venkateswara Swamy Bandaru Date: Mon, 8 Aug 2016 18:04:29 +0530 Subject: [PATCH] qcacmn: Add framework for external group interrupt handling Change-Id: I68a3c597e452e1975a97f9262870e16538f6dc4c CRs-Fixed: 1042915 --- hif/inc/hif.h | 49 +++++++++++++++ hif/inc/hif_napi.h | 7 +++ hif/src/ce/ce_main.h | 14 +++++ hif/src/dispatcher/ahb_api.h | 2 + hif/src/dispatcher/dummy.c | 19 ++++++ hif/src/dispatcher/dummy.h | 2 + hif/src/dispatcher/multibus.c | 12 ++++ hif/src/dispatcher/multibus.h | 2 + hif/src/dispatcher/multibus_ahb.c | 2 + hif/src/dispatcher/multibus_pci.c | 2 + hif/src/dispatcher/multibus_sdio.c | 2 + hif/src/dispatcher/multibus_snoc.c | 2 + hif/src/hif_io32.h | 3 +- hif/src/hif_main.c | 91 ++++++++++++++++++++++++++++ hif/src/hif_main.h | 5 ++ hif/src/pcie/if_pci.c | 2 + hif/src/snoc/if_ahb.c | 95 +++++++++++++++++++++++++++--- hif/src/snoc/if_ahb.h | 4 ++ hif/src/snoc/if_snoc.c | 2 + 19 files changed, 308 insertions(+), 9 deletions(-) diff --git a/hif/inc/hif.h b/hif/inc/hif.h index 8468117dd4..c648caf7f0 100644 --- a/hif/inc/hif.h +++ b/hif/inc/hif.h @@ -100,8 +100,52 @@ typedef void *hif_handle_t; #define TARGET_TYPE_QCA8074 20 #endif +/* enum hif_ic_irq - enum defining integrated chip irq numbers + * defining irq nubers that can be used by external modules like datapath + */ +enum hif_ic_irq { + host2wbm_desc_feed = 18, + host2reo_re_injection, + host2reo_command, + host2rxdma_monitor_ring3, + host2rxdma_monitor_ring2, + host2rxdma_monitor_ring1, + reo2ost_exception, + wbm2host_rx_release, + reo2host_status, + reo2host_destination_ring4, + reo2host_destination_ring3, + reo2host_destination_ring2, + reo2host_destination_ring1, + rxdma2host_monitor_destination_mac3, + rxdma2host_monitor_destination_mac2, + rxdma2host_monitor_destination_mac1, + ppdu_end_interrupts_mac3, + ppdu_end_interrupts_mac2, + ppdu_end_interrupts_mac1, + rxdma2host_monitor_status_ring_mac3, + rxdma2host_monitor_status_ring_mac2, + rxdma2host_monitor_status_ring_mac1, + host2rxdma_host_buf_ring_mac3, + host2rxdma_host_buf_ring_mac2, + host2rxdma_host_buf_ring_mac1, + rxdma2host_destination_ring_mac3, + rxdma2host_destination_ring_mac2, + rxdma2host_destination_ring_mac1, + host2tcl_input_ring4, + host2tcl_input_ring3, + host2tcl_input_ring2, + host2tcl_input_ring1, + wbm2host_tx_completions_ring3, + wbm2host_tx_completions_ring2, + wbm2host_tx_completions_ring1, + tcl2host_status_ring, +}; + struct CE_state; #define CE_COUNT_MAX 12 +#define HIF_MAX_GRP_IRQ 16 +#define HIF_MAX_GROUP 8 #ifdef CONFIG_SLUB_DEBUG_ON #define QCA_NAPI_BUDGET 64 @@ -407,6 +451,7 @@ QDF_STATUS hif_diag_write_mem(struct hif_opaque_softc *scn, uint32_t address, uint8_t *data, int nbytes); typedef void (*fastpath_msg_handler)(void *, qdf_nbuf_t *, uint32_t); +typedef uint32_t (*ext_intr_handler)(void *, uint32_t); /* * Set the FASTPATH_mode_on flag in sc, for use by data path @@ -682,6 +727,10 @@ typedef void (*hdd_fake_resume_callback)(uint32_t val); void hif_fake_apps_suspend(hdd_fake_resume_callback callback); #endif +uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, + uint32_t numirq, uint32_t irq[], ext_intr_handler handler, + void *context); + #ifdef __cplusplus } #endif diff --git a/hif/inc/hif_napi.h b/hif/inc/hif_napi.h index 243301f907..edf1fd0679 100644 --- a/hif/inc/hif_napi.h +++ b/hif/inc/hif_napi.h @@ -194,6 +194,9 @@ static inline int hif_napi_event(struct hif_opaque_softc *hif, static inline int hif_napi_enabled(struct hif_opaque_softc *hif, int ce) { return 0; } +static inline int hif_ext_napi_enabled(struct hif_opaque_softc *hif, int ce) +{ return 0; } + /* called from hdd (napi_poll), using napi id as a selector */ static inline void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id) { return; } @@ -201,6 +204,10 @@ static inline void hif_napi_enable_irq(struct hif_opaque_softc *hif, int id) static inline int hif_napi_schedule(struct hif_opaque_softc *hif, int ce_id) { return 0; } +static inline int hif_napi_schedule_grp(struct hif_opaque_softc *hif, + uint32_t grp_id) +{ return 0; } + static inline int hif_napi_poll(struct napi_struct *napi, int budget) { return -EPERM; } diff --git a/hif/src/ce/ce_main.h b/hif/src/ce/ce_main.h index e58f30aac5..fbc0f6c5c3 100644 --- a/hif/src/ce/ce_main.h +++ b/hif/src/ce/ce_main.h @@ -113,6 +113,18 @@ struct ce_tasklet_entry { void *hif_ce_state; }; +struct hif_ext_group_entry { + uint32_t numirq; + uint32_t irq[HIF_MAX_GRP_IRQ]; + uint32_t grp_id; + void *context; + ext_intr_handler handler; + struct tasklet_struct intr_tq; + bool configured; + bool inited; + void *hif_state; +}; + struct ce_intr_stats { uint32_t ce_per_cpu[CE_COUNT_MAX][QDF_MAX_AVAILABLE_CPU]; }; @@ -121,6 +133,8 @@ struct HIF_CE_state { struct hif_softc ol_sc; bool started; struct ce_tasklet_entry tasklets[CE_COUNT_MAX]; + struct hif_ext_group_entry hif_ext_group[HIF_MAX_GROUP]; + uint32_t hif_num_extgroup; qdf_spinlock_t keep_awake_lock; qdf_spinlock_t irq_reg_lock; unsigned int keep_awake_count; diff --git a/hif/src/dispatcher/ahb_api.h b/hif/src/dispatcher/ahb_api.h index 3a715fd44e..75f1506484 100644 --- a/hif/src/dispatcher/ahb_api.h +++ b/hif/src/dispatcher/ahb_api.h @@ -35,6 +35,8 @@ void hif_ahb_disable_bus(struct hif_softc *scn); int hif_ahb_bus_configure(struct hif_softc *scn); void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id); void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id); +void hif_ahb_grp_irq_disable(struct hif_softc *scn, uint32_t grp_id); +void hif_ahb_grp_irq_enable(struct hif_softc *scn, uint32_t grp_id); int hif_ahb_dump_registers(struct hif_softc *scn); int hif_ahb_configure_legacy_irq(struct hif_pci_softc *sc); diff --git a/hif/src/dispatcher/dummy.c b/hif/src/dispatcher/dummy.c index 1690e058d8..6c2ebd7e75 100644 --- a/hif/src/dispatcher/dummy.c +++ b/hif/src/dispatcher/dummy.c @@ -232,6 +232,16 @@ hif_dummy_cancel_deferred_target_sleep(struct hif_softc *hif_sc) void hif_dummy_irq_enable(struct hif_softc *hif_sc, int irq_id) {} +/** + * hif_dummy_grp_irq_enable - dummy call + * hif_ctx: hif context + * @irq_id: grp id + * + * Return: none + */ +void hif_dummy_grp_irq_enable(struct hif_softc *hif_sc, uint32_t grp_id) +{} + /** * hif_dummy_irq_disable - dummy call * hif_ctx: hif context @@ -242,6 +252,15 @@ void hif_dummy_irq_enable(struct hif_softc *hif_sc, int irq_id) void hif_dummy_irq_disable(struct hif_softc *hif_sc, int irq_id) {} +/** + * hif_dummy_grp_irq_disable- dummy call + * hif_ctx: hif context + * @grp_id: grp id + * + * Return: none + */ +void hif_dummy_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id) +{} /** * 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 b531c1dd4e..6d8a2c756c 100644 --- a/hif/src/dispatcher/dummy.h +++ b/hif/src/dispatcher/dummy.h @@ -47,6 +47,8 @@ void hif_dummy_claim_device(struct hif_softc *hif_sc); void hif_dummy_cancel_deferred_target_sleep(struct hif_softc *hif_sc); void hif_dummy_irq_enable(struct hif_softc *hif_sc, int irq_id); void hif_dummy_irq_disable(struct hif_softc *hif_sc, int irq_id); +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_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/multibus.c b/hif/src/dispatcher/multibus.c index 5643b6f057..8b4e463f4a 100644 --- a/hif/src/dispatcher/multibus.c +++ b/hif/src/dispatcher/multibus.c @@ -59,6 +59,8 @@ static void hif_intialize_default_ops(struct hif_softc *hif_sc) bus_ops->hif_bus_reset_resume = &hif_dummy_bus_reset_resume; bus_ops->hif_bus_suspend_noirq = &hif_dummy_bus_suspend_noirq; bus_ops->hif_bus_resume_noirq = &hif_dummy_bus_resume_noirq; + bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; + bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; } #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *)) @@ -286,11 +288,21 @@ void hif_irq_enable(struct hif_softc *hif_sc, int irq_id) hif_sc->bus_ops.hif_irq_enable(hif_sc, irq_id); } +void hif_grp_irq_enable(struct hif_softc *hif_sc, uint32_t grp_id) +{ + hif_sc->bus_ops.hif_grp_irq_enable(hif_sc, grp_id); +} + void hif_irq_disable(struct hif_softc *hif_sc, int irq_id) { hif_sc->bus_ops.hif_irq_disable(hif_sc, irq_id); } +void hif_grp_irq_disable(struct hif_softc *hif_sc, uint32_t grp_id) +{ + hif_sc->bus_ops.hif_grp_irq_disable(hif_sc, grp_id); +} + 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 63423630c1..e90a94599f 100644 --- a/hif/src/dispatcher/multibus.h +++ b/hif/src/dispatcher/multibus.h @@ -61,7 +61,9 @@ struct hif_bus_ops { void (*hif_stop)(struct hif_softc *hif_sc); void (*hif_cancel_deferred_target_sleep)(struct hif_softc *hif_sc); void (*hif_irq_disable)(struct hif_softc *hif_sc, int ce_id); + void (*hif_grp_irq_disable)(struct hif_softc *hif_sc, uint32_t grp_id); void (*hif_irq_enable)(struct hif_softc *hif_sc, int ce_id); + void (*hif_grp_irq_enable)(struct hif_softc *hif_sc, uint32_t grp_id); int (*hif_dump_registers)(struct hif_softc *hif_sc); void (*hif_dump_target_memory)(struct hif_softc *hif_sc, void *ramdump_base, diff --git a/hif/src/dispatcher/multibus_ahb.c b/hif/src/dispatcher/multibus_ahb.c index d1bee78d60..d67c9ec697 100644 --- a/hif/src/dispatcher/multibus_ahb.c +++ b/hif/src/dispatcher/multibus_ahb.c @@ -66,6 +66,8 @@ QDF_STATUS hif_initialize_ahb_ops(struct hif_bus_ops *bus_ops) &hif_dummy_enable_power_management; bus_ops->hif_disable_power_management = &hif_dummy_disable_power_management; + bus_ops->hif_grp_irq_disable = &hif_ahb_grp_irq_disable; + bus_ops->hif_grp_irq_enable = &hif_ahb_grp_irq_enable; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_pci.c b/hif/src/dispatcher/multibus_pci.c index 5459105158..44f2953d0a 100644 --- a/hif/src/dispatcher/multibus_pci.c +++ b/hif/src/dispatcher/multibus_pci.c @@ -85,6 +85,8 @@ QDF_STATUS hif_initialize_pci_ops(struct hif_softc *hif_sc) &hif_pci_display_stats; bus_ops->hif_clear_stats = &hif_pci_clear_stats; + bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; + bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_sdio.c b/hif/src/dispatcher/multibus_sdio.c index fc27202551..1f957c4bfa 100644 --- a/hif/src/dispatcher/multibus_sdio.c +++ b/hif/src/dispatcher/multibus_sdio.c @@ -64,6 +64,8 @@ QDF_STATUS hif_initialize_sdio_ops(struct hif_softc *hif_sc) &hif_dummy_enable_power_management; bus_ops->hif_disable_power_management = &hif_dummy_disable_power_management; + bus_ops->hif_grp_irq_disable = &hif_dummy_grp_irq_disable; + bus_ops->hif_grp_irq_enable = &hif_dummy_grp_irq_enable; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/dispatcher/multibus_snoc.c b/hif/src/dispatcher/multibus_snoc.c index 2dc80d62e6..3d31077753 100644 --- a/hif/src/dispatcher/multibus_snoc.c +++ b/hif/src/dispatcher/multibus_snoc.c @@ -79,6 +79,8 @@ QDF_STATUS hif_initialize_snoc_ops(struct hif_bus_ops *bus_ops) &hif_snoc_display_stats; bus_ops->hif_clear_stats = &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; return QDF_STATUS_SUCCESS; } diff --git a/hif/src/hif_io32.h b/hif/src/hif_io32.h index 8c39893154..8c1453f49f 100644 --- a/hif/src/hif_io32.h +++ b/hif/src/hif_io32.h @@ -104,6 +104,7 @@ void hif_target_write_checked(struct hif_softc *scn, uint32_t offset, void hif_irq_enable(struct hif_softc *scn, int irq_id); void hif_irq_disable(struct hif_softc *scn, int irq_id); - +void hif_grp_irq_enable(struct hif_softc *scn, uint32_t grp_id); +void hif_grp_irq_disable(struct hif_softc *scn, uint32_t grp_id); #endif /* __HIF_IO32_H__ */ diff --git a/hif/src/hif_main.c b/hif/src/hif_main.c index 96c3241a73..936a45127e 100644 --- a/hif/src/hif_main.c +++ b/hif/src/hif_main.c @@ -375,6 +375,7 @@ struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx, uint32_t mode, scn->qdf_dev = qdf_ctx; scn->hif_con_param = mode; qdf_atomic_init(&scn->active_tasklet_cnt); + qdf_atomic_init(&scn->active_grp_tasklet_cnt); qdf_atomic_init(&scn->link_suspended); qdf_atomic_init(&scn->tasklet_from_intr); qdf_mem_copy(&scn->callbacks, cbk, sizeof(struct hif_driver_state_callbacks)); @@ -1017,3 +1018,93 @@ void hif_ramdump_handler(struct hif_opaque_softc *scn) hif_usb_ramdump_handler(); } #endif + +/** + * hif_register_ext_group_int_handler() - API to register external group + * interrupt handler. + * @hif_ctx : HIF Context + * @numirq: number of irq's in the group + * @irq: array of irq values + * @ext_intr_handler: callback interrupt handler function + * @context: context to passed in callback + * + * Return: status + */ +uint32_t hif_register_ext_group_int_handler(struct hif_opaque_softc *hif_ctx, + uint32_t numirq, uint32_t irq[], ext_intr_handler handler, + void *context) +{ + struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; + + if (scn->hif_init_done) { + HIF_ERROR("%s Called after HIF initialization \n", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (hif_state->hif_num_extgroup >= HIF_MAX_GROUP) { + HIF_ERROR("%s Max groups reached\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + if (numirq >= HIF_MAX_GRP_IRQ) { + HIF_ERROR("%s invalid numirq\n", __func__); + return QDF_STATUS_E_FAILURE; + } + + hif_ext_group = &hif_state->hif_ext_group[hif_state->hif_num_extgroup]; + + hif_ext_group->numirq = numirq; + qdf_mem_copy(&hif_ext_group->irq[0], irq, numirq * sizeof(irq[0])); + hif_ext_group->context = context; + hif_ext_group->handler = handler; + hif_ext_group->configured = true; + hif_ext_group->grp_id = hif_state->hif_num_extgroup; + + hif_state->hif_num_extgroup++; + return QDF_STATUS_SUCCESS; +} + +/** + * hif_ext_grp_tasklet() - grp tasklet + * data: context + * + * return: void + */ +void hif_ext_grp_tasklet(unsigned long data) +{ + struct hif_ext_group_entry *hif_ext_group = + (struct hif_ext_group_entry *)data; + struct HIF_CE_state *hif_state = hif_ext_group->hif_state; + struct hif_softc *scn = HIF_GET_SOFTC(hif_state); + + if (hif_ext_group->grp_id < HIF_MAX_GROUP) { + hif_ext_group->handler(hif_ext_group->context, HIF_MAX_BUDGET); + hif_grp_irq_enable(scn, hif_ext_group->grp_id); + } else { + HIF_ERROR("%s: ERROR - invalid grp_id = %d", + __func__, hif_ext_group->grp_id); + } + + qdf_atomic_dec(&scn->active_grp_tasklet_cnt); +} + +/** + * hif_grp_tasklet_kill() - grp tasklet kill + * scn: hif_softc + * + * return: void + */ +void hif_grp_tasklet_kill(struct hif_softc *scn) +{ + int i; + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + + for (i = 0; i < HIF_MAX_GROUP; i++) + if (hif_state->hif_ext_group[i].inited) { + tasklet_kill(&hif_state->hif_ext_group[i].intr_tq); + hif_state->hif_ext_group[i].inited = false; + } + qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); +} diff --git a/hif/src/hif_main.h b/hif/src/hif_main.h index 7e5d62c0d9..0d0ae165c6 100644 --- a/hif/src/hif_main.h +++ b/hif/src/hif_main.h @@ -51,6 +51,8 @@ #define HIF_MIN_SLEEP_INACTIVITY_TIME_MS 50 #define HIF_SLEEP_INACTIVITY_TIMER_PERIOD_MS 60 +#define HIF_MAX_BUDGET 0xFFFF + /* * This macro implementation is exposed for efficiency only. * The implementation may change and callers should @@ -136,6 +138,7 @@ struct hif_softc { /* No of copy engines supported */ unsigned int ce_count; atomic_t active_tasklet_cnt; + atomic_t active_grp_tasklet_cnt; atomic_t link_suspended; uint32_t *vaddr_rri_on_ddr; int linkstate_vote; @@ -218,4 +221,6 @@ void hif_ramdump_handler(struct hif_opaque_softc *scn); static inline void hif_usb_get_hw_info(struct hif_softc *scn) {} static inline void hif_ramdump_handler(struct hif_opaque_softc *scn) {} #endif +void hif_ext_grp_tasklet(unsigned long data); +void hif_grp_tasklet_kill(struct hif_softc *scn); #endif /* __HIF_MAIN_H__ */ diff --git a/hif/src/pcie/if_pci.c b/hif/src/pcie/if_pci.c index 0558d3d966..2a280fb792 100644 --- a/hif/src/pcie/if_pci.c +++ b/hif/src/pcie/if_pci.c @@ -2952,8 +2952,10 @@ void hif_pci_disable_isr(struct hif_softc *scn) hif_free_msi_ctx(scn); /* Cancel the pending tasklet */ ce_tasklet_kill(scn); + hif_grp_tasklet_kill(scn); tasklet_kill(&sc->intr_tq); qdf_atomic_set(&scn->active_tasklet_cnt, 0); + qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); } /* Function to reset SoC */ diff --git a/hif/src/snoc/if_ahb.c b/hif/src/snoc/if_ahb.c index 23c2b6a0b3..0b9bf3184f 100644 --- a/hif/src/snoc/if_ahb.c +++ b/hif/src/snoc/if_ahb.c @@ -32,6 +32,7 @@ #include "if_pci.h" #include "ahb_api.h" #include "pci_api.h" +#include "hif_napi.h" #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) #define IRQF_DISABLED 0x00000020 @@ -40,6 +41,7 @@ #define HIF_IC_CE0_IRQ_OFFSET 4 #define HIF_IC_MAX_IRQ 54 +static uint8_t ic_irqnum[HIF_IC_MAX_IRQ]; /* integrated chip irq names */ const char *ic_irqname[HIF_IC_MAX_IRQ] = { "misc_pulse1", @@ -98,7 +100,6 @@ const char *ic_irqname[HIF_IC_MAX_IRQ] = { "tcl2host_status_ring", }; -irqreturn_t hif_ahb_interrupt_handler(int irq, void *context); /** * hif_disable_isr() - disable isr * @@ -114,8 +115,10 @@ void hif_ahb_disable_isr(struct hif_softc *scn) hif_nointrs(scn); ce_tasklet_kill(scn); + hif_grp_tasklet_kill(scn); tasklet_kill(&sc->intr_tq); qdf_atomic_set(&scn->active_tasklet_cnt, 0); + qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); } /** @@ -246,17 +249,19 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc) int ret = 0; struct hif_softc *scn = HIF_GET_SOFTC(sc); struct platform_device *pdev = (struct platform_device *)sc->pdev; - struct HIF_CE_state *hif_ce_state = HIF_GET_CE_STATE(scn); + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; int irq = 0; - int i; + int i, j; /* configure per CE interrupts */ for (i = 0; i < scn->ce_count; i++) { irq = platform_get_irq_byname(pdev, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i]); + ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i] = irq; ret = request_irq(irq , hif_ahb_interrupt_handler, IRQF_TRIGGER_RISING, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i], - &hif_ce_state->tasklets[i]); + &hif_state->tasklets[i]); if (ret) { dev_err(&pdev->dev, "ath_request_irq failed\n"); ret = -1; @@ -265,6 +270,36 @@ int hif_ahb_configure_irq(struct hif_pci_softc *sc) hif_ahb_irq_enable(scn, i); } + /* configure external interrupts */ + for (i = 0; i < hif_state->hif_num_extgroup; i++) { + + hif_ext_group = &hif_state->hif_ext_group[i]; + if (hif_ext_group->configured) { + + tasklet_init(&hif_ext_group->intr_tq, + hif_ext_grp_tasklet, + (unsigned long)hif_ext_group); + hif_ext_group->inited = true; + + for (j = 0; j < hif_ext_group->numirq; j++) { + irq = platform_get_irq_byname(pdev, + ic_irqname[hif_ext_group->irq[j]]); + + ic_irqnum[hif_ext_group->irq[j]] = irq; + ret = request_irq(irq, + hif_ext_group_ahb_interrupt_handler, + IRQF_TRIGGER_RISING, "wlan_ahb", + hif_ext_group); + if (ret) { + dev_err(&pdev->dev, + "ath_request_irq failed\n"); + ret = -1; + goto end; + } + } + } + } + end: return ret; } @@ -275,6 +310,26 @@ irqreturn_t hif_ahb_interrupt_handler(int irq, void *context) return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry); } +irqreturn_t hif_ext_group_ahb_interrupt_handler(int irq, void *context) +{ + struct hif_ext_group_entry *hif_ext_group = context; + struct HIF_CE_state *hif_state = hif_ext_group->hif_state; + struct hif_softc *scn = HIF_GET_SOFTC(hif_state); + struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn); + uint32_t grp_id = hif_ext_group->grp_id; + + hif_grp_irq_disable(scn, grp_id); + + qdf_atomic_inc(&scn->active_grp_tasklet_cnt); + + if (hif_ext_napi_enabled(hif_hdl, grp_id)) { + hif_napi_schedule_grp(hif_hdl, grp_id); + } else { + tasklet_schedule(&hif_ext_group->intr_tq); + } + + return IRQ_HANDLED; +} /** * hif_target_sync() : ensure the target is ready @@ -493,9 +548,7 @@ void hif_ahb_reset_soc(struct hif_softc *hif_ctx) void hif_ahb_nointrs(struct hif_softc *scn) { int i; - int irq; struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn); - struct platform_device *pdev = (struct platform_device *)sc->pdev; struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); if (scn->request_irq_done == false) @@ -512,8 +565,8 @@ void hif_ahb_nointrs(struct hif_softc *scn) free_irq(sc->irq, sc); } else { for (i = 0; i < scn->ce_count; i++) { - irq = platform_get_irq_byname(pdev, ic_irqname[HIF_IC_CE0_IRQ_OFFSET + i]); - free_irq(irq, sc); + free_irq(ic_irqnum[HIF_IC_CE0_IRQ_OFFSET + i], + sc); } } } @@ -592,3 +645,29 @@ void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id) } } } + +void hif_ahb_grp_irq_disable(struct hif_softc *scn, uint32_t grp_id) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; + uint32_t i; + + hif_ext_group = &hif_state->hif_ext_group[grp_id]; + + for (i = 0; i < hif_ext_group->numirq; i++) { + disable_irq(ic_irqnum[hif_ext_group->irq[i]]); + } +} + +void hif_ahb_grp_irq_enable(struct hif_softc *scn, uint32_t grp_id) +{ + struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn); + struct hif_ext_group_entry *hif_ext_group; + uint32_t i; + + hif_ext_group = &hif_state->hif_ext_group[grp_id]; + + for (i = 0; i < hif_ext_group->numirq; i++) { + enable_irq(ic_irqnum[hif_ext_group->irq[i]]); + } +} diff --git a/hif/src/snoc/if_ahb.h b/hif/src/snoc/if_ahb.h index f5c9081a96..990d300e00 100644 --- a/hif/src/snoc/if_ahb.h +++ b/hif/src/snoc/if_ahb.h @@ -45,5 +45,9 @@ #define TCSR_WCSS0_HALTACK 0x52010 #define TCSR_WCSS1_HALTACK 0x52014 #define ATH_AHB_RESET_WAIT_MAX 10 /* Ms */ + +irqreturn_t hif_ahb_interrupt_handler(int irq, void *context); +irqreturn_t hif_ext_group_ahb_interrupt_handler(int irq, void *context); + #endif diff --git a/hif/src/snoc/if_snoc.c b/hif/src/snoc/if_snoc.c index 74acfbe96d..5eb123ef40 100644 --- a/hif/src/snoc/if_snoc.c +++ b/hif/src/snoc/if_snoc.c @@ -55,7 +55,9 @@ void hif_snoc_disable_isr(struct hif_softc *scn) { hif_nointrs(scn); ce_tasklet_kill(scn); + hif_grp_tasklet_kill(scn); qdf_atomic_set(&scn->active_tasklet_cnt, 0); + qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0); } /**