|
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(rtas);
|
|
|
|
|
|
struct rtas_suspend_me_data {
|
|
struct rtas_suspend_me_data {
|
|
atomic_t working; /* number of cpus accessing this struct */
|
|
atomic_t working; /* number of cpus accessing this struct */
|
|
|
|
+ atomic_t done;
|
|
int token; /* ibm,suspend-me */
|
|
int token; /* ibm,suspend-me */
|
|
int error;
|
|
int error;
|
|
struct completion *complete; /* wait on this until working == 0 */
|
|
struct completion *complete; /* wait on this until working == 0 */
|
|
@@ -689,7 +690,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
|
|
#ifdef CONFIG_PPC_PSERIES
|
|
#ifdef CONFIG_PPC_PSERIES
|
|
static void rtas_percpu_suspend_me(void *info)
|
|
static void rtas_percpu_suspend_me(void *info)
|
|
{
|
|
{
|
|
- long rc;
|
|
|
|
|
|
+ long rc = H_SUCCESS;
|
|
unsigned long msr_save;
|
|
unsigned long msr_save;
|
|
int cpu;
|
|
int cpu;
|
|
struct rtas_suspend_me_data *data =
|
|
struct rtas_suspend_me_data *data =
|
|
@@ -701,7 +702,8 @@ static void rtas_percpu_suspend_me(void *info)
|
|
msr_save = mfmsr();
|
|
msr_save = mfmsr();
|
|
mtmsr(msr_save & ~(MSR_EE));
|
|
mtmsr(msr_save & ~(MSR_EE));
|
|
|
|
|
|
- rc = plpar_hcall_norets(H_JOIN);
|
|
|
|
|
|
+ while (rc == H_SUCCESS && !atomic_read(&data->done))
|
|
|
|
+ rc = plpar_hcall_norets(H_JOIN);
|
|
|
|
|
|
mtmsr(msr_save);
|
|
mtmsr(msr_save);
|
|
|
|
|
|
@@ -724,6 +726,9 @@ static void rtas_percpu_suspend_me(void *info)
|
|
smp_processor_id(), rc);
|
|
smp_processor_id(), rc);
|
|
data->error = rc;
|
|
data->error = rc;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ atomic_set(&data->done, 1);
|
|
|
|
+
|
|
/* This cpu did the suspend or got an error; in either case,
|
|
/* This cpu did the suspend or got an error; in either case,
|
|
* we need to prod all other other cpus out of join state.
|
|
* we need to prod all other other cpus out of join state.
|
|
* Extra prods are harmless.
|
|
* Extra prods are harmless.
|
|
@@ -766,6 +771,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
|
|
}
|
|
}
|
|
|
|
|
|
atomic_set(&data.working, 0);
|
|
atomic_set(&data.working, 0);
|
|
|
|
+ atomic_set(&data.done, 0);
|
|
data.token = rtas_token("ibm,suspend-me");
|
|
data.token = rtas_token("ibm,suspend-me");
|
|
data.error = 0;
|
|
data.error = 0;
|
|
data.complete = &done;
|
|
data.complete = &done;
|