int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
{
	int ret;

	ret = stop_machine_create();
	if (ret)
		return ret;
	/* No CPUs can come up or down during this. */
	get_online_cpus();
	ret = __stop_machine(fn, data, cpus);
	put_online_cpus();
	stop_machine_destroy();
	return ret;
}
Exemplo n.º 2
0
static void do_suspend(void)
{
    int err;
    int cancelled = 1;

    shutting_down = SHUTDOWN_SUSPEND;

    err = stop_machine_create();
    if (err) {
        printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err);
        goto out;
    }

#ifdef CONFIG_PREEMPT
    /* If the kernel is preemptible, we need to freeze all the processes
       to prevent them from being in the middle of a pagetable update
       during suspend. */
    err = freeze_processes();
    if (err) {
        printk(KERN_ERR "xen suspend: freeze failed %d\n", err);
        goto out_destroy_sm;
    }
#endif

    err = dpm_suspend_start(PMSG_SUSPEND);
    if (err) {
        printk(KERN_ERR "xen suspend: dpm_suspend_start %d\n", err);
        goto out_thaw;
    }

    printk(KERN_DEBUG "suspending xenstore...\n");
    xs_suspend();

    err = dpm_suspend_noirq(PMSG_SUSPEND);
    if (err) {
        printk(KERN_ERR "dpm_suspend_noirq failed: %d\n", err);
        goto out_resume;
    }

    err = stop_machine(xen_suspend, &cancelled, cpumask_of(0));

    dpm_resume_noirq(PMSG_RESUME);

    if (err) {
        printk(KERN_ERR "failed to start xen_suspend: %d\n", err);
        cancelled = 1;
    }

out_resume:
    if (!cancelled) {
        xen_arch_resume();
        xs_resume();
    } else
        xs_suspend_cancel();

    dpm_resume_end(PMSG_RESUME);

    /* Make sure timer events get retriggered on all CPUs */
    clock_was_set();

out_thaw:
#ifdef CONFIG_PREEMPT
    thaw_processes();

out_destroy_sm:
#endif
    stop_machine_destroy();

out:
    shutting_down = SHUTDOWN_INVALID;
}