Skip to content

Commit

Permalink
Merge tag 'pci-v6.8-fixes-3' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/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
  • Loading branch information
torvalds committed Feb 17, 2024
2 parents ad645de + 172c0cf commit 4a75714
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 15 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -16837,6 +16837,7 @@ F: drivers/pci/controller/dwc/*designware*

PCI DRIVER FOR TI DRA7XX/J721E
M: Vignesh Raghavendra <[email protected]>
R: Siddharth Vadapalli <[email protected]>
L: [email protected]
L: [email protected]
L: [email protected] (moderated for non-subscribers)
Expand Down
37 changes: 22 additions & 15 deletions drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4a75714

Please sign in to comment.