From: "irqchip-bot for Samuel Holland" <tip-bot2@linutronix.de>
To: linux-kernel@vger.kernel.org
Cc: Samuel Holland <samuel@sholland.org>,
Marc Zyngier <maz@kernel.org>,
tglx@linutronix.de
Subject: [irqchip: irq/irqchip-next] irqchip/sifive-plic: Separate the enable and mask operations
Date: Sun, 10 Jul 2022 08:55:53 -0000 [thread overview]
Message-ID: <165744335323.15455.238417515877913725.tip-bot2@tip-bot2> (raw)
In-Reply-To: <20220701202440.59059-3-samuel@sholland.org>
The following commit has been merged into the irq/irqchip-next branch of irqchip:
Commit-ID: a1706a1c5062e0908528170f853601ed53f428c8
Gitweb: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms/a1706a1c5062e0908528170f853601ed53f428c8
Author: Samuel Holland <samuel@sholland.org>
AuthorDate: Fri, 01 Jul 2022 15:24:40 -05:00
Committer: Marc Zyngier <maz@kernel.org>
CommitterDate: Sun, 10 Jul 2022 09:50:04 +01:00
irqchip/sifive-plic: Separate the enable and mask operations
The PLIC has two per-IRQ checks before sending an IRQ to a hart context.
First, it checks that the IRQ's priority is nonzero. Then, it checks
that the enable bit is set for that combination of IRQ and context.
Currently, the PLIC driver sets both the priority value and the enable
bit in its (un)mask operations. However, modifying the enable bit is
problematic for two reasons:
1) The enable bits are packed, so changes are not atomic and require
taking a spinlock.
2) The following requirement from the PLIC spec, which explains the
racy (un)mask operations in plic_irq_eoi():
If the completion ID does not match an interrupt source
that is currently enabled for the target, the completion
is silently ignored.
Both of these problems are solved by using the priority value to mask
IRQs. Each IRQ has a separate priority register, so writing the priority
value is atomic. And since the enable bit remains set while an IRQ is
masked, the EOI operation works normally. The enable bits are still used
to control the IRQ's affinity.
Signed-off-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20220701202440.59059-3-samuel@sholland.org
---
drivers/irqchip/irq-sifive-plic.c | 55 ++++++++++++++++++------------
1 file changed, 34 insertions(+), 21 deletions(-)
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 46595e6..ba49381 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -108,9 +108,7 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
struct irq_data *d, int enable)
{
int cpu;
- struct plic_priv *priv = irq_data_get_irq_chip_data(d);
- writel(enable, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
for_each_cpu(cpu, mask) {
struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu);
@@ -118,16 +116,37 @@ static inline void plic_irq_toggle(const struct cpumask *mask,
}
}
-static void plic_irq_unmask(struct irq_data *d)
+static void plic_irq_enable(struct irq_data *d)
{
plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 1);
}
-static void plic_irq_mask(struct irq_data *d)
+static void plic_irq_disable(struct irq_data *d)
{
plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 0);
}
+static void plic_irq_unmask(struct irq_data *d)
+{
+ struct plic_priv *priv = irq_data_get_irq_chip_data(d);
+
+ writel(1, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
+}
+
+static void plic_irq_mask(struct irq_data *d)
+{
+ struct plic_priv *priv = irq_data_get_irq_chip_data(d);
+
+ writel(0, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID);
+}
+
+static void plic_irq_eoi(struct irq_data *d)
+{
+ struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
+
+ writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
+}
+
#ifdef CONFIG_SMP
static int plic_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
@@ -146,32 +165,21 @@ static int plic_set_affinity(struct irq_data *d,
if (cpu >= nr_cpu_ids)
return -EINVAL;
- plic_irq_mask(d);
+ plic_irq_disable(d);
irq_data_update_effective_affinity(d, cpumask_of(cpu));
- if (!irqd_irq_masked(d))
- plic_irq_unmask(d);
+ if (!irqd_irq_disabled(d))
+ plic_irq_enable(d);
return IRQ_SET_MASK_OK_DONE;
}
#endif
-static void plic_irq_eoi(struct irq_data *d)
-{
- struct plic_handler *handler = this_cpu_ptr(&plic_handlers);
-
- if (irqd_irq_masked(d)) {
- plic_irq_unmask(d);
- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
- plic_irq_mask(d);
- } else {
- writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM);
- }
-}
-
static struct irq_chip plic_edge_chip = {
.name = "SiFive PLIC",
+ .irq_enable = plic_irq_enable,
+ .irq_disable = plic_irq_disable,
.irq_ack = plic_irq_eoi,
.irq_mask = plic_irq_mask,
.irq_unmask = plic_irq_unmask,
@@ -184,6 +192,8 @@ static struct irq_chip plic_edge_chip = {
static struct irq_chip plic_chip = {
.name = "SiFive PLIC",
+ .irq_enable = plic_irq_enable,
+ .irq_disable = plic_irq_disable,
.irq_mask = plic_irq_mask,
.irq_unmask = plic_irq_unmask,
.irq_eoi = plic_irq_eoi,
@@ -429,8 +439,11 @@ static int __init __plic_init(struct device_node *node,
i * CONTEXT_ENABLE_SIZE;
handler->priv = priv;
done:
- for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
+ for (hwirq = 1; hwirq <= nr_irqs; hwirq++) {
plic_toggle(handler, hwirq, 0);
+ writel(1, priv->regs + PRIORITY_BASE +
+ hwirq * PRIORITY_PER_ID);
+ }
nr_handlers++;
}
prev parent reply other threads:[~2022-07-10 8:56 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-01 20:24 [PATCH v3 0/2] irqchip: RISC-V PLIC cleanup and optimization Samuel Holland
2022-07-01 20:24 ` [PATCH v3 1/2] irqchip/sifive-plic: Make better use of the effective affinity mask Samuel Holland
2022-07-07 13:31 ` [irqchip: irq/irqchip-next] " irqchip-bot for Samuel Holland
2022-07-10 8:55 ` irqchip-bot for Samuel Holland
2022-07-01 20:24 ` [PATCH v3 2/2] irqchip/sifive-plic: Separate the enable and mask operations Samuel Holland
2022-07-07 13:31 ` [irqchip: irq/irqchip-next] " irqchip-bot for Samuel Holland
2022-07-10 8:55 ` irqchip-bot for Samuel Holland [this message]
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=165744335323.15455.238417515877913725.tip-bot2@tip-bot2 \
--to=tip-bot2@linutronix.de \
--cc=linux-kernel@vger.kernel.org \
--cc=maz@kernel.org \
--cc=samuel@sholland.org \
--cc=tglx@linutronix.de \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®