Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-29 Thread Anup Patel
On Fri, May 29, 2020 at 4:40 PM Marc Zyngier  wrote:
>
> On 2020-05-29 11:45, Anup Patel wrote:
> > On Fri, May 29, 2020 at 3:39 PM Marc Zyngier  wrote:
> >>
> >> On 2020-05-21 14:32, Anup Patel wrote:
>
> [...]
>
> >> > +/* Get the OF device node used by INTC irq domain */
> >> > +struct device_node *riscv_of_intc_domain_node(void)
> >> > +{
> >> > + return intc_domain_node;
> >> > +}
> >> > +EXPORT_SYMBOL_GPL(riscv_of_intc_domain_node);
> >>
> >> Why do you need this? Why can't the timer node refer to its
> >> interrupt-parent? The irqchip shouldn't be in the business of
> >> working around DT issues.
> >>
> >> At worse, use the default irqdomain if you must, but please
> >> avoid this kind of construct.
> >
> > Even, I don't like exporting riscv_of_intc_domain_node().
> >
> > Thanks for your suggestion, I will certainly use the default irqdomain.
>
> This should be a last resort solution. The irqdomain should
> naturally come from the parent interrupt controller, accessible
> from the device (the timer in this case) node.
>
> Use it to for backward compatibility if you *really* must,
> but this is generally a very bad idea as it allows all kind
> of bizarre fallbacks and hides bugs.

Okay, I will explore other approaches and keep default irqdomain
as a last resort solution.

Regards,
Anup


Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-29 Thread Marc Zyngier

On 2020-05-29 11:45, Anup Patel wrote:

On Fri, May 29, 2020 at 3:39 PM Marc Zyngier  wrote:


On 2020-05-21 14:32, Anup Patel wrote:


[...]


> +/* Get the OF device node used by INTC irq domain */
> +struct device_node *riscv_of_intc_domain_node(void)
> +{
> + return intc_domain_node;
> +}
> +EXPORT_SYMBOL_GPL(riscv_of_intc_domain_node);

Why do you need this? Why can't the timer node refer to its
interrupt-parent? The irqchip shouldn't be in the business of
working around DT issues.

At worse, use the default irqdomain if you must, but please
avoid this kind of construct.


Even, I don't like exporting riscv_of_intc_domain_node().

Thanks for your suggestion, I will certainly use the default irqdomain.


This should be a last resort solution. The irqdomain should
naturally come from the parent interrupt controller, accessible
from the device (the timer in this case) node.

Use it to for backward compatibility if you *really* must,
but this is generally a very bad idea as it allows all kind
of bizarre fallbacks and hides bugs.

Thanks,

 M.
