mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
- Fix possible hang in machine_kexec_mask_interrupts(),
which incorrectly assumes that irq_set_irqchip_state()
will always be able to complete in a kexec crash path,
triggered on RK3399 embedded boards (Igor Velkov)
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-----BEGIN PGP SIGNATURE-----
iQJFBAABCgAvFiEEBpT5eoXrXCwVQwEKEnMQ0APhK1gFAmrd3X4RHG1pbmdvQGtl
cm5lbC5vcmcACgkQEnMQ0APhK1gDkQ//Z+vr/rkvqst2EpYPjnygPBvjB/TsVO6d
FoMUEm+3X8ss9EueryDaHfK52yj7JoPZeot/0Ff38FX9Tu+1kXsmbj07tRMMbk0n
lcX6z0bfIuFcPiFfZZzraZR7oX0J1tOLkl2BsZzjpw02FPJcOqpPPYhJNMIaRKD6
nR54X1sgOw5LP9UBX4OCCGF0+rxLxOeFsMt6mytv3Q7HZjWvVRKK2UK8g3GHn579
AYPli910m+BgHQUbpEy1PHzsxGmoBiO/0jk2h5q15snlXZMnKaLr30GWnU3qzJIf
T/Z33ouzP+plcPWA8K9GI7XE2Q+TpbtRbUejSqQor57HbAANEm517vnB3tS1Gjca
tZPo2fvAWpU6BlEDWS+R/03Djt/M5hSB8CGd8ArhPZTCSSgdcGNkoz7rThn6aj9D
awZBIfi/byLW8i8/m/x0a7IBMCKWCInSmgh87sfUSQTx3V46wS+4V3bMFitYUThv
prCeIA987cqYWrnbtFGzqTSISKaHaW52iZndU6/Q+vW5a5zfv6vFty3u1qWnCs5o
XvbRa4fRCLexY5S4+1jVjfhwXxcPpPDiR2WApVQWIls22ieidpMdWEPpTvWwCF7L
hXQv5Pa+KKgBpeEsZC2wPNJ8Ht2thgF5SWFyLFKTwg/fvEKniSJGks4vICeMLUJ2
6vbldnXh3Uo=
=vGaL
-----END PGP SIGNATURE-----
Merge tag 'irq-urgent-2026-10-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull kexec / irq fix from Ingo Molnar:
- Fix possible hang in machine_kexec_mask_interrupts(),
which incorrectly assumes that irq_set_irqchip_state()
will always be able to complete in a kexec crash path,
triggered on RK3399 embedded boards (Igor Velkov)
* tag 'irq-urgent-2026-10-25' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq/kexec: Do not take the bus lock of an interrupt chip on the crash path
This commit is contained in:
commit
2b19759b46
|
|
@ -83,6 +83,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -2748,6 +2748,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
|
||||
|
|
@ -2762,25 +2784,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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user