aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/rtas.c99
-rw-r--r--arch/powerpc/mm/stab.c1
-rw-r--r--arch/powerpc/platforms/40x/walnut.c3
-rw-r--r--arch/powerpc/platforms/44x/bamboo.c3
-rw-r--r--arch/powerpc/platforms/44x/ebony.c3
-rw-r--r--arch/powerpc/platforms/44x/sequoia.c3
-rw-r--r--arch/powerpc/platforms/embedded6xx/prpmc2800.c1
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig2
-rw-r--r--arch/powerpc/sysdev/uic.c18
9 files changed, 86 insertions, 47 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 214780798289..52e95c2158c0 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -19,6 +19,9 @@
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/capability.h> 20#include <linux/capability.h>
21#include <linux/delay.h> 21#include <linux/delay.h>
22#include <linux/smp.h>
23#include <linux/completion.h>
24#include <linux/cpumask.h>
22 25
23#include <asm/prom.h> 26#include <asm/prom.h>
24#include <asm/rtas.h> 27#include <asm/rtas.h>
@@ -34,6 +37,8 @@
34#include <asm/lmb.h> 37#include <asm/lmb.h>
35#include <asm/udbg.h> 38#include <asm/udbg.h>
36#include <asm/syscalls.h> 39#include <asm/syscalls.h>
40#include <asm/smp.h>
41#include <asm/atomic.h>
37 42
38struct rtas_t rtas = { 43struct rtas_t rtas = {
39 .lock = SPIN_LOCK_UNLOCKED 44 .lock = SPIN_LOCK_UNLOCKED
@@ -41,8 +46,10 @@ struct rtas_t rtas = {
41EXPORT_SYMBOL(rtas); 46EXPORT_SYMBOL(rtas);
42 47
43struct rtas_suspend_me_data { 48struct rtas_suspend_me_data {
44 long waiting; 49 atomic_t working; /* number of cpus accessing this struct */
45 struct rtas_args *args; 50 int token; /* ibm,suspend-me */
51 int error;
52 struct completion *complete; /* wait on this until working == 0 */
46}; 53};
47 54
48DEFINE_SPINLOCK(rtas_data_buf_lock); 55DEFINE_SPINLOCK(rtas_data_buf_lock);
@@ -657,50 +664,62 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE;
657#ifdef CONFIG_PPC_PSERIES 664#ifdef CONFIG_PPC_PSERIES
658static void rtas_percpu_suspend_me(void *info) 665static void rtas_percpu_suspend_me(void *info)
659{ 666{
660 int i;
661 long rc; 667 long rc;
662 long flags; 668 unsigned long msr_save;
669 int cpu;
663 struct rtas_suspend_me_data *data = 670 struct rtas_suspend_me_data *data =
664 (struct rtas_suspend_me_data *)info; 671 (struct rtas_suspend_me_data *)info;
665 672
666 /* 673 atomic_inc(&data->working);
667 * We use "waiting" to indicate our state. As long 674
668 * as it is >0, we are still trying to all join up. 675 /* really need to ensure MSR.EE is off for H_JOIN */
669 * If it goes to 0, we have successfully joined up and 676 msr_save = mfmsr();
670 * one thread got H_CONTINUE. If any error happens, 677 mtmsr(msr_save & ~(MSR_EE));
671 * we set it to <0. 678
672 */ 679 rc = plpar_hcall_norets(H_JOIN);
673 local_irq_save(flags); 680
674 do { 681 mtmsr(msr_save);
675 rc = plpar_hcall_norets(H_JOIN);
676 smp_rmb();
677 } while (rc == H_SUCCESS && data->waiting > 0);
678 if (rc == H_SUCCESS)
679 goto out;
680 682
681 if (rc == H_CONTINUE) { 683 if (rc == H_SUCCESS) {
682 data->waiting = 0; 684 /* This cpu was prodded and the suspend is complete. */
683 data->args->args[data->args->nargs] = 685 goto out;
684 rtas_call(ibm_suspend_me_token, 0, 1, NULL); 686 } else if (rc == H_CONTINUE) {
685 for_each_possible_cpu(i) 687 /* All other cpus are in H_JOIN, this cpu does
686 plpar_hcall_norets(H_PROD,i); 688 * the suspend.
689 */
690 printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n",
691 smp_processor_id());
692 data->error = rtas_call(data->token, 0, 1, NULL);
693
694 if (data->error)
695 printk(KERN_DEBUG "ibm,suspend-me returned %d\n",
696 data->error);
687 } else { 697 } else {
688 data->waiting = -EBUSY; 698 printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n",
689 printk(KERN_ERR "Error on H_JOIN hypervisor call\n"); 699 smp_processor_id(), rc);
700 data->error = rc;
690 } 701 }
691 702 /* This cpu did the suspend or got an error; in either case,
703 * we need to prod all other other cpus out of join state.
704 * Extra prods are harmless.
705 */
706 for_each_online_cpu(cpu)
707 plpar_hcall_norets(H_PROD, get_hard_smp_processor_id(cpu));
692out: 708out:
693 local_irq_restore(flags); 709 if (atomic_dec_return(&data->working) == 0)
694 return; 710 complete(data->complete);
695} 711}
696 712
697static int rtas_ibm_suspend_me(struct rtas_args *args) 713static int rtas_ibm_suspend_me(struct rtas_args *args)
698{ 714{
699 int i;
700 long state; 715 long state;
701 long rc; 716 long rc;
702 unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; 717 unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
703 struct rtas_suspend_me_data data; 718 struct rtas_suspend_me_data data;
719 DECLARE_COMPLETION_ONSTACK(done);
720
721 if (!rtas_service_present("ibm,suspend-me"))
722 return -ENOSYS;
704 723
705 /* Make sure the state is valid */ 724 /* Make sure the state is valid */
706 rc = plpar_hcall(H_VASI_STATE, retbuf, 725 rc = plpar_hcall(H_VASI_STATE, retbuf,
@@ -721,25 +740,23 @@ static int rtas_ibm_suspend_me(struct rtas_args *args)
721 return 0; 740 return 0;
722 } 741 }
723 742
724 data.waiting = 1; 743 atomic_set(&data.working, 0);
725 data.args = args; 744 data.token = rtas_token("ibm,suspend-me");
745 data.error = 0;
746 data.complete = &done;
726 747
727 /* Call function on all CPUs. One of us will make the 748 /* Call function on all CPUs. One of us will make the
728 * rtas call 749 * rtas call
729 */ 750 */
730 if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0)) 751 if (on_each_cpu(rtas_percpu_suspend_me, &data, 1, 0))
731 data.waiting = -EINVAL; 752 data.error = -EINVAL;
732 753
733 if (data.waiting != 0) 754 wait_for_completion(&done);
734 printk(KERN_ERR "Error doing global join\n");
735 755
736 /* Prod each CPU. This won't hurt, and will wake 756 if (data.error != 0)
737 * anyone we successfully put to sleep with H_JOIN. 757 printk(KERN_ERR "Error doing global join\n");
738 */
739 for_each_possible_cpu(i)
740 plpar_hcall_norets(H_PROD, i);
741 758
742 return data.waiting; 759 return data.error;
743} 760}
744#else /* CONFIG_PPC_PSERIES */ 761#else /* CONFIG_PPC_PSERIES */
745static int rtas_ibm_suspend_me(struct rtas_args *args) 762static int rtas_ibm_suspend_me(struct rtas_args *args)
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c
index 9e85bda76216..50448d5de9d2 100644
--- a/arch/powerpc/mm/stab.c
+++ b/arch/powerpc/mm/stab.c
@@ -20,6 +20,7 @@
20#include <asm/lmb.h> 20#include <asm/lmb.h>
21#include <asm/abs_addr.h> 21#include <asm/abs_addr.h>
22#include <asm/firmware.h> 22#include <asm/firmware.h>
23#include <asm/iseries/hv_call.h>
23 24
24struct stab_entry { 25struct stab_entry {
25 unsigned long esid_data; 26 unsigned long esid_data;
diff --git a/arch/powerpc/platforms/40x/walnut.c b/arch/powerpc/platforms/40x/walnut.c
index eb0c136b1c44..ff6db2431798 100644
--- a/arch/powerpc/platforms/40x/walnut.c
+++ b/arch/powerpc/platforms/40x/walnut.c
@@ -17,12 +17,13 @@
17 */ 17 */
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/of_platform.h>
21
20#include <asm/machdep.h> 22#include <asm/machdep.h>
21#include <asm/prom.h> 23#include <asm/prom.h>
22#include <asm/udbg.h> 24#include <asm/udbg.h>
23#include <asm/time.h> 25#include <asm/time.h>
24#include <asm/uic.h> 26#include <asm/uic.h>
25#include <asm/of_platform.h>
26 27
27static struct of_device_id walnut_of_bus[] = { 28static struct of_device_id walnut_of_bus[] = {
28 { .compatible = "ibm,plb3", }, 29 { .compatible = "ibm,plb3", },
diff --git a/arch/powerpc/platforms/44x/bamboo.c b/arch/powerpc/platforms/44x/bamboo.c
index 470e1a3fd755..be23f112184f 100644
--- a/arch/powerpc/platforms/44x/bamboo.c
+++ b/arch/powerpc/platforms/44x/bamboo.c
@@ -14,12 +14,13 @@
14 * option) any later version. 14 * option) any later version.
15 */ 15 */
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/of_platform.h>
18
17#include <asm/machdep.h> 19#include <asm/machdep.h>
18#include <asm/prom.h> 20#include <asm/prom.h>
19#include <asm/udbg.h> 21#include <asm/udbg.h>
20#include <asm/time.h> 22#include <asm/time.h>
21#include <asm/uic.h> 23#include <asm/uic.h>
22#include <asm/of_platform.h>
23#include "44x.h" 24#include "44x.h"
24 25
25static struct of_device_id bamboo_of_bus[] = { 26static struct of_device_id bamboo_of_bus[] = {
diff --git a/arch/powerpc/platforms/44x/ebony.c b/arch/powerpc/platforms/44x/ebony.c
index 40e18fcb666c..6cd3476767cc 100644
--- a/arch/powerpc/platforms/44x/ebony.c
+++ b/arch/powerpc/platforms/44x/ebony.c
@@ -17,12 +17,13 @@
17 */ 17 */
18 18
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/of_platform.h>
21
20#include <asm/machdep.h> 22#include <asm/machdep.h>
21#include <asm/prom.h> 23#include <asm/prom.h>
22#include <asm/udbg.h> 24#include <asm/udbg.h>
23#include <asm/time.h> 25#include <asm/time.h>
24#include <asm/uic.h> 26#include <asm/uic.h>
25#include <asm/of_platform.h>
26 27
27#include "44x.h" 28#include "44x.h"
28 29
diff --git a/arch/powerpc/platforms/44x/sequoia.c b/arch/powerpc/platforms/44x/sequoia.c
index 30700b31d43b..21a9dd14f297 100644
--- a/arch/powerpc/platforms/44x/sequoia.c
+++ b/arch/powerpc/platforms/44x/sequoia.c
@@ -14,12 +14,13 @@
14 * option) any later version. 14 * option) any later version.
15 */ 15 */
16#include <linux/init.h> 16#include <linux/init.h>
17#include <linux/of_platform.h>
18
17#include <asm/machdep.h> 19#include <asm/machdep.h>
18#include <asm/prom.h> 20#include <asm/prom.h>
19#include <asm/udbg.h> 21#include <asm/udbg.h>
20#include <asm/time.h> 22#include <asm/time.h>
21#include <asm/uic.h> 23#include <asm/uic.h>
22#include <asm/of_platform.h>
23#include "44x.h" 24#include "44x.h"
24 25
25static struct of_device_id sequoia_of_bus[] = { 26static struct of_device_id sequoia_of_bus[] = {
diff --git a/arch/powerpc/platforms/embedded6xx/prpmc2800.c b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
index e484cac75095..653a5eb91c90 100644
--- a/arch/powerpc/platforms/embedded6xx/prpmc2800.c
+++ b/arch/powerpc/platforms/embedded6xx/prpmc2800.c
@@ -144,6 +144,7 @@ static int __init prpmc2800_probe(void)
144 strncpy(prpmc2800_platform_name, m, 144 strncpy(prpmc2800_platform_name, m,
145 min((int)len, PLATFORM_NAME_MAX - 1)); 145 min((int)len, PLATFORM_NAME_MAX - 1));
146 146
147 _set_L2CR(_get_L2CR() | L2CR_L2E);
147 return 1; 148 return 1;
148} 149}
149 150
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 16e4e401b820..306a9d07491d 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -21,7 +21,7 @@ config PPC_SPLPAR
21 21
22config EEH 22config EEH
23 bool "PCI Extended Error Handling (EEH)" if EMBEDDED 23 bool "PCI Extended Error Handling (EEH)" if EMBEDDED
24 depends on PPC_PSERIES 24 depends on PPC_PSERIES && PCI
25 default y if !EMBEDDED 25 default y if !EMBEDDED
26 26
27config SCANLOG 27config SCANLOG
diff --git a/arch/powerpc/sysdev/uic.c b/arch/powerpc/sysdev/uic.c
index 5149716c734d..847a5496b869 100644
--- a/arch/powerpc/sysdev/uic.c
+++ b/arch/powerpc/sysdev/uic.c
@@ -97,6 +97,22 @@ static void uic_ack_irq(unsigned int virq)
97 spin_unlock_irqrestore(&uic->lock, flags); 97 spin_unlock_irqrestore(&uic->lock, flags);
98} 98}
99 99
100static void uic_mask_ack_irq(unsigned int virq)
101{
102 struct uic *uic = get_irq_chip_data(virq);
103 unsigned int src = uic_irq_to_hw(virq);
104 unsigned long flags;
105 u32 er, sr;
106
107 sr = 1 << (31-src);
108 spin_lock_irqsave(&uic->lock, flags);
109 er = mfdcr(uic->dcrbase + UIC_ER);
110 er &= ~sr;
111 mtdcr(uic->dcrbase + UIC_ER, er);
112 mtdcr(uic->dcrbase + UIC_SR, sr);
113 spin_unlock_irqrestore(&uic->lock, flags);
114}
115
100static int uic_set_irq_type(unsigned int virq, unsigned int flow_type) 116static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
101{ 117{
102 struct uic *uic = get_irq_chip_data(virq); 118 struct uic *uic = get_irq_chip_data(virq);
@@ -152,7 +168,7 @@ static struct irq_chip uic_irq_chip = {
152 .typename = " UIC ", 168 .typename = " UIC ",
153 .unmask = uic_unmask_irq, 169 .unmask = uic_unmask_irq,
154 .mask = uic_mask_irq, 170 .mask = uic_mask_irq,
155/* .mask_ack = uic_mask_irq_and_ack, */ 171 .mask_ack = uic_mask_ack_irq,
156 .ack = uic_ack_irq, 172 .ack = uic_ack_irq,
157 .set_type = uic_set_irq_type, 173 .set_type = uic_set_irq_type,
158}; 174};