x86: Re-initialise HPET on resume from S3
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 18 Nov 2008 15:55:14 +0000 (15:55 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 18 Nov 2008 15:55:14 +0000 (15:55 +0000)
Signed-off-by: Guanqun Lu <guanqun.lu@intel.com>
Signed-off-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hpet.c
xen/arch/x86/time.c

index 83ab2f1887276b4f7fe542387de7e65f1adae544..5c2bc02885bdc18313b5e4ee87353aed6ea6f2eb 100644 (file)
@@ -264,15 +264,10 @@ int hpet_legacy_irq_tick(void)
 
 u64 hpet_setup(void)
 {
-    static u64 hpet_rate;
-    static int initialised;
+    u64 hpet_rate;
     u32 hpet_id, hpet_period, cfg;
     int i;
 
-    if ( initialised )
-        return hpet_rate;
-    initialised = 1;
-
     if ( hpet_address == 0 )
         return 0;
 
index f3cd4234fe5a03a8f27cf0aecca06dc832c7090a..acd8750b7d99dcb462738a58031d3ef0abe241c1 100644 (file)
@@ -60,6 +60,7 @@ struct platform_timesource {
     u64 frequency;
     u64 (*read_counter)(void);
     int (*init)(struct platform_timesource *);
+    void (*resume)(struct platform_timesource *);
     int counter_bits;
 };
 
@@ -396,12 +397,21 @@ static int init_hpet(struct platform_timesource *pts)
     return 1;
 }
 
+static void resume_hpet(struct platform_timesource *pts)
+{
+    u64 hpet_rate = hpet_setup();
+
+    BUG_ON(hpet_rate == 0);
+    pts->frequency = hpet_rate;
+}
+
 static struct platform_timesource plt_hpet =
 {
     .name = "HPET",
     .read_counter = read_hpet_count,
     .counter_bits = 32,
-    .init = init_hpet
+    .init = init_hpet,
+    .resume = resume_hpet
 };
 
 /************************************************************
@@ -566,6 +576,10 @@ static void platform_time_calibration(void)
 
 static void resume_platform_timer(void)
 {
+    /* Timer source can be reset when backing from S3 to S0 */
+    if ( plt_src.resume )
+        plt_src.resume(&plt_src);
+
     /* No change in platform_stime across suspend/resume. */
     platform_timer_stamp = plt_stamp64;
     plt_stamp = plt_src.read_counter();
@@ -1214,13 +1228,13 @@ int time_resume(void)
 {
     /*u64 tmp = */init_pit_and_calibrate_tsc();
 
-    disable_pit_irq();
-
     /* Disable this while calibrate_tsc_ap() also is skipped. */
     /*set_time_scale(&this_cpu(cpu_time).tsc_scale, tmp);*/
 
     resume_platform_timer();
 
+    disable_pit_irq();
+
     init_percpu_time();
 
     do_settime(get_cmos_time() + cmos_utc_offset, 0, NOW());