From dc68b406783edf33af0e997fb98e9e048b4d46e8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 14 Oct 2019 14:14:06 -0500 Subject: PCI/PM: Correct pci_pm_thaw_noirq() documentation According to the documentation, pci_pm_thaw_noirq() did not put the device into the full-power state and restore its standard configuration registers. This is incorrect, so update the documentation to match the code. Link: https://lore.kernel.org/r/20191014230016.240912-3-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- Documentation/power/pci.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Documentation/power') diff --git a/Documentation/power/pci.rst b/Documentation/power/pci.rst index 0e2ef7429304..1525c594d631 100644 --- a/Documentation/power/pci.rst +++ b/Documentation/power/pci.rst @@ -600,17 +600,17 @@ using the following PCI bus type's callbacks:: respectively. -The first of them, pci_pm_thaw_noirq(), is analogous to pci_pm_resume_noirq(), -but it doesn't put the device into the full power state and doesn't attempt to -restore its standard configuration registers. It also executes the device -driver's pm->thaw_noirq() callback, if defined, instead of pm->resume_noirq(). +The first of them, pci_pm_thaw_noirq(), is analogous to pci_pm_resume_noirq(). +It puts the device into the full power state and restores its standard +configuration registers. It also executes the device driver's pm->thaw_noirq() +callback, if defined, instead of pm->resume_noirq(). The pci_pm_thaw() routine is similar to pci_pm_resume(), but it runs the device driver's pm->thaw() callback instead of pm->resume(). It is executed asynchronously for different PCI devices that don't depend on each other in a known way. -The complete phase it the same as for system resume. +The complete phase is the same as for system resume. After saving the image, devices need to be powered down before the system can enter the target sleep state (ACPI S4 for ACPI-based systems). This is done in -- cgit v1.2.3 From 85a9b0507db2fbbfe7912dc3b33d322f200e2ca7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 8 Oct 2019 15:28:00 -0500 Subject: PCI/PM: Note that PME can be generated from D0 Per PCIe r5.0 sec 7.5.2.1, PME may be generated from D0, so update Documentation/power/pci.rst to reflect that. Link: https://lore.kernel.org/r/20191016194450.68959-1-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- Documentation/power/pci.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation/power') diff --git a/Documentation/power/pci.rst b/Documentation/power/pci.rst index 1525c594d631..8a4abb7c7363 100644 --- a/Documentation/power/pci.rst +++ b/Documentation/power/pci.rst @@ -130,8 +130,8 @@ a full power-on reset sequence and the power-on defaults are restored to the device by hardware just as at initial power up. PCI devices supporting the PCI PM Spec can be programmed to generate PMEs -while in a low-power state (D1-D3), but they are not required to be capable -of generating PMEs from all supported low-power states. In particular, the +while in any power state (D0-D3), but they are not required to be capable +of generating PMEs from all supported power states. In particular, the capability of generating PMEs from D3cold is optional and depends on the presence of additional voltage (3.3Vaux) allowing the device to remain sufficiently active to generate a wakeup signal. -- cgit v1.2.3 From b64cf7a1711d7796fdac19a23bc63d378a6e7ed1 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 8 Oct 2019 15:25:23 -0500 Subject: PCI/PM: Wrap long lines in documentation Documentation/power/pci.rst is wrapped to fit in 80 columns, but directory structure changes made a few lines longer. Wrap them so they all fit in 80 columns again. Link: https://lore.kernel.org/r/20191014230016.240912-7-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- Documentation/power/pci.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'Documentation/power') diff --git a/Documentation/power/pci.rst b/Documentation/power/pci.rst index 8a4abb7c7363..a90e82c70a3b 100644 --- a/Documentation/power/pci.rst +++ b/Documentation/power/pci.rst @@ -426,12 +426,12 @@ pm->runtime_idle() callback. 2.4. System-Wide Power Transitions ---------------------------------- There are a few different types of system-wide power transitions, described in -Documentation/driver-api/pm/devices.rst. Each of them requires devices to be handled -in a specific way and the PM core executes subsystem-level power management -callbacks for this purpose. They are executed in phases such that each phase -involves executing the same subsystem-level callback for every device belonging -to the given subsystem before the next phase begins. These phases always run -after tasks have been frozen. +Documentation/driver-api/pm/devices.rst. Each of them requires devices to be +handled in a specific way and the PM core executes subsystem-level power +management callbacks for this purpose. They are executed in phases such that +each phase involves executing the same subsystem-level callback for every device +belonging to the given subsystem before the next phase begins. These phases +always run after tasks have been frozen. 2.4.1. System Suspend ^^^^^^^^^^^^^^^^^^^^^ @@ -636,12 +636,12 @@ System restore requires a hibernation image to be loaded into memory and the pre-hibernation memory contents to be restored before the pre-hibernation system activity can be resumed. -As described in Documentation/driver-api/pm/devices.rst, the hibernation image is loaded -into memory by a fresh instance of the kernel, called the boot kernel, which in -turn is loaded and run by a boot loader in the usual way. After the boot kernel -has loaded the image, it needs to replace its own code and data with the code -and data of the "hibernated" kernel stored within the image, called the image -kernel. For this purpose all devices are frozen just like before creating +As described in Documentation/driver-api/pm/devices.rst, the hibernation image +is loaded into memory by a fresh instance of the kernel, called the boot kernel, +which in turn is loaded and run by a boot loader in the usual way. After the +boot kernel has loaded the image, it needs to replace its own code and data with +the code and data of the "hibernated" kernel stored within the image, called the +image kernel. For this purpose all devices are frozen just like before creating the image during hibernation, in the prepare, freeze, freeze_noirq @@ -691,8 +691,8 @@ controlling the runtime power management of their devices. At the time of this writing there are two ways to define power management callbacks for a PCI device driver, the recommended one, based on using a -dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and the -"legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and +dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and +the "legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and .resume() callbacks from struct pci_driver are used. The legacy approach, however, doesn't allow one to define runtime power management callbacks and is not really suitable for any new drivers. Therefore it is not covered by this -- cgit v1.2.3 From 89cdbc3546354c359558a1809133902028c57da4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 31 Oct 2019 17:53:04 -0500 Subject: PCI/PM: Remove unused pci_driver.resume_early() hook The struct pci_driver.resume_early() hook is one of the legacy PCI power management callbacks, and there are no remaining users of it. Remove it. Link: https://lore.kernel.org/r/20191101204558.210235-6-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- Documentation/power/pci.rst | 2 +- drivers/pci/pci-driver.c | 23 ++++++----------------- include/linux/pci.h | 2 -- 3 files changed, 7 insertions(+), 20 deletions(-) (limited to 'Documentation/power') diff --git a/Documentation/power/pci.rst b/Documentation/power/pci.rst index a90e82c70a3b..ff7029b94068 100644 --- a/Documentation/power/pci.rst +++ b/Documentation/power/pci.rst @@ -692,7 +692,7 @@ controlling the runtime power management of their devices. At the time of this writing there are two ways to define power management callbacks for a PCI device driver, the recommended one, based on using a dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and -the "legacy" one, in which the .suspend(), .suspend_late(), .resume_early(), and +the "legacy" one, in which the .suspend(), .suspend_late(), and .resume() callbacks from struct pci_driver are used. The legacy approach, however, doesn't allow one to define runtime power management callbacks and is not really suitable for any new drivers. Therefore it is not covered by this diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 5337cbbd69de..fc372c2d529a 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -630,15 +630,6 @@ Fixup: return 0; } -static int pci_legacy_resume_early(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - - return drv && drv->resume_early ? - drv->resume_early(pci_dev) : 0; -} - static int pci_legacy_resume(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -662,8 +653,7 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev) static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) { struct pci_driver *drv = pci_dev->driver; - bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume - || drv->resume_early); + bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume); /* * Legacy PM support is used by default, so warn if the new framework is @@ -944,7 +934,7 @@ static int pci_pm_resume_noirq(struct device *dev) pcie_pme_root_status_cleanup(pci_dev); if (pci_has_legacy_pm_support(pci_dev)) - return pci_legacy_resume_early(dev); + return 0; if (pm && pm->resume_noirq) return pm->resume_noirq(dev); @@ -1074,9 +1064,8 @@ static int pci_pm_thaw_noirq(struct device *dev) } /* - * Both the legacy ->resume_early() and the new pm->thaw_noirq() - * callbacks assume the device has been returned to D0 and its - * config state has been restored. + * The pm->thaw_noirq() callback assumes the device has been + * returned to D0 and its config state has been restored. * * In addition, pci_restore_state() restores MSI-X state in MMIO * space, which requires the device to be in D0, so return it to D0 @@ -1087,7 +1076,7 @@ static int pci_pm_thaw_noirq(struct device *dev) pci_restore_state(pci_dev); if (pci_has_legacy_pm_support(pci_dev)) - return pci_legacy_resume_early(dev); + return 0; if (pm && pm->thaw_noirq) return pm->thaw_noirq(dev); @@ -1219,7 +1208,7 @@ static int pci_pm_restore_noirq(struct device *dev) pci_fixup_device(pci_fixup_resume_early, pci_dev); if (pci_has_legacy_pm_support(pci_dev)) - return pci_legacy_resume_early(dev); + return 0; if (pm && pm->restore_noirq) return pm->restore_noirq(dev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 4846306d521c..dd4596fc1208 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -806,7 +806,6 @@ struct module; * context, so it can sleep. * @suspend: Put device into low power state. * @suspend_late: Put device into low power state. - * @resume_early: Wake device from low power state. * @resume: Wake device from low power state. * (Please see Documentation/power/pci.rst for descriptions * of PCI Power Management and the related functions.) @@ -830,7 +829,6 @@ struct pci_driver { void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ int (*suspend)(struct pci_dev *dev, pm_message_t state); /* Device suspended */ int (*suspend_late)(struct pci_dev *dev, pm_message_t state); - int (*resume_early)(struct pci_dev *dev); int (*resume)(struct pci_dev *dev); /* Device woken up */ void (*shutdown)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); /* On PF */ -- cgit v1.2.3 From 1a1daf097e21e544dd3e7c0ff620d78a9795fbf2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 31 Oct 2019 17:37:54 -0500 Subject: PCI/PM: Remove unused pci_driver.suspend_late() hook The struct pci_driver.suspend_late() hook is one of the legacy PCI power management callbacks, and there are no remaining users of it. Remove it. Link: https://lore.kernel.org/r/20191101204558.210235-7-helgaas@kernel.org Signed-off-by: Bjorn Helgaas Reviewed-by: Rafael J. Wysocki --- Documentation/power/pci.rst | 10 +++++----- drivers/pci/pci-driver.c | 22 +--------------------- include/linux/pci.h | 2 -- 3 files changed, 6 insertions(+), 28 deletions(-) (limited to 'Documentation/power') diff --git a/Documentation/power/pci.rst b/Documentation/power/pci.rst index ff7029b94068..0924d29636ad 100644 --- a/Documentation/power/pci.rst +++ b/Documentation/power/pci.rst @@ -692,11 +692,11 @@ controlling the runtime power management of their devices. At the time of this writing there are two ways to define power management callbacks for a PCI device driver, the recommended one, based on using a dev_pm_ops structure described in Documentation/driver-api/pm/devices.rst, and -the "legacy" one, in which the .suspend(), .suspend_late(), and -.resume() callbacks from struct pci_driver are used. The legacy approach, -however, doesn't allow one to define runtime power management callbacks and is -not really suitable for any new drivers. Therefore it is not covered by this -document (refer to the source code to learn more about it). +the "legacy" one, in which the .suspend() and .resume() callbacks from struct +pci_driver are used. The legacy approach, however, doesn't allow one to define +runtime power management callbacks and is not really suitable for any new +drivers. Therefore it is not covered by this document (refer to the source code +to learn more about it). It is recommended that all PCI device drivers define a struct dev_pm_ops object containing pointers to power management (PM) callbacks that will be executed by diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index fc372c2d529a..e89fd90eaa93 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -599,32 +599,12 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state) static int pci_legacy_suspend_late(struct device *dev, pm_message_t state) { struct pci_dev *pci_dev = to_pci_dev(dev); - struct pci_driver *drv = pci_dev->driver; - - if (drv && drv->suspend_late) { - pci_power_t prev = pci_dev->current_state; - int error; - - error = drv->suspend_late(pci_dev, state); - suspend_report_result(drv->suspend_late, error); - if (error) - return error; - - if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0 - && pci_dev->current_state != PCI_UNKNOWN) { - pci_WARN_ONCE(pci_dev, pci_dev->current_state != prev, - "PCI PM: Device state not saved by %pS\n", - drv->suspend_late); - goto Fixup; - } - } if (!pci_dev->state_saved) pci_save_state(pci_dev); pci_pm_set_unknown_state(pci_dev); -Fixup: pci_fixup_device(pci_fixup_suspend_late, pci_dev); return 0; @@ -653,7 +633,7 @@ static void pci_pm_default_suspend(struct pci_dev *pci_dev) static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev) { struct pci_driver *drv = pci_dev->driver; - bool ret = drv && (drv->suspend || drv->suspend_late || drv->resume); + bool ret = drv && (drv->suspend || drv->resume); /* * Legacy PM support is used by default, so warn if the new framework is diff --git a/include/linux/pci.h b/include/linux/pci.h index dd4596fc1208..9b0e35e09874 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -805,7 +805,6 @@ struct module; * The remove function always gets called from process * context, so it can sleep. * @suspend: Put device into low power state. - * @suspend_late: Put device into low power state. * @resume: Wake device from low power state. * (Please see Documentation/power/pci.rst for descriptions * of PCI Power Management and the related functions.) @@ -828,7 +827,6 @@ struct pci_driver { int (*probe)(struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove)(struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ int (*suspend)(struct pci_dev *dev, pm_message_t state); /* Device suspended */ - int (*suspend_late)(struct pci_dev *dev, pm_message_t state); int (*resume)(struct pci_dev *dev); /* Device woken up */ void (*shutdown)(struct pci_dev *dev); int (*sriov_configure)(struct pci_dev *dev, int num_vfs); /* On PF */ -- cgit v1.2.3