Messages in this thread | | | From | Todd Kjos <> | Date | Wed, 23 Jun 2021 10:28:26 -0700 | Subject | Re: [PATCH v2 2/6] genirq: Allow an interrupt to be marked as 'raw' |
| |
On Tue, Nov 24, 2020 at 6:15 AM Marc Zyngier <maz@kernel.org> wrote: > > Some interrupts (such as the rescheduling IPI) rely on not going through > the irq_enter()/irq_exit() calls. To distinguish such interrupts, add > a new IRQ flag that allows the low-level handling code to sidestep the > enter()/exit() calls. > > Only the architecture code is expected to use this. It will do the wrong > thing on normal interrupts. Note that this is a band-aid until we can > move to some more correct infrastructure (such as kernel/entry/common.c). > > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > include/linux/irq.h | 2 ++ > kernel/irq/Kconfig | 3 +++ > kernel/irq/debugfs.c | 1 + > kernel/irq/irqdesc.c | 17 ++++++++++++----- > kernel/irq/settings.h | 15 +++++++++++++++ > 5 files changed, 33 insertions(+), 5 deletions(-) > > diff --git a/include/linux/irq.h b/include/linux/irq.h > index c55f218d5b61..605ba5949255 100644 > --- a/include/linux/irq.h > +++ b/include/linux/irq.h > @@ -72,6 +72,7 @@ enum irqchip_irq_state; > * mechanism and from core side polling. > * IRQ_DISABLE_UNLAZY - Disable lazy irq disable > * IRQ_HIDDEN - Don't show up in /proc/interrupts > + * IRQ_RAW - Skip tick management and irqtime accounting > */ > enum { > IRQ_TYPE_NONE = 0x00000000, > @@ -99,6 +100,7 @@ enum { > IRQ_IS_POLLED = (1 << 18), > IRQ_DISABLE_UNLAZY = (1 << 19), > IRQ_HIDDEN = (1 << 20), > + IRQ_RAW = (1 << 21), > }; > > #define IRQF_MODIFY_MASK \ > diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig > index 164a031cfdb6..ae9b13d5ee91 100644 > --- a/kernel/irq/Kconfig > +++ b/kernel/irq/Kconfig > @@ -109,6 +109,9 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR > config GENERIC_IRQ_RESERVATION_MODE > bool > > +config ARCH_WANTS_IRQ_RAW > + bool > + > # Support forced irq threading > config IRQ_FORCED_THREADING > bool > diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c > index e4cff358b437..f53475d88072 100644 > --- a/kernel/irq/debugfs.c > +++ b/kernel/irq/debugfs.c > @@ -140,6 +140,7 @@ static const struct irq_bit_descr irqdesc_states[] = { > BIT_MASK_DESCR(_IRQ_IS_POLLED), > BIT_MASK_DESCR(_IRQ_DISABLE_UNLAZY), > BIT_MASK_DESCR(_IRQ_HIDDEN), > + BIT_MASK_DESCR(_IRQ_RAW), > }; > > static const struct irq_bit_descr irqdesc_istates[] = { > diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c > index 1a7723604399..f5beee546a6f 100644 > --- a/kernel/irq/irqdesc.c > +++ b/kernel/irq/irqdesc.c > @@ -667,10 +667,9 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, > { > struct pt_regs *old_regs = set_irq_regs(regs); > unsigned int irq = hwirq; > + struct irq_desc *desc; > int ret = 0; > > - irq_enter(); > - > #ifdef CONFIG_IRQ_DOMAIN > if (lookup) > irq = irq_find_mapping(domain, hwirq); > @@ -680,14 +679,22 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq, > * Some hardware gives randomly wrong interrupts. Rather > * than crashing, do something sensible. > */ > - if (unlikely(!irq || irq >= nr_irqs)) { > + if (unlikely(!irq || irq >= nr_irqs || !(desc = irq_to_desc(irq)))) {
I see a checkpatch error here:
ERROR:ASSIGN_IN_IF: do not use assignment in if condition #96: FILE: kernel/irq/irqdesc.c:682:
> ack_bad_irq(irq); > ret = -EINVAL; > + goto out; > + } > + > + if (IS_ENABLED(CONFIG_ARCH_WANTS_IRQ_RAW) && > + unlikely(irq_settings_is_raw(desc))) { > + generic_handle_irq_desc(desc); > } else { > - generic_handle_irq(irq); > + irq_enter(); > + generic_handle_irq_desc(desc); > + irq_exit(); > } > > - irq_exit(); > +out: > set_irq_regs(old_regs); > return ret; > } > diff --git a/kernel/irq/settings.h b/kernel/irq/settings.h > index 51acdf43eadc..0033d459fdac 100644 > --- a/kernel/irq/settings.h > +++ b/kernel/irq/settings.h > @@ -18,6 +18,7 @@ enum { > _IRQ_IS_POLLED = IRQ_IS_POLLED, > _IRQ_DISABLE_UNLAZY = IRQ_DISABLE_UNLAZY, > _IRQ_HIDDEN = IRQ_HIDDEN, > + _IRQ_RAW = IRQ_RAW, > _IRQF_MODIFY_MASK = IRQF_MODIFY_MASK, > }; > > @@ -33,6 +34,7 @@ enum { > #define IRQ_IS_POLLED GOT_YOU_MORON > #define IRQ_DISABLE_UNLAZY GOT_YOU_MORON > #define IRQ_HIDDEN GOT_YOU_MORON > +#define IRQ_RAW GOT_YOU_MORON > #undef IRQF_MODIFY_MASK > #define IRQF_MODIFY_MASK GOT_YOU_MORON > > @@ -180,3 +182,16 @@ static inline bool irq_settings_is_hidden(struct irq_desc *desc) > { > return desc->status_use_accessors & _IRQ_HIDDEN; > } > + > +static inline bool irq_settings_is_raw(struct irq_desc *desc) > +{ > + if (IS_ENABLED(CONFIG_ARCH_WANTS_IRQ_RAW)) > + return desc->status_use_accessors & _IRQ_RAW; > + > + /* > + * Using IRQ_RAW on architectures that don't expect it is > + * likely to be wrong. > + */ > + WARN_ON_ONCE(1); > + return false; > +} > -- > 2.28.0 > > -- > To unsubscribe from this group and stop receiving emails from it, send an email to kernel-team+unsubscribe@android.com. >
| |