aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/power/qos.c24
-rw-r--r--drivers/base/power/runtime.c148
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/pm_qos.h3
-rw-r--r--include/linux/pm_runtime.h5
5 files changed, 154 insertions, 28 deletions
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c
index 86de6c50fc41..03f4bd069ca8 100644
--- a/drivers/base/power/qos.c
+++ b/drivers/base/power/qos.c
@@ -47,21 +47,29 @@ static DEFINE_MUTEX(dev_pm_qos_mtx);
47static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); 47static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
48 48
49/** 49/**
50 * dev_pm_qos_read_value - Get PM QoS constraint for a given device. 50 * __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
51 * @dev: Device to get the PM QoS constraint value for.
52 *
53 * This routine must be called with dev->power.lock held.
54 */
55s32 __dev_pm_qos_read_value(struct device *dev)
56{
57 struct pm_qos_constraints *c = dev->power.constraints;
58
59 return c ? pm_qos_read_value(c) : 0;
60}
61
62/**
63 * dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
51 * @dev: Device to get the PM QoS constraint value for. 64 * @dev: Device to get the PM QoS constraint value for.
52 */ 65 */
53s32 dev_pm_qos_read_value(struct device *dev) 66s32 dev_pm_qos_read_value(struct device *dev)
54{ 67{
55 struct pm_qos_constraints *c;
56 unsigned long flags; 68 unsigned long flags;
57 s32 ret = 0; 69 s32 ret;
58 70
59 spin_lock_irqsave(&dev->power.lock, flags); 71 spin_lock_irqsave(&dev->power.lock, flags);
60 72 ret = __dev_pm_qos_read_value(dev);
61 c = dev->power.constraints;
62 if (c)
63 ret = pm_qos_read_value(c);
64
65 spin_unlock_irqrestore(&dev->power.lock, flags); 73 spin_unlock_irqrestore(&dev->power.lock, flags);
66 74
67 return ret; 75 return ret;
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 8c78443bca8f..068f7ed1f009 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -279,6 +279,47 @@ static int rpm_callback(int (*cb)(struct device *), struct device *dev)
279 return retval != -EACCES ? retval : -EIO; 279 return retval != -EACCES ? retval : -EIO;
280} 280}
281 281
282struct rpm_qos_data {
283 ktime_t time_now;
284 s64 constraint_ns;
285};
286
287/**
288 * rpm_update_qos_constraint - Update a given PM QoS constraint data.
289 * @dev: Device whose timing data to use.
290 * @data: PM QoS constraint data to update.
291 *
292 * Use the suspend timing data of @dev to update PM QoS constraint data pointed
293 * to by @data.
294 */
295static int rpm_update_qos_constraint(struct device *dev, void *data)
296{
297 struct rpm_qos_data *qos = data;
298 unsigned long flags;
299 s64 delta_ns;
300 int ret = 0;
301
302 spin_lock_irqsave(&dev->power.lock, flags);
303
304 if (dev->power.max_time_suspended_ns < 0)
305 goto out;
306
307 delta_ns = dev->power.max_time_suspended_ns -
308 ktime_to_ns(ktime_sub(qos->time_now, dev->power.suspend_time));
309 if (delta_ns <= 0) {
310 ret = -EBUSY;
311 goto out;
312 }
313
314 if (qos->constraint_ns > delta_ns || qos->constraint_ns == 0)
315 qos->constraint_ns = delta_ns;
316
317 out:
318 spin_unlock_irqrestore(&dev->power.lock, flags);
319
320 return ret;
321}
322
282/** 323/**
283 * rpm_suspend - Carry out runtime suspend of given device. 324 * rpm_suspend - Carry out runtime suspend of given device.
284 * @dev: Device to suspend. 325 * @dev: Device to suspend.
@@ -305,6 +346,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
305{ 346{
306 int (*callback)(struct device *); 347 int (*callback)(struct device *);
307 struct device *parent = NULL; 348 struct device *parent = NULL;
349 struct rpm_qos_data qos;
308 int retval; 350 int retval;
309 351
310 trace_rpm_suspend(dev, rpmflags); 352 trace_rpm_suspend(dev, rpmflags);
@@ -400,8 +442,38 @@ static int rpm_suspend(struct device *dev, int rpmflags)
400 goto out; 442 goto out;
401 } 443 }
402 444
445 qos.constraint_ns = __dev_pm_qos_read_value(dev);
446 if (qos.constraint_ns < 0) {
447 /* Negative constraint means "never suspend". */
448 retval = -EPERM;
449 goto out;
450 }
451 qos.constraint_ns *= NSEC_PER_USEC;
452 qos.time_now = ktime_get();
453
403 __update_runtime_status(dev, RPM_SUSPENDING); 454 __update_runtime_status(dev, RPM_SUSPENDING);
404 455
456 if (!dev->power.ignore_children) {
457 if (dev->power.irq_safe)
458 spin_unlock(&dev->power.lock);
459 else
460 spin_unlock_irq(&dev->power.lock);
461
462 retval = device_for_each_child(dev, &qos,
463 rpm_update_qos_constraint);
464
465 if (dev->power.irq_safe)
466 spin_lock(&dev->power.lock);
467 else
468 spin_lock_irq(&dev->power.lock);
469
470 if (retval)
471 goto fail;
472 }
473
474 dev->power.suspend_time = qos.time_now;
475 dev->power.max_time_suspended_ns = qos.constraint_ns ? : -1;
476
405 if (dev->pm_domain) 477 if (dev->pm_domain)
406 callback = dev->pm_domain->ops.runtime_suspend; 478 callback = dev->pm_domain->ops.runtime_suspend;
407 else if (dev->type && dev->type->pm) 479 else if (dev->type && dev->type->pm)
@@ -414,27 +486,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
414 callback = NULL; 486 callback = NULL;
415 487
416 retval = rpm_callback(callback, dev); 488 retval = rpm_callback(callback, dev);
417 if (retval) { 489 if (retval)
418 __update_runtime_status(dev, RPM_ACTIVE); 490 goto fail;
419 dev->power.deferred_resume = false;
420 if (retval == -EAGAIN || retval == -EBUSY) {
421 dev->power.runtime_error = 0;
422 491
423 /*
424 * If the callback routine failed an autosuspend, and
425 * if the last_busy time has been updated so that there
426 * is a new autosuspend expiration time, automatically
427 * reschedule another autosuspend.
428 */
429 if ((rpmflags & RPM_AUTO) &&
430 pm_runtime_autosuspend_expiration(dev) != 0)
431 goto repeat;
432 } else {
433 pm_runtime_cancel_pending(dev);
434 }
435 wake_up_all(&dev->power.wait_queue);
436 goto out;
437 }
438 no_callback: 492 no_callback:
439 __update_runtime_status(dev, RPM_SUSPENDED); 493 __update_runtime_status(dev, RPM_SUSPENDED);
440 pm_runtime_deactivate_timer(dev); 494 pm_runtime_deactivate_timer(dev);
@@ -466,6 +520,29 @@ static int rpm_suspend(struct device *dev, int rpmflags)
466 trace_rpm_return_int(dev, _THIS_IP_, retval); 520 trace_rpm_return_int(dev, _THIS_IP_, retval);
467 521
468 return retval; 522 return retval;
523
524 fail:
525 __update_runtime_status(dev, RPM_ACTIVE);
526 dev->power.suspend_time = ktime_set(0, 0);
527 dev->power.max_time_suspended_ns = -1;
528 dev->power.deferred_resume = false;
529 if (retval == -EAGAIN || retval == -EBUSY) {
530 dev->power.runtime_error = 0;
531
532 /*
533 * If the callback routine failed an autosuspend, and
534 * if the last_busy time has been updated so that there
535 * is a new autosuspend expiration time, automatically
536 * reschedule another autosuspend.
537 */
538 if ((rpmflags & RPM_AUTO) &&
539 pm_runtime_autosuspend_expiration(dev) != 0)
540 goto repeat;
541 } else {
542 pm_runtime_cancel_pending(dev);
543 }
544 wake_up_all(&dev->power.wait_queue);
545 goto out;
469} 546}
470 547
471/** 548/**
@@ -620,6 +697,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
620 if (dev->power.no_callbacks) 697 if (dev->power.no_callbacks)
621 goto no_callback; /* Assume success. */ 698 goto no_callback; /* Assume success. */
622 699
700 dev->power.suspend_time = ktime_set(0, 0);
701 dev->power.max_time_suspended_ns = -1;
702
623 __update_runtime_status(dev, RPM_RESUMING); 703 __update_runtime_status(dev, RPM_RESUMING);
624 704
625 if (dev->pm_domain) 705 if (dev->pm_domain)
@@ -1279,6 +1359,9 @@ void pm_runtime_init(struct device *dev)
1279 setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn, 1359 setup_timer(&dev->power.suspend_timer, pm_suspend_timer_fn,
1280 (unsigned long)dev); 1360 (unsigned long)dev);
1281 1361
1362 dev->power.suspend_time = ktime_set(0, 0);
1363 dev->power.max_time_suspended_ns = -1;
1364
1282 init_waitqueue_head(&dev->power.wait_queue); 1365 init_waitqueue_head(&dev->power.wait_queue);
1283} 1366}
1284 1367
@@ -1296,3 +1379,28 @@ void pm_runtime_remove(struct device *dev)
1296 if (dev->power.irq_safe && dev->parent) 1379 if (dev->power.irq_safe && dev->parent)
1297 pm_runtime_put_sync(dev->parent); 1380 pm_runtime_put_sync(dev->parent);
1298} 1381}
1382
1383/**
1384 * pm_runtime_update_max_time_suspended - Update device's suspend time data.
1385 * @dev: Device to handle.
1386 * @delta_ns: Value to subtract from the device's max_time_suspended_ns field.
1387 *
1388 * Update the device's power.max_time_suspended_ns field by subtracting
1389 * @delta_ns from it. The resulting value of power.max_time_suspended_ns is
1390 * never negative.
1391 */
1392void pm_runtime_update_max_time_suspended(struct device *dev, s64 delta_ns)
1393{
1394 unsigned long flags;
1395
1396 spin_lock_irqsave(&dev->power.lock, flags);
1397
1398 if (delta_ns > 0 && dev->power.max_time_suspended_ns > 0) {
1399 if (dev->power.max_time_suspended_ns > delta_ns)
1400 dev->power.max_time_suspended_ns -= delta_ns;
1401 else
1402 dev->power.max_time_suspended_ns = 0;
1403 }
1404
1405 spin_unlock_irqrestore(&dev->power.lock, flags);
1406}
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 3f3ed83a9aa5..a7676efa6831 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -521,6 +521,8 @@ struct dev_pm_info {
521 unsigned long active_jiffies; 521 unsigned long active_jiffies;
522 unsigned long suspended_jiffies; 522 unsigned long suspended_jiffies;
523 unsigned long accounting_timestamp; 523 unsigned long accounting_timestamp;
524 ktime_t suspend_time;
525 s64 max_time_suspended_ns;
524#endif 526#endif
525 struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ 527 struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */
526 struct pm_qos_constraints *constraints; 528 struct pm_qos_constraints *constraints;
diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h
index 83b0ea302a80..775a3236343d 100644
--- a/include/linux/pm_qos.h
+++ b/include/linux/pm_qos.h
@@ -78,6 +78,7 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
78int pm_qos_request_active(struct pm_qos_request *req); 78int pm_qos_request_active(struct pm_qos_request *req);
79s32 pm_qos_read_value(struct pm_qos_constraints *c); 79s32 pm_qos_read_value(struct pm_qos_constraints *c);
80 80
81s32 __dev_pm_qos_read_value(struct device *dev);
81s32 dev_pm_qos_read_value(struct device *dev); 82s32 dev_pm_qos_read_value(struct device *dev);
82int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, 83int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
83 s32 value); 84 s32 value);
@@ -119,6 +120,8 @@ static inline int pm_qos_request_active(struct pm_qos_request *req)
119static inline s32 pm_qos_read_value(struct pm_qos_constraints *c) 120static inline s32 pm_qos_read_value(struct pm_qos_constraints *c)
120 { return 0; } 121 { return 0; }
121 122
123static inline s32 __dev_pm_qos_read_value(struct device *dev)
124 { return 0; }
122static inline s32 dev_pm_qos_read_value(struct device *dev) 125static inline s32 dev_pm_qos_read_value(struct device *dev)
123 { return 0; } 126 { return 0; }
124static inline int dev_pm_qos_add_request(struct device *dev, 127static inline int dev_pm_qos_add_request(struct device *dev,
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index d3085e72a0ee..609daae7a014 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -45,6 +45,8 @@ extern void pm_runtime_irq_safe(struct device *dev);
45extern void __pm_runtime_use_autosuspend(struct device *dev, bool use); 45extern void __pm_runtime_use_autosuspend(struct device *dev, bool use);
46extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay); 46extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
47extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev); 47extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
48extern void pm_runtime_update_max_time_suspended(struct device *dev,
49 s64 delta_ns);
48 50
49static inline bool pm_children_suspended(struct device *dev) 51static inline bool pm_children_suspended(struct device *dev)
50{ 52{
@@ -148,6 +150,9 @@ static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
148static inline unsigned long pm_runtime_autosuspend_expiration( 150static inline unsigned long pm_runtime_autosuspend_expiration(
149 struct device *dev) { return 0; } 151 struct device *dev) { return 0; }
150 152
153static inline void pm_runtime_update_max_time_suspended(struct device *dev,
154 s64 delta_ns) {}
155
151#endif /* !CONFIG_PM_RUNTIME */ 156#endif /* !CONFIG_PM_RUNTIME */
152 157
153static inline int pm_runtime_idle(struct device *dev) 158static inline int pm_runtime_idle(struct device *dev)