Re: [PATCH v2 2/6] genirq: Allow an interrupt to be marked as 'raw'

From: Todd Kjos
Date: Wed Jun 23 2021 - 13:28:46 EST


On Tue, Nov 24, 2020 at 6:15 AM Marc Zyngier <maz@xxxxxxxxxx> 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@xxxxxxxxxx>
> ---
> 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@xxxxxxxxxxx.
>