Skip to content

Commit 9c8e9c9

Browse files
committed
PCI/MSI: Move non-mask check back into low level accessors
The recent rework of PCI/MSI[X] masking moved the non-mask checks from the low level accessors into the higher level mask/unmask functions. This missed the fact that these accessors can be invoked from other places as well. The missing checks break XEN-PV which sets pci_msi_ignore_mask and also violates the virtual MSIX and the msi_attrib.maskbit protections. Instead of sprinkling checks all over the place, lift them back into the low level accessor functions. To avoid checking three different conditions combine them into one property of msi_desc::msi_attrib. [ josef: Fixed the missed conversion in the core code ] Fixes: fcacdfb ("PCI/MSI: Provide a new set of mask and unmask functions") Reported-by: Josef Johansson <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Josef Johansson <[email protected]> Cc: Bjorn Helgaas <[email protected]> Cc: [email protected]
1 parent debe436 commit 9c8e9c9

File tree

3 files changed

+17
-15
lines changed

3 files changed

+17
-15
lines changed

drivers/pci/msi.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ static noinline void pci_msi_update_mask(struct msi_desc *desc, u32 clear, u32 s
148148
raw_spinlock_t *lock = &desc->dev->msi_lock;
149149
unsigned long flags;
150150

151+
if (!desc->msi_attrib.can_mask)
152+
return;
153+
151154
raw_spin_lock_irqsave(lock, flags);
152155
desc->msi_mask &= ~clear;
153156
desc->msi_mask |= set;
@@ -181,7 +184,8 @@ static void pci_msix_write_vector_ctrl(struct msi_desc *desc, u32 ctrl)
181184
{
182185
void __iomem *desc_addr = pci_msix_desc_addr(desc);
183186

184-
writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
187+
if (desc->msi_attrib.can_mask)
188+
writel(ctrl, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
185189
}
186190

187191
static inline void pci_msix_mask(struct msi_desc *desc)
@@ -200,23 +204,17 @@ static inline void pci_msix_unmask(struct msi_desc *desc)
200204

201205
static void __pci_msi_mask_desc(struct msi_desc *desc, u32 mask)
202206
{
203-
if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual)
204-
return;
205-
206207
if (desc->msi_attrib.is_msix)
207208
pci_msix_mask(desc);
208-
else if (desc->msi_attrib.maskbit)
209+
else
209210
pci_msi_mask(desc, mask);
210211
}
211212

212213
static void __pci_msi_unmask_desc(struct msi_desc *desc, u32 mask)
213214
{
214-
if (pci_msi_ignore_mask || desc->msi_attrib.is_virtual)
215-
return;
216-
217215
if (desc->msi_attrib.is_msix)
218216
pci_msix_unmask(desc);
219-
else if (desc->msi_attrib.maskbit)
217+
else
220218
pci_msi_unmask(desc, mask);
221219
}
222220

@@ -484,7 +482,8 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
484482
entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT);
485483
entry->msi_attrib.is_virtual = 0;
486484
entry->msi_attrib.entry_nr = 0;
487-
entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT);
485+
entry->msi_attrib.can_mask = !pci_msi_ignore_mask &&
486+
!!(control & PCI_MSI_FLAGS_MASKBIT);
488487
entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
489488
entry->msi_attrib.multi_cap = (control & PCI_MSI_FLAGS_QMASK) >> 1;
490489
entry->msi_attrib.multiple = ilog2(__roundup_pow_of_two(nvec));
@@ -495,7 +494,7 @@ msi_setup_entry(struct pci_dev *dev, int nvec, struct irq_affinity *affd)
495494
entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_32;
496495

497496
/* Save the initial mask status */
498-
if (entry->msi_attrib.maskbit)
497+
if (entry->msi_attrib.can_mask)
499498
pci_read_config_dword(dev, entry->mask_pos, &entry->msi_mask);
500499

501500
out:
@@ -639,10 +638,13 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
639638
entry->msi_attrib.is_virtual =
640639
entry->msi_attrib.entry_nr >= vec_count;
641640

641+
entry->msi_attrib.can_mask = !pci_msi_ignore_mask &&
642+
!entry->msi_attrib.is_virtual;
643+
642644
entry->msi_attrib.default_irq = dev->irq;
643645
entry->mask_base = base;
644646

645-
if (!entry->msi_attrib.is_virtual) {
647+
if (entry->msi_attrib.can_mask) {
646648
addr = pci_msix_desc_addr(entry);
647649
entry->msix_ctrl = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
648650
}

include/linux/msi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ struct msi_desc {
148148
u8 is_msix : 1;
149149
u8 multiple : 3;
150150
u8 multi_cap : 3;
151-
u8 maskbit : 1;
151+
u8 can_mask : 1;
152152
u8 is_64 : 1;
153153
u8 is_virtual : 1;
154154
u16 entry_nr;

kernel/irq/msi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,10 +529,10 @@ static bool msi_check_reservation_mode(struct irq_domain *domain,
529529

530530
/*
531531
* Checking the first MSI descriptor is sufficient. MSIX supports
532-
* masking and MSI does so when the maskbit is set.
532+
* masking and MSI does so when the can_mask attribute is set.
533533
*/
534534
desc = first_msi_entry(dev);
535-
return desc->msi_attrib.is_msix || desc->msi_attrib.maskbit;
535+
return desc->msi_attrib.is_msix || desc->msi_attrib.can_mask;
536536
}
537537

538538
int __msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,

0 commit comments

Comments
 (0)