Skip to content

Commit 442a5d0

Browse files
committed
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-sleep'
* pm-core: PM-runtime: Switch autosuspend over to using hrtimers * pm-qos: PM / QoS: Change to use DEFINE_SHOW_ATTRIBUTE macro * pm-domains: PM / Domains: remove define_genpd_open_function() and define_genpd_debugfs_fops() * pm-sleep: PM / sleep: convert to DEFINE_SHOW_ATTRIBUTE
5 parents 6f049e7 + 8234f67 + 96c6935 + d32dcc6 + 943a10f commit 442a5d0

File tree

6 files changed

+68
-107
lines changed

6 files changed

+68
-107
lines changed

drivers/base/power/domain.c

Lines changed: 24 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2749,7 +2749,7 @@ static int genpd_summary_one(struct seq_file *s,
27492749
return 0;
27502750
}
27512751

2752-
static int genpd_summary_show(struct seq_file *s, void *data)
2752+
static int summary_show(struct seq_file *s, void *data)
27532753
{
27542754
struct generic_pm_domain *genpd;
27552755
int ret = 0;
@@ -2772,7 +2772,7 @@ static int genpd_summary_show(struct seq_file *s, void *data)
27722772
return ret;
27732773
}
27742774

2775-
static int genpd_status_show(struct seq_file *s, void *data)
2775+
static int status_show(struct seq_file *s, void *data)
27762776
{
27772777
static const char * const status_lookup[] = {
27782778
[GPD_STATE_ACTIVE] = "on",
@@ -2799,7 +2799,7 @@ static int genpd_status_show(struct seq_file *s, void *data)
27992799
return ret;
28002800
}
28012801

2802-
static int genpd_sub_domains_show(struct seq_file *s, void *data)
2802+
static int sub_domains_show(struct seq_file *s, void *data)
28032803
{
28042804
struct generic_pm_domain *genpd = s->private;
28052805
struct gpd_link *link;
@@ -2816,7 +2816,7 @@ static int genpd_sub_domains_show(struct seq_file *s, void *data)
28162816
return ret;
28172817
}
28182818

2819-
static int genpd_idle_states_show(struct seq_file *s, void *data)
2819+
static int idle_states_show(struct seq_file *s, void *data)
28202820
{
28212821
struct generic_pm_domain *genpd = s->private;
28222822
unsigned int i;
@@ -2845,7 +2845,7 @@ static int genpd_idle_states_show(struct seq_file *s, void *data)
28452845
return ret;
28462846
}
28472847

2848-
static int genpd_active_time_show(struct seq_file *s, void *data)
2848+
static int active_time_show(struct seq_file *s, void *data)
28492849
{
28502850
struct generic_pm_domain *genpd = s->private;
28512851
ktime_t delta = 0;
@@ -2865,7 +2865,7 @@ static int genpd_active_time_show(struct seq_file *s, void *data)
28652865
return ret;
28662866
}
28672867

2868-
static int genpd_total_idle_time_show(struct seq_file *s, void *data)
2868+
static int total_idle_time_show(struct seq_file *s, void *data)
28692869
{
28702870
struct generic_pm_domain *genpd = s->private;
28712871
ktime_t delta = 0, total = 0;
@@ -2893,7 +2893,7 @@ static int genpd_total_idle_time_show(struct seq_file *s, void *data)
28932893
}
28942894

28952895

2896-
static int genpd_devices_show(struct seq_file *s, void *data)
2896+
static int devices_show(struct seq_file *s, void *data)
28972897
{
28982898
struct generic_pm_domain *genpd = s->private;
28992899
struct pm_domain_data *pm_data;
@@ -2919,7 +2919,7 @@ static int genpd_devices_show(struct seq_file *s, void *data)
29192919
return ret;
29202920
}
29212921

2922-
static int genpd_perf_state_show(struct seq_file *s, void *data)
2922+
static int perf_state_show(struct seq_file *s, void *data)
29232923
{
29242924
struct generic_pm_domain *genpd = s->private;
29252925

@@ -2932,37 +2932,14 @@ static int genpd_perf_state_show(struct seq_file *s, void *data)
29322932
return 0;
29332933
}
29342934

2935-
#define define_genpd_open_function(name) \
2936-
static int genpd_##name##_open(struct inode *inode, struct file *file) \
2937-
{ \
2938-
return single_open(file, genpd_##name##_show, inode->i_private); \
2939-
}
2940-
2941-
define_genpd_open_function(summary);
2942-
define_genpd_open_function(status);
2943-
define_genpd_open_function(sub_domains);
2944-
define_genpd_open_function(idle_states);
2945-
define_genpd_open_function(active_time);
2946-
define_genpd_open_function(total_idle_time);
2947-
define_genpd_open_function(devices);
2948-
define_genpd_open_function(perf_state);
2949-
2950-
#define define_genpd_debugfs_fops(name) \
2951-
static const struct file_operations genpd_##name##_fops = { \
2952-
.open = genpd_##name##_open, \
2953-
.read = seq_read, \
2954-
.llseek = seq_lseek, \
2955-
.release = single_release, \
2956-
}
2957-
2958-
define_genpd_debugfs_fops(summary);
2959-
define_genpd_debugfs_fops(status);
2960-
define_genpd_debugfs_fops(sub_domains);
2961-
define_genpd_debugfs_fops(idle_states);
2962-
define_genpd_debugfs_fops(active_time);
2963-
define_genpd_debugfs_fops(total_idle_time);
2964-
define_genpd_debugfs_fops(devices);
2965-
define_genpd_debugfs_fops(perf_state);
2935+
DEFINE_SHOW_ATTRIBUTE(summary);
2936+
DEFINE_SHOW_ATTRIBUTE(status);
2937+
DEFINE_SHOW_ATTRIBUTE(sub_domains);
2938+
DEFINE_SHOW_ATTRIBUTE(idle_states);
2939+
DEFINE_SHOW_ATTRIBUTE(active_time);
2940+
DEFINE_SHOW_ATTRIBUTE(total_idle_time);
2941+
DEFINE_SHOW_ATTRIBUTE(devices);
2942+
DEFINE_SHOW_ATTRIBUTE(perf_state);
29662943

29672944
static int __init genpd_debug_init(void)
29682945
{
@@ -2975,7 +2952,7 @@ static int __init genpd_debug_init(void)
29752952
return -ENOMEM;
29762953

29772954
d = debugfs_create_file("pm_genpd_summary", S_IRUGO,
2978-
genpd_debugfs_dir, NULL, &genpd_summary_fops);
2955+
genpd_debugfs_dir, NULL, &summary_fops);
29792956
if (!d)
29802957
return -ENOMEM;
29812958

@@ -2985,20 +2962,20 @@ static int __init genpd_debug_init(void)
29852962
return -ENOMEM;
29862963

29872964
debugfs_create_file("current_state", 0444,
2988-
d, genpd, &genpd_status_fops);
2965+
d, genpd, &status_fops);
29892966
debugfs_create_file("sub_domains", 0444,
2990-
d, genpd, &genpd_sub_domains_fops);
2967+
d, genpd, &sub_domains_fops);
29912968
debugfs_create_file("idle_states", 0444,
2992-
d, genpd, &genpd_idle_states_fops);
2969+
d, genpd, &idle_states_fops);
29932970
debugfs_create_file("active_time", 0444,
2994-
d, genpd, &genpd_active_time_fops);
2971+
d, genpd, &active_time_fops);
29952972
debugfs_create_file("total_idle_time", 0444,
2996-
d, genpd, &genpd_total_idle_time_fops);
2973+
d, genpd, &total_idle_time_fops);
29972974
debugfs_create_file("devices", 0444,
2998-
d, genpd, &genpd_devices_fops);
2975+
d, genpd, &devices_fops);
29992976
if (genpd->set_performance_state)
30002977
debugfs_create_file("perf_state", 0444,
3001-
d, genpd, &genpd_perf_state_fops);
2978+
d, genpd, &perf_state_fops);
30022979
}
30032980

