Skip to content

Commit e4719b5

Browse files
committed
Merge back PM core changes for v5.17.
2 parents 544e737 + 2cdbd92 commit e4719b5

File tree

8 files changed

+131
-75
lines changed

8 files changed

+131
-75
lines changed

Documentation/power/runtime_pm.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,10 @@ defined in include/linux/pm.h:
265265
RPM_SUSPENDED, which means that each device is initially regarded by the
266266
PM core as 'suspended', regardless of its real hardware status
267267

268+
`enum rpm_status last_status;`
269+
- the last runtime PM status of the device captured before disabling runtime
270+
PM for it (invalid initially and when disable_depth is 0)
271+
268272
`unsigned int runtime_auto;`
269273
- if set, indicates that the user space has allowed the device driver to
270274
power manage the device at run time via the /sys/devices/.../power/control
@@ -333,10 +337,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
333337

334338
`int pm_runtime_resume(struct device *dev);`
335339
- execute the subsystem-level resume callback for the device; returns 0 on
336-
success, 1 if the device's runtime PM status was already 'active' or
337-
error code on failure, where -EAGAIN means it may be safe to attempt to
338-
resume the device again in future, but 'power.runtime_error' should be
339-
checked additionally, and -EACCES means that 'power.disable_depth' is
340+
success, 1 if the device's runtime PM status is already 'active' (also if
341+
'power.disable_depth' is nonzero, but the status was 'active' when it was
342+
changing from 0 to 1) or error code on failure, where -EAGAIN means it may
343+
be safe to attempt to resume the device again in future, but
344+
'power.runtime_error' should be checked additionally, and -EACCES means
345+
that the callback could not be run, because 'power.disable_depth' was
340346
different from 0
341347

342348
`int pm_runtime_resume_and_get(struct device *dev);`

drivers/base/core.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,7 @@ static void device_link_release_fn(struct work_struct *work)
485485
/* Ensure that all references to the link object have been dropped. */
486486
device_link_synchronize_removal();
487487

488-
while (refcount_dec_not_one(&link->rpm_active))
489-
pm_runtime_put(link->supplier);
488+
pm_runtime_release_supplier(link, true);
490489

491490
put_device(link->consumer);
492491
put_device(link->supplier);

drivers/base/power/runtime.c

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -305,19 +305,40 @@ static int rpm_get_suppliers(struct device *dev)
305305
return 0;
306306
}
307307

308+
/**
309+
* pm_runtime_release_supplier - Drop references to device link's supplier.
310+
* @link: Target device link.
311+
* @check_idle: Whether or not to check if the supplier device is idle.
312+
*
313+
* Drop all runtime PM references associated with @link to its supplier device
314+
* and if @check_idle is set, check if that device is idle (and so it can be
315+
* suspended).
316+
*/
317+
void pm_runtime_release_supplier(struct device_link *link, bool check_idle)
318+
{
319+
struct device *supplier = link->supplier;
320+
321+
/*
322+
* The additional power.usage_count check is a safety net in case
323+
* the rpm_active refcount becomes saturated, in which case
324+
* refcount_dec_not_one() would return true forever, but it is not
325+
* strictly necessary.
326+
*/
327+
while (refcount_dec_not_one(&link->rpm_active) &&
328+
atomic_read(&supplier->power.usage_count) > 0)
329+
pm_runtime_put_noidle(supplier);
330+
331+
if (check_idle)
332+
pm_request_idle(supplier);
333+
}
334+
308335
static void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
309336
{
310337
struct device_link *link;
311338

312339
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
313-
device_links_read_lock_held()) {
314-
315-
while (refcount_dec_not_one(&link->rpm_active))
316-
pm_runtime_put_noidle(link->supplier);
317-
318-
if (try_to_suspend)
319-
pm_request_idle(link->supplier);
320-
}
340+
device_links_read_lock_held())
341+
pm_runtime_release_supplier(link, try_to_suspend);
321342
}
322343

323344
static void rpm_put_suppliers(struct device *dev)
@@ -742,13 +763,15 @@ static int rpm_resume(struct device *dev, int rpmflags)
742763
trace_rpm_resume_rcuidle(dev, rpmflags);
743764

