diff options
author | Alexandru Gagniuc | 2019-02-27 21:58:17 +0100 |
---|---|---|
committer | Bjorn Helgaas | 2019-03-05 22:04:13 +0100 |
commit | e8303bb7a75c113388badcc49b2a84b4121c1b3e (patch) | |
tree | 191bc959359be088dc553e69b45d82c3d4a96ff9 /drivers/pci/pcie/portdrv_core.c | |
parent | PCI/portdrv: Support PCIe services on subtractive decode bridges (diff) | |
download | kernel-qcow2-linux-e8303bb7a75c113388badcc49b2a84b4121c1b3e.tar.gz kernel-qcow2-linux-e8303bb7a75c113388badcc49b2a84b4121c1b3e.tar.xz kernel-qcow2-linux-e8303bb7a75c113388badcc49b2a84b4121c1b3e.zip |
PCI/LINK: Report degraded links via link bandwidth notification
A warning is generated when a PCIe device is probed with a degraded link,
but there was no similar mechanism to warn when the link becomes degraded
after probing. The Link Bandwidth Notification provides this mechanism.
Use the Link Bandwidth Management Interrupt to detect bandwidth changes,
and rescan the bandwidth, looking for the weakest point. This is the same
logic used in probe().
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Diffstat (limited to 'drivers/pci/pcie/portdrv_core.c')
-rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index f458ac9cb70c..7d04f9d087a6 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -99,7 +99,7 @@ static int pcie_message_numbers(struct pci_dev *dev, int mask, */ static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask) { - int nr_entries, nvec; + int nr_entries, nvec, pcie_irq; u32 pme = 0, aer = 0, dpc = 0; /* Allocate the maximum possible number of MSI/MSI-X vectors */ @@ -135,10 +135,13 @@ static int pcie_port_enable_irq_vec(struct pci_dev *dev, int *irqs, int mask) return nr_entries; } - /* PME and hotplug share an MSI/MSI-X vector */ - if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP)) { - irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pci_irq_vector(dev, pme); - irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pci_irq_vector(dev, pme); + /* PME, hotplug and bandwidth notification share an MSI/MSI-X vector */ + if (mask & (PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP | + PCIE_PORT_SERVICE_BWNOTIF)) { + pcie_irq = pci_irq_vector(dev, pme); + irqs[PCIE_PORT_SERVICE_PME_SHIFT] = pcie_irq; + irqs[PCIE_PORT_SERVICE_HP_SHIFT] = pcie_irq; + irqs[PCIE_PORT_SERVICE_BWNOTIF_SHIFT] = pcie_irq; } if (mask & PCIE_PORT_SERVICE_AER) @@ -250,6 +253,10 @@ static int get_port_device_capability(struct pci_dev *dev) pci_aer_available() && services & PCIE_PORT_SERVICE_AER) services |= PCIE_PORT_SERVICE_DPC; + if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM || + pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) + services |= PCIE_PORT_SERVICE_BWNOTIF; + return services; } |