summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2019-06-12 13:57:39 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-07-26 09:14:26 +0200
commit529e71cae929209bdc4f7ba835a52d64c4e878e2 (patch)
treee7c3b40dce566d99f9908ed41092aa8e700ef5bc
parent4d8504004c864dfb98b6fa691c47da1d9714d4bd (diff)
downloadlinux-stable-529e71cae929209bdc4f7ba835a52d64c4e878e2.tar.gz
linux-stable-529e71cae929209bdc4f7ba835a52d64c4e878e2.tar.bz2
linux-stable-529e71cae929209bdc4f7ba835a52d64c4e878e2.zip
PCI: Do not poll for PME if the device is in D3cold
commit 000dd5316e1c756a1c028f22e01d06a38249dd4d upstream. PME polling does not take into account that a device that is directly connected to the host bridge may go into D3cold as well. This leads to a situation where the PME poll thread reads from a config space of a device that is in D3cold and gets incorrect information because the config space is not accessible. Here is an example from Intel Ice Lake system where two PCIe root ports are in D3cold (I've instrumented the kernel to log the PMCSR register contents): [ 62.971442] pcieport 0000:00:07.1: Check PME status, PMCSR=0xffff [ 62.971504] pcieport 0000:00:07.0: Check PME status, PMCSR=0xffff Since 0xffff is interpreted so that PME is pending, the root ports will be runtime resumed. This repeats over and over again essentially blocking all runtime power management. Prevent this from happening by checking whether the device is in D3cold before its PME status is read. Fixes: 71a83bd727cc ("PCI/PM: add runtime PM support to PCIe port") Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Reviewed-by: Lukas Wunner <lukas@wunner.de> Cc: 3.6+ <stable@vger.kernel.org> # v3.6+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/pci/pci.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 61f2ef28ea1c..c65465385d8c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2004,6 +2004,13 @@ static void pci_pme_list_scan(struct work_struct *work)
*/
if (bridge && bridge->current_state != PCI_D0)
continue;
+ /*
+ * If the device is in D3cold it should not be
+ * polled either.
+ */
+ if (pme_dev->dev->current_state == PCI_D3cold)
+ continue;
+
pci_pme_wakeup(pme_dev->dev, NULL);
} else {
list_del(&pme_dev->list);