744765
repeat:
745-
if (dev->power.runtime_error)
766+
if (dev->power.runtime_error) {
746767
retval = -EINVAL;
747-
else if (dev->power.disable_depth == 1 && dev->power.is_suspended
748-
&& dev->power.runtime_status == RPM_ACTIVE)
749-
retval = 1;
750-
else if (dev->power.disable_depth > 0)
751-
retval = -EACCES;
768+
} else if (dev->power.disable_depth > 0) {
769+
if (dev->power.runtime_status == RPM_ACTIVE &&
770+
dev->power.last_status == RPM_ACTIVE)
771+
retval = 1;
772+
else
773+
retval = -EACCES;
774+
}
752775
if (retval)
753776
goto out;
754777

@@ -1410,8 +1433,10 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
14101433
/* Update time accounting before disabling PM-runtime. */
14111434
update_pm_runtime_accounting(dev);
14121435

1413-
if (!dev->power.disable_depth++)
1436+
if (!dev->power.disable_depth++) {
14141437
__pm_runtime_barrier(dev);
1438+
dev->power.last_status = dev->power.runtime_status;
1439+
}
14151440

14161441
out:
14171442
spin_unlock_irq(&dev->power.lock);
@@ -1428,23 +1453,23 @@ void pm_runtime_enable(struct device *dev)
14281453

14291454
spin_lock_irqsave(&dev->power.lock, flags);
14301455

1431-
if (dev->power.disable_depth > 0) {
1432-
dev->power.disable_depth--;
1433-
1434-
/* About to enable runtime pm, set accounting_timestamp to now */
1435-
if (!dev->power.disable_depth)
1436-
dev->power.accounting_timestamp = ktime_get_mono_fast_ns();
1437-
} else {
1456+
if (!dev->power.disable_depth) {
14381457
dev_warn(dev, "Unbalanced %s!\n", __func__);
1458+
goto out;
14391459
}
14401460

1441-
WARN(!dev->power.disable_depth &&
1442-
dev->power.runtime_status == RPM_SUSPENDED &&
1443-
!dev->power.ignore_children &&
1444-
atomic_read(&dev->power.child_count) > 0,
1445-
"Enabling runtime PM for inactive device (%s) with active children\n",
1446-
dev_name(dev));
1461+
if (--dev->power.disable_depth > 0)
1462+
goto out;
1463+
1464+
dev->power.last_status = RPM_INVALID;
1465+
dev->power.accounting_timestamp = ktime_get_mono_fast_ns();
1466+
1467+
if (dev->power.runtime_status == RPM_SUSPENDED &&
1468+
!dev->power.ignore_children &&
1469+
atomic_read(&dev->power.child_count) > 0)
1470+
dev_warn(dev, "Enabling runtime PM for inactive device with active children\n");
14471471

1472+
out:
14481473
spin_unlock_irqrestore(&dev->power.lock, flags);
14491474
}
14501475
EXPORT_SYMBOL_GPL(pm_runtime_enable);
@@ -1640,6 +1665,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
16401665
void pm_runtime_init(struct device *dev)
16411666
{
16421667
dev->power.runtime_status = RPM_SUSPENDED;
1668+
dev->power.last_status = RPM_INVALID;
16431669
dev->power.idle_notification = false;
16441670

16451671
dev->power.disable_depth = 1;
@@ -1772,9 +1798,7 @@ void pm_runtime_drop_link(struct device_link *link)
17721798
return;
17731799

17741800
pm_runtime_drop_link_count(link->consumer);
1775-
1776-
while (refcount_dec_not_one(&link->rpm_active))
1777-
pm_runtime_put(link->supplier);
1801+
pm_runtime_release_supplier(link, true);
17781802
}
17791803

17801804
static bool pm_runtime_need_not_resume(struct device *dev)

drivers/mmc/host/jz4740_mmc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,17 +1103,17 @@ static int jz4740_mmc_remove(struct platform_device *pdev)
11031103
return 0;
11041104
}
11051105

1106-
static int __maybe_unused jz4740_mmc_suspend(struct device *dev)
1106+
static int jz4740_mmc_suspend(struct device *dev)
11071107
{
11081108
return pinctrl_pm_select_sleep_state(dev);
11091109
}
11101110

