Ejemplo n.º 1
0
Archivo: rtas.c Proyecto: 710leo/LVS
static int __rtas_suspend_cpu(struct rtas_suspend_me_data *data, int wake_when_done)
{
	long rc = H_SUCCESS;
	unsigned long msr_save;
	int cpu;

	stop_topology_update();
	atomic_inc(&data->working);

	/* really need to ensure MSR.EE is off for H_JOIN */
	msr_save = mfmsr();
	mtmsr(msr_save & ~(MSR_EE));

	while (rc == H_SUCCESS && !data->done)
		rc = plpar_hcall_norets(H_JOIN);

	mtmsr(msr_save);

	if (rc == H_SUCCESS) {
		/* This cpu was prodded and the suspend is complete. */
		goto out;
	} else if (rc == H_CONTINUE) {
		/* All other cpus are in H_JOIN, this cpu does
		 * the suspend.
		 */
		return __rtas_suspend_last_cpu(data, wake_when_done);
	}

	printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
	       smp_processor_id(), rc);
	data->error = rc;

	if (wake_when_done) {
		smp_wmb();
		data->done = 1;
		/* Ensure data->done is seen on all CPUs that are about to wake up
		 as a result of the H_PROD below */
		mb();
		start_topology_update();

		/* This cpu did the suspend or got an error; in either case,
		 * we need to prod all other other cpus out of join state.
		 * Extra prods are harmless.
		 */
		for_each_online_cpu(cpu)
			plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
	}
out:
	if (atomic_dec_return(&data->working) == 0)
		complete(data->complete);
	return rc;
}
Ejemplo n.º 2
0
int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data)
{
	atomic_inc(&data->working);
	return __rtas_suspend_last_cpu(data, 0);
}