From: Marc Zyngier <maz@kernel.org>
To: LAK <linux-arm-kernel@lists.infradead.org>,
linux-kernel <linux-kernel@vger.kernel.org>
Cc: Will Deacon <will@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Android Kernel Team <kernel-team@android.com>,
Valentin Schneider <Valentin.Schneider@arm.com>
Subject: [PATCH 1/2] genirq: Allow an interrupt to be marked as 'naked'
Date: Sun, 1 Nov 2020 13:14:29 +0000 [thread overview]
Message-ID: <20201101131430.257038-2-maz@kernel.org> (raw)
In-Reply-To: <20201101131430.257038-1-maz@kernel.org>
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.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
include/linux/irq.h | 4 +++-
kernel/irq/debugfs.c | 1 +
kernel/irq/irqdesc.c | 17 ++++++++++++-----
kernel/irq/settings.h | 7 +++++++
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c54365309e97..af5ba7336925 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_NAKED - Bypass irq_enter()/irq_exit()
*/
enum {
IRQ_TYPE_NONE = 0x00000000,
@@ -99,13 +100,14 @@ enum {
IRQ_IS_POLLED = (1 << 18),
IRQ_DISABLE_UNLAZY = (1 << 19),
IRQ_HIDDEN = (1 << 20),
+ IRQ_NAKED = (1 << 21),
};
#define IRQF_MODIFY_MASK \
(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
- IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN)
+ IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN | IRQ_NAKED)
#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index e4cff358b437..e031d6afc0f8 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_NAKED),
};
static const struct irq_bit_descr irqdesc_istates[] = {
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 1a7723604399..c08a1c19d061 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)) {
+ desc = irq_to_desc(irq);
+ if (unlikely(!desc || irq >= nr_irqs)) {
ack_bad_irq(irq);
ret = -EINVAL;
+ goto out;
+ }
+
+ if (unlikely(irq_settings_is_naked(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 403378b9947b..587e67f9c302 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_NAKED = IRQ_NAKED,
_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_NAKED GOT_YOU_MORON
#undef IRQF_MODIFY_MASK
#define IRQF_MODIFY_MASK GOT_YOU_MORON
@@ -174,3 +176,8 @@ static inline bool irq_settings_is_hidden(struct irq_desc *desc)
{
return desc->status_use_accessors & _IRQ_HIDDEN;
}
+
+static inline bool irq_settings_is_naked(struct irq_desc *desc)
+{
+ return desc->status_use_accessors & _IRQ_NAKED;
+}
--
2.28.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <maz@kernel.org>
To: LAK <linux-arm-kernel@lists.infradead.org>,
linux-kernel <linux-kernel@vger.kernel.org>
Cc: Will Deacon <will@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Thomas Gleixner <tglx@linutronix.de>,
Valentin Schneider <Valentin.Schneider@arm.com>,
Peter Zijlstra <peterz@infradead.org>,
Android Kernel Team <kernel-team@android.com>
Subject: [PATCH 1/2] genirq: Allow an interrupt to be marked as 'naked'
Date: Sun, 1 Nov 2020 13:14:29 +0000 [thread overview]
Message-ID: <20201101131430.257038-2-maz@kernel.org> (raw)
In-Reply-To: <20201101131430.257038-1-maz@kernel.org>
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.
Signed-off-by: Marc Zyngier <maz@kernel.org>
---
include/linux/irq.h | 4 +++-
kernel/irq/debugfs.c | 1 +
kernel/irq/irqdesc.c | 17 ++++++++++++-----
kernel/irq/settings.h | 7 +++++++
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c54365309e97..af5ba7336925 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_NAKED - Bypass irq_enter()/irq_exit()
*/
enum {
IRQ_TYPE_NONE = 0x00000000,
@@ -99,13 +100,14 @@ enum {
IRQ_IS_POLLED = (1 << 18),
IRQ_DISABLE_UNLAZY = (1 << 19),
IRQ_HIDDEN = (1 << 20),
+ IRQ_NAKED = (1 << 21),
};
#define IRQF_MODIFY_MASK \
(IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL | IRQ_NO_BALANCING | \
IRQ_PER_CPU | IRQ_NESTED_THREAD | IRQ_NOTHREAD | IRQ_PER_CPU_DEVID | \
- IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN)
+ IRQ_IS_POLLED | IRQ_DISABLE_UNLAZY | IRQ_HIDDEN | IRQ_NAKED)
#define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index e4cff358b437..e031d6afc0f8 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_NAKED),
};
static const struct irq_bit_descr irqdesc_istates[] = {
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 1a7723604399..c08a1c19d061 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)) {
+ desc = irq_to_desc(irq);
+ if (unlikely(!desc || irq >= nr_irqs)) {
ack_bad_irq(irq);
ret = -EINVAL;
+ goto out;
+ }
+
+ if (unlikely(irq_settings_is_naked(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 403378b9947b..587e67f9c302 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_NAKED = IRQ_NAKED,
_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_NAKED GOT_YOU_MORON
#undef IRQF_MODIFY_MASK
#define IRQF_MODIFY_MASK GOT_YOU_MORON
@@ -174,3 +176,8 @@ static inline bool irq_settings_is_hidden(struct irq_desc *desc)
{
return desc->status_use_accessors & _IRQ_HIDDEN;
}
+
+static inline bool irq_settings_is_naked(struct irq_desc *desc)
+{
+ return desc->status_use_accessors & _IRQ_NAKED;
+}
--
2.28.0
next prev parent reply other threads:[~2020-11-01 13:15 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-01 13:14 [PATCH 0/2] arm64: Allow the rescheduling IPI to bypass irq_enter/exit Marc Zyngier
2020-11-01 13:14 ` Marc Zyngier
2020-11-01 13:14 ` Marc Zyngier [this message]
2020-11-01 13:14 ` [PATCH 1/2] genirq: Allow an interrupt to be marked as 'naked' Marc Zyngier
2020-11-01 14:33 ` David Laight
2020-11-01 14:33 ` David Laight
2020-11-01 13:14 ` [PATCH 2/2] arm64: Mark the recheduling IPI as naked interrupt Marc Zyngier
2020-11-01 13:14 ` Marc Zyngier
2020-11-01 14:30 ` [PATCH 0/2] arm64: Allow the rescheduling IPI to bypass irq_enter/exit David Laight
2020-11-01 14:30 ` David Laight
2020-11-02 10:30 ` Valentin Schneider
2020-11-02 10:30 ` Valentin Schneider
2020-11-10 13:03 ` Peter Zijlstra
2020-11-10 13:03 ` Peter Zijlstra
[not found] ` <19286daf276f46aa@fake-msgid>
2020-11-10 15:48 ` Valentin Schneider
2020-11-10 15:48 ` Valentin Schneider
2020-11-03 20:32 ` Thomas Gleixner
2020-11-03 20:32 ` Thomas Gleixner
2020-11-20 9:20 ` Marc Zyngier
2020-11-20 9:20 ` Marc Zyngier
2020-11-20 14:17 ` Thomas Gleixner
2020-11-20 14:17 ` Thomas Gleixner
2020-11-22 16:13 ` Marc Zyngier
2020-11-22 16:13 ` Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201101131430.257038-2-maz@kernel.org \
--to=maz@kernel.org \
--cc=Valentin.Schneider@arm.com \
--cc=catalin.marinas@arm.com \
--cc=kernel-team@android.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@linutronix.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.