Re: [PATCH v5 4/6] clocksource/drivers/timer-riscv: Use per-CPU timer interrupt

2020-05-28 Thread Atish Patra
On Thu, May 21, 2020 at 6:34 AM Anup Patel  wrote:
>
> Instead of directly calling RISC-V timer interrupt handler from
> RISC-V local interrupt conntroller driver, this patch implements
> RISC-V timer interrupt as a per-CPU interrupt using per-CPU APIs
> of Linux IRQ subsystem.
>
> Signed-off-by: Anup Patel 
> ---
>  arch/riscv/include/asm/irq.h  |  2 --
>  drivers/clocksource/timer-riscv.c | 30 +++---
>  drivers/irqchip/irq-riscv-intc.c  |  8 
>  3 files changed, 27 insertions(+), 13 deletions(-)
>
> diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
> index a9e5f07a7e9c..9807ad164015 100644
> --- a/arch/riscv/include/asm/irq.h
> +++ b/arch/riscv/include/asm/irq.h
> @@ -10,8 +10,6 @@
>  #include 
>  #include 
>
> -void riscv_timer_interrupt(void);
> -
>  #include 
>
>  #endif /* _ASM_RISCV_IRQ_H */
> diff --git a/drivers/clocksource/timer-riscv.c 
> b/drivers/clocksource/timer-riscv.c
> index c4f15c4068c0..5fb7c5ba5c91 100644
> --- a/drivers/clocksource/timer-riscv.c
> +++ b/drivers/clocksource/timer-riscv.c
> @@ -14,6 +14,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
> +#include 
>  #include 
>  #include 
>
> @@ -39,6 +42,7 @@ static int riscv_clock_next_event(unsigned long delta,
> return 0;
>  }
>
> +static unsigned int riscv_clock_event_irq;
>  static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
> .name   = "riscv_timer_clockevent",
> .features   = CLOCK_EVT_FEAT_ONESHOT,
> @@ -74,30 +78,35 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
> struct clock_event_device *ce = per_cpu_ptr(_clock_event, cpu);
>
> ce->cpumask = cpumask_of(cpu);
> +   ce->irq = riscv_clock_event_irq;
> clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fff);
>
> -   csr_set(CSR_IE, IE_TIE);
> +   enable_percpu_irq(riscv_clock_event_irq,
> + irq_get_trigger_type(riscv_clock_event_irq));
> return 0;
>  }
>
>  static int riscv_timer_dying_cpu(unsigned int cpu)
>  {
> -   csr_clear(CSR_IE, IE_TIE);
> +   disable_percpu_irq(riscv_clock_event_irq);
> return 0;
>  }
>
>  /* called directly from the low-level interrupt handler */
> -void riscv_timer_interrupt(void)
> +static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
>  {
> struct clock_event_device *evdev = this_cpu_ptr(_clock_event);
>
> csr_clear(CSR_IE, IE_TIE);
> evdev->event_handler(evdev);
> +
> +   return IRQ_HANDLED;
>  }
>
>  static int __init riscv_timer_init_dt(struct device_node *n)
>  {
> int cpuid, hartid, error;
> +   struct of_phandle_args oirq;
>
> hartid = riscv_of_processor_hartid(n);
> if (hartid < 0) {
> @@ -115,6 +124,13 @@ static int __init riscv_timer_init_dt(struct device_node 
> *n)
> if (cpuid != smp_processor_id())
> return 0;
>
> +   oirq.np = riscv_of_intc_domain_node();
> +   oirq.args_count = 1;
> +   oirq.args[0] = RV_IRQ_TIMER;
> +   riscv_clock_event_irq = irq_create_of_mapping();
> +   if (!riscv_clock_event_irq)
> +   return -ENODEV;
> +

As the error case will result in a system without a clock, a warning message
may be a good option.

> pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
>__func__, cpuid, hartid);
> error = clocksource_register_hz(_clocksource, riscv_timebase);
> @@ -126,6 +142,14 @@ static int __init riscv_timer_init_dt(struct device_node 
> *n)
>
> sched_clock_register(riscv_sched_clock, 64, riscv_timebase);
>
> +   error = request_percpu_irq(riscv_clock_event_irq,
> +   riscv_timer_interrupt,
> +   "riscv-timer", _clock_event);
> +   if (error) {
> +   pr_err("registering percpu irq failed [%d]\n", error);
> +   return error;
> +   }
> +
> error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
>  "clockevents/riscv/timer:starting",
>  riscv_timer_starting_cpu, riscv_timer_dying_cpu);
> diff --git a/drivers/irqchip/irq-riscv-intc.c 
> b/drivers/irqchip/irq-riscv-intc.c
> index 2f364e6a87f9..d4fbc3543459 100644
> --- a/drivers/irqchip/irq-riscv-intc.c
> +++ b/drivers/irqchip/irq-riscv-intc.c
> @@ -23,20 +23,12 @@ static struct irq_domain *intc_domain;
>
>  static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
>  {
> -   struct pt_regs *old_regs;
> unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
>
> if (unlikely(cause >= BITS_PER_LONG))
> panic("unexpected interrupt cause");
>
> switch (cause) {
> -   case RV_IRQ_TIMER:
> -   old_regs = set_irq_regs(regs);
> -   irq_enter();
> -   riscv_timer_interrupt();
> -   irq_exit();
> - 

RE: [PATCH v5 4/6] clocksource/drivers/timer-riscv: Use per-CPU timer interrupt

2020-05-22 Thread Anup Patel


> -Original Message-
> From: Daniel Lezcano 
> Sent: 22 May 2020 18:38
> To: Anup Patel ; Palmer Dabbelt
> ; Paul Walmsley ; Albert
> Ou ; Thomas Gleixner ; Jason
> Cooper ; Marc Zyngier 
> Cc: Atish Patra ; Alistair Francis
> ; Anup Patel ; linux-
> ri...@lists.infradead.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v5 4/6] clocksource/drivers/timer-riscv: Use per-CPU timer
> interrupt
> 
> On 21/05/2020 15:32, Anup Patel wrote:
> > Instead of directly calling RISC-V timer interrupt handler from RISC-V
> > local interrupt conntroller driver, this patch implements RISC-V timer
> > interrupt as a per-CPU interrupt using per-CPU APIs of Linux IRQ
> > subsystem.
> >
> > Signed-off-by: Anup Patel 
> 
> via which tree do you want this patch to be merged ?

What is your suggestion ?

This series is primarily change in arch/riscv and drivers/irqchip.

Regards,
Anup

> 
> > ---
> >  arch/riscv/include/asm/irq.h  |  2 --
> >  drivers/clocksource/timer-riscv.c | 30 +++---
> > drivers/irqchip/irq-riscv-intc.c  |  8 
> >  3 files changed, 27 insertions(+), 13 deletions(-)
> >
> > diff --git a/arch/riscv/include/asm/irq.h
> > b/arch/riscv/include/asm/irq.h index a9e5f07a7e9c..9807ad164015 100644
> > --- a/arch/riscv/include/asm/irq.h
> > +++ b/arch/riscv/include/asm/irq.h
> > @@ -10,8 +10,6 @@
> >  #include 
> >  #include 
> >
> > -void riscv_timer_interrupt(void);
> > -
> >  #include 
> >
> >  #endif /* _ASM_RISCV_IRQ_H */
> > diff --git a/drivers/clocksource/timer-riscv.c
> > b/drivers/clocksource/timer-riscv.c
> > index c4f15c4068c0..5fb7c5ba5c91 100644
> > --- a/drivers/clocksource/timer-riscv.c
> > +++ b/drivers/clocksource/timer-riscv.c
> > @@ -14,6 +14,9 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include  #include
> > + #include 
> >  #include 
> >  #include 
> >
> > @@ -39,6 +42,7 @@ static int riscv_clock_next_event(unsigned long delta,
> > return 0;
> >  }
> >
> > +static unsigned int riscv_clock_event_irq;
> >  static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
> > .name   = "riscv_timer_clockevent",
> > .features   = CLOCK_EVT_FEAT_ONESHOT,
> > @@ -74,30 +78,35 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
> > struct clock_event_device *ce = per_cpu_ptr(_clock_event,
> > cpu);
> >
> > ce->cpumask = cpumask_of(cpu);
> > +   ce->irq = riscv_clock_event_irq;
> > clockevents_config_and_register(ce, riscv_timebase, 100,
> > 0x7fff);
> >
> > -   csr_set(CSR_IE, IE_TIE);
> > +   enable_percpu_irq(riscv_clock_event_irq,
> > + irq_get_trigger_type(riscv_clock_event_irq));
> > return 0;
> >  }
> >
> >  static int riscv_timer_dying_cpu(unsigned int cpu)  {
> > -   csr_clear(CSR_IE, IE_TIE);
> > +   disable_percpu_irq(riscv_clock_event_irq);
> > return 0;
> >  }
> >
> >  /* called directly from the low-level interrupt handler */ -void
> > riscv_timer_interrupt(void)
> > +static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
> >  {
> > struct clock_event_device *evdev = this_cpu_ptr(_clock_event);
> >
> > csr_clear(CSR_IE, IE_TIE);
> > evdev->event_handler(evdev);
> > +
> > +   return IRQ_HANDLED;
> >  }
> >
> >  static int __init riscv_timer_init_dt(struct device_node *n)  {
> > int cpuid, hartid, error;
> > +   struct of_phandle_args oirq;
> >
> > hartid = riscv_of_processor_hartid(n);
> > if (hartid < 0) {
> > @@ -115,6 +124,13 @@ static int __init riscv_timer_init_dt(struct
> device_node *n)
> > if (cpuid != smp_processor_id())
> > return 0;
> >
> > +   oirq.np = riscv_of_intc_domain_node();
> > +   oirq.args_count = 1;
> > +   oirq.args[0] = RV_IRQ_TIMER;
> > +   riscv_clock_event_irq = irq_create_of_mapping();
> > +   if (!riscv_clock_event_irq)
> > +   return -ENODEV;
> > +
> > pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
> >__func__, cpuid, hartid);
> > error = clocksource_register_hz(_clocksource, riscv_timebase);
> > @@ -126,6 +142,14 @@ static int __init riscv_timer_init_dt(struct
> > device_node *n)
> >
> > sched_clock_register(riscv_sched_clock, 64, riscv_timebase);
> >
> > +   error = request_percpu_irq(riscv_clock_

Re: [PATCH v5 4/6] clocksource/drivers/timer-riscv: Use per-CPU timer interrupt

2020-05-22 Thread Daniel Lezcano
On 21/05/2020 15:32, Anup Patel wrote:
> Instead of directly calling RISC-V timer interrupt handler from
> RISC-V local interrupt conntroller driver, this patch implements
> RISC-V timer interrupt as a per-CPU interrupt using per-CPU APIs
> of Linux IRQ subsystem.
> 
> Signed-off-by: Anup Patel 

via which tree do you want this patch to be merged ?

> ---
>  arch/riscv/include/asm/irq.h  |  2 --
>  drivers/clocksource/timer-riscv.c | 30 +++---
>  drivers/irqchip/irq-riscv-intc.c  |  8 
>  3 files changed, 27 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
> index a9e5f07a7e9c..9807ad164015 100644
> --- a/arch/riscv/include/asm/irq.h
> +++ b/arch/riscv/include/asm/irq.h
> @@ -10,8 +10,6 @@
>  #include 
>  #include 
>  
> -void riscv_timer_interrupt(void);
> -
>  #include 
>  
>  #endif /* _ASM_RISCV_IRQ_H */
> diff --git a/drivers/clocksource/timer-riscv.c 
> b/drivers/clocksource/timer-riscv.c
> index c4f15c4068c0..5fb7c5ba5c91 100644
> --- a/drivers/clocksource/timer-riscv.c
> +++ b/drivers/clocksource/timer-riscv.c
> @@ -14,6 +14,9 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
> +#include 
>  #include 
>  #include 
>  
> @@ -39,6 +42,7 @@ static int riscv_clock_next_event(unsigned long delta,
>   return 0;
>  }
>  
> +static unsigned int riscv_clock_event_irq;
>  static DEFINE_PER_CPU(struct clock_event_device, riscv_clock_event) = {
>   .name   = "riscv_timer_clockevent",
>   .features   = CLOCK_EVT_FEAT_ONESHOT,
> @@ -74,30 +78,35 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
>   struct clock_event_device *ce = per_cpu_ptr(_clock_event, cpu);
>  
>   ce->cpumask = cpumask_of(cpu);
> + ce->irq = riscv_clock_event_irq;
>   clockevents_config_and_register(ce, riscv_timebase, 100, 0x7fff);
>  
> - csr_set(CSR_IE, IE_TIE);
> + enable_percpu_irq(riscv_clock_event_irq,
> +   irq_get_trigger_type(riscv_clock_event_irq));
>   return 0;
>  }
>  
>  static int riscv_timer_dying_cpu(unsigned int cpu)
>  {
> - csr_clear(CSR_IE, IE_TIE);
> + disable_percpu_irq(riscv_clock_event_irq);
>   return 0;
>  }
>  
>  /* called directly from the low-level interrupt handler */
> -void riscv_timer_interrupt(void)
> +static irqreturn_t riscv_timer_interrupt(int irq, void *dev_id)
>  {
>   struct clock_event_device *evdev = this_cpu_ptr(_clock_event);
>  
>   csr_clear(CSR_IE, IE_TIE);
>   evdev->event_handler(evdev);
> +
> + return IRQ_HANDLED;
>  }
>  
>  static int __init riscv_timer_init_dt(struct device_node *n)
>  {
>   int cpuid, hartid, error;
> + struct of_phandle_args oirq;
>  
>   hartid = riscv_of_processor_hartid(n);
>   if (hartid < 0) {
> @@ -115,6 +124,13 @@ static int __init riscv_timer_init_dt(struct device_node 
> *n)
>   if (cpuid != smp_processor_id())
>   return 0;
>  
> + oirq.np = riscv_of_intc_domain_node();
> + oirq.args_count = 1;
> + oirq.args[0] = RV_IRQ_TIMER;
> + riscv_clock_event_irq = irq_create_of_mapping();
> + if (!riscv_clock_event_irq)
> + return -ENODEV;
> +
>   pr_info("%s: Registering clocksource cpuid [%d] hartid [%d]\n",
>  __func__, cpuid, hartid);
>   error = clocksource_register_hz(_clocksource, riscv_timebase);
> @@ -126,6 +142,14 @@ static int __init riscv_timer_init_dt(struct device_node 
> *n)
>  
>   sched_clock_register(riscv_sched_clock, 64, riscv_timebase);
>  
> + error = request_percpu_irq(riscv_clock_event_irq,
> + riscv_timer_interrupt,
> + "riscv-timer", _clock_event);
> + if (error) {
> + pr_err("registering percpu irq failed [%d]\n", error);
> + return error;
> + }
> +
>   error = cpuhp_setup_state(CPUHP_AP_RISCV_TIMER_STARTING,
>"clockevents/riscv/timer:starting",
>riscv_timer_starting_cpu, riscv_timer_dying_cpu);
> diff --git a/drivers/irqchip/irq-riscv-intc.c 
> b/drivers/irqchip/irq-riscv-intc.c
> index 2f364e6a87f9..d4fbc3543459 100644
> --- a/drivers/irqchip/irq-riscv-intc.c
> +++ b/drivers/irqchip/irq-riscv-intc.c
> @@ -23,20 +23,12 @@ static struct irq_domain *intc_domain;
>  
>  static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
>  {
> - struct pt_regs *old_regs;
>   unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;
>  
>   if (unlikely(cause >= BITS_PER_LONG))
>   panic("unexpected interrupt cause");
>  
>   switch (cause) {
> - 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:
>   /*
> 


--