PCI/portdrv: Use shared MSI/MSI-X vector for Bandwidth Management [Linux 5.1]

PCI/portdrv: Use shared MSI/MSI-X vector for Bandwidth Management [Linux 5.1]

This Linux kernel change "PCI/portdrv: Use shared MSI/MSI-X vector for Bandwidth Management" is included in the Linux 5.1 release. This change is authored by Alex Williamson <alex.williamson [at] redhat.com> on Mon Apr 22 16:43:30 2019 -0600. The commit for this change in Linux stable tree is 15d2aba (patch).

PCI/portdrv: Use shared MSI/MSI-X vector for Bandwidth Management

The Interrupt Message Number in the PCIe Capabilities register (PCIe r4.0,
sec 7.5.3.2) indicates which MSI/MSI-X vector is shared by interrupts
related to the PCIe Capability, including Link Bandwidth Management and
Link Autonomous Bandwidth Interrupts (Link Control, 7.5.3.7), Command
Completed and Hot-Plug Interrupts (Slot Control, 7.5.3.10), and the PME
Interrupt (Root Control, 7.5.3.12).

pcie_message_numbers() checked whether we want to enable PME or Hot-Plug
interrupts but neglected to check for Link Bandwidth Management, so if we
only wanted the Bandwidth Management interrupts, it decided we didn't need
any vectors at all.  Then pcie_port_enable_irq_vec() tried to reallocate
zero vectors, which failed, resulting in fallback to INTx.

On some systems, e.g., an X79-based workstation, that INTx seems broken or
not handled correctly, so we got spurious IRQ16 interrupts for Bandwidth
Management events.

Change pcie_message_numbers() so that if we want Link Bandwidth Management
interrupts, we use the shared MSI/MSI-X vector from the PCIe Capabilities
register.

Fixes: e8303bb7a75c ("PCI/LINK: Report degraded links via link bandwidth notification")
Link: https://lore.kernel.org/lkml/155597243666.19387.1205950870601742062.stgit@gimli.home
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
[bhelgaas: changelog]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>

There are 3 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/pci/pcie/portdrv_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 7d04f9d..1b33012 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -55,7 +55,8 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask,
     * 7.8.2, 7.10.10, 7.31.2.
     */

-   if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) {
+   if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP |
+           PCIE_PORT_SERVICE_BWNOTIF)) {
        pcie_capability_read_word(dev, PCI_EXP_FLAGS, &reg16);
        *pme = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
        nvec = *pme + 1;

Leave a Reply

Your email address will not be published. Required fields are marked *