Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/x86/xen/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ static void __init xen_init_time_common(void)
paravirt_set_sched_clock(xen_sched_clock);

x86_platform.calibrate_tsc = xen_tsc_khz;
x86_platform.calibrate_cpu = xen_tsc_khz;
x86_platform.get_wallclock = xen_get_wallclock;
}

Expand Down
30 changes: 24 additions & 6 deletions drivers/xen/xenbus/xenbus_probe_frontend.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,17 @@ static int xenbus_uevent_frontend(const struct device *_dev,
}


/* Condition for wait_for_devices(): bumped on every backend state change. */
static atomic_t frontend_wait_seq = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(frontend_wait_wq);

static void backend_changed(struct xenbus_watch *watch,
const char *path, const char *token)
{
xenbus_otherend_changed(watch, path, token, 1);

atomic_inc(&frontend_wait_seq);
wake_up(&frontend_wait_wq);
}

static void xenbus_frontend_delayed_resume(struct work_struct *w)
Expand Down Expand Up @@ -265,7 +272,7 @@ static int print_device_status(struct device *dev, void *data)
static int ready_to_wait_for_devices;

static bool wait_loop(unsigned long start, unsigned int max_delay,
unsigned int *seconds_waited)
unsigned int *seconds_waited, unsigned int seq)
{
if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
if (!*seconds_waited)
Expand All @@ -278,7 +285,8 @@ static bool wait_loop(unsigned long start, unsigned int max_delay,
}
}

schedule_timeout_interruptible(HZ/10);
wait_event_interruptible_timeout(frontend_wait_wq,
atomic_read(&frontend_wait_seq) != seq, HZ/10);

return false;
}
Expand All @@ -301,18 +309,28 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
unsigned long start = jiffies;
struct device_driver *drv = xendrv ? &xendrv->driver : NULL;
unsigned int seconds_waited = 0;
unsigned int seq;

if (!ready_to_wait_for_devices || !xen_domain())
return;

while (exists_non_essential_connecting_device(drv))
if (wait_loop(start, 30, &seconds_waited))
/* Sample the sequence before checking, so a change in between wakes us. */
for (;;) {
seq = atomic_read(&frontend_wait_seq);
if (!exists_non_essential_connecting_device(drv))
break;
if (wait_loop(start, 30, &seconds_waited, seq))
break;
}

/* Skips PVKB and PVFB check.*/
while (exists_essential_connecting_device(drv))
if (wait_loop(start, 270, &seconds_waited))
for (;;) {
seq = atomic_read(&frontend_wait_seq);
if (!exists_essential_connecting_device(drv))
break;
if (wait_loop(start, 270, &seconds_waited, seq))
break;
}

if (seconds_waited)
printk("\n");
Expand Down