Skip to content

Commit 6cbf821

Browse files
rjwysockijbarnes993
authored andcommitted
PCI PM: Run-time callbacks for PCI bus type
Introduce run-time PM callbacks for the PCI bus type. Make the new callbacks work in analogy with the existing system sleep PM callbacks, so that the drivers already converted to struct dev_pm_ops can use their suspend and resume routines for run-time PM without modifications. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
1 parent 552be54 commit 6cbf821

File tree

5 files changed

+184
-34
lines changed

5 files changed

+184
-34
lines changed

drivers/pci/pci-driver.c

Lines changed: 133 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/slab.h>
1818
#include <linux/sched.h>
1919
#include <linux/cpu.h>
20+
#include <linux/pm_runtime.h>
2021
#include "pci.h"
2122

2223
struct pci_dynid {
@@ -404,6 +405,35 @@ static void pci_device_shutdown(struct device *dev)
404405
pci_msix_shutdown(pci_dev);
405406
}
406407

408+
#ifdef CONFIG_PM_OPS
409+
410+
/* Auxiliary functions used for system resume and run-time resume. */
411+
412+
/**
413+
* pci_restore_standard_config - restore standard config registers of PCI device
414+
* @pci_dev: PCI device to handle
415+
*/
416+
static int pci_restore_standard_config(struct pci_dev *pci_dev)
417+
{
418+
pci_update_current_state(pci_dev, PCI_UNKNOWN);
419+
420+
if (pci_dev->current_state != PCI_D0) {
421+
int error = pci_set_power_state(pci_dev, PCI_D0);
422+
if (error)
423+
return error;
424+
}
425+
426+
return pci_restore_state(pci_dev);
427+
}
428+
429+
static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
430+
{
431+
pci_restore_standard_config(pci_dev);
432+
pci_fixup_device(pci_fixup_resume_early, pci_dev);
433+
}
434+
435+
#endif
436+
407437
#ifdef CONFIG_PM_SLEEP
408438

409439
/*
@@ -520,29 +550,6 @@ static int pci_legacy_resume(struct device *dev)
520550

521551
/* Auxiliary functions used by the new power management framework */
522552

523-
/**
524-
* pci_restore_standard_config - restore standard config registers of PCI device
525-
* @pci_dev: PCI device to handle
526-
*/
527-
static int pci_restore_standard_config(struct pci_dev *pci_dev)
528-
{
529-
pci_update_current_state(pci_dev, PCI_UNKNOWN);
530-
531-
if (pci_dev->current_state != PCI_D0) {
532-
int error = pci_set_power_state(pci_dev, PCI_D0);
533-
if (error)
534-
return error;
535-
}
536-
537-
return pci_restore_state(pci_dev);
538-
}
539-
540-
static void pci_pm_default_resume_noirq(struct pci_dev *pci_dev)
541-
{
542-
pci_restore_standard_config(pci_dev);
543-
pci_fixup_device(pci_fixup_resume_early, pci_dev);
544-
}
545-
546553
static void pci_pm_default_resume(struct pci_dev *pci_dev)
547554
{
548555
pci_fixup_device(pci_fixup_resume, pci_dev);
@@ -581,6 +588,17 @@ static int pci_pm_prepare(struct device *dev)
581588
struct device_driver *drv = dev->driver;
582589
int error = 0;
583590

591+
/*
592+
* PCI devices suspended at run time need to be resumed at this
593+
* point, because in general it is necessary to reconfigure them for
594+
* system suspend. Namely, if the device is supposed to wake up the
595+
* system from the sleep state, we may need to reconfigure it for this
596+
* purpose. In turn, if the device is not supposed to wake up the
597+
* system from the sleep state, we'll have to prevent it from signaling
598+
* wake-up.
599+
*/
600+
pm_runtime_resume(dev);
601+
584602
if (drv && drv->pm && drv->pm->prepare)
585603
error = drv->pm->prepare(dev);
586604

@@ -595,6 +613,13 @@ static void pci_pm_complete(struct device *dev)
595613
drv->pm->complete(dev);
596614
}
597615

616+
#else /* !CONFIG_PM_SLEEP */
617+
618+
#define pci_pm_prepare NULL
619+
#define pci_pm_complete NULL
620+
621+
#endif /* !CONFIG_PM_SLEEP */
622+
598623
#ifdef CONFIG_SUSPEND
599624

600625
static int pci_pm_suspend(struct device *dev)
@@ -681,7 +706,7 @@ static int pci_pm_resume_noirq(struct device *dev)
681706
struct device_driver *drv = dev->driver;
682707
int error = 0;
683708

684-
pci_pm_default_resume_noirq(pci_dev);
709+
pci_pm_default_resume_early(pci_dev);
685710

686711
if (pci_has_legacy_pm_support(pci_dev))
687712
return pci_legacy_resume_early(dev);
@@ -879,7 +904,7 @@ static int pci_pm_restore_noirq(struct device *dev)
879904
struct device_driver *drv = dev->driver;
880905
int error = 0;
881906

