]> err.no Git - linux-2.6/blobdiff - arch/i386/xen/time.c
Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[linux-2.6] / arch / i386 / xen / time.c
index 2aab44bec2a576b35f9c6cf0c6346e985a3a0dea..dfd6db69ead5072dd5a7430ad4750285d44d7031 100644 (file)
@@ -88,7 +88,7 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
        u64 state_time;
        struct vcpu_runstate_info *state;
 
-       preempt_disable();
+       BUG_ON(preemptible());
 
        state = &__get_cpu_var(runstate);
 
@@ -103,8 +103,6 @@ static void get_runstate_snapshot(struct vcpu_runstate_info *res)
                *res = *state;
                barrier();
        } while (get64(&state->state_entry_time) != state_time);
-
-       preempt_enable();
 }
 
 static void setup_runstate_info(int cpu)
@@ -179,9 +177,19 @@ static void do_stolen_accounting(void)
 unsigned long long xen_sched_clock(void)
 {
        struct vcpu_runstate_info state;
-       cycle_t now = xen_clocksource_read();
+       cycle_t now;
+       u64 ret;
        s64 offset;
 
+       /*
+        * Ideally sched_clock should be called on a per-cpu basis
+        * anyway, so preempt should already be disabled, but that's
+        * not current practice at the moment.
+        */
+       preempt_disable();
+
+       now = xen_clocksource_read();
+
        get_runstate_snapshot(&state);
 
        WARN_ON(state.state != RUNSTATE_running);
@@ -190,9 +198,13 @@ unsigned long long xen_sched_clock(void)
        if (offset < 0)
                offset = 0;
 
-       return state.time[RUNSTATE_blocked] +
+       ret = state.time[RUNSTATE_blocked] +
                state.time[RUNSTATE_running] +
                offset;
+
+       preempt_enable();
+
+       return ret;
 }
 
 
@@ -400,6 +412,7 @@ static void xen_timerop_set_mode(enum clock_event_mode mode,
                break;
 
        case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_RESUME:
                break;
 
        case CLOCK_EVT_MODE_UNUSED:
@@ -462,6 +475,8 @@ static void xen_vcpuop_set_mode(enum clock_event_mode mode,
                    HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
                        BUG();
                break;
+       case CLOCK_EVT_MODE_RESUME:
+               break;
        }
 }
 
@@ -519,7 +534,7 @@ static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
        return ret;
 }
 
-static void xen_setup_timer(int cpu)
+void xen_setup_timer(int cpu)
 {
        const char *name;
        struct clock_event_device *evt;
@@ -535,16 +550,20 @@ static void xen_setup_timer(int cpu)
                                      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
                                      name, NULL);
 
-       evt = &get_cpu_var(xen_clock_events);
+       evt = &per_cpu(xen_clock_events, cpu);
        memcpy(evt, xen_clockevent, sizeof(*evt));
 
        evt->cpumask = cpumask_of_cpu(cpu);
        evt->irq = irq;
-       clockevents_register_device(evt);
 
        setup_runstate_info(cpu);
+}
+
+void xen_setup_cpu_clockevents(void)
+{
+       BUG_ON(preemptible());
 
-       put_cpu_var(xen_clock_events);
+       clockevents_register_device(&__get_cpu_var(xen_clock_events));
 }
 
 __init void xen_time_init(void)
@@ -570,4 +589,5 @@ __init void xen_time_init(void)
        tsc_disable = 0;
 
        xen_setup_timer(cpu);
+       xen_setup_cpu_clockevents();
 }