Staging: hv: util: Adjust guest time in a process context
authorK. Y. Srinivasan <kys@microsoft.com>
Sat, 27 Aug 2011 18:31:31 +0000 (11:31 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 29 Aug 2011 18:05:30 +0000 (11:05 -0700)
The current code was adjusting guest time in interrupt context; do this
in process context since we may have to initiate cross-processor
interrupts as part of setting time.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/hv/hv_util.c

index 876d44a8a8616aa82fd4eb9325de6979b85c6621..e29a2a23eda548653a867c921f17ab051dc7f097 100644 (file)
@@ -106,6 +106,24 @@ static inline void do_adj_guesttime(u64 hosttime)
        do_settimeofday(&host_ts);
 }
 
+/*
+ * Set the host time in a process context.
+ */
+
+struct adj_time_work {
+       struct work_struct work;
+       u64     host_time;
+};
+
+static void hv_set_host_time(struct work_struct *work)
+{
+       struct adj_time_work    *wrk;
+
+       wrk = container_of(work, struct adj_time_work, work);
+       do_adj_guesttime(wrk->host_time);
+       kfree(wrk);
+}
+
 /*
  * Synchronize time with host after reboot, restore, etc.
  *
@@ -119,17 +137,26 @@ static inline void do_adj_guesttime(u64 hosttime)
  */
 static inline void adj_guesttime(u64 hosttime, u8 flags)
 {
+       struct adj_time_work    *wrk;
        static s32 scnt = 50;
 
+       wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC);
+       if (wrk == NULL)
+               return;
+
+       wrk->host_time = hosttime;
        if ((flags & ICTIMESYNCFLAG_SYNC) != 0) {
-               do_adj_guesttime(hosttime);
+               INIT_WORK(&wrk->work, hv_set_host_time);
+               schedule_work(&wrk->work);
                return;
        }
 
        if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) {
                scnt--;
-               do_adj_guesttime(hosttime);
-       }
+               INIT_WORK(&wrk->work, hv_set_host_time);
+               schedule_work(&wrk->work);
+       } else
+               kfree(wrk);
 }
 
 /*