882-
pci_pm_default_resume_noirq(pci_dev);
907+
pci_pm_default_resume_early(pci_dev);
883908

884909
if (pci_has_legacy_pm_support(pci_dev))
885910
return pci_legacy_resume_early(dev);
@@ -931,6 +956,84 @@ static int pci_pm_restore(struct device *dev)
931956

932957
#endif /* !CONFIG_HIBERNATION */
933958

959+
#ifdef CONFIG_PM_RUNTIME
960+
961+
static int pci_pm_runtime_suspend(struct device *dev)
962+
{
963+
struct pci_dev *pci_dev = to_pci_dev(dev);
964+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
965+
pci_power_t prev = pci_dev->current_state;
966+
int error;
967+
968+
if (!pm || !pm->runtime_suspend)
969+
return -ENOSYS;
970+
971+
error = pm->runtime_suspend(dev);
972+
suspend_report_result(pm->runtime_suspend, error);
973+
if (error)
974+
return error;
975+
976+
pci_fixup_device(pci_fixup_suspend, pci_dev);
977+
978+
if (!pci_dev->state_saved && pci_dev->current_state != PCI_D0
979+
&& pci_dev->current_state != PCI_UNKNOWN) {
980+
WARN_ONCE(pci_dev->current_state != prev,
981+
"PCI PM: State of device not saved by %pF\n",
982+
pm->runtime_suspend);
983+
return 0;
984+
}
985+
986+
if (!pci_dev->state_saved)
987+
pci_save_state(pci_dev);
988+
989+
pci_finish_runtime_suspend(pci_dev);
990+
991+
return 0;
992+
}
993+
994+
static int pci_pm_runtime_resume(struct device *dev)
995+
{
996+
struct pci_dev *pci_dev = to_pci_dev(dev);
997+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
998+
999+
if (!pm || !pm->runtime_resume)
1000+
return -ENOSYS;
1001+
1002+
pci_pm_default_resume_early(pci_dev);
1003+
__pci_enable_wake(pci_dev, PCI_D0, true, false);
1004+
pci_fixup_device(pci_fixup_resume, pci_dev);
1005+
1006+
return pm->runtime_resume(dev);
1007+
}
1008+
1009+
static int pci_pm_runtime_idle(struct device *dev)
1010+
{
1011+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
1012+
1013+
if (!pm)
1014+
return -ENOSYS;
1015+
1016+
if (pm->runtime_idle) {
1017+
int ret = pm->runtime_idle(dev);
1018+
if (ret)
1019+
return ret;
1020+
}
1021+
1022+
pm_runtime_suspend(dev);
1023+
1024+
return 0;
1025+
}
1026+
1027+
#else /* !CONFIG_PM_RUNTIME */
1028+
1029+
#define pci_pm_runtime_suspend NULL
1030+
#define pci_pm_runtime_resume NULL
1031+
#define pci_pm_runtime_idle NULL
1032+
1033+
#endif /* !CONFIG_PM_RUNTIME */
1034+
1035+
#ifdef CONFIG_PM_OPS
1036+
9341037
const struct dev_pm_ops pci_dev_pm_ops = {
9351038
.prepare = pci_pm_prepare,
9361039
.complete = pci_pm_complete,
@@ -946,15 +1049,18 @@ const struct dev_pm_ops pci_dev_pm_ops = {
9461049
.thaw_noirq = pci_pm_thaw_noirq,
9471050
.poweroff_noirq = pci_pm_poweroff_noirq,
9481051
.restore_noirq = pci_pm_restore_noirq,
1052+
.runtime_suspend = pci_pm_runtime_suspend,
1053+
.runtime_resume = pci_pm_runtime_resume,
1054+
.runtime_idle = pci_pm_runtime_idle,
9491055
};
9501056

9511057
#define PCI_PM_OPS_PTR (&pci_dev_pm_ops)
9521058

953-
#else /* !CONFIG_PM_SLEEP */
1059+
#else /* !COMFIG_PM_OPS */
9541060

9551061
#define PCI_PM_OPS_PTR NULL
9561062

957-
#endif /* !CONFIG_PM_SLEEP */
1063+
#endif /* !COMFIG_PM_OPS */
9581064

9591065
/**
9601066
* __pci_register_driver - register a new pci driver

drivers/pci/pci.c

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,9 +1302,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
13021302
}
13031303

13041304
/**
1305-
* pci_enable_wake - enable PCI device as wakeup event source
1305+
* __pci_enable_wake - enable PCI device as wakeup event source
13061306
* @dev: PCI device affected
13071307
* @state: PCI state from which device will issue wakeup events
1308+
* @runtime: True if the events are to be generated at run time
13081309
* @enable: True to enable event generation; false to disable
13091310
*
13101311
* This enables the device as a wakeup event source, or disables it.
@@ -1320,11 +1321,12 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
13201321
* Error code depending on the platform is returned if both the platform and
13211322
* the native mechanism fail to enable the generation of wake-up events
13221323
*/
1323-
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
1324+
int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
1325+
bool runtime, bool enable)
13241326
{
13251327
int ret = 0;
13261328

1327-
if (enable && !device_may_wakeup(&dev->dev))
1329+
if (enable && !runtime && !device_may_wakeup(&dev->dev))
13281330
return -EINVAL;
13291331

13301332
/* Don't do the same thing twice in a row for one device. */
@@ -1344,19 +1346,24 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
13441346
pci_pme_active(dev, true);
13451347
else
13461348
ret = 1;
1347-
error = platform_pci_sleep_wake(dev, true);
1349+
error = runtime ? platform_pci_run_wake(dev, true) :
1350+
platform_pci_sleep_wake(dev, true);
13481351
if (ret)
13491352
ret = error;
13501353
if (!ret)
13511354
dev->wakeup_prepared = true;
13521355
} else {
1353-
platform_pci_sleep_wake(dev, false);
1356+
if (runtime)
1357+
platform_pci_run_wake(dev, false);
1358+
else
1359+
platform_pci_sleep_wake(dev, false);
13541360
pci_pme_active(dev, false);
13551361
dev->wakeup_prepared = false;
13561362
}
13571363

