Skip to content

Commit b56ebe7

Browse files
Koichiro DenKAGA-KOKO
authored andcommitted
x86/apic/msi: Fix misconfigured non-maskable MSI quirk
commit ef8dd01 ("genirq/msi: Make interrupt allocation less convoluted"), reworked the code so that the x86 specific quirk for affinity setting of non-maskable PCI/MSI interrupts is not longer activated if necessary. This could be solved by restoring the original logic in the core MSI code, but after a deeper analysis it turned out that the quirk flag is not required at all. The quirk is only required when the PCI/MSI device cannot mask the MSI interrupts, which in turn also prevents reservation mode from being enabled for the affected interrupt. This allows ot remove the NOMASK quirk bit completely as msi_set_affinity() can instead check whether reservation mode is enabled for the interrupt, which gives exactly the same answer. Even in the momentary non-existing case that the reservation mode would be not set for a maskable MSI interrupt this would not cause any harm as it just would cause msi_set_affinity() to go needlessly through the functionaly equivalent slow path, which works perfectly fine with maskable interrupts as well. Rework msi_set_affinity() to query the reservation mode and remove all NOMASK quirk logic from the core code. [ tglx: Massaged changelog ] Fixes: ef8dd01 ("genirq/msi: Make interrupt allocation less convoluted") Suggested-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Koichiro Den <den@valinux.co.jp> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20231026032036.2462428-1-den@valinux.co.jp
1 parent 441ccc3 commit b56ebe7

File tree

5 files changed

+8
-45
lines changed

5 files changed

+8
-45
lines changed