--
Jazz is not dead. It just smells funny...


Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-29 Thread Anup Patel
On Fri, May 29, 2020 at 3:39 PM Marc Zyngier  wrote:
>
> On 2020-05-21 14:32, Anup Patel wrote:
> > The RISC-V per-HART local interrupt controller manages software
> > interrupts, timer interrupts, external interrupts (which are routed
> > via the platform level interrupt controller) and other per-HART
> > local interrupts.
> >
> > This patch adds a driver for the RISC-V local interrupt controller.
> > It is a major re-write over perviously submitted version.
> > (Refer, https://www.spinics.net/lists/devicetree/msg241230.html)
> >
> > Few advantages of this new driver over previous one are:
> > 1. All local interrupts are registered as per-CPU interrupts
> > 2. The RISC-V timer driver can register timer interrupt handler
> >using kernel irq subsystem without relying on arch/riscv to
> >explicitly call it's interrupt handler
> > 3. The KVM RISC-V can use this driver to implement interrupt
> >handler for per-HART guest external interrupt defined by
> >the RISC-V H-Extension
> > 4. In future, we can develop drivers for devices with per-HART
> >interrupts without changing arch code or this driver (example,
> >CLINT timer driver for RISC-V M-mode kernel)
>
> Most of this is cover letter material, and doesn't belong to the
> changelog.

Okay, I will drop this from commit description.

>
> >
> > The RISC-V INTC driver is compliant with RISC-V Hart-Level Interrupt
> > Controller DT bindings located at:
> > Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
> >
> > Signed-off-by: Palmer Dabbelt 
>
> Is Palmer the author? If so, you're missing the 'From' line at the top.
> Otherwise, you're missing a Co-developed-by tag.

Palmer had submitted the first implementation of RISC-V INTC driver
more than 2 years back. That driver had separate IRQ domain for
each CPU and did not use per-CPU interrupts.

The driver added by this patch is re-write to have only one IRQ
domain with all per-CPU interrupts.

I kept Palmer's SoB to acknowledge his initial efforts. I will add
Co-developed-by tag like you suggested.

>
> > Signed-off-by: Anup Patel 
> > ---
> >  arch/riscv/Kconfig |   1 +
> >  arch/riscv/include/asm/irq.h   |   2 -
> >  arch/riscv/kernel/irq.c|  33 +-
> >  arch/riscv/kernel/traps.c  |   2 -
> >  drivers/irqchip/Kconfig|  13 ++
> >  drivers/irqchip/Makefile   |   1 +
> >  drivers/irqchip/irq-riscv-intc.c   | 158 +
> >  drivers/irqchip/irq-sifive-plic.c  |  38 +-
> >  include/linux/cpuhotplug.h |   1 +
> >  include/linux/irqchip/irq-riscv-intc.h |  20 
> >  10 files changed, 229 insertions(+), 40 deletions(-)
> >  create mode 100644 drivers/irqchip/irq-riscv-intc.c
> >  create mode 100644 include/linux/irqchip/irq-riscv-intc.h
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index 90a008e28f7e..822cb0e1a380 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -40,6 +40,7 @@ config RISCV
> >   select HAVE_PERF_REGS
> >   select HAVE_PERF_USER_STACK_DUMP
> >   select HAVE_SYSCALL_TRACEPOINTS
> > + select HANDLE_DOMAIN_IRQ
> >   select IRQ_DOMAIN
> >   select SPARSE_IRQ
> >   select SYSCTL_EXCEPTION_TRACE
> > diff --git a/arch/riscv/include/asm/irq.h
> > b/arch/riscv/include/asm/irq.h
> > index 0183e15ace66..a9e5f07a7e9c 100644
> > --- a/arch/riscv/include/asm/irq.h
> > +++ b/arch/riscv/include/asm/irq.h
> > @@ -10,8 +10,6 @@
> >  #include 
> >  #include 
> >
> > -#define NR_IRQS 0
> > -
> >  void riscv_timer_interrupt(void);
> >
> >  #include 
> > diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
> > index bb0bfcd537e7..eb8777642ce6 100644
> > --- a/arch/riscv/kernel/irq.c
> > +++ b/arch/riscv/kernel/irq.c
> > @@ -7,7 +7,6 @@
> >
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> >  #include 
> >
> > @@ -19,39 +18,13 @@ int arch_show_interrupts(struct seq_file *p, int
> > prec)
> >
> >  asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
> >  {
> > - struct pt_regs *old_regs;
> > -
> > - switch (regs->cause & ~CAUSE_IRQ_FLAG) {
> > - case RV_IRQ_TIMER:
> > - old_regs = set_irq_regs(regs);
> > - irq_enter();
> > - riscv_timer_interrupt();
> > - irq_exit();
> > - set_irq_regs(old_regs);
> > - break;
> > -#ifdef CONFIG_SMP
> > - case RV_IRQ_SOFT:
> > - /*
> > -  * We only use software interrupts to pass IPIs, so if a 
> > non-SMP
> > -  * system gets one, then we don't know what to do.
> > -  */
> > - handle_IPI(regs);
> > - break;
> > -#endif
> > - case RV_IRQ_EXT:
> > - old_regs = set_irq_regs(regs);
> > - irq_enter();
> > + if (handle_arch_irq)
> >   handle_arch_irq(regs);
> > - irq_exit();
> > - 

Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-29 Thread Marc Zyngier

On 2020-05-21 14:32, Anup Patel wrote:

The RISC-V per-HART local interrupt controller manages software
interrupts, timer interrupts, external interrupts (which are routed
via the platform level interrupt controller) and other per-HART
local interrupts.

This patch adds a driver for the RISC-V local interrupt controller.
It is a major re-write over perviously submitted version.
(Refer, https://www.spinics.net/lists/devicetree/msg241230.html)

Few advantages of this new driver over previous one are:
1. All local interrupts are registered as per-CPU interrupts
2. The RISC-V timer driver can register timer interrupt handler
   using kernel irq subsystem without relying on arch/riscv to
   explicitly call it's interrupt handler
3. The KVM RISC-V can use this driver to implement interrupt
   handler for per-HART guest external interrupt defined by
   the RISC-V H-Extension
4. In future, we can develop drivers for devices with per-HART
   interrupts without changing arch code or this driver (example,
   CLINT timer driver for RISC-V M-mode kernel)


Most of this is cover letter material, and doesn't belong to the 
changelog.




The RISC-V INTC driver is compliant with RISC-V Hart-Level Interrupt
Controller DT bindings located at:
Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt

Signed-off-by: Palmer Dabbelt 


Is Palmer the author? If so, you're missing the 'From' line at the top.
Otherwise, you're missing a Co-developed-by tag.


Signed-off-by: Anup Patel 
---
 arch/riscv/Kconfig |   1 +
 arch/riscv/include/asm/irq.h   |   2 -
 arch/riscv/kernel/irq.c|  33 +-
 arch/riscv/kernel/traps.c  |   2 -
 drivers/irqchip/Kconfig|  13 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-riscv-intc.c   | 158 +
 drivers/irqchip/irq-sifive-plic.c  |  38 +-
 include/linux/cpuhotplug.h |   1 +
 include/linux/irqchip/irq-riscv-intc.h |  20 
 10 files changed, 229 insertions(+), 40 deletions(-)
 create mode 100644 drivers/irqchip/irq-riscv-intc.c
 create mode 100644 include/linux/irqchip/irq-riscv-intc.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 90a008e28f7e..822cb0e1a380 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -40,6 +40,7 @@ config RISCV
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_SYSCALL_TRACEPOINTS
+   select HANDLE_DOMAIN_IRQ
select IRQ_DOMAIN
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/riscv/include/asm/irq.h 
b/arch/riscv/include/asm/irq.h

index 0183e15ace66..a9e5f07a7e9c 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -10,8 +10,6 @@
 #include 
 #include 

-#define NR_IRQS 0
-
 void riscv_timer_interrupt(void);

 #include 
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index bb0bfcd537e7..eb8777642ce6 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -7,7 +7,6 @@

 #include 
 #include 
-#include 
 #include 
 #include 

@@ -19,39 +18,13 @@ int arch_show_interrupts(struct seq_file *p, int 
prec)


 asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
 {
-   struct pt_regs *old_regs;
-
-   switch (regs->cause & ~CAUSE_IRQ_FLAG) {
-   case RV_IRQ_TIMER:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
-   riscv_timer_interrupt();
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-#ifdef CONFIG_SMP
-   case RV_IRQ_SOFT:
-   /*
-* We only use software interrupts to pass IPIs, so if a non-SMP
-* system gets one, then we don't know what to do.
-*/
-   handle_IPI(regs);
-   break;
-#endif
-   case RV_IRQ_EXT:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
+   if (handle_arch_irq)
handle_arch_irq(regs);
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-   default:
-   pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
-   BUG();
-   }
 }

 void __init init_IRQ(void)
 {
irqchip_init();
+   if (!handle_arch_irq)
+   panic("No interrupt controller found.");
 }
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 7f58fa53033f..f48c76aadbf3 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -178,6 +178,4 @@ void trap_init(void)
csr_write(CSR_SCRATCH, 0);
/* Set the exception vector address */
csr_write(CSR_TVEC, _exception);
-   /* Enable interrupts */
-   csr_write(CSR_IE, IE_SIE);
 }
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a85aada04a64..95d6137a8117 100644
--- a/drivers/irqchip/Kconfig
+++ 

Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-28 Thread Anup Patel
On Fri, May 29, 2020 at 8:10 AM Palmer Dabbelt  wrote:
>
> On Thu, 21 May 2020 06:32:58 PDT (-0700), Anup Patel wrote:
> > The RISC-V per-HART local interrupt controller manages software
> > interrupts, timer interrupts, external interrupts (which are routed
> > via the platform level interrupt controller) and other per-HART
> > local interrupts.
> >
> > This patch adds a driver for the RISC-V local interrupt controller.
> > It is a major re-write over perviously submitted version.
> > (Refer, https://www.spinics.net/lists/devicetree/msg241230.html)
> >
> > Few advantages of this new driver over previous one are:
> > 1. All local interrupts are registered as per-CPU interrupts
> > 2. The RISC-V timer driver can register timer interrupt handler
> >using kernel irq subsystem without relying on arch/riscv to
> >explicitly call it's interrupt handler
> > 3. The KVM RISC-V can use this driver to implement interrupt
> >handler for per-HART guest external interrupt defined by
> >the RISC-V H-Extension
> > 4. In future, we can develop drivers for devices with per-HART
> >interrupts without changing arch code or this driver (example,
> >CLINT timer driver for RISC-V M-mode kernel)
> >
> > The RISC-V INTC driver is compliant with RISC-V Hart-Level Interrupt
> > Controller DT bindings located at:
> > Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt
> >
> > Signed-off-by: Palmer Dabbelt 
> > Signed-off-by: Anup Patel 
> > ---
> >  arch/riscv/Kconfig |   1 +
> >  arch/riscv/include/asm/irq.h   |   2 -
> >  arch/riscv/kernel/irq.c|  33 +-
> >  arch/riscv/kernel/traps.c  |   2 -
> >  drivers/irqchip/Kconfig|  13 ++
> >  drivers/irqchip/Makefile   |   1 +
> >  drivers/irqchip/irq-riscv-intc.c   | 158 +
> >  drivers/irqchip/irq-sifive-plic.c  |  38 +-
> >  include/linux/cpuhotplug.h |   1 +
> >  include/linux/irqchip/irq-riscv-intc.h |  20 
> >  10 files changed, 229 insertions(+), 40 deletions(-)
> >  create mode 100644 drivers/irqchip/irq-riscv-intc.c
> >  create mode 100644 include/linux/irqchip/irq-riscv-intc.h
> >
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index 90a008e28f7e..822cb0e1a380 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -40,6 +40,7 @@ config RISCV
> >   select HAVE_PERF_REGS
> >   select HAVE_PERF_USER_STACK_DUMP
> >   select HAVE_SYSCALL_TRACEPOINTS
> > + select HANDLE_DOMAIN_IRQ
> >   select IRQ_DOMAIN
> >   select SPARSE_IRQ
> >   select SYSCTL_EXCEPTION_TRACE
> > diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
> > index 0183e15ace66..a9e5f07a7e9c 100644
> > --- a/arch/riscv/include/asm/irq.h
> > +++ b/arch/riscv/include/asm/irq.h
> > @@ -10,8 +10,6 @@
> >  #include 
> >  #include 
> >
> > -#define NR_IRQS 0
> > -
> >  void riscv_timer_interrupt(void);
> >
> >  #include 
> > diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
> > index bb0bfcd537e7..eb8777642ce6 100644
> > --- a/arch/riscv/kernel/irq.c
> > +++ b/arch/riscv/kernel/irq.c
> > @@ -7,7 +7,6 @@
> >
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> >  #include 
> >
> > @@ -19,39 +18,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
> >
> >  asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
> >  {
> > - struct pt_regs *old_regs;
> > -
> > - switch (regs->cause & ~CAUSE_IRQ_FLAG) {
> > - case RV_IRQ_TIMER:
> > - old_regs = set_irq_regs(regs);
> > - irq_enter();
> > - riscv_timer_interrupt();
> > - irq_exit();
> > - set_irq_regs(old_regs);
> > - break;
> > -#ifdef CONFIG_SMP
> > - case RV_IRQ_SOFT:
> > - /*
> > -  * We only use software interrupts to pass IPIs, so if a 
> > non-SMP
> > -  * system gets one, then we don't know what to do.
> > -  */
> > - handle_IPI(regs);
> > - break;
> > -#endif
> > - case RV_IRQ_EXT:
> > - old_regs = set_irq_regs(regs);
> > - irq_enter();
> > + if (handle_arch_irq)
> >   handle_arch_irq(regs);
> > - irq_exit();
> > - set_irq_regs(old_regs);
> > - break;
> > - default:
> > - pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
> > - BUG();
> > - }
> >  }
> >
> >  void __init init_IRQ(void)
> >  {
> >   irqchip_init();
> > + if (!handle_arch_irq)
> > + panic("No interrupt controller found.");
> >  }
> > diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
> > index 7f58fa53033f..f48c76aadbf3 100644
> > --- a/arch/riscv/kernel/traps.c
> > +++ b/arch/riscv/kernel/traps.c
> > @@ -178,6 +178,4 @@ void trap_init(void)
> >   csr_write(CSR_SCRATCH, 0);
> >   /* Set 

Re: [PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-28 Thread Palmer Dabbelt

On Thu, 21 May 2020 06:32:58 PDT (-0700), Anup Patel wrote:

The RISC-V per-HART local interrupt controller manages software
interrupts, timer interrupts, external interrupts (which are routed
via the platform level interrupt controller) and other per-HART
local interrupts.

This patch adds a driver for the RISC-V local interrupt controller.
It is a major re-write over perviously submitted version.
(Refer, https://www.spinics.net/lists/devicetree/msg241230.html)

Few advantages of this new driver over previous one are:
1. All local interrupts are registered as per-CPU interrupts
2. The RISC-V timer driver can register timer interrupt handler
   using kernel irq subsystem without relying on arch/riscv to
   explicitly call it's interrupt handler
3. The KVM RISC-V can use this driver to implement interrupt
   handler for per-HART guest external interrupt defined by
   the RISC-V H-Extension
4. In future, we can develop drivers for devices with per-HART
   interrupts without changing arch code or this driver (example,
   CLINT timer driver for RISC-V M-mode kernel)

The RISC-V INTC driver is compliant with RISC-V Hart-Level Interrupt
Controller DT bindings located at:
Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt

Signed-off-by: Palmer Dabbelt 
Signed-off-by: Anup Patel 
---
 arch/riscv/Kconfig |   1 +
 arch/riscv/include/asm/irq.h   |   2 -
 arch/riscv/kernel/irq.c|  33 +-
 arch/riscv/kernel/traps.c  |   2 -
 drivers/irqchip/Kconfig|  13 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-riscv-intc.c   | 158 +
 drivers/irqchip/irq-sifive-plic.c  |  38 +-
 include/linux/cpuhotplug.h |   1 +
 include/linux/irqchip/irq-riscv-intc.h |  20 
 10 files changed, 229 insertions(+), 40 deletions(-)
 create mode 100644 drivers/irqchip/irq-riscv-intc.c
 create mode 100644 include/linux/irqchip/irq-riscv-intc.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 90a008e28f7e..822cb0e1a380 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -40,6 +40,7 @@ config RISCV
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_SYSCALL_TRACEPOINTS
+   select HANDLE_DOMAIN_IRQ
select IRQ_DOMAIN
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 0183e15ace66..a9e5f07a7e9c 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -10,8 +10,6 @@
 #include 
 #include 

-#define NR_IRQS 0
-
 void riscv_timer_interrupt(void);

 #include 
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index bb0bfcd537e7..eb8777642ce6 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -7,7 +7,6 @@

 #include 
 #include 
-#include 
 #include 
 #include 

@@ -19,39 +18,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)

 asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
 {
-   struct pt_regs *old_regs;
-
-   switch (regs->cause & ~CAUSE_IRQ_FLAG) {
-   case RV_IRQ_TIMER:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
-   riscv_timer_interrupt();
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-#ifdef CONFIG_SMP
-   case RV_IRQ_SOFT:
-   /*
-* We only use software interrupts to pass IPIs, so if a non-SMP
-* system gets one, then we don't know what to do.
-*/
-   handle_IPI(regs);
-   break;
-#endif
-   case RV_IRQ_EXT:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
+   if (handle_arch_irq)
handle_arch_irq(regs);
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-   default:
-   pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
-   BUG();
-   }
 }

 void __init init_IRQ(void)
 {
irqchip_init();
+   if (!handle_arch_irq)
+   panic("No interrupt controller found.");
 }
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 7f58fa53033f..f48c76aadbf3 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -178,6 +178,4 @@ void trap_init(void)
csr_write(CSR_SCRATCH, 0);
/* Set the exception vector address */
csr_write(CSR_TVEC, _exception);
-   /* Enable interrupts */
-   csr_write(CSR_IE, IE_SIE);
 }
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a85aada04a64..95d6137a8117 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -493,6 +493,19 @@ config TI_SCI_INTA_IRQCHIP
  If you wish to use interrupt aggregator irq resources managed by the
  TI System Controller, say Y here. Otherwise, 

[PATCH v5 3/6] irqchip: RISC-V per-HART local interrupt controller driver

2020-05-21 Thread Anup Patel
The RISC-V per-HART local interrupt controller manages software
interrupts, timer interrupts, external interrupts (which are routed
via the platform level interrupt controller) and other per-HART
local interrupts.

This patch adds a driver for the RISC-V local interrupt controller.
It is a major re-write over perviously submitted version.
(Refer, https://www.spinics.net/lists/devicetree/msg241230.html)

Few advantages of this new driver over previous one are:
1. All local interrupts are registered as per-CPU interrupts
2. The RISC-V timer driver can register timer interrupt handler
   using kernel irq subsystem without relying on arch/riscv to
   explicitly call it's interrupt handler
3. The KVM RISC-V can use this driver to implement interrupt
   handler for per-HART guest external interrupt defined by
   the RISC-V H-Extension
4. In future, we can develop drivers for devices with per-HART
   interrupts without changing arch code or this driver (example,
   CLINT timer driver for RISC-V M-mode kernel)

The RISC-V INTC driver is compliant with RISC-V Hart-Level Interrupt
Controller DT bindings located at:
Documentation/devicetree/bindings/interrupt-controller/riscv,cpu-intc.txt

Signed-off-by: Palmer Dabbelt 
Signed-off-by: Anup Patel 
---
 arch/riscv/Kconfig |   1 +
 arch/riscv/include/asm/irq.h   |   2 -
 arch/riscv/kernel/irq.c|  33 +-
 arch/riscv/kernel/traps.c  |   2 -
 drivers/irqchip/Kconfig|  13 ++
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-riscv-intc.c   | 158 +
 drivers/irqchip/irq-sifive-plic.c  |  38 +-
 include/linux/cpuhotplug.h |   1 +
 include/linux/irqchip/irq-riscv-intc.h |  20 
 10 files changed, 229 insertions(+), 40 deletions(-)
 create mode 100644 drivers/irqchip/irq-riscv-intc.c
 create mode 100644 include/linux/irqchip/irq-riscv-intc.h

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 90a008e28f7e..822cb0e1a380 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -40,6 +40,7 @@ config RISCV
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
select HAVE_SYSCALL_TRACEPOINTS
+   select HANDLE_DOMAIN_IRQ
select IRQ_DOMAIN
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 0183e15ace66..a9e5f07a7e9c 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -10,8 +10,6 @@
 #include 
 #include 
 
-#define NR_IRQS 0
-
 void riscv_timer_interrupt(void);
 
 #include 
diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c
index bb0bfcd537e7..eb8777642ce6 100644
--- a/arch/riscv/kernel/irq.c
+++ b/arch/riscv/kernel/irq.c
@@ -7,7 +7,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -19,39 +18,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 
 asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
 {
-   struct pt_regs *old_regs;
-
-   switch (regs->cause & ~CAUSE_IRQ_FLAG) {
-   case RV_IRQ_TIMER:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
-   riscv_timer_interrupt();
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-#ifdef CONFIG_SMP
-   case RV_IRQ_SOFT:
-   /*
-* We only use software interrupts to pass IPIs, so if a non-SMP
-* system gets one, then we don't know what to do.
-*/
-   handle_IPI(regs);
-   break;
-#endif
-   case RV_IRQ_EXT:
-   old_regs = set_irq_regs(regs);
-   irq_enter();
+   if (handle_arch_irq)
handle_arch_irq(regs);
-   irq_exit();
-   set_irq_regs(old_regs);
-   break;
-   default:
-   pr_alert("unexpected interrupt cause 0x%lx", regs->cause);
-   BUG();
-   }
 }
 
 void __init init_IRQ(void)
 {
irqchip_init();
+   if (!handle_arch_irq)
+   panic("No interrupt controller found.");
 }
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 7f58fa53033f..f48c76aadbf3 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -178,6 +178,4 @@ void trap_init(void)
csr_write(CSR_SCRATCH, 0);
/* Set the exception vector address */
csr_write(CSR_TVEC, _exception);
-   /* Enable interrupts */
-   csr_write(CSR_IE, IE_SIE);
 }
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index a85aada04a64..95d6137a8117 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -493,6 +493,19 @@ config TI_SCI_INTA_IRQCHIP
  If you wish to use interrupt aggregator irq resources managed by the
  TI System Controller, say Y here. Otherwise, say N.
 
+config RISCV_INTC
+   bool "RISC-V Local