13581364
return ret;
13591365
}
1366+
EXPORT_SYMBOL(__pci_enable_wake);
13601367

13611368
/**
13621369
* pci_wake_from_d3 - enable/disable device to wake up from D3_hot or D3_cold
@@ -1465,6 +1472,31 @@ int pci_back_from_sleep(struct pci_dev *dev)
14651472
return pci_set_power_state(dev, PCI_D0);
14661473
}
14671474

1475+
/**
1476+
* pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend.
1477+
* @dev: PCI device being suspended.
1478+
*
1479+
* Prepare @dev to generate wake-up events at run time and put it into a low
1480+
* power state.
1481+
*/
1482+
int pci_finish_runtime_suspend(struct pci_dev *dev)
1483+
{
1484+
pci_power_t target_state = pci_target_state(dev);
1485+
int error;
1486+
1487+
if (target_state == PCI_POWER_ERROR)
1488+
return -EIO;
1489+
1490+
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
1491+
1492+
error = pci_set_power_state(dev, target_state);
1493+
1494+
if (error)
1495+
__pci_enable_wake(dev, target_state, true, false);
1496+
1497+
return error;
1498+
}
1499+
14681500
/**
14691501
* pci_dev_run_wake - Check if device can generate run-time wake-up events.
14701502
* @dev: Device to check.
@@ -2978,7 +3010,6 @@ EXPORT_SYMBOL(pci_save_state);
29783010
EXPORT_SYMBOL(pci_restore_state);
29793011
EXPORT_SYMBOL(pci_pme_capable);
29803012
EXPORT_SYMBOL(pci_pme_active);
2981-
EXPORT_SYMBOL(pci_enable_wake);
29823013
EXPORT_SYMBOL(pci_wake_from_d3);
29833014
EXPORT_SYMBOL(pci_target_state);
29843015
EXPORT_SYMBOL(pci_prepare_to_sleep);

drivers/pci/pci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
5555
extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
5656
extern void pci_disable_enabled_device(struct pci_dev *dev);
5757
extern bool pci_check_pme_status(struct pci_dev *dev);
58+
extern int pci_finish_runtime_suspend(struct pci_dev *dev);
5859
extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
5960
extern void pci_pme_wakeup_bus(struct pci_bus *bus);
6061
extern void pci_pm_init(struct pci_dev *dev);

include/linux/pci.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,20 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state);
777777
pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
778778
bool pci_pme_capable(struct pci_dev *dev, pci_power_t state);
779779
void pci_pme_active(struct pci_dev *dev, bool enable);
780-
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable);
780+
int __pci_enable_wake(struct pci_dev *dev, pci_power_t state,
781+
bool runtime, bool enable);
781782
int pci_wake_from_d3(struct pci_dev *dev, bool enable);
782783
pci_power_t pci_target_state(struct pci_dev *dev);
783784
int pci_prepare_to_sleep(struct pci_dev *dev);
784785
int pci_back_from_sleep(struct pci_dev *dev);
785786
bool pci_dev_run_wake(struct pci_dev *dev);
786787

788+
static inline int pci_enable_wake(struct pci_dev *dev, pci_power_t state,
789+
bool enable)
790+
{
791+
return __pci_enable_wake(dev, state, false, enable);
792+
}
793+
787794
/* For use by arch with custom probe code */
788795
void set_pcie_port_type(struct pci_dev *pdev);
789796
void set_pcie_hotplug_bridge(struct pci_dev *pdev);

kernel/power/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,8 @@ config PM_RUNTIME
222222
and the bus type drivers of the buses the devices are on are
223223
responsible for the actual handling of the autosuspend requests and
224224
wake-up events.
225+
226+
config PM_OPS
227+
bool
228+
depends on PM_SLEEP || PM_RUNTIME
229+
default y

0 commit comments

Comments
 (0)