diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-28 16:29:09 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-28 16:29:09 -0400 |
commit | 9936328b41ce4bce8f20269dcac8cb476c8d0820 (patch) | |
tree | 12f6172b4f98d054f787309d477ff575d8f3f1fc | |
parent | 8c7ae38d1ce12a0eaeba655df8562552b3596c7f (diff) | |
parent | 0fa635aec9abd718bd18c0bda2261351a0811efc (diff) |
Merge tag 'pci-v5.1-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI fixes from Bjorn Helgaas:
"PCI fixes:
- Clear level-triggered interrupts for the bandwidth notification
supported added for v5.1 (Alexandru Gagniuc)
- Clear bandwidth notification interrupts before enabling them (Lukas
Wunner)
- Report post-enumeration bandwidth changes only once for
multi-function devices (Lukas Wunner)"
* tag 'pci-v5.1-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
PCI/LINK: Deduplicate bandwidth reports for multi-function devices
PCI/LINK: Clear bandwidth notification interrupt before enabling it
PCI/LINK: Supply IRQ handler so level-triggered IRQs are acked
-rw-r--r-- | drivers/pci/pci.h | 1 | ||||
-rw-r--r-- | drivers/pci/pcie/bw_notification.c | 23 | ||||
-rw-r--r-- | drivers/pci/probe.c | 2 |
3 files changed, 19 insertions, 7 deletions
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 224d88634115..d994839a3e24 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h | |||
@@ -273,6 +273,7 @@ enum pcie_link_width pcie_get_width_cap(struct pci_dev *dev); | |||
273 | u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, | 273 | u32 pcie_bandwidth_capable(struct pci_dev *dev, enum pci_bus_speed *speed, |
274 | enum pcie_link_width *width); | 274 | enum pcie_link_width *width); |
275 | void __pcie_print_link_status(struct pci_dev *dev, bool verbose); | 275 | void __pcie_print_link_status(struct pci_dev *dev, bool verbose); |
276 | void pcie_report_downtraining(struct pci_dev *dev); | ||
276 | 277 | ||
277 | /* Single Root I/O Virtualization */ | 278 | /* Single Root I/O Virtualization */ |
278 | struct pci_sriov { | 279 | struct pci_sriov { |
diff --git a/drivers/pci/pcie/bw_notification.c b/drivers/pci/pcie/bw_notification.c index d2eae3b7cc0f..4fa9e3523ee1 100644 --- a/drivers/pci/pcie/bw_notification.c +++ b/drivers/pci/pcie/bw_notification.c | |||
@@ -30,6 +30,8 @@ static void pcie_enable_link_bandwidth_notification(struct pci_dev *dev) | |||
30 | { | 30 | { |
31 | u16 lnk_ctl; | 31 | u16 lnk_ctl; |
32 | 32 | ||
33 | pcie_capability_write_word(dev, PCI_EXP_LNKSTA, PCI_EXP_LNKSTA_LBMS); | ||
34 | |||
33 | pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnk_ctl); | 35 | pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnk_ctl); |
34 | lnk_ctl |= PCI_EXP_LNKCTL_LBMIE; | 36 | lnk_ctl |= PCI_EXP_LNKCTL_LBMIE; |
35 | pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl); | 37 | pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl); |
@@ -44,11 +46,10 @@ static void pcie_disable_link_bandwidth_notification(struct pci_dev *dev) | |||
44 | pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl); | 46 | pcie_capability_write_word(dev, PCI_EXP_LNKCTL, lnk_ctl); |
45 | } | 47 | } |
46 | 48 | ||
47 | static irqreturn_t pcie_bw_notification_handler(int irq, void *context) | 49 | static irqreturn_t pcie_bw_notification_irq(int irq, void *context) |
48 | { | 50 | { |
49 | struct pcie_device *srv = context; | 51 | struct pcie_device *srv = context; |
50 | struct pci_dev *port = srv->port; | 52 | struct pci_dev *port = srv->port; |
51 | struct pci_dev *dev; | ||
52 | u16 link_status, events; | 53 | u16 link_status, events; |
53 | int ret; | 54 | int ret; |
54 | 55 | ||
@@ -58,17 +59,26 @@ static irqreturn_t pcie_bw_notification_handler(int irq, void *context) | |||
58 | if (ret != PCIBIOS_SUCCESSFUL || !events) | 59 | if (ret != PCIBIOS_SUCCESSFUL || !events) |
59 | return IRQ_NONE; | 60 | return IRQ_NONE; |
60 | 61 | ||
62 | pcie_capability_write_word(port, PCI_EXP_LNKSTA, events); | ||
63 | pcie_update_link_speed(port->subordinate, link_status); | ||
64 | return IRQ_WAKE_THREAD; | ||
65 | } | ||
66 | |||
67 | static irqreturn_t pcie_bw_notification_handler(int irq, void *context) | ||
68 | { | ||
69 | struct pcie_device *srv = context; | ||
70 | struct pci_dev *port = srv->port; | ||
71 | struct pci_dev *dev; | ||
72 | |||
61 | /* | 73 | /* |
62 | * Print status from downstream devices, not this root port or | 74 | * Print status from downstream devices, not this root port or |
63 | * downstream switch port. | 75 | * downstream switch port. |
64 | */ | 76 | */ |
65 | down_read(&pci_bus_sem); | 77 | down_read(&pci_bus_sem); |
66 | list_for_each_entry(dev, &port->subordinate->devices, bus_list) | 78 | list_for_each_entry(dev, &port->subordinate->devices, bus_list) |
67 | __pcie_print_link_status(dev, false); | 79 | pcie_report_downtraining(dev); |
68 | up_read(&pci_bus_sem); | 80 | up_read(&pci_bus_sem); |
69 | 81 | ||
70 | pcie_update_link_speed(port->subordinate, link_status); | ||
71 | pcie_capability_write_word(port, PCI_EXP_LNKSTA, events); | ||
72 | return IRQ_HANDLED; | 82 | return IRQ_HANDLED; |
73 | } | 83 | } |
74 | 84 | ||
@@ -80,7 +90,8 @@ static int pcie_bandwidth_notification_probe(struct pcie_device *srv) | |||
80 | if (!pcie_link_bandwidth_notification_supported(srv->port)) | 90 | if (!pcie_link_bandwidth_notification_supported(srv->port)) |
81 | return -ENODEV; | 91 | return -ENODEV; |
82 | 92 | ||
83 | ret = request_threaded_irq(srv->irq, NULL, pcie_bw_notification_handler, | 93 | ret = request_threaded_irq(srv->irq, pcie_bw_notification_irq, |
94 | pcie_bw_notification_handler, | ||
84 | IRQF_SHARED, "PCIe BW notif", srv); | 95 | IRQF_SHARED, "PCIe BW notif", srv); |
85 | if (ret) | 96 | if (ret) |
86 | return ret; | 97 | return ret; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 2ec0df04e0dc..7e12d0163863 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -2388,7 +2388,7 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn) | |||
2388 | return dev; | 2388 | return dev; |
2389 | } | 2389 | } |
2390 | 2390 | ||
2391 | static void pcie_report_downtraining(struct pci_dev *dev) | 2391 | void pcie_report_downtraining(struct pci_dev *dev) |
2392 | { | 2392 | { |
2393 | if (!pci_is_pcie(dev)) | 2393 | if (!pci_is_pcie(dev)) |
2394 | return; | 2394 | return; |