* [PATCH v2 0/2] irqchip/riscv-aplic: Use trigger specific flow handlers in MSI mode
@ 2026-11-10 12:06 Troy Mitchell
2026-11-10 12:06 ` [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources Troy Mitchell
2026-11-10 12:06 ` [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level " Troy Mitchell
0 siblings, 2 replies; 6+ messages in thread
From: Troy Mitchell @ 2026-11-10 12:06 UTC (permalink / raw)
To: Anup Patel, Thomas Gleixner, Radu Rendec, Paul Walmsley,
Palmer Dabbelt, Albert Ou, Alexandre Ghiti,
Björn Töpel
Cc: Anup Patel, linux-riscv, linux-kernel, Troy Mitchell
In MSI mode the APLIC handles all sources with handle_fasteoi_irq().
For edge-triggered sources this loses an interrupt which arrives on
the new CPU while the previous one is still being handled after an
affinity change. The fasteoi flow also never calls irq_ack(), where
IMSIC applies an affinity change deferred while a previous vector move
was in flight. Such a change stays pending, and later affinity changes
of the interrupt only update the pending mask.
Use handle_edge_irq() for edge-triggered sources and
handle_fasteoi_ack_irq() for level-triggered sources.
---
Changes in v2:
- Use handle_edge_irq() for edge-triggered sources instead of calling
the parent ack from the EOI callback
- Use handle_fasteoi_ack_irq() for level-triggered sources
- Split into two patches
- Link to v1: https://patch.msgid.link/20261104-aplic-affinity-fix-v1-1-e538cd76e563@linux.dev
To: Anup Patel <anup@brainfault.org>
To: Thomas Gleixner <tglx@kernel.org>
To: Radu Rendec <radu@rendec.net>
To: Paul Walmsley <pjw@kernel.org>
To: Palmer Dabbelt <palmer@dabbelt.com>
To: Albert Ou <aou@eecs.berkeley.edu>
To: Alexandre Ghiti <alex@ghiti.fr>
To: Björn Töpel <bjorn@rivosinc.com>
Cc: Anup Patel <apatel@ventanamicro.com>
Cc: linux-riscv@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
Troy Mitchell (2):
irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources
irqchip/riscv-aplic: Apply pending affinity changes for level MSI sources
drivers/irqchip/Kconfig | 1 +
drivers/irqchip/irq-riscv-aplic-msi.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20260909-aplic-affinity-fix-80a4b30bd03e
Best regards,
--
Troy Mitchell <troy.mitchell@linux.dev>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources 2026-11-10 12:06 [PATCH v2 0/2] irqchip/riscv-aplic: Use trigger specific flow handlers in MSI mode Troy Mitchell @ 2026-11-10 12:06 ` Troy Mitchell 2026-11-11 0:07 ` Thomas Gleixner 2026-11-10 12:06 ` [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level " Troy Mitchell 1 sibling, 1 reply; 6+ messages in thread From: Troy Mitchell @ 2026-11-10 12:06 UTC (permalink / raw) To: Anup Patel, Thomas Gleixner, Radu Rendec, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel Cc: Anup Patel, linux-riscv, linux-kernel, Troy Mitchell In MSI mode, all APLIC interrupts are handled by handle_fasteoi_irq(). For an edge-triggered source the APLIC forwards each edge as an MSI and keeps no state after that, so an edge which the CPU side drops is lost. After an affinity change, the next MSI can arrive on the new CPU while the previous one is still being handled on the old CPU, and handle_fasteoi_irq() then drops it. The fasteoi flow also never calls irq_ack(), which is where IMSIC applies an affinity change that was deferred while a previous vector move was in flight. Such a change stays pending, and later affinity changes of the interrupt only update the pending mask. Use handle_edge_irq() for edge-triggered sources. It acknowledges the interrupt before invoking the handler. If the interrupt is still in progress on the previous target CPU, it either waits for it to complete or marks it pending so that the handler runs again. Fixes: ca8df97fe679 ("irqchip/riscv-aplic: Add support for MSI-mode") Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev> --- drivers/irqchip/irq-riscv-aplic-msi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c index fb8d1838609f..44f0df83f93e 100644 --- a/drivers/irqchip/irq-riscv-aplic-msi.c +++ b/drivers/irqchip/irq-riscv-aplic-msi.c @@ -69,6 +69,20 @@ static int aplic_msi_irq_set_type(struct irq_data *d, unsigned int type) if (rc) return rc; + + /* + * Edge-triggered sources are fire and forget, so they must be + * acknowledged before the handler runs. The edge flow handler also + * replays an interrupt which arrives while the previous one is + * still being handled on another CPU after an affinity change. + */ + if (type & IRQ_TYPE_EDGE_BOTH) + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), + handle_edge_irq, "edge"); + else + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), + handle_fasteoi_irq, "fasteoi"); + /* * Updating sourcecfg register for level-triggered interrupts * requires interrupt retriggering when APLIC is in MSI mode. -- 2.56.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources 2026-11-10 12:06 ` [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources Troy Mitchell @ 2026-11-11 0:07 ` Thomas Gleixner 2026-11-11 1:11 ` Troy Mitchell 0 siblings, 1 reply; 6+ messages in thread From: Thomas Gleixner @ 2026-11-11 0:07 UTC (permalink / raw) To: Troy Mitchell, Anup Patel, Radu Rendec, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel Cc: Anup Patel, linux-riscv, linux-kernel, Troy Mitchell On Tue, Nov 10 2026 at 12:06, Troy Mitchell wrote: > In MSI mode, all APLIC interrupts are handled by handle_fasteoi_irq(). > For an edge-triggered source the APLIC forwards each edge as an MSI and > keeps no state after that, so an edge which the CPU side drops is lost. > After an affinity change, the next MSI can arrive on the new CPU while > the previous one is still being handled on the old CPU, and > handle_fasteoi_irq() then drops it. > > The fasteoi flow also never calls irq_ack(), which is where IMSIC applies > an affinity change that was deferred while a previous vector move was in > flight. Such a change stays pending, and later affinity changes of the > interrupt only update the pending mask. > > Use handle_edge_irq() for edge-triggered sources. It acknowledges the > interrupt before invoking the handler. If the interrupt is still in > progress on the previous target CPU, it either waits for it to complete > or marks it pending so that the handler runs again. > > Fixes: ca8df97fe679 ("irqchip/riscv-aplic: Add support for MSI-mode") > Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev> Not that I care at all about showing up in some made up git-tag metrics, but in general it's a matter of courtesy to point out that the solution to the problem was suggested by someone else, no? > + /* > + * Edge-triggered sources are fire and forget, so they must be > + * acknowledged before the handler runs. The edge flow handler also > + * replays an interrupt which arrives while the previous one is > + * still being handled on another CPU after an affinity change. > + */ > + if (type & IRQ_TYPE_EDGE_BOTH) > + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), > + handle_edge_irq, "edge"); > + else > + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), > + handle_fasteoi_irq, "fasteoi"); > + https://docs.kernel.org/process/maintainer-tip.html#bracket-rules Thanks, tglx ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources 2026-11-11 0:07 ` Thomas Gleixner @ 2026-11-11 1:11 ` Troy Mitchell 0 siblings, 0 replies; 6+ messages in thread From: Troy Mitchell @ 2026-11-11 1:11 UTC (permalink / raw) To: Thomas Gleixner, Troy Mitchell, Anup Patel, Radu Rendec, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel Cc: Anup Patel, linux-riscv, linux-kernel [-- Attachment #1: Type: text/plain, Size: 2235 bytes --] Hi Thomas, On Wed Nov 11, 2026 at 12:07 AM GMT, Thomas Gleixner wrote: > On Tue, Nov 10 2026 at 12:06, Troy Mitchell wrote: >> In MSI mode, all APLIC interrupts are handled by handle_fasteoi_irq(). >> For an edge-triggered source the APLIC forwards each edge as an MSI and >> keeps no state after that, so an edge which the CPU side drops is lost. >> After an affinity change, the next MSI can arrive on the new CPU while >> the previous one is still being handled on the old CPU, and >> handle_fasteoi_irq() then drops it. >> >> The fasteoi flow also never calls irq_ack(), which is where IMSIC applies >> an affinity change that was deferred while a previous vector move was in >> flight. Such a change stays pending, and later affinity changes of the >> interrupt only update the pending mask. >> >> Use handle_edge_irq() for edge-triggered sources. It acknowledges the >> interrupt before invoking the handler. If the interrupt is still in >> progress on the previous target CPU, it either waits for it to complete >> or marks it pending so that the handler runs again. >> >> Fixes: ca8df97fe679 ("irqchip/riscv-aplic: Add support for MSI-mode") >> Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev> > > Not that I care at all about showing up in some made up git-tag metrics, > but in general it's a matter of courtesy to point out that the solution > to the problem was suggested by someone else, no? I'm so orry about that. Will add your Suggested-by in v3. > >> + /* >> + * Edge-triggered sources are fire and forget, so they must be >> + * acknowledged before the handler runs. The edge flow handler also >> + * replays an interrupt which arrives while the previous one is >> + * still being handled on another CPU after an affinity change. >> + */ >> + if (type & IRQ_TYPE_EDGE_BOTH) >> + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), >> + handle_edge_irq, "edge"); >> + else >> + irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), >> + handle_fasteoi_irq, "fasteoi"); >> + > > https://docs.kernel.org/process/maintainer-tip.html#bracket-rules Will add the braces in v3. Thanks for your review! -- Troy Mitchell [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 260 bytes --] ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level MSI sources 2026-11-10 12:06 [PATCH v2 0/2] irqchip/riscv-aplic: Use trigger specific flow handlers in MSI mode Troy Mitchell 2026-11-10 12:06 ` [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources Troy Mitchell @ 2026-11-10 12:06 ` Troy Mitchell 2026-11-11 0:09 ` Thomas Gleixner 1 sibling, 1 reply; 6+ messages in thread From: Troy Mitchell @ 2026-11-10 12:06 UTC (permalink / raw) To: Anup Patel, Thomas Gleixner, Radu Rendec, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel Cc: Anup Patel, linux-riscv, linux-kernel, Troy Mitchell IMSIC rejects an affinity change with -EBUSY while a previous vector move is still in flight, and the IRQ core then records the new mask as pending. The change is applied by irq_move_irq() in the IMSIC irq_ack callback, but level-triggered APLIC MSI interrupts are handled by handle_fasteoi_irq(), which never calls irq_ack. The pending change is therefore never applied. While it is pending, later affinity changes only update the pending mask, so the interrupt stays on its old CPU. Use handle_fasteoi_ack_irq() for level-triggered sources. It acks the interrupt before invoking the handler, so a pending affinity change is applied on the next interrupt, and the EOI retrigger then targets the new CPU. Fixes: 58d868b67a9a ("RISC-V: Select CONFIG_GENERIC_PENDING_IRQ") Signed-off-by: Troy Mitchell <troy.mitchell@linux.dev> --- drivers/irqchip/Kconfig | 1 + drivers/irqchip/irq-riscv-aplic-msi.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 136bab41f801..a639a0c2f3d2 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -645,6 +645,7 @@ config RISCV_APLIC_MSI bool depends on RISCV_APLIC select GENERIC_MSI_IRQ + select IRQ_FASTEOI_HIERARCHY_HANDLERS default RISCV_APLIC config RISCV_IMSIC diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c index 44f0df83f93e..0e71b427da34 100644 --- a/drivers/irqchip/irq-riscv-aplic-msi.c +++ b/drivers/irqchip/irq-riscv-aplic-msi.c @@ -75,13 +75,16 @@ static int aplic_msi_irq_set_type(struct irq_data *d, unsigned int type) * acknowledged before the handler runs. The edge flow handler also * replays an interrupt which arrives while the previous one is * still being handled on another CPU after an affinity change. + * + * Level-triggered sources use the fasteoi flow, but still need the + * ack so that the IMSIC parent applies deferred affinity changes. */ if (type & IRQ_TYPE_EDGE_BOTH) irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), handle_edge_irq, "edge"); else irq_set_chip_handler_name_locked(d, irq_data_get_irq_chip(d), - handle_fasteoi_irq, "fasteoi"); + handle_fasteoi_ack_irq, "fasteoi"); /* * Updating sourcecfg register for level-triggered interrupts @@ -181,7 +184,7 @@ static const struct msi_domain_template aplic_msi_template = { .info = { .bus_token = DOMAIN_BUS_WIRED_TO_MSI, .flags = MSI_FLAG_USE_DEV_FWNODE, - .handler = handle_fasteoi_irq, + .handler = handle_fasteoi_ack_irq, .handler_name = "fasteoi", }, }; -- 2.56.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level MSI sources 2026-11-10 12:06 ` [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level " Troy Mitchell @ 2026-11-11 0:09 ` Thomas Gleixner 0 siblings, 0 replies; 6+ messages in thread From: Thomas Gleixner @ 2026-11-11 0:09 UTC (permalink / raw) To: Troy Mitchell, Anup Patel, Radu Rendec, Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Björn Töpel Cc: Anup Patel, linux-riscv, linux-kernel, Troy Mitchell On Tue, Nov 10 2026 at 12:06, Troy Mitchell wrote: > IMSIC rejects an affinity change with -EBUSY while a previous vector > move is still in flight, and the IRQ core then records the new mask as > pending. The change is applied by irq_move_irq() in the IMSIC irq_ack > callback, but level-triggered APLIC MSI interrupts are handled by > handle_fasteoi_irq(), which never calls irq_ack. > > The pending change is therefore never applied. While it is pending, > later affinity changes only update the pending mask, so the interrupt > stays on its old CPU. > > Use handle_fasteoi_ack_irq() for level-triggered sources. It acks the > interrupt before invoking the handler, so a pending affinity change is > applied on the next interrupt, and the EOI retrigger then targets the > new CPU. Smart! ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-11-11 1:11 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-11-10 12:06 [PATCH v2 0/2] irqchip/riscv-aplic: Use trigger specific flow handlers in MSI mode Troy Mitchell 2026-11-10 12:06 ` [PATCH v2 1/2] irqchip/riscv-aplic: Use handle_edge_irq() for edge-triggered MSI sources Troy Mitchell 2026-11-11 0:07 ` Thomas Gleixner 2026-11-11 1:11 ` Troy Mitchell 2026-11-10 12:06 ` [PATCH v2 2/2] irqchip/riscv-aplic: Apply pending affinity changes for level " Troy Mitchell 2026-11-11 0:09 ` Thomas Gleixner
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®