diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index c9517a348836..cffb34f6f3a9 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c @@ -16,9 +16,11 @@ #include #include #include +#include #include #include +#include "../pci-host-common.h" #include "../../pci.h" #include "pcie-designware.h" @@ -1218,18 +1220,14 @@ static int dw_pcie_pme_turn_off(struct dw_pcie *pci) int dw_pcie_suspend_noirq(struct dw_pcie *pci) { - u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); + bool pme_capable = false; int ret = 0; u32 val; if (!dw_pcie_link_up(pci)) goto stop_link; - /* - * If L1SS is supported, then do not put the link into L2 as some - * devices such as NVMe expect low resume latency. - */ - if (dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKCTL) & PCI_EXP_LNKCTL_ASPM_L1) + if (!pci_host_common_d3cold_possible(pci->pp.bridge, &pme_capable)) return 0; if (pci->pp.ops->pme_turn_off) { @@ -1273,6 +1271,15 @@ int dw_pcie_suspend_noirq(struct dw_pcie *pci) udelay(1); stop_link: + /* + * TODO: "pme_capable" means some downstream device is wakeup- + * enabled and is capable of generating PME from D3cold, which + * requires auxiliary power. Instead of always skipping power off + * if PME is supported from D3cold, query the pwrctrl core and skip + * power off only if device supports PME from D3cold and Vaux is + * not supported. + */ + pci->pp.skip_pwrctrl_off = pme_capable; dw_pcie_stop_link(pci); if (pci->pp.ops->deinit) pci->pp.ops->deinit(&pci->pp); @@ -1290,8 +1297,6 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci) if (!pci->suspended) return 0; - pci->suspended = false; - if (pci->pp.ops->init) { ret = pci->pp.ops->init(&pci->pp); if (ret) { @@ -1313,6 +1318,8 @@ int dw_pcie_resume_noirq(struct dw_pcie *pci) if (pci->pp.ops->post_init) pci->pp.ops->post_init(&pci->pp); + pci->suspended = false; + return 0; err_stop_link: diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h index 3e69ef60165b..e759c5c7257e 100644 --- a/drivers/pci/controller/dwc/pcie-designware.h +++ b/drivers/pci/controller/dwc/pcie-designware.h @@ -450,6 +450,7 @@ struct dw_pcie_rp { bool ecam_enabled; bool native_ecam; bool skip_l23_ready; + bool skip_pwrctrl_off; }; struct dw_pcie_ep_ops {