mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
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 for19ea025e1d
("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/20191008034238.2503-1-jian-hong@endlessm.com Fixes:f2440d9acb
("PCI MSI: Refactor interrupt masking code") Signed-off-by: Jian-Hong Pan <jian-hong@endlessm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: stable@vger.kernel.org
This commit is contained in:
parent
901c4ddbe2
commit
e045fa29e8
1 changed files with 2 additions and 1 deletions
|
@ -213,12 +213,13 @@ u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag)
|
||||||
|
|
||||||
if (pci_msi_ignore_mask)
|
if (pci_msi_ignore_mask)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
desc_addr = pci_msix_desc_addr(desc);
|
desc_addr = pci_msix_desc_addr(desc);
|
||||||
if (!desc_addr)
|
if (!desc_addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
mask_bits &= ~PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
||||||
if (flag)
|
if (flag & PCI_MSIX_ENTRY_CTRL_MASKBIT)
|
||||||
mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
mask_bits |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
||||||
|
|
||||||
writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
writel(mask_bits, desc_addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
|
||||||
|
|
Loading…
Reference in a new issue