diff options
Diffstat (limited to 'drivers/base/power/runtime.c')
| -rw-r--r-- | drivers/base/power/runtime.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 70624695b6d5..ccd296dbb95c 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c | |||
| @@ -95,7 +95,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status) | |||
| 95 | static void pm_runtime_deactivate_timer(struct device *dev) | 95 | static void pm_runtime_deactivate_timer(struct device *dev) |
| 96 | { | 96 | { |
| 97 | if (dev->power.timer_expires > 0) { | 97 | if (dev->power.timer_expires > 0) { |
| 98 | hrtimer_cancel(&dev->power.suspend_timer); | 98 | hrtimer_try_to_cancel(&dev->power.suspend_timer); |
| 99 | dev->power.timer_expires = 0; | 99 | dev->power.timer_expires = 0; |
| 100 | } | 100 | } |
| 101 | } | 101 | } |
| @@ -121,7 +121,7 @@ static void pm_runtime_cancel_pending(struct device *dev) | |||
| 121 | * Compute the autosuspend-delay expiration time based on the device's | 121 | * Compute the autosuspend-delay expiration time based on the device's |
| 122 | * power.last_busy time. If the delay has already expired or is disabled | 122 | * power.last_busy time. If the delay has already expired or is disabled |
| 123 | * (negative) or the power.use_autosuspend flag isn't set, return 0. | 123 | * (negative) or the power.use_autosuspend flag isn't set, return 0. |
| 124 | * Otherwise return the expiration time in jiffies (adjusted to be nonzero). | 124 | * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero). |
| 125 | * | 125 | * |
| 126 | * This function may be called either with or without dev->power.lock held. | 126 | * This function may be called either with or without dev->power.lock held. |
| 127 | * Either way it can be racy, since power.last_busy may be updated at any time. | 127 | * Either way it can be racy, since power.last_busy may be updated at any time. |
| @@ -130,7 +130,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev) | |||
| 130 | { | 130 | { |
| 131 | int autosuspend_delay; | 131 | int autosuspend_delay; |
| 132 | u64 last_busy, expires = 0; | 132 | u64 last_busy, expires = 0; |
| 133 | u64 now = ktime_to_ns(ktime_get()); | 133 | u64 now = ktime_get_mono_fast_ns(); |
| 134 | 134 | ||
| 135 | if (!dev->power.use_autosuspend) | 135 | if (!dev->power.use_autosuspend) |
| 136 | goto out; | 136 | goto out; |
| @@ -141,7 +141,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev) | |||
| 141 | 141 | ||
| 142 | last_busy = READ_ONCE(dev->power.last_busy); | 142 | last_busy = READ_ONCE(dev->power.last_busy); |
| 143 | 143 | ||
| 144 | expires = last_busy + autosuspend_delay * NSEC_PER_MSEC; | 144 | expires = last_busy + (u64)autosuspend_delay * NSEC_PER_MSEC; |
| 145 | if (expires <= now) | 145 | if (expires <= now) |
| 146 | expires = 0; /* Already expired. */ | 146 | expires = 0; /* Already expired. */ |
| 147 | 147 | ||
| @@ -525,7 +525,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) | |||
| 525 | * We add a slack of 25% to gather wakeups | 525 | * We add a slack of 25% to gather wakeups |
| 526 | * without sacrificing the granularity. | 526 | * without sacrificing the granularity. |
| 527 | */ | 527 | */ |
| 528 | u64 slack = READ_ONCE(dev->power.autosuspend_delay) * | 528 | u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) * |
| 529 | (NSEC_PER_MSEC >> 2); | 529 | (NSEC_PER_MSEC >> 2); |
| 530 | 530 | ||
| 531 | dev->power.timer_expires = expires; | 531 | dev->power.timer_expires = expires; |
| @@ -905,8 +905,11 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer) | |||
| 905 | spin_lock_irqsave(&dev->power.lock, flags); | 905 | spin_lock_irqsave(&dev->power.lock, flags); |
| 906 | 906 | ||
| 907 | expires = dev->power.timer_expires; | 907 | expires = dev->power.timer_expires; |
| 908 | /* If 'expire' is after 'jiffies' we've been called too early. */ | 908 | /* |
| 909 | if (expires > 0 && expires < ktime_to_ns(ktime_get())) { | 909 | * If 'expires' is after the current time, we've been called |
| 910 | * too early. | ||
| 911 | */ | ||
| 912 | if (expires > 0 && expires < ktime_get_mono_fast_ns()) { | ||
| 910 | dev->power.timer_expires = 0; | 913 | dev->power.timer_expires = 0; |
| 911 | rpm_suspend(dev, dev->power.timer_autosuspends ? | 914 | rpm_suspend(dev, dev->power.timer_autosuspends ? |
| 912 | (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC); | 915 | (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC); |
| @@ -925,7 +928,7 @@ static enum hrtimer_restart pm_suspend_timer_fn(struct hrtimer *timer) | |||
| 925 | int pm_schedule_suspend(struct device *dev, unsigned int delay) | 928 | int pm_schedule_suspend(struct device *dev, unsigned int delay) |
| 926 | { | 929 | { |
| 927 | unsigned long flags; | 930 | unsigned long flags; |
| 928 | ktime_t expires; | 931 | u64 expires; |
| 929 | int retval; | 932 | int retval; |
| 930 | 933 | ||
| 931 | spin_lock_irqsave(&dev->power.lock, flags); | 934 | spin_lock_irqsave(&dev->power.lock, flags); |
| @@ -942,8 +945,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay) | |||
| 942 | /* Other scheduled or pending requests need to be canceled. */ | 945 | /* Other scheduled or pending requests need to be canceled. */ |
| 943 | pm_runtime_cancel_pending(dev); | 946 | pm_runtime_cancel_pending(dev); |
| 944 | 947 | ||
| 945 | expires = ktime_add(ktime_get(), ms_to_ktime(delay)); | 948 | expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC; |
| 946 | dev->power.timer_expires = ktime_to_ns(expires); | 949 | dev->power.timer_expires = expires; |
| 947 | dev->power.timer_autosuspends = 0; | 950 | dev->power.timer_autosuspends = 0; |
| 948 | hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS); | 951 | hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS); |
| 949 | 952 | ||
