]> xenbits.xensource.com Git - legacy/linux-2.6.18-xen.git/commitdiff
Do not call clock_was_set() from interrupt context.
authorIan Campbell <ian.campbell@xensource.com>
Mon, 2 Jul 2007 16:19:24 +0000 (17:19 +0100)
committerIan Campbell <ian.campbell@xensource.com>
Mon, 2 Jul 2007 16:19:24 +0000 (17:19 +0100)
Currently clock_was_set() is a nop but on newer kernels it is not and
cannot be called from interrupt context. Prepare for that by deferring
to a workqueue. Since a timer interrupt can occur before
init_workqueue() is called we need to protect against the possibility
that keventd hasn't started yet.

(drop unused variable max_ntp_tick).

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
arch/i386/kernel/time-xen.c

index 750148353d7d6bd9ee612a77039d2fa2ef062adb..940d09c92073442c6513764d74977b4c4aa0fc0c 100644 (file)
@@ -130,6 +130,12 @@ static DEFINE_PER_CPU(struct vcpu_runstate_info, runstate);
 /* Must be signed, as it's compared with s64 quantities which can be -ve. */
 #define NS_PER_TICK (1000000000LL/HZ)
 
+static void __clock_was_set(void *unused)
+{
+       clock_was_set();
+}
+static DECLARE_WORK(clock_was_set_work, __clock_was_set, NULL);
+
 static inline void __normalize_time(time_t *sec, s64 *nsec)
 {
        while (*nsec >= NSEC_PER_SEC) {
@@ -365,7 +371,6 @@ void do_gettimeofday(struct timeval *tv)
 {
        unsigned long seq;
        unsigned long usec, sec;
-       unsigned long max_ntp_tick;
        unsigned long flags;
        s64 nsec;
        unsigned int cpu;
@@ -677,7 +682,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
        if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) {
                update_wallclock();
-               clock_was_set();
+               if (keventd_up())
+                       schedule_work(&clock_was_set_work);
        }
 
        write_sequnlock(&xtime_lock);