|
@@ -721,17 +721,20 @@ static int hrtimer_switch_to_hres(void)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
+static void clock_was_set_work(struct work_struct *work)
|
|
|
+{
|
|
|
+ clock_was_set();
|
|
|
+}
|
|
|
+
|
|
|
+static DECLARE_WORK(hrtimer_work, clock_was_set_work);
|
|
|
+
|
|
|
/*
|
|
|
- * Called from timekeeping code to reprogramm the hrtimer interrupt
|
|
|
- * device. If called from the timer interrupt context we defer it to
|
|
|
- * softirq context.
|
|
|
+ * Called from timekeeping and resume code to reprogramm the hrtimer
|
|
|
+ * interrupt device on all cpus.
|
|
|
*/
|
|
|
void clock_was_set_delayed(void)
|
|
|
{
|
|
|
- struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
|
|
|
-
|
|
|
- cpu_base->clock_was_set = 1;
|
|
|
- __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
|
|
|
+ schedule_work(&hrtimer_work);
|
|
|
}
|
|
|
|
|
|
#else
|
|
@@ -775,12 +778,7 @@ void clock_was_set(void)
|
|
|
* During resume we might have to reprogram the high resolution timer
|
|
|
* interrupt on all online CPUs. However, all other CPUs will be
|
|
|
* stopped with IRQs interrupts disabled so the clock_was_set() call
|
|
|
- * must be deferred to the softirq.
|
|
|
- *
|
|
|
- * The one-shot timer has already been programmed to fire immediately
|
|
|
- * (see tick_resume_oneshot()) and this interrupt will trigger the
|
|
|
- * softirq to run early enough to correctly reprogram the timers on
|
|
|
- * all CPUs.
|
|
|
+ * must be deferred.
|
|
|
*/
|
|
|
void hrtimers_resume(void)
|
|
|
{
|
|
@@ -789,8 +787,10 @@ void hrtimers_resume(void)
|
|
|
WARN_ONCE(!irqs_disabled(),
|
|
|
KERN_INFO "hrtimers_resume() called with IRQs enabled!");
|
|
|
|
|
|
- cpu_base->clock_was_set = 1;
|
|
|
- __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
|
|
|
+ /* Retrigger on the local CPU */
|
|
|
+ retrigger_next_event(NULL);
|
|
|
+ /* And schedule a retrigger for all others */
|
|
|
+ clock_was_set_delayed();
|
|
|
}
|
|
|
|
|
|
static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
|
|
@@ -1441,13 +1441,6 @@ void hrtimer_peek_ahead_timers(void)
|
|
|
|
|
|
static void run_hrtimer_softirq(struct softirq_action *h)
|
|
|
{
|
|
|
- struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
|
|
|
-
|
|
|
- if (cpu_base->clock_was_set) {
|
|
|
- cpu_base->clock_was_set = 0;
|
|
|
- clock_was_set();
|
|
|
- }
|
|
|
-
|
|
|
hrtimer_peek_ahead_timers();
|
|
|
}
|
|
|
|