qcacmn: Add framework for external group interrupt handling
Change-Id: I68a3c597e452e1975a97f9262870e16538f6dc4c CRs-Fixed: 1042915
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
9fd9af065c
commit
31108f318c
@@ -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
|
||||
|
@@ -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; }
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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__ */
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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__ */
|
||||
|
@@ -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 */
|
||||
|
@@ -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]]);
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user