diff options
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index fdfe14c4bdef..ee4c7609b649 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(rtas); | |||
46 | 46 | ||
47 | struct rtas_suspend_me_data { | 47 | struct rtas_suspend_me_data { |
48 | atomic_t working; /* number of cpus accessing this struct */ | 48 | atomic_t working; /* number of cpus accessing this struct */ |
49 | atomic_t done; | ||
49 | int token; /* ibm,suspend-me */ | 50 | int token; /* ibm,suspend-me */ |
50 | int error; | 51 | int error; |
51 | struct completion *complete; /* wait on this until working == 0 */ | 52 | struct completion *complete; /* wait on this until working == 0 */ |
@@ -689,7 +690,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | |||
689 | #ifdef CONFIG_PPC_PSERIES | 690 | #ifdef CONFIG_PPC_PSERIES |
690 | static void rtas_percpu_suspend_me(void *info) | 691 | static void rtas_percpu_suspend_me(void *info) |
691 | { | 692 | { |
692 | long rc; | 693 | long rc = H_SUCCESS; |
693 | unsigned long msr_save; | 694 | unsigned long msr_save; |
694 | int cpu; | 695 | int cpu; |
695 | struct rtas_suspend_me_data *data = | 696 | struct rtas_suspend_me_data *data = |
@@ -701,7 +702,8 @@ static void rtas_percpu_suspend_me(void *info) | |||
701 | msr_save = mfmsr(); | 702 | msr_save = mfmsr(); |
702 | mtmsr(msr_save & ~(MSR_EE)); | 703 | mtmsr(msr_save & ~(MSR_EE)); |
703 | 704 | ||
704 | rc = plpar_hcall_norets(H_JOIN); | 705 | while (rc == H_SUCCESS && !atomic_read(&data->done)) |
706 | rc = plpar_hcall_norets(H_JOIN); | ||
705 | 707 | ||
706 | mtmsr(msr_save); | 708 | mtmsr(msr_save); |
707 | 709 | ||
@@ -724,6 +726,9 @@ static void rtas_percpu_suspend_me(void *info) | |||
724 | smp_processor_id(), rc); | 726 | smp_processor_id(), rc); |
725 | data->error = rc; | 727 | data->error = rc; |
726 | } | 728 | } |
729 | |||
730 | atomic_set(&data->done, 1); | ||
731 | |||
727 | /* This cpu did the suspend or got an error; in either case, | 732 | /* This cpu did the suspend or got an error; in either case, |
728 | * we need to prod all other other cpus out of join state. | 733 | * we need to prod all other other cpus out of join state. |
729 | * Extra prods are harmless. | 734 | * Extra prods are harmless. |
@@ -766,6 +771,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) | |||
766 | } | 771 | } |
767 | 772 | ||
768 | atomic_set(&data.working, 0); | 773 | atomic_set(&data.working, 0); |
774 | atomic_set(&data.done, 0); | ||
769 | data.token = rtas_token("ibm,suspend-me"); | 775 | data.token = rtas_token("ibm,suspend-me"); |
770 | data.error = 0; | 776 | data.error = 0; |
771 | data.complete = &done; | 777 | data.complete = &done; |