* FAILED: patch "[PATCH] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path" failed to apply to 6.12-stable tree
@ 2026-11-07 10:25 Sasha Levin
2026-11-08 13:13 ` [PATCH 6.12.y] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path Thomas Gleixner
0 siblings, 1 reply; 2+ messages in thread
From: Sasha Levin @ 2026-11-07 10:25 UTC (permalink / raw)
To: iav, tglx; +Cc: stable
The patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 717862eac6eff0eea8ac30a0c0de0bed84922aab
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107052534-failed-6.12-717862eac6ef@kernel.org' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 717862eac6eff0eea8ac30a0c0de0bed84922aab Mon Sep 17 00:00:00 2001
From: Igor Velkov <iav@iav.lv>
Date: Thu, 15 Oct 2026 21:51:50 +0300
Subject: [PATCH] genirq/kexec: Do not take the bus lock of an interrupt chip
on the crash path
machine_kexec_mask_interrupts() calls irq_set_irqchip_state() for every
started interrupt. That function takes the bus lock of the chip and
desc->lock, and syncs the chip when it drops them. On the crash path
interrupts are off and the other CPUs are stopped, so a chip whose bus
transfer is completed by an interrupt never returns from the sync.
On RK3399 boards with an RK808 PMIC the RTC alarm interrupt belongs to
the regmap-irq chip of the RK808, which sits on I2C. rk808_irq_chip sets
init_ack_masked, so regmap_irq_sync_unlock() writes the ack register on
every unlock, and the I2C controller needs its own interrupt to finish
the transfer. A panic with a crash kernel loaded prints
SMP: stopping secondary CPUs
and then nothing until the watchdog resets the board.
machine_kexec_mask_interrupts() takes neither lock for the other
operations on the descriptor. Move the search for the chip that
implements irq_set_irqchip_state() into __irq_set_irqchip_state(), which
takes no locks, and call it from machine_kexec_mask_interrupts().
Fixes: 78fd584cdec0 ("arm64: kdump: implement machine_crash_shutdown()")
Suggested-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Igor Velkov <iav@iav.lv>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261015-kexec-irq-bus-lock-v2-1-2af15f0757b6@iav.lv
---
kernel/irq/internals.h | 1 +
kernel/irq/kexec.c | 2 +-
kernel/irq/manage.c | 43 +++++++++++++++++++++++-------------------
3 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 0ce21dd454047..4dff3ccae1812 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -81,6 +81,7 @@ enum {
#include "settings.h"
extern int __irq_set_trigger(struct irq_desc *desc, unsigned long flags);
+extern int __irq_set_irqchip_state(struct irq_desc *desc, enum irqchip_irq_state which, bool val);
extern void __disable_irq(struct irq_desc *desc);
extern void __enable_irq(struct irq_desc *desc);
diff --git a/kernel/irq/kexec.c b/kernel/irq/kexec.c
index 1a3deffe6b5b6..f245b98764225 100644
--- a/kernel/irq/kexec.c
+++ b/kernel/irq/kexec.c
@@ -25,7 +25,7 @@ void machine_kexec_mask_interrupts(void)
* First try to remove the active state from an interrupt which is forwarded
* to a VM. If the interrupt is not forwarded, try to EOI the interrupt.
*/
- check_eoi = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
+ check_eoi = __irq_set_irqchip_state(desc, IRQCHIP_STATE_ACTIVE, false);
}
if (check_eoi && chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 57eff26fa646a..bdb47837c66fc 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2735,6 +2735,28 @@ int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool *
}
EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
+int __irq_set_irqchip_state(struct irq_desc *desc, enum irqchip_irq_state which, bool val)
+{
+ struct irq_data *data = irq_desc_get_irq_data(desc);
+ struct irq_chip *chip;
+
+ do {
+ chip = irq_data_get_irq_chip(data);
+
+ if (WARN_ON_ONCE(!chip))
+ return -ENODEV;
+
+ if (chip->irq_set_irqchip_state)
+ break;
+
+ data = irqd_get_parent_data(data);
+ } while (data);
+
+ if (data)
+ return chip->irq_set_irqchip_state(data, which, val);
+ return -EINVAL;
+}
+
/**
* irq_set_irqchip_state - set the state of a forwarded interrupt.
* @irq: Interrupt line that is forwarded to a VM
@@ -2749,25 +2771,8 @@ EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
*/
int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool val)
{
- scoped_irqdesc_get_and_buslock(irq, 0) {
- struct irq_data *data = irq_desc_get_irq_data(scoped_irqdesc);
- struct irq_chip *chip;
-
- do {
- chip = irq_data_get_irq_chip(data);
-
- if (WARN_ON_ONCE(!chip))
- return -ENODEV;
-
- if (chip->irq_set_irqchip_state)
- break;
-
- data = irqd_get_parent_data(data);
- } while (data);
-
- if (data)
- return chip->irq_set_irqchip_state(data, which, val);
- }
+ scoped_irqdesc_get_and_buslock(irq, 0)
+ return __irq_set_irqchip_state(scoped_irqdesc, which, val);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 6.12.y] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path
2026-11-07 10:25 FAILED: patch "[PATCH] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path" failed to apply to 6.12-stable tree Sasha Levin
@ 2026-11-08 13:13 ` Thomas Gleixner
0 siblings, 0 replies; 2+ messages in thread
From: Thomas Gleixner @ 2026-11-08 13:13 UTC (permalink / raw)
To: Sasha Levin, iav; +Cc: stable
From: Igor Velkov <iav@iav.lv>
commit 717862eac6eff0eea8ac30a0c0de0bed84922aab upstream.
machine_kexec_mask_interrupts() calls irq_set_irqchip_state() for every
started interrupt. That function takes the bus lock of the chip and
desc->lock, and syncs the chip when it drops them. On the crash path
interrupts are off and the other CPUs are stopped, so a chip whose bus
transfer is completed by an interrupt never returns from the sync.
On RK3399 boards with an RK808 PMIC the RTC alarm interrupt belongs to
the regmap-irq chip of the RK808, which sits on I2C. rk808_irq_chip sets
init_ack_masked, so regmap_irq_sync_unlock() writes the ack register on
every unlock, and the I2C controller needs its own interrupt to finish
the transfer. A panic with a crash kernel loaded prints
SMP: stopping secondary CPUs
and then nothing until the watchdog resets the board.
machine_kexec_mask_interrupts() takes neither lock for the other
operations on the descriptor. Move the search for the chip that
implements irq_set_irqchip_state() into __irq_set_irqchip_state(), which
takes no locks, and call it from machine_kexec_mask_interrupts().
Fixes: 78fd584cdec0 ("arm64: kdump: implement machine_crash_shutdown()")
Suggested-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Igor Velkov <iav@iav.lv>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20261015-kexec-irq-bus-lock-v2-1-2af15f0757b6@iav.lv
---
kernel/irq/internals.h | 1 +
kernel/irq/kexec.c | 2 +-
kernel/irq/manage.c | 49 +++++++++++++++++++++++++------------------------
3 files changed, 27 insertions(+), 25 deletions(-)
---
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -75,6 +75,7 @@ enum {
#include "settings.h"
extern int __irq_set_trigger(struct irq_desc *desc, unsigned long flags);
+extern int __irq_set_irqchip_state(struct irq_desc *desc, enum irqchip_irq_state which, bool val);
extern void __disable_irq(struct irq_desc *desc);
extern void __enable_irq(struct irq_desc *desc);
--- a/kernel/irq/kexec.c
+++ b/kernel/irq/kexec.c
@@ -25,7 +25,7 @@ void machine_kexec_mask_interrupts(void)
* First try to remove the active state from an interrupt which is forwarded
* to a VM. If the interrupt is not forwarded, try to EOI the interrupt.
*/
- check_eoi = irq_set_irqchip_state(i, IRQCHIP_STATE_ACTIVE, false);
+ check_eoi = __irq_set_irqchip_state(desc, IRQCHIP_STATE_ACTIVE, false);
}
if (check_eoi && chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2854,6 +2854,28 @@ int irq_get_irqchip_state(unsigned int i
}
EXPORT_SYMBOL_GPL(irq_get_irqchip_state);
+int __irq_set_irqchip_state(struct irq_desc *desc, enum irqchip_irq_state which, bool val)
+{
+ struct irq_data *data = irq_desc_get_irq_data(desc);
+ struct irq_chip *chip;
+
+ do {
+ chip = irq_data_get_irq_chip(data);
+
+ if (WARN_ON_ONCE(!chip))
+ return -ENODEV;
+
+ if (chip->irq_set_irqchip_state)
+ break;
+
+ data = irqd_get_parent_data(data);
+ } while (data);
+
+ if (data)
+ return chip->irq_set_irqchip_state(data, which, val);
+ return -EINVAL;
+}
+
/**
* irq_set_irqchip_state - set the state of a forwarded interrupt.
* @irq: Interrupt line that is forwarded to a VM
@@ -2870,36 +2892,15 @@ int irq_set_irqchip_state(unsigned int i
bool val)
{
struct irq_desc *desc;
- struct irq_data *data;
- struct irq_chip *chip;
unsigned long flags;
- int err = -EINVAL;
+ int err;
desc = irq_get_desc_buslock(irq, &flags, 0);
if (!desc)
- return err;
-
- data = irq_desc_get_irq_data(desc);
-
- do {
- chip = irq_data_get_irq_chip(data);
- if (WARN_ON_ONCE(!chip)) {
- err = -ENODEV;
- goto out_unlock;
- }
- if (chip->irq_set_irqchip_state)
- break;
-#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
- data = data->parent_data;
-#else
- data = NULL;
-#endif
- } while (data);
+ return -EINVAL;
- if (data)
- err = chip->irq_set_irqchip_state(data, which, val);
+ err = __irq_set_irqchip_state(desc, which, val);
-out_unlock:
irq_put_desc_busunlock(desc, flags);
return err;
}
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-11-08 13:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:25 FAILED: patch "[PATCH] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path" failed to apply to 6.12-stable tree Sasha Levin
2026-11-08 13:13 ` [PATCH 6.12.y] genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path Thomas Gleixner
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.