lkml.org 
[lkml]   [2020]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip: irq/core] irqchip/xilinx: Enable generic irq multi handler
    The following commit has been merged into the irq/core branch of tip:

    Commit-ID: a0789993bf8266e62fea6b4613945ba081c71e7d
    Gitweb: https://git.kernel.org/tip/a0789993bf8266e62fea6b4613945ba081c71e7d
    Author: Michal Simek <michal.simek@xilinx.com>
    AuthorDate: Tue, 17 Mar 2020 18:25:59 +05:30
    Committer: Marc Zyngier <maz@kernel.org>
    CommitterDate: Sun, 22 Mar 2020 11:52:53

    irqchip/xilinx: Enable generic irq multi handler

    Register default arch handler via driver instead of directly pointing to
    xilinx intc controller. This patch makes architecture code more generic.

    Driver calls generic domain specific irq handler which does the most of
    things self. Also get rid of concurrent_irq counting which hasn't been
    exported anywhere.
    Based on this loop was also optimized by using do/while loop instead of
    goto loop.

    Signed-off-by: Michal Simek <michal.simek@xilinx.com>
    Signed-off-by: Marc Zyngier <maz@kernel.org>
    Reviewed-by: Stefan Asserhall <stefan.asserhall@xilinx.com>
    Link: https://lore.kernel.org/r/20200317125600.15913-4-mubin.usman.sayyed@xilinx.com
    ---
    arch/microblaze/Kconfig | 2 ++-
    arch/microblaze/include/asm/irq.h | 3 +---
    arch/microblaze/kernel/irq.c | 21 +-------------------
    drivers/irqchip/irq-xilinx-intc.c | 34 +++++++++++++++++-------------
    4 files changed, 23 insertions(+), 37 deletions(-)

    diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
    index 6a331bd..242f58e 100644
    --- a/arch/microblaze/Kconfig
    +++ b/arch/microblaze/Kconfig
    @@ -47,6 +47,8 @@ config MICROBLAZE
    select CPU_NO_EFFICIENT_FFS
    select MMU_GATHER_NO_RANGE if MMU
    select SPARSE_IRQ
    + select GENERIC_IRQ_MULTI_HANDLER
    + select HANDLE_DOMAIN_IRQ

    # Endianness selection
    choice
    diff --git a/arch/microblaze/include/asm/irq.h b/arch/microblaze/include/asm/irq.h
    index eac2fb4..5166f08 100644
    --- a/arch/microblaze/include/asm/irq.h
    +++ b/arch/microblaze/include/asm/irq.h
    @@ -14,7 +14,4 @@
    struct pt_regs;
    extern void do_IRQ(struct pt_regs *regs);

    -/* should be defined in each interrupt controller driver */
    -extern unsigned int xintc_get_irq(void);
    -
    #endif /* _ASM_MICROBLAZE_IRQ_H */
    diff --git a/arch/microblaze/kernel/irq.c b/arch/microblaze/kernel/irq.c
    index 903dad8..0b37dde 100644
    --- a/arch/microblaze/kernel/irq.c
    +++ b/arch/microblaze/kernel/irq.c
    @@ -20,29 +20,10 @@
    #include <linux/irqchip.h>
    #include <linux/of_irq.h>

    -static u32 concurrent_irq;
    -
    void __irq_entry do_IRQ(struct pt_regs *regs)
    {
    - unsigned int irq;
    - struct pt_regs *old_regs = set_irq_regs(regs);
    trace_hardirqs_off();
    -
    - irq_enter();
    - irq = xintc_get_irq();
    -next_irq:
    - BUG_ON(!irq);
    - generic_handle_irq(irq);
    -
    - irq = xintc_get_irq();
    - if (irq != -1U) {
    - pr_debug("next irq: %d\n", irq);
    - ++concurrent_irq;
    - goto next_irq;
    - }
    -
    - irq_exit();
    - set_irq_regs(old_regs);
    + handle_arch_irq(regs);
    trace_hardirqs_on();
    }

    diff --git a/drivers/irqchip/irq-xilinx-intc.c b/drivers/irqchip/irq-xilinx-intc.c
    index 1d3d273..ea74181 100644
    --- a/drivers/irqchip/irq-xilinx-intc.c
    +++ b/drivers/irqchip/irq-xilinx-intc.c
    @@ -124,20 +124,6 @@ static unsigned int xintc_get_irq_local(struct xintc_irq_chip *irqc)
    return irq;
    }

    -unsigned int xintc_get_irq(void)
    -{
    - unsigned int irq = -1;
    - u32 hwirq;
    -
    - hwirq = xintc_read(primary_intc, IVR);
    - if (hwirq != -1U)
    - irq = irq_find_mapping(primary_intc->root_domain, hwirq);
    -
    - pr_debug("irq-xilinx: hwirq=%d, irq=%d\n", hwirq, irq);
    -
    - return irq;
    -}
    -
    static int xintc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
    {
    struct xintc_irq_chip *irqc = d->host_data;
    @@ -177,6 +163,25 @@ static void xil_intc_irq_handler(struct irq_desc *desc)
    chained_irq_exit(chip, desc);
    }

    +static void xil_intc_handle_irq(struct pt_regs *regs)
    +{
    + u32 hwirq;
    + struct xintc_irq_chip *irqc = primary_intc;
    +
    + do {
    + hwirq = xintc_read(irqc, IVR);
    + if (likely(hwirq != -1U)) {
    + int ret;
    +
    + ret = handle_domain_irq(irqc->root_domain, hwirq, regs);
    + WARN_ONCE(ret, "Unhandled HWIRQ %d\n", hwirq);
    + continue;
    + }
    +
    + break;
    + } while (1);
    +}
    +
    static int __init xilinx_intc_of_init(struct device_node *intc,
    struct device_node *parent)
    {
    @@ -246,6 +251,7 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
    } else {
    primary_intc = irqc;
    irq_set_default_host(primary_intc->root_domain);
    + set_handle_irq(xil_intc_handle_irq);
    }

    return 0;
    \
     
     \ /
      Last update: 2020-03-29 22:29    [W:4.071 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site