1111-
static int __maybe_unused jz4740_mmc_resume(struct device *dev)
1111+
static int jz4740_mmc_resume(struct device *dev)
11121112
{
11131113
return pinctrl_select_default_state(dev);
11141114
}
11151115

1116-
static SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
1116+
DEFINE_SIMPLE_DEV_PM_OPS(jz4740_mmc_pm_ops, jz4740_mmc_suspend,
11171117
jz4740_mmc_resume);
11181118

11191119
static struct platform_driver jz4740_mmc_driver = {
@@ -1123,7 +1123,7 @@ static struct platform_driver jz4740_mmc_driver = {
11231123
.name = "jz4740-mmc",
11241124
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
11251125
.of_match_table = of_match_ptr(jz4740_mmc_of_match),
1126-
.pm = pm_ptr(&jz4740_mmc_pm_ops),
1126+
.pm = pm_sleep_ptr(&jz4740_mmc_pm_ops),
11271127
},
11281128
};
11291129

drivers/mmc/host/mxcmmc.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,6 @@ static int mxcmci_remove(struct platform_device *pdev)
11831183
return 0;
11841184
}
11851185

1186-
#ifdef CONFIG_PM_SLEEP
11871186
static int mxcmci_suspend(struct device *dev)
11881187
{
11891188
struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -1210,17 +1209,16 @@ static int mxcmci_resume(struct device *dev)
12101209

12111210
return ret;
12121211
}
1213-
#endif
12141212

1215-
static SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
1213+
DEFINE_SIMPLE_DEV_PM_OPS(mxcmci_pm_ops, mxcmci_suspend, mxcmci_resume);
12161214

12171215
static struct platform_driver mxcmci_driver = {
12181216
.probe = mxcmci_probe,
12191217
.remove = mxcmci_remove,
12201218
.driver = {
12211219
.name = DRIVER_NAME,
12221220
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
1223-
.pm = &mxcmci_pm_ops,
1221+
.pm = pm_sleep_ptr(&mxcmci_pm_ops),
12241222
.of_match_table = mxcmci_of_match,
12251223
}
12261224
};

drivers/net/ethernet/realtek/r8169_main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5441,7 +5441,9 @@ static struct pci_driver rtl8169_pci_driver = {
54415441
.probe = rtl_init_one,
54425442
.remove = rtl_remove_one,
54435443
.shutdown = rtl_shutdown,
5444-
.driver.pm = pm_ptr(&rtl8169_pm_ops),
5444+
#ifdef CONFIG_PM
5445+
.driver.pm = &rtl8169_pm_ops,
5446+
#endif
54455447
};
54465448

54475449
module_pci_driver(rtl8169_pci_driver);

include/linux/pm.h

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -300,47 +300,59 @@ struct dev_pm_ops {
300300
int (*runtime_idle)(struct device *dev);
301301
};
302302

303+
#define SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
304+
.suspend = pm_sleep_ptr(suspend_fn), \
305+
.resume = pm_sleep_ptr(resume_fn), \
306+
.freeze = pm_sleep_ptr(suspend_fn), \
307+
.thaw = pm_sleep_ptr(resume_fn), \
308+
.poweroff = pm_sleep_ptr(suspend_fn), \
309+
.restore = pm_sleep_ptr(resume_fn),
310+
311+
#define LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
312+
.suspend_late = pm_sleep_ptr(suspend_fn), \
313+
.resume_early = pm_sleep_ptr(resume_fn), \
314+
.freeze_late = pm_sleep_ptr(suspend_fn), \
315+
.thaw_early = pm_sleep_ptr(resume_fn), \
316+
.poweroff_late = pm_sleep_ptr(suspend_fn), \
317+
.restore_early = pm_sleep_ptr(resume_fn),
318+
319+
#define NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
320+
.suspend_noirq = pm_sleep_ptr(suspend_fn), \
321+
.resume_noirq = pm_sleep_ptr(resume_fn), \
322+
.freeze_noirq = pm_sleep_ptr(suspend_fn), \
323+
.thaw_noirq = pm_sleep_ptr(resume_fn), \
324+
.poweroff_noirq = pm_sleep_ptr(suspend_fn), \
325+
.restore_noirq = pm_sleep_ptr(resume_fn),
326+
327+
#define RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
328+
.runtime_suspend = suspend_fn, \
329+
.runtime_resume = resume_fn, \
330+
.runtime_idle = idle_fn,
331+
303332
#ifdef CONFIG_PM_SLEEP
304333
#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
305-
.suspend = suspend_fn, \
306-
.resume = resume_fn, \
307-
.freeze = suspend_fn, \
308-
.thaw = resume_fn, \
309-
.poweroff = suspend_fn, \
310-
.restore = resume_fn,
334+
SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
311335
#else
312336
#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
313337
#endif
314338

