diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-02-17 08:06:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-02-17 08:06:20 -0800 |
commit | 4a7571485c467b76cc19fae304452fd56921c789 (patch) | |
tree | 1e507668fbfe67a5168e0bf40ca65ebdc3946749 | |
parent | ad645dea35c1381890bb190f208f8e62c61e3cbd (diff) | |
parent | 172c0cf519fb52860157c57067f1a58cfc0aa861 (diff) | |
download | lwn-4a7571485c467b76cc19fae304452fd56921c789.tar.gz lwn-4a7571485c467b76cc19fae304452fd56921c789.zip |
Merge tag 'pci-v6.8-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
Pull pci fixes from Bjorn Helgaas:
- Keep bridges in D0 if we need to poll downstream devices for PME to
resolve a v6.6 regression where we failed to enumerate devices below
bridges put in D3hot by runtime PM, e.g., NVMe drives connected via
Thunderbolt or USB4 docks (Alex Williamson)
- Add Siddharth Vadapalli as PCI TI DRA7XX/J721E reviewer
* tag 'pci-v6.8-fixes-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci:
MAINTAINERS: Add Siddharth Vadapalli as PCI TI DRA7XX/J721E reviewer
PCI: Fix active state requirement in PME polling
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/pci/pci.c | 37 |
2 files changed, 23 insertions, 15 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index a0697e2fb8e8..d87384c64a13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16837,6 +16837,7 @@ F: drivers/pci/controller/dwc/*designware* PCI DRIVER FOR TI DRA7XX/J721E M: Vignesh Raghavendra <vigneshr@ti.com> +R: Siddharth Vadapalli <s-vadapalli@ti.com> L: linux-omap@vger.kernel.org L: linux-pci@vger.kernel.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 9ab9b1008d8b..c3585229c12a 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2522,29 +2522,36 @@ static void pci_pme_list_scan(struct work_struct *work) if (pdev->pme_poll) { struct pci_dev *bridge = pdev->bus->self; struct device *dev = &pdev->dev; - int pm_status; + struct device *bdev = bridge ? &bridge->dev : NULL; + int bref = 0; /* - * If bridge is in low power state, the - * configuration space of subordinate devices - * may be not accessible + * If we have a bridge, it should be in an active/D0 + * state or the configuration space of subordinate + * devices may not be accessible or stable over the + * course of the call. */ - if (bridge && bridge->current_state != PCI_D0) - continue; + if (bdev) { + bref = pm_runtime_get_if_active(bdev, true); + if (!bref) + continue; + + if (bridge->current_state != PCI_D0) + goto put_bridge; + } /* - * If the device is in a low power state it - * should not be polled either. + * The device itself should be suspended but config + * space must be accessible, therefore it cannot be in + * D3cold. */ - pm_status = pm_runtime_get_if_active(dev, true); - if (!pm_status) - continue; - - if (pdev->current_state != PCI_D3cold) + if (pm_runtime_suspended(dev) && + pdev->current_state != PCI_D3cold) pci_pme_wakeup(pdev, NULL); - if (pm_status > 0) - pm_runtime_put(dev); +put_bridge: + if (bref > 0) + pm_runtime_put(bdev); } else { list_del(&pme_dev->list); kfree(pme_dev); |