Message ID | 20200521133301.816665-2-anup.patel@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | New RISC-V Local Interrupt Controller Driver | expand |
On Thu, May 21, 2020 at 6:34 AM Anup Patel <anup.patel@wdc.com> wrote: > > Currently, the IPI handling routine riscv_software_interrupt() does > not take any argument and also does not perform irq_enter()/irq_exit(). > > This patch makes IPI handling routine more self-contained by: > 1. Passing "pt_regs *" argument > 2. Explicitly doing irq_enter()/irq_exit() > 3. Explicitly save/restore "pt_regs *" using set_irq_regs() > > With above changes, IPI handling routine does not depend on caller > function to perform irq_enter()/irq_exit() and save/restore of > "pt_regs *" hence its more self-contained. This also enables us > to call IPI handling routine from IRQCHIP drivers. > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > --- > arch/riscv/include/asm/irq.h | 1 - > arch/riscv/include/asm/smp.h | 3 +++ > arch/riscv/kernel/irq.c | 16 ++++++++++------ > arch/riscv/kernel/smp.c | 11 +++++++++-- > 4 files changed, 22 insertions(+), 9 deletions(-) > > diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h > index 6e1b0e0325eb..0183e15ace66 100644 > --- a/arch/riscv/include/asm/irq.h > +++ b/arch/riscv/include/asm/irq.h > @@ -13,7 +13,6 @@ > #define NR_IRQS 0 > > void riscv_timer_interrupt(void); > -void riscv_software_interrupt(void); > > #include <asm-generic/irq.h> > > diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h > index f4c7cfda6b7f..40bb1c15a731 100644 > --- a/arch/riscv/include/asm/smp.h > +++ b/arch/riscv/include/asm/smp.h > @@ -28,6 +28,9 @@ void show_ipi_stats(struct seq_file *p, int prec); > /* SMP initialization hook for setup_arch */ > void __init setup_smp(void); > > +/* Called from C code, this handles an IPI. */ > +void handle_IPI(struct pt_regs *regs); > + > /* Hook for the generic smp_call_function_many() routine. */ > void arch_send_call_function_ipi_mask(struct cpumask *mask); > > diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c > index 345c4f2eba13..bb0bfcd537e7 100644 > --- a/arch/riscv/kernel/irq.c > +++ b/arch/riscv/kernel/irq.c > @@ -19,12 +19,15 @@ 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 = set_irq_regs(regs); > + struct pt_regs *old_regs; > > - irq_enter(); > 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: > @@ -32,19 +35,20 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs) > * We only use software interrupts to pass IPIs, so if a non-SMP > * system gets one, then we don't know what to do. > */ > - riscv_software_interrupt(); > + handle_IPI(regs); > break; > #endif > case RV_IRQ_EXT: > + old_regs = set_irq_regs(regs); > + irq_enter(); > handle_arch_irq(regs); > + irq_exit(); > + set_irq_regs(old_regs); > break; > default: > pr_alert("unexpected interrupt cause 0x%lx", regs->cause); > BUG(); > } > - irq_exit(); > - > - set_irq_regs(old_regs); > } > > void __init init_IRQ(void) > diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c > index a65a8fa0c22d..b1d4f452f843 100644 > --- a/arch/riscv/kernel/smp.c > +++ b/arch/riscv/kernel/smp.c > @@ -123,11 +123,14 @@ static inline void clear_ipi(void) > clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id())); > } > > -void riscv_software_interrupt(void) > +void handle_IPI(struct pt_regs *regs) > { > + struct pt_regs *old_regs = set_irq_regs(regs); > unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; > unsigned long *stats = ipi_data[smp_processor_id()].stats; > > + irq_enter(); > + > clear_ipi(); > > while (true) { > @@ -138,7 +141,7 @@ void riscv_software_interrupt(void) > > ops = xchg(pending_ipis, 0); > if (ops == 0) > - return; > + goto done; > > if (ops & (1 << IPI_RESCHEDULE)) { > stats[IPI_RESCHEDULE]++; > @@ -160,6 +163,10 @@ void riscv_software_interrupt(void) > /* Order data access and bit testing. */ > mb(); > } > + > +done: > + irq_exit(); > + set_irq_regs(old_regs); > } > > static const char * const ipi_names[] = { > -- > 2.25.1 > > Reviewed-by: Atish Patra <atish.patra@wdc.com>
On Thu, 21 May 2020 06:32:56 PDT (-0700), Anup Patel wrote: > Currently, the IPI handling routine riscv_software_interrupt() does > not take any argument and also does not perform irq_enter()/irq_exit(). > > This patch makes IPI handling routine more self-contained by: > 1. Passing "pt_regs *" argument > 2. Explicitly doing irq_enter()/irq_exit() > 3. Explicitly save/restore "pt_regs *" using set_irq_regs() > > With above changes, IPI handling routine does not depend on caller > function to perform irq_enter()/irq_exit() and save/restore of > "pt_regs *" hence its more self-contained. This also enables us > to call IPI handling routine from IRQCHIP drivers. > > Signed-off-by: Anup Patel <anup.patel@wdc.com> > --- > arch/riscv/include/asm/irq.h | 1 - > arch/riscv/include/asm/smp.h | 3 +++ > arch/riscv/kernel/irq.c | 16 ++++++++++------ > arch/riscv/kernel/smp.c | 11 +++++++++-- > 4 files changed, 22 insertions(+), 9 deletions(-) > > diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h > index 6e1b0e0325eb..0183e15ace66 100644 > --- a/arch/riscv/include/asm/irq.h > +++ b/arch/riscv/include/asm/irq.h > @@ -13,7 +13,6 @@ > #define NR_IRQS 0 > > void riscv_timer_interrupt(void); > -void riscv_software_interrupt(void); > > #include <asm-generic/irq.h> > > diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h > index f4c7cfda6b7f..40bb1c15a731 100644 > --- a/arch/riscv/include/asm/smp.h > +++ b/arch/riscv/include/asm/smp.h > @@ -28,6 +28,9 @@ void show_ipi_stats(struct seq_file *p, int prec); > /* SMP initialization hook for setup_arch */ > void __init setup_smp(void); > > +/* Called from C code, this handles an IPI. */ > +void handle_IPI(struct pt_regs *regs); > + > /* Hook for the generic smp_call_function_many() routine. */ > void arch_send_call_function_ipi_mask(struct cpumask *mask); > > diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c > index 345c4f2eba13..bb0bfcd537e7 100644 > --- a/arch/riscv/kernel/irq.c > +++ b/arch/riscv/kernel/irq.c > @@ -19,12 +19,15 @@ 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 = set_irq_regs(regs); > + struct pt_regs *old_regs; > > - irq_enter(); > 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: > @@ -32,19 +35,20 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs) > * We only use software interrupts to pass IPIs, so if a non-SMP > * system gets one, then we don't know what to do. > */ > - riscv_software_interrupt(); > + handle_IPI(regs); > break; > #endif > case RV_IRQ_EXT: > + old_regs = set_irq_regs(regs); > + irq_enter(); > handle_arch_irq(regs); > + irq_exit(); > + set_irq_regs(old_regs); > break; > default: > pr_alert("unexpected interrupt cause 0x%lx", regs->cause); > BUG(); > } > - irq_exit(); > - > - set_irq_regs(old_regs); > } > > void __init init_IRQ(void) > diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c > index a65a8fa0c22d..b1d4f452f843 100644 > --- a/arch/riscv/kernel/smp.c > +++ b/arch/riscv/kernel/smp.c > @@ -123,11 +123,14 @@ static inline void clear_ipi(void) > clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id())); > } > > -void riscv_software_interrupt(void) > +void handle_IPI(struct pt_regs *regs) > { > + struct pt_regs *old_regs = set_irq_regs(regs); > unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; > unsigned long *stats = ipi_data[smp_processor_id()].stats; > > + irq_enter(); > + > clear_ipi(); > > while (true) { > @@ -138,7 +141,7 @@ void riscv_software_interrupt(void) > > ops = xchg(pending_ipis, 0); > if (ops == 0) > - return; > + goto done; > > if (ops & (1 << IPI_RESCHEDULE)) { > stats[IPI_RESCHEDULE]++; > @@ -160,6 +163,10 @@ void riscv_software_interrupt(void) > /* Order data access and bit testing. */ > mb(); > } > + > +done: > + irq_exit(); > + set_irq_regs(old_regs); > } > > static const char * const ipi_names[] = { I guess we still have to figure out which tree these are going in through, but I'm going to start acking them as I review them just so it all stays together. Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> Acked-by: Palmer Dabbelt <palmerdabbelt@google.com>
diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h index 6e1b0e0325eb..0183e15ace66 100644 --- a/arch/riscv/include/asm/irq.h +++ b/arch/riscv/include/asm/irq.h @@ -13,7 +13,6 @@ #define NR_IRQS 0 void riscv_timer_interrupt(void); -void riscv_software_interrupt(void); #include <asm-generic/irq.h> diff --git a/arch/riscv/include/asm/smp.h b/arch/riscv/include/asm/smp.h index f4c7cfda6b7f..40bb1c15a731 100644 --- a/arch/riscv/include/asm/smp.h +++ b/arch/riscv/include/asm/smp.h @@ -28,6 +28,9 @@ void show_ipi_stats(struct seq_file *p, int prec); /* SMP initialization hook for setup_arch */ void __init setup_smp(void); +/* Called from C code, this handles an IPI. */ +void handle_IPI(struct pt_regs *regs); + /* Hook for the generic smp_call_function_many() routine. */ void arch_send_call_function_ipi_mask(struct cpumask *mask); diff --git a/arch/riscv/kernel/irq.c b/arch/riscv/kernel/irq.c index 345c4f2eba13..bb0bfcd537e7 100644 --- a/arch/riscv/kernel/irq.c +++ b/arch/riscv/kernel/irq.c @@ -19,12 +19,15 @@ 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 = set_irq_regs(regs); + struct pt_regs *old_regs; - irq_enter(); 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: @@ -32,19 +35,20 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs) * We only use software interrupts to pass IPIs, so if a non-SMP * system gets one, then we don't know what to do. */ - riscv_software_interrupt(); + handle_IPI(regs); break; #endif case RV_IRQ_EXT: + old_regs = set_irq_regs(regs); + irq_enter(); handle_arch_irq(regs); + irq_exit(); + set_irq_regs(old_regs); break; default: pr_alert("unexpected interrupt cause 0x%lx", regs->cause); BUG(); } - irq_exit(); - - set_irq_regs(old_regs); } void __init init_IRQ(void) diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index a65a8fa0c22d..b1d4f452f843 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -123,11 +123,14 @@ static inline void clear_ipi(void) clint_clear_ipi(cpuid_to_hartid_map(smp_processor_id())); } -void riscv_software_interrupt(void) +void handle_IPI(struct pt_regs *regs) { + struct pt_regs *old_regs = set_irq_regs(regs); unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits; unsigned long *stats = ipi_data[smp_processor_id()].stats; + irq_enter(); + clear_ipi(); while (true) { @@ -138,7 +141,7 @@ void riscv_software_interrupt(void) ops = xchg(pending_ipis, 0); if (ops == 0) - return; + goto done; if (ops & (1 << IPI_RESCHEDULE)) { stats[IPI_RESCHEDULE]++; @@ -160,6 +163,10 @@ void riscv_software_interrupt(void) /* Order data access and bit testing. */ mb(); } + +done: + irq_exit(); + set_irq_regs(old_regs); } static const char * const ipi_names[] = {
Currently, the IPI handling routine riscv_software_interrupt() does not take any argument and also does not perform irq_enter()/irq_exit(). This patch makes IPI handling routine more self-contained by: 1. Passing "pt_regs *" argument 2. Explicitly doing irq_enter()/irq_exit() 3. Explicitly save/restore "pt_regs *" using set_irq_regs() With above changes, IPI handling routine does not depend on caller function to perform irq_enter()/irq_exit() and save/restore of "pt_regs *" hence its more self-contained. This also enables us to call IPI handling routine from IRQCHIP drivers. Signed-off-by: Anup Patel <anup.patel@wdc.com> --- arch/riscv/include/asm/irq.h | 1 - arch/riscv/include/asm/smp.h | 3 +++ arch/riscv/kernel/irq.c | 16 ++++++++++------ arch/riscv/kernel/smp.c | 11 +++++++++-- 4 files changed, 22 insertions(+), 9 deletions(-)