]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.0.4/pci-pciehp-disable-data-link-layer-state-changed-event-on-suspend.patch
Linux 5.0.4
[thirdparty/kernel/stable-queue.git] / releases / 5.0.4 / pci-pciehp-disable-data-link-layer-state-changed-event-on-suspend.patch
1 From bbe54ea5330d828cc396d451c0e1e5c3f9764c1e Mon Sep 17 00:00:00 2001
2 From: Mika Westerberg <mika.westerberg@linux.intel.com>
3 Date: Thu, 31 Jan 2019 20:07:46 +0300
4 Subject: PCI: pciehp: Disable Data Link Layer State Changed event on suspend
5
6 From: Mika Westerberg <mika.westerberg@linux.intel.com>
7
8 commit bbe54ea5330d828cc396d451c0e1e5c3f9764c1e upstream.
9
10 Commit 0e157e528604 ("PCI/PME: Implement runtime PM callbacks") tried to
11 solve an issue where the hierarchy immediately wakes up when it is
12 transitioned into D3cold. However, it turns out to prevent PME
13 propagation on some systems that do not support D3cold.
14
15 I looked more closely at what might cause the immediate wakeup. It happens
16 when the ACPI power resource of the root port is turned off. The AML code
17 associated with the _OFF() method of the ACPI power resource starts a PCIe
18 L2/L3 Ready transition and waits for it to complete. Right after the L2/L3
19 Ready transition is started the root port receives a PME from the
20 downstream port.
21
22 The simplest hierarchy where this happens looks like this:
23
24 00:1d.0 PCIe Root Port
25 ^
26 |
27 v
28 05:00.0 PCIe switch #1 upstream port
29 06:01.0 PCIe switch #1 downstream hotplug port
30 ^
31 |
32 v
33 08:00.0 PCIe switch #2 upstream port
34
35 It seems that the PCIe link between the two switches, before
36 PME_Turn_Off/PME_TO_Ack is complete for the whole hierarchy, goes
37 inactive and triggers PME towards the root port bringing it back to D0.
38 The L2/L3 Ready sequence is described in PCIe r4.0 spec sections 5.2 and
39 5.3.3 but unfortunately they do not state what happens if DLLSCE is
40 enabled during the sequence.
41
42 Disabling Data Link Layer State Changed event (DLLSCE) seems to prevent
43 the issue and still allows the downstream hotplug port to notice when a
44 device is plugged/unplugged.
45
46 Link: https://bugzilla.kernel.org/show_bug.cgi?id=202593
47 Fixes: 0e157e528604 ("PCI/PME: Implement runtime PM callbacks")
48 Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
49 Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
50 Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
51 CC: stable@vger.kernel.org # v4.20+
52 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53
54 ---
55 drivers/pci/hotplug/pciehp_hpc.c | 17 +++++++++++++++--
56 1 file changed, 15 insertions(+), 2 deletions(-)
57
58 --- a/drivers/pci/hotplug/pciehp_hpc.c
59 +++ b/drivers/pci/hotplug/pciehp_hpc.c
60 @@ -736,12 +736,25 @@ void pcie_clear_hotplug_events(struct co
61
62 void pcie_enable_interrupt(struct controller *ctrl)
63 {
64 - pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_HPIE, PCI_EXP_SLTCTL_HPIE);
65 + u16 mask;
66 +
67 + mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE;
68 + pcie_write_cmd(ctrl, mask, mask);
69 }
70
71 void pcie_disable_interrupt(struct controller *ctrl)
72 {
73 - pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_HPIE);
74 + u16 mask;
75 +
76 + /*
77 + * Mask hot-plug interrupt to prevent it triggering immediately
78 + * when the link goes inactive (we still get PME when any of the
79 + * enabled events is detected). Same goes with Link Layer State
80 + * changed event which generates PME immediately when the link goes
81 + * inactive so mask it as well.
82 + */
83 + mask = PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_DLLSCE;
84 + pcie_write_cmd(ctrl, 0, mask);
85 }
86
87 /*