aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2016-06-02 04:17:12 -0400
committerBjorn Helgaas <bhelgaas@google.com>2016-06-13 15:57:36 -0400
commit9d26d3a8f1b0c442339a235f9508bdad8af91043 (patch)
treefda7bf01c07d954d9dceb2a0f1c7a9beba74a67e
parent43f7f88b9362e1f26603b45932069bbd6e15a1e1 (diff)
PCI: Put PCIe ports into D3 during suspend
Currently the Linux PCI core does not touch power state of PCI bridges and PCIe ports when system suspend is entered. Leaving them in D0 consumes power unnecessarily and may prevent the CPU from entering deeper C-states. With recent PCIe hardware we can power down the ports to save power given that we take into account few restrictions: - The PCIe port hardware is recent enough, starting from 2015. - Devices connected to PCIe ports are effectively in D3cold once the port is transitioned to D3 (the config space is not accessible anymore and the link may be powered down). - Devices behind the PCIe port need to be allowed to transition to D3cold and back. There is a way both drivers and userspace can forbid this. - If the device behind the PCIe port is capable of waking the system it needs to be able to do so from D3cold. This patch adds a new flag to struct pci_device called 'bridge_d3'. This flag is set and cleared by the PCI core whenever there is a change in power management state of any of the devices behind the PCIe port. When system later on is suspended we only need to check this flag and if it is true transition the port to D3 otherwise we leave it in D0. Also provide override mechanism via command line parameter "pcie_port_pm=[off|force]" that can be used to disable or enable the feature regardless of the BIOS manufacturing date. Tested-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--drivers/pci/bus.c1
-rw-r--r--drivers/pci/pci-driver.c5
-rw-r--r--drivers/pci/pci-sysfs.c5
-rw-r--r--drivers/pci/pci.c175
-rw-r--r--drivers/pci/pci.h11
-rw-r--r--drivers/pci/remove.c2
-rw-r--r--drivers/usb/host/xhci-pci.c2
-rw-r--r--include/linux/pci.h3
9 files changed, 203 insertions, 5 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82b42c958d1c..86edee4cedd4 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3047,6 +3047,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
3047 compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe 3047 compat Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
3048 ports driver. 3048 ports driver.
3049 3049
3050 pcie_port_pm= [PCIE] PCIe port power management handling:
3051 off Disable power management of all PCIe ports
3052 force Forcibly enable power management of all PCIe ports
3053
3050 pcie_pme= [PCIE,PM] Native PCIe PME signaling options: 3054 pcie_pme= [PCIE,PM] Native PCIe PME signaling options:
3051 nomsi Do not use MSI for native PCIe PME signaling (this makes 3055 nomsi Do not use MSI for native PCIe PME signaling (this makes
3052 all PCIe root ports use INTx for all services). 3056 all PCIe root ports use INTx for all services).
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index dd7cdbee8029..28731360b457 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -291,6 +291,7 @@ void pci_bus_add_device(struct pci_dev *dev)
291 pci_fixup_device(pci_fixup_final, dev); 291 pci_fixup_device(pci_fixup_final, dev);
292 pci_create_sysfs_dev_files(dev); 292 pci_create_sysfs_dev_files(dev);
293 pci_proc_attach_device(dev); 293 pci_proc_attach_device(dev);
294 pci_bridge_d3_device_changed(dev);
294 295
295 dev->match_driver = true; 296 dev->match_driver = true;
296 retval = device_attach(&dev->dev); 297 retval = device_attach(&dev->dev);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d7ffd66814bb..e39a67c8ef39 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -777,7 +777,7 @@ static int pci_pm_suspend_noirq(struct device *dev)
777 777
778 if (!pci_dev->state_saved) { 778 if (!pci_dev->state_saved) {
779 pci_save_state(pci_dev); 779 pci_save_state(pci_dev);
780 if (!pci_has_subordinate(pci_dev)) 780 if (pci_power_manageable(pci_dev))
781 pci_prepare_to_sleep(pci_dev); 781 pci_prepare_to_sleep(pci_dev);
782 } 782 }
783 783
@@ -1144,7 +1144,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
1144 return -ENOSYS; 1144 return -ENOSYS;
1145 1145
1146 pci_dev->state_saved = false; 1146 pci_dev->state_saved = false;
1147 pci_dev->no_d3cold = false;
1148 error = pm->runtime_suspend(dev); 1147 error = pm->runtime_suspend(dev);
1149 if (error) { 1148 if (error) {
1150 /* 1149 /*
@@ -1161,8 +1160,6 @@ static int pci_pm_runtime_suspend(struct device *dev)
1161 1160
1162 return error; 1161 return error;
1163 } 1162 }
1164 if (!pci_dev->d3cold_allowed)
1165 pci_dev->no_d3cold = true;
1166 1163
1167 pci_fixup_device(pci_fixup_suspend, pci_dev); 1164 pci_fixup_device(pci_fixup_suspend, pci_dev);
1168 1165
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index d319a9ca9b7b..bcd10c795284 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -406,6 +406,11 @@ static ssize_t d3cold_allowed_store(struct device *dev,
406 return -EINVAL; 406 return -EINVAL;
407 407
408 pdev->d3cold_allowed = !!val; 408 pdev->d3cold_allowed = !!val;
409 if (pdev->d3cold_allowed)
410 pci_d3cold_enable(pdev);
411 else
412 pci_d3cold_disable(pdev);
413
409 pm_runtime_resume(dev); 414 pm_runtime_resume(dev);
410 415
411 return count; 416 return count;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c8b4dbdd1bdd..9ff7183e25a2 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -9,6 +9,7 @@
9 9
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/delay.h> 11#include <linux/delay.h>
12#include <linux/dmi.h>
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/of.h> 14#include <linux/of.h>
14#include <linux/of_pci.h> 15#include <linux/of_pci.h>
@@ -101,6 +102,21 @@ unsigned int pcibios_max_latency = 255;
101/* If set, the PCIe ARI capability will not be used. */ 102/* If set, the PCIe ARI capability will not be used. */
102static bool pcie_ari_disabled; 103static bool pcie_ari_disabled;
103 104
105/* Disable bridge_d3 for all PCIe ports */
106static bool pci_bridge_d3_disable;
107/* Force bridge_d3 for all PCIe ports */
108static bool pci_bridge_d3_force;
109
110static int __init pcie_port_pm_setup(char *str)
111{
112 if (!strcmp(str, "off"))
113 pci_bridge_d3_disable = true;
114 else if (!strcmp(str, "force"))
115 pci_bridge_d3_force = true;
116 return 1;
117}
118__setup("pcie_port_pm=", pcie_port_pm_setup);
119
104/** 120/**
105 * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children 121 * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
106 * @bus: pointer to PCI bus structure to search 122 * @bus: pointer to PCI bus structure to search
@@ -2156,6 +2172,164 @@ void pci_config_pm_runtime_put(struct pci_dev *pdev)
2156} 2172}
2157 2173
2158/** 2174/**
2175 * pci_bridge_d3_possible - Is it possible to put the bridge into D3
2176 * @bridge: Bridge to check
2177 *
2178 * This function checks if it is possible to move the bridge to D3.
2179 * Currently we only allow D3 for recent enough PCIe ports.
2180 */
2181static bool pci_bridge_d3_possible(struct pci_dev *bridge)
2182{
2183 unsigned int year;
2184
2185 if (!pci_is_pcie(bridge))
2186 return false;
2187
2188 switch (pci_pcie_type(bridge)) {
2189 case PCI_EXP_TYPE_ROOT_PORT:
2190 case PCI_EXP_TYPE_UPSTREAM:
2191 case PCI_EXP_TYPE_DOWNSTREAM:
2192 if (pci_bridge_d3_disable)
2193 return false;
2194 if (pci_bridge_d3_force)
2195 return true;
2196
2197 /*
2198 * It should be safe to put PCIe ports from 2015 or newer
2199 * to D3.
2200 */
2201 if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) &&
2202 year >= 2015) {
2203 return true;
2204 }
2205 break;
2206 }
2207
2208 return false;
2209}
2210
2211static int pci_dev_check_d3cold(struct pci_dev *dev, void *data)
2212{
2213 bool *d3cold_ok = data;
2214 bool no_d3cold;
2215
2216 /*
2217 * The device needs to be allowed to go D3cold and if it is wake
2218 * capable to do so from D3cold.
2219 */
2220 no_d3cold = dev->no_d3cold || !dev->d3cold_allowed ||
2221 (device_may_wakeup(&dev->dev) && !pci_pme_capable(dev, PCI_D3cold)) ||
2222 !pci_power_manageable(dev);
2223
2224 *d3cold_ok = !no_d3cold;
2225
2226 return no_d3cold;
2227}
2228
2229/*
2230 * pci_bridge_d3_update - Update bridge D3 capabilities
2231 * @dev: PCI device which is changed
2232 * @remove: Is the device being removed
2233 *
2234 * Update upstream bridge PM capabilities accordingly depending on if the
2235 * device PM configuration was changed or the device is being removed. The
2236 * change is also propagated upstream.
2237 */
2238static void pci_bridge_d3_update(struct pci_dev *dev, bool remove)
2239{
2240 struct pci_dev *bridge;
2241 bool d3cold_ok = true;
2242
2243 bridge = pci_upstream_bridge(dev);
2244 if (!bridge || !pci_bridge_d3_possible(bridge))
2245 return;
2246
2247 pci_dev_get(bridge);
2248 /*
2249 * If the device is removed we do not care about its D3cold
2250 * capabilities.
2251 */
2252 if (!remove)
2253 pci_dev_check_d3cold(dev, &d3cold_ok);
2254
2255 if (d3cold_ok) {
2256 /*
2257 * We need to go through all children to find out if all of
2258 * them can still go to D3cold.
2259 */
2260 pci_walk_bus(bridge->subordinate, pci_dev_check_d3cold,
2261 &d3cold_ok);
2262 }
2263
2264 if (bridge->bridge_d3 != d3cold_ok) {
2265 bridge->bridge_d3 = d3cold_ok;
2266 /* Propagate change to upstream bridges */
2267 pci_bridge_d3_update(bridge, false);
2268 }
2269
2270 pci_dev_put(bridge);
2271}
2272
2273/**
2274 * pci_bridge_d3_device_changed - Update bridge D3 capabilities on change
2275 * @dev: PCI device that was changed
2276 *
2277 * If a device is added or its PM configuration, such as is it allowed to
2278 * enter D3cold, is changed this function updates upstream bridge PM
2279 * capabilities accordingly.
2280 */
2281void pci_bridge_d3_device_changed(struct pci_dev *dev)
2282{
2283 pci_bridge_d3_update(dev, false);
2284}
2285
2286/**
2287 * pci_bridge_d3_device_removed - Update bridge D3 capabilities on remove
2288 * @dev: PCI device being removed
2289 *
2290 * Function updates upstream bridge PM capabilities based on other devices
2291 * still left on the bus.
2292 */
2293void pci_bridge_d3_device_removed(struct pci_dev *dev)
2294{
2295 pci_bridge_d3_update(dev, true);
2296}
2297
2298/**
2299 * pci_d3cold_enable - Enable D3cold for device
2300 * @dev: PCI device to handle
2301 *
2302 * This function can be used in drivers to enable D3cold from the device
2303 * they handle. It also updates upstream PCI bridge PM capabilities
2304 * accordingly.
2305 */
2306void pci_d3cold_enable(struct pci_dev *dev)
2307{
2308 if (dev->no_d3cold) {
2309 dev->no_d3cold = false;
2310 pci_bridge_d3_device_changed(dev);
2311 }
2312}
2313EXPORT_SYMBOL_GPL(pci_d3cold_enable);
2314
2315/**
2316 * pci_d3cold_disable - Disable D3cold for device
2317 * @dev: PCI device to handle
2318 *
2319 * This function can be used in drivers to disable D3cold from the device
2320 * they handle. It also updates upstream PCI bridge PM capabilities
2321 * accordingly.
2322 */
2323void pci_d3cold_disable(struct pci_dev *dev)
2324{
2325 if (!dev->no_d3cold) {
2326 dev->no_d3cold = true;
2327 pci_bridge_d3_device_changed(dev);
2328 }
2329}
2330EXPORT_SYMBOL_GPL(pci_d3cold_disable);
2331
2332/**
2159 * pci_pm_init - Initialize PM functions of given PCI device 2333 * pci_pm_init - Initialize PM functions of given PCI device
2160 * @dev: PCI device to handle. 2334 * @dev: PCI device to handle.
2161 */ 2335 */
@@ -2189,6 +2363,7 @@ void pci_pm_init(struct pci_dev *dev)
2189 dev->pm_cap = pm; 2363 dev->pm_cap = pm;
2190 dev->d3_delay = PCI_PM_D3_WAIT; 2364 dev->d3_delay = PCI_PM_D3_WAIT;
2191 dev->d3cold_delay = PCI_PM_D3COLD_WAIT; 2365 dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
2366 dev->bridge_d3 = pci_bridge_d3_possible(dev);
2192 dev->d3cold_allowed = true; 2367 dev->d3cold_allowed = true;
2193 2368
2194 dev->d1_support = false; 2369 dev->d1_support = false;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index a814bbb80fcb..9730c474b016 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -82,6 +82,8 @@ void pci_pm_init(struct pci_dev *dev);
82void pci_ea_init(struct pci_dev *dev); 82void pci_ea_init(struct pci_dev *dev);
83void pci_allocate_cap_save_buffers(struct pci_dev *dev); 83void pci_allocate_cap_save_buffers(struct pci_dev *dev);
84void pci_free_cap_save_buffers(struct pci_dev *dev); 84void pci_free_cap_save_buffers(struct pci_dev *dev);
85void pci_bridge_d3_device_changed(struct pci_dev *dev);
86void pci_bridge_d3_device_removed(struct pci_dev *dev);
85 87
86static inline void pci_wakeup_event(struct pci_dev *dev) 88static inline void pci_wakeup_event(struct pci_dev *dev)
87{ 89{
@@ -94,6 +96,15 @@ static inline bool pci_has_subordinate(struct pci_dev *pci_dev)
94 return !!(pci_dev->subordinate); 96 return !!(pci_dev->subordinate);
95} 97}
96 98
99static inline bool pci_power_manageable(struct pci_dev *pci_dev)
100{
101 /*
102 * Currently we allow normal PCI devices and PCI bridges transition
103 * into D3 if their bridge_d3 is set.
104 */
105 return !pci_has_subordinate(pci_dev) || pci_dev->bridge_d3;
106}
107
97struct pci_vpd_ops { 108struct pci_vpd_ops {
98 ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf); 109 ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
99 ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf); 110 ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 8982026637d5..d1ef7acf6930 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -96,6 +96,8 @@ static void pci_remove_bus_device(struct pci_dev *dev)
96 dev->subordinate = NULL; 96 dev->subordinate = NULL;
97 } 97 }
98 98
99 pci_bridge_d3_device_removed(dev);
100
99 pci_destroy_dev(dev); 101 pci_destroy_dev(dev);
100} 102}
101 103
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 48672fac7ff3..ac352fe391f4 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -382,7 +382,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
382 * need to have the registers polled during D3, so avoid D3cold. 382 * need to have the registers polled during D3, so avoid D3cold.
383 */ 383 */
384 if (xhci->quirks & XHCI_COMP_MODE_QUIRK) 384 if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
385 pdev->no_d3cold = true; 385 pci_d3cold_disable(pdev);
386 386
387 if (xhci->quirks & XHCI_PME_STUCK_QUIRK) 387 if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
388 xhci_pme_quirk(hcd); 388 xhci_pme_quirk(hcd);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8d748345b158..8597b423cb63 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -294,6 +294,7 @@ struct pci_dev {
294 unsigned int d2_support:1; /* Low power state D2 is supported */ 294 unsigned int d2_support:1; /* Low power state D2 is supported */
295 unsigned int no_d1d2:1; /* D1 and D2 are forbidden */ 295 unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
296 unsigned int no_d3cold:1; /* D3cold is forbidden */ 296 unsigned int no_d3cold:1; /* D3cold is forbidden */
297 unsigned int bridge_d3:1; /* Allow D3 for bridge */
297 unsigned int d3cold_allowed:1; /* D3cold is allowed by user */ 298 unsigned int d3cold_allowed:1; /* D3cold is allowed by user */
298 unsigned int mmio_always_on:1; /* disallow turning off io/mem 299 unsigned int mmio_always_on:1; /* disallow turning off io/mem
299 decoding during bar sizing */ 300 decoding during bar sizing */
@@ -1083,6 +1084,8 @@ int pci_back_from_sleep(struct pci_dev *dev);
1083bool pci_dev_run_wake(struct pci_dev *dev); 1084bool pci_dev_run_wake(struct pci_dev *dev);
1084bool pci_check_pme_status(struct pci_dev *dev); 1085bool pci_check_pme_status(struct pci_dev *dev);
1085void pci_pme_wakeup_bus(struct pci_bus *bus); 1086void pci_pme_wakeup_bus(struct pci_bus *bus);
1087void pci_d3cold_enable(struct pci_dev *dev);
1088void pci_d3cold_disable(struct pci_dev *dev);
1086 1089
1087static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state, 1090static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
1088 bool enable) 1091 bool enable)