On Tue, Jun 30, 2020 at 05:01:07PM -0500, Bjorn Helgaas wrote: > On Mon, Jun 22, 2020 at 07:12:48PM +0300, Mika Westerberg wrote: > > Commit 6ae72bfa656e ("PCI: Unify pcie_find_root_port() and > > pci_find_pcie_root_port()") unified the root port finding functionality > > into a single function but missed the fact that the passed in device may > > already be a root port. This causes the kernel to block power management > > of PCIe hierarchies in recent systems because ->bridge_d3 started to > > return false for such ports after the commit in question. > > > > Fixes: 6ae72bfa656e ("PCI: Unify pcie_find_root_port() and pci_find_pcie_root_port()") > > Signed-off-by: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > > Cc: stable@xxxxxxxxxxxxxxx > > --- > > include/linux/pci.h | 7 ++++++- > > 1 file changed, 6 insertions(+), 1 deletion(-) > > > > diff --git a/include/linux/pci.h b/include/linux/pci.h > > index c79d83304e52..c17c24f5eeed 100644 > > --- a/include/linux/pci.h > > +++ b/include/linux/pci.h > > @@ -2169,8 +2169,13 @@ static inline int pci_pcie_type(const struct pci_dev *dev) > > */ > > static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev) > > { > > - struct pci_dev *bridge = pci_upstream_bridge(dev); > > + struct pci_dev *bridge; > > > > + /* If dev is already root port */ > > + if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) > > + return dev; > > + > > + bridge = pci_upstream_bridge(dev); > > while (bridge) { > > if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT) > > return bridge; > > I applied the patch below, which is slightly simplified but I think > still equivalent, to for-linus for v5.8. Let me know if it's not. Thanks I just tested and it also works fine. > I dropped the stable tag because 6ae72bfa656e was merged for v5.8-rc1, > and I assume v5.7 works correctly so it doesn't need any change. Right, makes sense.