30042981
return 0;

drivers/base/power/runtime.c

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
*/
99

1010
#include <linux/sched/mm.h>
11+
#include <linux/ktime.h>
12+
#include <linux/hrtimer.h>
1113
#include <linux/export.h>
1214
#include <linux/pm_runtime.h>
1315
#include <linux/pm_wakeirq.h>
@@ -93,7 +95,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status)
9395
static void pm_runtime_deactivate_timer(struct device *dev)
9496
{
9597
if (dev->power.timer_expires > 0) {
96-
del_timer(&dev->power.suspend_timer);
98+
hrtimer_cancel(&dev->power.suspend_timer);
9799
dev->power.timer_expires = 0;
98100
}
99101
}
@@ -124,12 +126,11 @@ static void pm_runtime_cancel_pending(struct device *dev)
124126
* This function may be called either with or without dev->power.lock held.
125127
* Either way it can be racy, since power.last_busy may be updated at any time.
126128
*/
127-
unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
129+
u64 pm_runtime_autosuspend_expiration(struct device *dev)
128130
{
129131
int autosuspend_delay;
130-
long elapsed;
131-
unsigned long last_busy;
132-
unsigned long expires = 0;
132+
u64 last_busy, expires = 0;
133+
u64 now = ktime_to_ns(ktime_get());
133134

134135
if (!dev->power.use_autosuspend)
135136
goto out;
@@ -139,19 +140,9 @@ unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
139140
goto out;
140141

141142
last_busy = READ_ONCE(dev->power.last_busy);
142-
elapsed = jiffies - last_busy;
143-
if (elapsed < 0)
144-
goto out; /* jiffies has wrapped around. */
145143

146-
/*
147-
* If the autosuspend_delay is >= 1 second, align the timer by rounding
148-
* up to the nearest second.
149-
*/
150-
expires = last_busy + msecs_to_jiffies(autosuspend_delay);
151-
if (autosuspend_delay >= 1000)
152-
expires = round_jiffies(expires);
153-
expires += !expires;
154-
if (elapsed >= expires - last_busy)
144+
expires = last_busy + autosuspend_delay * NSEC_PER_MSEC;
145+
if (expires <= now)
155146
expires = 0; /* Already expired. */
156147

157148
out:
@@ -515,7 +506,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
515506
/* If the autosuspend_delay time hasn't expired yet, reschedule. */
516507
if ((rpmflags & RPM_AUTO)
517508
&& dev->power.runtime_status != RPM_SUSPENDING) {
518-
unsigned long expires = pm_runtime_autosuspend_expiration(dev);
509+
u64 expires = pm_runtime_autosuspend_expiration(dev);
519510

520511
if (expires != 0) {
521512
/* Pending requests need to be canceled. */
@@ -528,10 +519,20 @@ static int rpm_suspend(struct device *dev, int rpmflags)
528519
* expire; pm_suspend_timer_fn() will take care of the
529520
* rest.
530521
*/
531-
if (!(dev->power.timer_expires && time_before_eq(
532-
dev->power.timer_expires, expires))) {
522+
if (!(dev->power.timer_expires &&
523+
dev->power.timer_expires <= expires)) {
524+
/*
525+
* We add a slack of 25% to gather wakeups
526+
* without sacrificing the granularity.
527+
*/
528+
u64 slack = READ_ONCE(dev->power.autosuspend_delay) *
529+
(NSEC_PER_MSEC >> 2);
530+
533531
dev->power.timer_expires = expires;
534-
mod_timer(&dev->power.suspend_timer, expires);
532+
hrtimer_start_range_ns(&dev->power.suspend_timer,
533+
ns_to_ktime(expires),
534+
slack,
535+
HRTIMER_MODE_ABS);
535536
}
536537
dev->power.timer_autosuspends = 1;
537538
goto out;
@@ -895,23 +896,25 @@ static void pm_runtime_work(struct work_struct *work)
895896
*
896897
* Check if the time is right and queue a suspend request.
897898
*/
898-
static void pm_suspend_timer_fn(struct timer_list *t)
899+
static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer)
899900
{
900-
struct device *dev = from_timer(dev, t, power.suspend_timer);
901+
struct device *dev = container_of(timer, struct device, power.suspend_timer);
901902
unsigned long flags;
902-
unsigned long expires;
903+
u64 expires;
903904

904905
spin_lock_irqsave(&dev->power.lock, flags);
905906

906907
expires = dev->power.timer_expires;
907908
/* If 'expire' is after 'jiffies' we've been called too early. */
908-
if (expires > 0 && !time_after(expires, jiffies)) {
909+
if (expires > 0 && expires < ktime_to_ns(ktime_get())) {
909910
dev->power.timer_expires = 0;
910911
rpm_suspend(dev, dev->power.timer_autosuspends ?
911912
(RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
912913
}
913914

914915
spin_unlock_irqrestore(&dev->power.lock, flags);
916+
917+
return HRTIMER_NORESTART;
915918
}
916919

917920
/**
@@ -922,6 +925,7 @@ static void pm_suspend_timer_fn(struct timer_list *t)
922925
int pm_schedule_suspend(struct device *dev, unsigned int delay)
923926
{
924927
unsigned long flags;
928+
ktime_t expires;
925929
int retval;
926930

927931
spin_lock_irqsave(&dev->power.lock, flags);
@@ -938,10 +942,10 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
938942
/* Other scheduled or pending requests need to be canceled. */
939943
pm_runtime_cancel_pending(dev);
940944

941-
dev->power.timer_expires = jiffies + msecs_to_jiffies(delay);
942-
dev->power.timer_expires += !dev->power.timer_expires;
945+
expires = ktime_add(ktime_get(), ms_to_ktime(delay));
946+
dev->power.timer_expires = ktime_to_ns(expires);
943947
dev->power.timer_autosuspends = 0;
944-
mod_timer(&dev->power.suspend_timer, dev->power.timer_expires);
948+
hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
945949

946950
out:
947951
spin_unlock_irqrestore(&dev->power.lock, flags);
@@ -1491,7 +1495,8 @@ void pm_runtime_init(struct device *dev)
14911495
INIT_WORK(&dev->power.work, pm_runtime_work);
14921496

14931497
dev->power.timer_expires = 0;
1494-
timer_setup(&dev->power.suspend_timer, pm_suspend_timer_fn, 0);
1498+
hrtimer_init(&dev->power.suspend_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
1499+
dev->power.suspend_timer.function = pm_suspend_timer_fn;
14951500

14961501
init_waitqueue_head(&dev->power.wait_queue);
14971502
}

include/linux/pm.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/spinlock.h>
2727
#include <linux/wait.h>
2828
#include <linux/timer.h>
29+
#include <linux/hrtimer.h>
2930
#include <linux/completion.h>
3031

3132
/*
@@ -608,7 +609,7 @@ struct dev_pm_info {
608609
unsigned int should_wakeup:1;
609610
#endif
610611
#ifdef CONFIG_PM
611-
struct timer_list suspend_timer;
612+
struct hrtimer suspend_timer;
612613
unsigned long timer_expires;
613614
struct work_struct work;
614615
wait_queue_head_t wait_queue;
@@ -631,7 +632,7 @@ struct dev_pm_info {
631632
enum rpm_status runtime_status;
632633
int runtime_error;
633634
int autosuspend_delay;
634-
unsigned long last_busy;
635+
u64 last_busy;
635636
unsigned long active_jiffies;
636637
unsigned long suspended_jiffies;
637638
unsigned long accounting_timestamp;

include/linux/pm_runtime.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ extern void pm_runtime_no_callbacks(struct device *dev);
5151
extern void pm_runtime_irq_safe(struct device *dev);
5252
extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
5353
extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
54-
extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
54+
extern u64 pm_runtime_autosuspend_expiration(struct device *dev);
5555
extern void pm_runtime_update_max_time_suspended(struct device *dev,
5656
s64 delta_ns);
5757
extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
@@ -105,7 +105,7 @@ static inline bool pm_runtime_callbacks_present(struct device *dev)
105105

106106
static inline void pm_runtime_mark_last_busy(struct device *dev)
107107
{
108-
WRITE_ONCE(dev->power.last_busy, jiffies);
108+
WRITE_ONCE(dev->power.last_busy, ktime_to_ns(ktime_get()));
109109
}
110110

111111
static inline bool pm_runtime_is_irq_safe(struct device *dev)
@@ -168,7 +168,7 @@ static inline void __pm_runtime_use_autosuspend(struct device *dev,
168168
bool use) {}
169169
static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
170170
int delay) {}
171-
static inline unsigned long pm_runtime_autosuspend_expiration(
171+
static inline u64 pm_runtime_autosuspend_expiration(
172172
struct device *dev) { return 0; }
173173
static inline void pm_runtime_set_memalloc_noio(struct device *dev,
174174
bool enable){}

kernel/power/main.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -318,23 +318,12 @@ static int suspend_stats_show(struct seq_file *s, void *unused)
318318

319319
return 0;
320320
}
321-
322-
static int suspend_stats_open(struct inode *inode, struct file *file)
323-
{
324-
return single_open(file, suspend_stats_show, NULL);
325-
}
326-
327-
static const struct file_operations suspend_stats_operations = {
328-
.open = suspend_stats_open,
329-
.read = seq_read,
330-
.llseek = seq_lseek,
331-
.release = single_release,
332-
};
321+
DEFINE_SHOW_ATTRIBUTE(suspend_stats);
333322

334323
static int __init pm_debugfs_init(void)
335324
{
336325
debugfs_create_file("suspend_stats", S_IFREG | S_IRUGO,
337-
NULL, NULL, &suspend_stats_operations);
326+
NULL, NULL, &suspend_stats_fops);
338327
return 0;
339328
}
340329

0 commit comments

Comments
 (0)