Skip to content

Commit e045fa2

Browse files
starnightbjorn-helgaas
authored andcommitted
PCI/MSI: Fix incorrect MSI-X masking on resume
When a driver enables MSI-X, msix_program_entries() reads the MSI-X Vector Control register for each vector and saves it in desc->masked. Each register is 32 bits and bit 0 is the actual Mask bit. When we restored these registers during resume, we previously set the Mask bit if *any* bit in desc->masked was set instead of when the Mask bit itself was set: pci_restore_state pci_restore_msi_state __pci_restore_msix_state for_each_pci_msi_entry msix_mask_irq(entry, entry->masked) <-- entire u32 word __pci_msix_desc_mask_irq(desc, flag) mask_bits = desc->masked & ~PCI_MSIX_ENTRY_CTRL_MASKBIT if (flag) <-- testing entire u32, not just bit 0 mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL) This means that after resume, MSI-X vectors were masked when they shouldn't be, which leads to timeouts like this: nvme nvme0: I/O 978 QID 3 timeout, completion polled On resume, set the Mask bit only when the saved Mask bit from suspend was set. This should remove the need for 19ea025 ("nvme: Add quirk for Kingston NVME SSD running FW E8FK11.T"). [bhelgaas: commit log, move fix to __pci_msix_desc_mask_irq()] Link: https://bugzilla.kernel.org/show_bug.cgi?id=204887 Link: https://lore.kernel.org/r/[email protected] Fixes: f2440d9 ("PCI MSI: Refactor interrupt masking code") Signed-off-by: Jian-Hong Pan <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]> Cc: [email protected]
1 parent 901c4dd commit e045fa2

File tree

1 file changed

+2
-1
lines changed

1 file changed

+2
-1
lines changed

drivers/pci/msi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,13 @@ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag)
213213

214214
if (pci_msi_ignore_mask)
215215
return 0;
216+
216217
desc_addr = pci_msix_desc_addr(desc);
217218
if (!desc_addr)
218219
return 0;
219220

220221
mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
221-
if (flag)
222+
if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT)
222223
mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
223224

224225
writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);

0 commit comments

Comments
 (0)