diff options
author | David S. Miller <davem@davemloft.net> | 2021-07-27 21:02:21 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-07-27 21:02:21 +0100 |
commit | f34d9224503f13cae35ae9d6a43199e3666bbe99 (patch) | |
tree | f9aed3fc8f61a9576d3c632bf70fb5a4977bc0cd | |
parent | 8ca34a13f7f9b3fa2c464160ffe8cc1a72088204 (diff) | |
parent | 176086d870359fa5e4fe226fdcf43340187134c2 (diff) |
Merge branch 'ipa-interrupts'
Alex Elder says:
====================
net: ipa: IPA interrupt cleanup
The first patch in this series makes all IPA interrupt handling be
done in a threaded context. The remaining ones refactor some code
to simplify that threaded handler function.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ipa/ipa_interrupt.c | 57 |
1 files changed, 19 insertions, 38 deletions
diff --git a/drivers/net/ipa/ipa_interrupt.c b/drivers/net/ipa/ipa_interrupt.c index 9fd158dd9047..aa37f03f4557 100644 --- a/drivers/net/ipa/ipa_interrupt.c +++ b/drivers/net/ipa/ipa_interrupt.c @@ -74,21 +74,25 @@ static void ipa_interrupt_process(struct ipa_interrupt *interrupt, u32 irq_id) iowrite32(mask, ipa->reg_virt + offset); } -/* Process all IPA interrupt types that have been signaled */ -static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt) +/* IPA IRQ handler is threaded */ +static irqreturn_t ipa_isr_thread(int irq, void *dev_id) { + struct ipa_interrupt *interrupt = dev_id; struct ipa *ipa = interrupt->ipa; u32 enabled = interrupt->enabled; + u32 pending; u32 offset; u32 mask; + ipa_clock_get(ipa); + /* The status register indicates which conditions are present, * including conditions whose interrupt is not enabled. Handle * only the enabled ones. */ offset = ipa_reg_irq_stts_offset(ipa->version); - mask = ioread32(ipa->reg_virt + offset); - while ((mask &= enabled)) { + pending = ioread32(ipa->reg_virt + offset); + while ((mask = pending & enabled)) { do { u32 irq_id = __ffs(mask); @@ -96,43 +100,20 @@ static void ipa_interrupt_process_all(struct ipa_interrupt *interrupt) ipa_interrupt_process(interrupt, irq_id); } while (mask); - mask = ioread32(ipa->reg_virt + offset); + pending = ioread32(ipa->reg_virt + offset); } -} - -/* Threaded part of the IPA IRQ handler */ -static irqreturn_t ipa_isr_thread(int irq, void *dev_id) -{ - struct ipa_interrupt *interrupt = dev_id; - - ipa_clock_get(interrupt->ipa); - ipa_interrupt_process_all(interrupt); + /* If any disabled interrupts are pending, clear them */ + if (pending) { + struct device *dev = &ipa->pdev->dev; - ipa_clock_put(interrupt->ipa); - - return IRQ_HANDLED; -} - -/* Hard part (i.e., "real" IRQ handler) of the IRQ handler */ -static irqreturn_t ipa_isr(int irq, void *dev_id) -{ - struct ipa_interrupt *interrupt = dev_id; - struct ipa *ipa = interrupt->ipa; - u32 offset; - u32 mask; - - offset = ipa_reg_irq_stts_offset(ipa->version); - mask = ioread32(ipa->reg_virt + offset); - if (mask & interrupt->enabled) - return IRQ_WAKE_THREAD; - - /* Nothing in the mask was supposed to cause an interrupt */ - offset = ipa_reg_irq_clr_offset(ipa->version); - iowrite32(mask, ipa->reg_virt + offset); + dev_dbg(dev, "clearing disabled IPA interrupts 0x%08x\n", + pending); + offset = ipa_reg_irq_clr_offset(ipa->version); + iowrite32(pending, ipa->reg_virt + offset); + } - dev_err(&ipa->pdev->dev, "%s: unexpected interrupt, mask 0x%08x\n", - __func__, mask); + ipa_clock_put(ipa); return IRQ_HANDLED; } @@ -260,7 +241,7 @@ struct ipa_interrupt *ipa_interrupt_config(struct ipa *ipa) offset = ipa_reg_irq_en_offset(ipa->version); iowrite32(0, ipa->reg_virt + offset); - ret = request_threaded_irq(irq, ipa_isr, ipa_isr_thread, IRQF_ONESHOT, + ret = request_threaded_irq(irq, NULL, ipa_isr_thread, IRQF_ONESHOT, "ipa", interrupt); if (ret) { dev_err(dev, "error %d requesting \"ipa\" IRQ\n", ret); |