315339
#ifdef CONFIG_PM_SLEEP
316340
#define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
317-
.suspend_late = suspend_fn, \
318-
.resume_early = resume_fn, \
319-
.freeze_late = suspend_fn, \
320-
.thaw_early = resume_fn, \
321-
.poweroff_late = suspend_fn, \
322-
.restore_early = resume_fn,
341+
LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
323342
#else
324343
#define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
325344
#endif
326345

327346
#ifdef CONFIG_PM_SLEEP
328347
#define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
329-
.suspend_noirq = suspend_fn, \
330-
.resume_noirq = resume_fn, \
331-
.freeze_noirq = suspend_fn, \
332-
.thaw_noirq = resume_fn, \
333-
.poweroff_noirq = suspend_fn, \
334-
.restore_noirq = resume_fn,
348+
NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
335349
#else
336350
#define SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
337351
#endif
338352

339353
#ifdef CONFIG_PM
340354
#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
341-
.runtime_suspend = suspend_fn, \
342-
.runtime_resume = resume_fn, \
343-
.runtime_idle = idle_fn,
355+
RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn)
344356
#else
345357
#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn)
346358
#endif
@@ -349,9 +361,9 @@ struct dev_pm_ops {
349361
* Use this if you want to use the same suspend and resume callbacks for suspend
350362
* to RAM and hibernation.
351363
*/
352-
#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
353-
const struct dev_pm_ops __maybe_unused name = { \
354-
SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
364+
#define DEFINE_SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
365+
static const struct dev_pm_ops name = { \
366+
SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
355367
}
356368

357369
/*
@@ -367,17 +379,27 @@ const struct dev_pm_ops __maybe_unused name = { \
367379
* .resume_early(), to the same routines as .runtime_suspend() and
368380
* .runtime_resume(), respectively (and analogously for hibernation).
369381
*/
382+
#define DEFINE_UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \
383+
static const struct dev_pm_ops name = { \
384+
SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
385+
RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
386+
}
387+
388+
/* Deprecated. Use DEFINE_SIMPLE_DEV_PM_OPS() instead. */
389+
#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
390+
const struct dev_pm_ops __maybe_unused name = { \
391+
SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
392+
}
393+
394+
/* Deprecated. Use DEFINE_UNIVERSAL_DEV_PM_OPS() instead. */
370395
#define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \
371396
const struct dev_pm_ops __maybe_unused name = { \
372397
SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
373398
SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
374399
}
375400

376-
#ifdef CONFIG_PM
377-
#define pm_ptr(_ptr) (_ptr)
378-
#else
379-
#define pm_ptr(_ptr) NULL
380-
#endif
401+
#define pm_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM), (_ptr))
402+
#define pm_sleep_ptr(_ptr) PTR_IF(IS_ENABLED(CONFIG_PM_SLEEP), (_ptr))
381403

382404
/*
383405
* PM_EVENT_ messages
@@ -499,6 +521,7 @@ const struct dev_pm_ops __maybe_unused name = { \
499521
*/
500522

501523
enum rpm_status {
524+
RPM_INVALID = -1,
502525
RPM_ACTIVE = 0,
503526
RPM_RESUMING,
504527
RPM_SUSPENDED,
@@ -612,6 +635,7 @@ struct dev_pm_info {
612635
unsigned int links_count;
613636
enum rpm_request request;
614637
enum rpm_status runtime_status;
638+
enum rpm_status last_status;
615639
int runtime_error;
616640
int autosuspend_delay;
617641
u64 last_busy;

0 commit comments

Comments
 (0)