arch/x86/kernel/apic/msi.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
5555
* caused by the non-atomic update of the address/data pair.
5656
*
5757
* Direct update is possible when:
58-
* - The MSI is maskable (remapped MSI does not use this code path)).
59-
* The quirk bit is not set in this case.
58+
* - The MSI is maskable (remapped MSI does not use this code path).
59+
* The reservation mode bit is set in this case.
6060
* - The new vector is the same as the old vector
6161
* - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
6262
* - The interrupt is not yet started up
6363
* - The new destination CPU is the same as the old destination CPU
6464
*/
65-
if (!irqd_msi_nomask_quirk(irqd) ||
65+
if (!irqd_can_reserve(irqd) ||
6666
cfg->vector == old_cfg.vector ||
6767
old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
6868
!irqd_is_started(irqd) ||
@@ -215,8 +215,6 @@ static bool x86_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
215215
if (WARN_ON_ONCE(domain != real_parent))
216216
return false;
217217
info->chip->irq_set_affinity = msi_set_affinity;
218-
/* See msi_set_affinity() for the gory details */
219-
info->flags |= MSI_FLAG_NOMASK_QUIRK;
220218
break;
221219
case DOMAIN_BUS_DMAR:
222220
case DOMAIN_BUS_AMDVI:

include/linux/irq.h

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,6 @@ struct irq_data {
215215
* IRQD_SINGLE_TARGET - IRQ allows only a single affinity target
216216
* IRQD_DEFAULT_TRIGGER_SET - Expected trigger already been set
217217
* IRQD_CAN_RESERVE - Can use reservation mode
218-
* IRQD_MSI_NOMASK_QUIRK - Non-maskable MSI quirk for affinity change
219-
* required
220218
* IRQD_HANDLE_ENFORCE_IRQCTX - Enforce that handle_irq_*() is only invoked
221219
* from actual interrupt context.
222220
* IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call
@@ -247,11 +245,10 @@ enum {
247245
IRQD_SINGLE_TARGET = BIT(24),
248246
IRQD_DEFAULT_TRIGGER_SET = BIT(25),
249247
IRQD_CAN_RESERVE = BIT(26),
250-
IRQD_MSI_NOMASK_QUIRK = BIT(27),
251-
IRQD_HANDLE_ENFORCE_IRQCTX = BIT(28),
252-
IRQD_AFFINITY_ON_ACTIVATE = BIT(29),
253-
IRQD_IRQ_ENABLED_ON_SUSPEND = BIT(30),
254-
IRQD_RESEND_WHEN_IN_PROGRESS = BIT(31),
248+
IRQD_HANDLE_ENFORCE_IRQCTX = BIT(27),
249+
IRQD_AFFINITY_ON_ACTIVATE = BIT(28),
250+
IRQD_IRQ_ENABLED_ON_SUSPEND = BIT(29),
251+
IRQD_RESEND_WHEN_IN_PROGRESS = BIT(30),
255252
};
256253

257254
#define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors)
@@ -426,21 +423,6 @@ static inline bool irqd_can_reserve(struct irq_data *d)
426423
return __irqd_to_state(d) & IRQD_CAN_RESERVE;
427424
}
428425

429-
static inline void irqd_set_msi_nomask_quirk(struct irq_data *d)
430-
{
431-
__irqd_to_state(d) |= IRQD_MSI_NOMASK_QUIRK;
432-
}
433-
434-
static inline void irqd_clr_msi_nomask_quirk(struct irq_data *d)
435-
{
436-
__irqd_to_state(d) &= ~IRQD_MSI_NOMASK_QUIRK;
437-
}
438-
439-
static inline bool irqd_msi_nomask_quirk(struct irq_data *d)
440-
{
441-
return __irqd_to_state(d) & IRQD_MSI_NOMASK_QUIRK;
442-
}
443-
444426
static inline void irqd_set_affinity_on_activate(struct irq_data *d)
445427
{
446428
__irqd_to_state(d) |= IRQD_AFFINITY_ON_ACTIVATE;

include/linux/msi.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,6 @@ enum {
547547
MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 5),
548548
/* Free MSI descriptors */
549549
MSI_FLAG_FREE_MSI_DESCS = (1 << 6),
550-
/*
551-
* Quirk to handle MSI implementations which do not provide
552-
* masking. Currently known to affect x86, but has to be partially
553-
* handled in the core MSI code.
554-
*/
555-
MSI_FLAG_NOMASK_QUIRK = (1 << 7),
556550

557551
/* Mask for the generic functionality */
558552
MSI_GENERIC_FLAGS_MASK = GENMASK(15, 0),

kernel/irq/debugfs.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ static const struct irq_bit_descr irqdata_states[] = {
121121
BIT_MASK_DESCR(IRQD_AFFINITY_ON_ACTIVATE),
122122
BIT_MASK_DESCR(IRQD_MANAGED_SHUTDOWN),
123123
BIT_MASK_DESCR(IRQD_CAN_RESERVE),
124-
BIT_MASK_DESCR(IRQD_MSI_NOMASK_QUIRK),
125124

126125
BIT_MASK_DESCR(IRQD_FORWARDED_TO_VCPU),
127126

kernel/irq/msi.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,6 @@ static int msi_handle_pci_fail(struct irq_domain *domain, struct msi_desc *desc,
12041204

12051205
#define VIRQ_CAN_RESERVE 0x01
12061206
#define VIRQ_ACTIVATE 0x02
1207-
#define VIRQ_NOMASK_QUIRK 0x04
12081207

12091208
static int msi_init_virq(struct irq_domain *domain, int virq, unsigned int vflags)
12101209
{
@@ -1213,8 +1212,6 @@ static int msi_init_virq(struct irq_domain *domain, int virq, unsigned int vflag
12131212

12141213
if (!(vflags & VIRQ_CAN_RESERVE)) {
12151214
irqd_clr_can_reserve(irqd);
1216-
if (vflags & VIRQ_NOMASK_QUIRK)
1217-
irqd_set_msi_nomask_quirk(irqd);
12181215

12191216
/*
12201217
* If the interrupt is managed but no CPU is available to
@@ -1275,15 +1272,8 @@ static int __msi_domain_alloc_irqs(struct device *dev, struct irq_domain *domain
12751272
* Interrupt can use a reserved vector and will not occupy
12761273
* a real device vector until the interrupt is requested.
12771274
*/
1278-
if (msi_check_reservation_mode(domain, info, dev)) {
1275+
if (msi_check_reservation_mode(domain, info, dev))
12791276
vflags |= VIRQ_CAN_RESERVE;
1280-
/*
1281-
* MSI affinity setting requires a special quirk (X86) when
1282-
* reservation mode is active.
1283-
*/
1284-
if (info->flags & MSI_FLAG_NOMASK_QUIRK)
1285-
vflags |= VIRQ_NOMASK_QUIRK;
1286-
}
12871277

12881278
xa_for_each_range(xa, idx, desc, ctrl->first, ctrl->last) {
12891279
if (!msi_desc_match(desc, MSI_DESC_NOTASSOCIATED))

0 commit comments

Comments
 (0)