|
@@ -509,13 +509,14 @@ static inline int hrtimer_hres_active(void)
|
|
* next event
|
|
* next event
|
|
* Called with interrupts disabled and base->lock held
|
|
* Called with interrupts disabled and base->lock held
|
|
*/
|
|
*/
|
|
-static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
|
|
|
|
|
|
+static void
|
|
|
|
+hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
struct hrtimer_clock_base *base = cpu_base->clock_base;
|
|
struct hrtimer_clock_base *base = cpu_base->clock_base;
|
|
- ktime_t expires;
|
|
|
|
|
|
+ ktime_t expires, expires_next;
|
|
|
|
|
|
- cpu_base->expires_next.tv64 = KTIME_MAX;
|
|
|
|
|
|
+ expires_next.tv64 = KTIME_MAX;
|
|
|
|
|
|
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
|
|
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++, base++) {
|
|
struct hrtimer *timer;
|
|
struct hrtimer *timer;
|
|
@@ -531,10 +532,15 @@ static void hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base)
|
|
*/
|
|
*/
|
|
if (expires.tv64 < 0)
|
|
if (expires.tv64 < 0)
|
|
expires.tv64 = 0;
|
|
expires.tv64 = 0;
|
|
- if (expires.tv64 < cpu_base->expires_next.tv64)
|
|
|
|
- cpu_base->expires_next = expires;
|
|
|
|
|
|
+ if (expires.tv64 < expires_next.tv64)
|
|
|
|
+ expires_next = expires;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (skip_equal && expires_next.tv64 == cpu_base->expires_next.tv64)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ cpu_base->expires_next.tv64 = expires_next.tv64;
|
|
|
|
+
|
|
if (cpu_base->expires_next.tv64 != KTIME_MAX)
|
|
if (cpu_base->expires_next.tv64 != KTIME_MAX)
|
|
tick_program_event(cpu_base->expires_next, 1);
|
|
tick_program_event(cpu_base->expires_next, 1);
|
|
}
|
|
}
|
|
@@ -617,7 +623,7 @@ static void retrigger_next_event(void *arg)
|
|
base->clock_base[CLOCK_REALTIME].offset =
|
|
base->clock_base[CLOCK_REALTIME].offset =
|
|
timespec_to_ktime(realtime_offset);
|
|
timespec_to_ktime(realtime_offset);
|
|
|
|
|
|
- hrtimer_force_reprogram(base);
|
|
|
|
|
|
+ hrtimer_force_reprogram(base, 0);
|
|
spin_unlock(&base->lock);
|
|
spin_unlock(&base->lock);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -730,7 +736,8 @@ static int hrtimer_switch_to_hres(void)
|
|
static inline int hrtimer_hres_active(void) { return 0; }
|
|
static inline int hrtimer_hres_active(void) { return 0; }
|
|
static inline int hrtimer_is_hres_enabled(void) { return 0; }
|
|
static inline int hrtimer_is_hres_enabled(void) { return 0; }
|
|
static inline int hrtimer_switch_to_hres(void) { return 0; }
|
|
static inline int hrtimer_switch_to_hres(void) { return 0; }
|
|
-static inline void hrtimer_force_reprogram(struct hrtimer_cpu_base *base) { }
|
|
|
|
|
|
+static inline void
|
|
|
|
+hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
|
|
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
|
|
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
|
|
struct hrtimer_clock_base *base,
|
|
struct hrtimer_clock_base *base,
|
|
int wakeup)
|
|
int wakeup)
|
|
@@ -873,19 +880,29 @@ static void __remove_hrtimer(struct hrtimer *timer,
|
|
struct hrtimer_clock_base *base,
|
|
struct hrtimer_clock_base *base,
|
|
unsigned long newstate, int reprogram)
|
|
unsigned long newstate, int reprogram)
|
|
{
|
|
{
|
|
- if (timer->state & HRTIMER_STATE_ENQUEUED) {
|
|
|
|
- /*
|
|
|
|
- * Remove the timer from the rbtree and replace the
|
|
|
|
- * first entry pointer if necessary.
|
|
|
|
- */
|
|
|
|
- if (base->first == &timer->node) {
|
|
|
|
- base->first = rb_next(&timer->node);
|
|
|
|
- /* Reprogram the clock event device. if enabled */
|
|
|
|
- if (reprogram && hrtimer_hres_active())
|
|
|
|
- hrtimer_force_reprogram(base->cpu_base);
|
|
|
|
|
|
+ if (!(timer->state & HRTIMER_STATE_ENQUEUED))
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Remove the timer from the rbtree and replace the first
|
|
|
|
+ * entry pointer if necessary.
|
|
|
|
+ */
|
|
|
|
+ if (base->first == &timer->node) {
|
|
|
|
+ base->first = rb_next(&timer->node);
|
|
|
|
+#ifdef CONFIG_HIGH_RES_TIMERS
|
|
|
|
+ /* Reprogram the clock event device. if enabled */
|
|
|
|
+ if (reprogram && hrtimer_hres_active()) {
|
|
|
|
+ ktime_t expires;
|
|
|
|
+
|
|
|
|
+ expires = ktime_sub(hrtimer_get_expires(timer),
|
|
|
|
+ base->offset);
|
|
|
|
+ if (base->cpu_base->expires_next.tv64 == expires.tv64)
|
|
|
|
+ hrtimer_force_reprogram(base->cpu_base, 1);
|
|
}
|
|
}
|
|
- rb_erase(&timer->node, &base->active);
|
|
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
+ rb_erase(&timer->node, &base->active);
|
|
|
|
+out:
|
|
timer->state = newstate;
|
|
timer->state = newstate;
|
|
}
|
|
}
|
|
|
|
|