On Thu, Aug 12, 2021 at 11:39 PM Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> wrote: > > Some platforms cannot detect ethernet hotplug once its upstream port is > runtime suspended because PME isn't granted by BIOS _OSC. The issue can > be workarounded by "pcie_ports=native". > > The vendor confirmed that the PME in _OSC is disabled intentionally for > system stability issues on the other OS, so we should also honor the PME > setting here. > > So before marking PME support status for the device, check > PCI_EXP_RTCTL_PMEIE bit to ensure PME interrupt is either enabled by > firmware or OS. > > Cc: Lukas Wunner <lukas@xxxxxxxxx> > Cc: Mika Westerberg <mika.westerberg@xxxxxxxxxxxxxxx> > Cc: Rafael J. Wysocki <rafael.j.wysocki@xxxxxxxxx> > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=213873 > Signed-off-by: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> A gentle ping... > --- > v2: > - Instead of prevent root port from runtime suspending, skip > initializing PME status for the downstream device. > > drivers/pci/pci.c | 28 +++++++++++++++++++++++++++- > 1 file changed, 27 insertions(+), 1 deletion(-) > > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c > index aacf575c15cf..4344dc302edd 100644 > --- a/drivers/pci/pci.c > +++ b/drivers/pci/pci.c > @@ -2294,6 +2294,32 @@ void pci_pme_wakeup_bus(struct pci_bus *bus) > pci_walk_bus(bus, pci_pme_wakeup, (void *)true); > } > > +#ifdef CONFIG_PCIE_PME > +static bool pci_pcie_port_pme_enabled(struct pci_dev *dev) > +{ > + struct pci_dev *bridge = pci_upstream_bridge(dev); > + u16 val; > + int ret; > + > + if (!bridge) > + return true; > + > + if (pci_pcie_type(bridge) != PCI_EXP_TYPE_ROOT_PORT && > + pci_pcie_type(bridge) != PCI_EXP_TYPE_RC_EC) > + return true; > + > + ret = pcie_capability_read_word(bridge, PCI_EXP_RTCTL, &val); > + if (ret) > + return false; > + > + return val & PCI_EXP_RTCTL_PMEIE; > +} > +#else > +static bool pci_pcie_port_pme_enabled(struct pci_dev *dev) > +{ > + return true; > +} > +#endif > > /** > * pci_pme_capable - check the capability of PCI device to generate PME# > @@ -3095,7 +3121,7 @@ void pci_pm_init(struct pci_dev *dev) > } > > pmc &= PCI_PM_CAP_PME_MASK; > - if (pmc) { > + if (pmc && pci_pcie_port_pme_enabled(dev)) { > pci_info(dev, "PME# supported from%s%s%s%s%s\n", > (pmc & PCI_PM_CAP_PME_D0) ? " D0" : "", > (pmc & PCI_PM_CAP_PME_D1) ? " D1" : "", > -- > 2.32.0 >