diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-14 10:43:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-14 10:43:11 -0400 |
commit | a2c7a54fcc36dc3d0d461e883d9535f8f52f5a3f (patch) | |
tree | 3bc7e727e6ebe67d7099b01a1b3cc159840912ca /arch/powerpc/platforms | |
parent | 674825d05001e218afe5a04438683e1e597e14fb (diff) | |
parent | e34166ad63eac4d0fa98b4c4ed7a98202a18faef (diff) |
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Benjamin Herrenschmidt:
"This is mostly bug fixes (some of them regressions, some of them I
deemed worth merging now) along with some patches from Li Zhong
hooking up the new context tracking stuff (for the new full NO_HZ)"
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (25 commits)
powerpc: Set show_unhandled_signals to 1 by default
powerpc/perf: Fix setting of "to" addresses for BHRB
powerpc/pmu: Fix order of interpreting BHRB target entries
powerpc/perf: Move BHRB code into CONFIG_PPC64 region
powerpc: select HAVE_CONTEXT_TRACKING for pSeries
powerpc: Use the new schedule_user API on userspace preemption
powerpc: Exit user context on notify resume
powerpc: Exception hooks for context tracking subsystem
powerpc: Syscall hooks for context tracking subsystem
powerpc/booke64: Fix kernel hangs at kernel_dbg_exc
powerpc: Fix irq_set_affinity() return values
powerpc: Provide __bswapdi2
powerpc/powernv: Fix starting of secondary CPUs on OPALv2 and v3
powerpc/powernv: Detect OPAL v3 API version
powerpc: Fix MAX_STACK_TRACE_ENTRIES too low warning again
powerpc: Make CONFIG_RTAS_PROC depend on CONFIG_PROC_FS
powerpc: Bring all threads online prior to migration/hibernation
powerpc/rtas_flash: Fix validate_flash buffer overflow issue
powerpc/kexec: Fix kexec when using VMX optimised memcpy
powerpc: Fix build errors STRICT_MM_TYPECHECKS
...
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/Kconfig | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 30 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci-ioda.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/powernv.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 16 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/smp.c | 62 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/suspend.c | 22 | ||||
-rw-r--r-- | arch/powerpc/platforms/wsp/ics.c | 2 |
11 files changed, 150 insertions, 10 deletions
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index a881232a3cce..b62aab3e22ec 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -128,7 +128,7 @@ config PPC_RTAS_DAEMON | |||
128 | 128 | ||
129 | config RTAS_PROC | 129 | config RTAS_PROC |
130 | bool "Proc interface to RTAS" | 130 | bool "Proc interface to RTAS" |
131 | depends on PPC_RTAS | 131 | depends on PPC_RTAS && PROC_FS |
132 | default y | 132 | default y |
133 | 133 | ||
134 | config RTAS_FLASH | 134 | config RTAS_FLASH |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index ade4463226c6..628c564ceadb 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_platform.h> | 16 | #include <linux/of_platform.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/slab.h> | ||
18 | #include <asm/opal.h> | 19 | #include <asm/opal.h> |
19 | #include <asm/firmware.h> | 20 | #include <asm/firmware.h> |
20 | 21 | ||
@@ -28,6 +29,8 @@ struct opal { | |||
28 | static struct device_node *opal_node; | 29 | static struct device_node *opal_node; |
29 | static DEFINE_SPINLOCK(opal_write_lock); | 30 | static DEFINE_SPINLOCK(opal_write_lock); |
30 | extern u64 opal_mc_secondary_handler[]; | 31 | extern u64 opal_mc_secondary_handler[]; |
32 | static unsigned int *opal_irqs; | ||
33 | static unsigned int opal_irq_count; | ||
31 | 34 | ||
32 | int __init early_init_dt_scan_opal(unsigned long node, | 35 | int __init early_init_dt_scan_opal(unsigned long node, |
33 | const char *uname, int depth, void *data) | 36 | const char *uname, int depth, void *data) |
@@ -53,7 +56,11 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
53 | opal.entry, entryp, entrysz); | 56 | opal.entry, entryp, entrysz); |
54 | 57 | ||
55 | powerpc_firmware_features |= FW_FEATURE_OPAL; | 58 | powerpc_firmware_features |= FW_FEATURE_OPAL; |
56 | if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { | 59 | if (of_flat_dt_is_compatible(node, "ibm,opal-v3")) { |
60 | powerpc_firmware_features |= FW_FEATURE_OPALv2; | ||
61 | powerpc_firmware_features |= FW_FEATURE_OPALv3; | ||
62 | printk("OPAL V3 detected !\n"); | ||
63 | } else if (of_flat_dt_is_compatible(node, "ibm,opal-v2")) { | ||
57 | powerpc_firmware_features |= FW_FEATURE_OPALv2; | 64 | powerpc_firmware_features |= FW_FEATURE_OPALv2; |
58 | printk("OPAL V2 detected !\n"); | 65 | printk("OPAL V2 detected !\n"); |
59 | } else { | 66 | } else { |
@@ -144,6 +151,13 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
144 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { | 151 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { |
145 | len = total_len; | 152 | len = total_len; |
146 | rc = opal_console_write(vtermno, &len, data); | 153 | rc = opal_console_write(vtermno, &len, data); |
154 | |||
155 | /* Closed or other error drop */ | ||
156 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && | ||
157 | rc != OPAL_BUSY_EVENT) { | ||
158 | written = total_len; | ||
159 | break; | ||
160 | } | ||
147 | if (rc == OPAL_SUCCESS) { | 161 | if (rc == OPAL_SUCCESS) { |
148 | total_len -= len; | 162 | total_len -= len; |
149 | data += len; | 163 | data += len; |
@@ -316,6 +330,8 @@ static int __init opal_init(void) | |||
316 | irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); | 330 | irqs = of_get_property(opal_node, "opal-interrupts", &irqlen); |
317 | pr_debug("opal: Found %d interrupts reserved for OPAL\n", | 331 | pr_debug("opal: Found %d interrupts reserved for OPAL\n", |
318 | irqs ? (irqlen / 4) : 0); | 332 | irqs ? (irqlen / 4) : 0); |
333 | opal_irq_count = irqlen / 4; | ||
334 | opal_irqs = kzalloc(opal_irq_count * sizeof(unsigned int), GFP_KERNEL); | ||
319 | for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { | 335 | for (i = 0; irqs && i < (irqlen / 4); i++, irqs++) { |
320 | unsigned int hwirq = be32_to_cpup(irqs); | 336 | unsigned int hwirq = be32_to_cpup(irqs); |
321 | unsigned int irq = irq_create_mapping(NULL, hwirq); | 337 | unsigned int irq = irq_create_mapping(NULL, hwirq); |
@@ -327,7 +343,19 @@ static int __init opal_init(void) | |||
327 | if (rc) | 343 | if (rc) |
328 | pr_warning("opal: Error %d requesting irq %d" | 344 | pr_warning("opal: Error %d requesting irq %d" |
329 | " (0x%x)\n", rc, irq, hwirq); | 345 | " (0x%x)\n", rc, irq, hwirq); |
346 | opal_irqs[i] = irq; | ||
330 | } | 347 | } |
331 | return 0; | 348 | return 0; |
332 | } | 349 | } |
333 | subsys_initcall(opal_init); | 350 | subsys_initcall(opal_init); |
351 | |||
352 | void opal_shutdown(void) | ||
353 | { | ||
354 | unsigned int i; | ||
355 | |||
356 | for (i = 0; i < opal_irq_count; i++) { | ||
357 | if (opal_irqs[i]) | ||
358 | free_irq(opal_irqs[i], 0); | ||
359 | opal_irqs[i] = 0; | ||
360 | } | ||
361 | } | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 1da578b7c1bf..3937aaae5bc4 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -1048,6 +1048,12 @@ static u32 pnv_ioda_bdfn_to_pe(struct pnv_phb *phb, struct pci_bus *bus, | |||
1048 | return phb->ioda.pe_rmap[(bus->number << 8) | devfn]; | 1048 | return phb->ioda.pe_rmap[(bus->number << 8) | devfn]; |
1049 | } | 1049 | } |
1050 | 1050 | ||
1051 | static void pnv_pci_ioda_shutdown(struct pnv_phb *phb) | ||
1052 | { | ||
1053 | opal_pci_reset(phb->opal_id, OPAL_PCI_IODA_TABLE_RESET, | ||
1054 | OPAL_ASSERT_RESET); | ||
1055 | } | ||
1056 | |||
1051 | void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) | 1057 | void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) |
1052 | { | 1058 | { |
1053 | struct pci_controller *hose; | 1059 | struct pci_controller *hose; |
@@ -1178,6 +1184,9 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, int ioda_type) | |||
1178 | /* Setup TCEs */ | 1184 | /* Setup TCEs */ |
1179 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; | 1185 | phb->dma_dev_setup = pnv_pci_ioda_dma_dev_setup; |
1180 | 1186 | ||
1187 | /* Setup shutdown function for kexec */ | ||
1188 | phb->shutdown = pnv_pci_ioda_shutdown; | ||
1189 | |||
1181 | /* Setup MSI support */ | 1190 | /* Setup MSI support */ |
1182 | pnv_pci_init_ioda_msis(phb); | 1191 | pnv_pci_init_ioda_msis(phb); |
1183 | 1192 | ||
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 55dfca844ddf..163bd7422f1c 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -450,6 +450,18 @@ static void pnv_pci_dma_dev_setup(struct pci_dev *pdev) | |||
450 | pnv_pci_dma_fallback_setup(hose, pdev); | 450 | pnv_pci_dma_fallback_setup(hose, pdev); |
451 | } | 451 | } |
452 | 452 | ||
453 | void pnv_pci_shutdown(void) | ||
454 | { | ||
455 | struct pci_controller *hose; | ||
456 | |||
457 | list_for_each_entry(hose, &hose_list, list_node) { | ||
458 | struct pnv_phb *phb = hose->private_data; | ||
459 | |||
460 | if (phb && phb->shutdown) | ||
461 | phb->shutdown(phb); | ||
462 | } | ||
463 | } | ||
464 | |||
453 | /* Fixup wrong class code in p7ioc and p8 root complex */ | 465 | /* Fixup wrong class code in p7ioc and p8 root complex */ |
454 | static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) | 466 | static void pnv_p7ioc_rc_quirk(struct pci_dev *dev) |
455 | { | 467 | { |
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 48dc4bb856a1..25d76c4df50b 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -86,6 +86,7 @@ struct pnv_phb { | |||
86 | void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); | 86 | void (*dma_dev_setup)(struct pnv_phb *phb, struct pci_dev *pdev); |
87 | void (*fixup_phb)(struct pci_controller *hose); | 87 | void (*fixup_phb)(struct pci_controller *hose); |
88 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); | 88 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); |
89 | void (*shutdown)(struct pnv_phb *phb); | ||
89 | 90 | ||
90 | union { | 91 | union { |
91 | struct { | 92 | struct { |
@@ -158,4 +159,5 @@ extern void pnv_pci_init_ioda_hub(struct device_node *np); | |||
158 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 159 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
159 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 160 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, |
160 | u64 *startp, u64 *endp); | 161 | u64 *startp, u64 *endp); |
162 | |||
161 | #endif /* __POWERNV_PCI_H */ | 163 | #endif /* __POWERNV_PCI_H */ |
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index 8a9df7f9667e..a1c6f83fc391 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h | |||
@@ -9,8 +9,10 @@ static inline void pnv_smp_init(void) { } | |||
9 | 9 | ||
10 | #ifdef CONFIG_PCI | 10 | #ifdef CONFIG_PCI |
11 | extern void pnv_pci_init(void); | 11 | extern void pnv_pci_init(void); |
12 | extern void pnv_pci_shutdown(void); | ||
12 | #else | 13 | #else |
13 | static inline void pnv_pci_init(void) { } | 14 | static inline void pnv_pci_init(void) { } |
15 | static inline void pnv_pci_shutdown(void) { } | ||
14 | #endif | 16 | #endif |
15 | 17 | ||
16 | #endif /* _POWERNV_H */ | 18 | #endif /* _POWERNV_H */ |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index db1ad1c8f68f..d4459bfc92f7 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -78,7 +78,9 @@ static void pnv_show_cpuinfo(struct seq_file *m) | |||
78 | if (root) | 78 | if (root) |
79 | model = of_get_property(root, "model", NULL); | 79 | model = of_get_property(root, "model", NULL); |
80 | seq_printf(m, "machine\t\t: PowerNV %s\n", model); | 80 | seq_printf(m, "machine\t\t: PowerNV %s\n", model); |
81 | if (firmware_has_feature(FW_FEATURE_OPALv2)) | 81 | if (firmware_has_feature(FW_FEATURE_OPALv3)) |
82 | seq_printf(m, "firmware\t: OPAL v3\n"); | ||
83 | else if (firmware_has_feature(FW_FEATURE_OPALv2)) | ||
82 | seq_printf(m, "firmware\t: OPAL v2\n"); | 84 | seq_printf(m, "firmware\t: OPAL v2\n"); |
83 | else if (firmware_has_feature(FW_FEATURE_OPAL)) | 85 | else if (firmware_has_feature(FW_FEATURE_OPAL)) |
84 | seq_printf(m, "firmware\t: OPAL v1\n"); | 86 | seq_printf(m, "firmware\t: OPAL v1\n"); |
@@ -126,6 +128,17 @@ static void pnv_progress(char *s, unsigned short hex) | |||
126 | { | 128 | { |
127 | } | 129 | } |
128 | 130 | ||
131 | static void pnv_shutdown(void) | ||
132 | { | ||
133 | /* Let the PCI code clear up IODA tables */ | ||
134 | pnv_pci_shutdown(); | ||
135 | |||
136 | /* And unregister all OPAL interrupts so they don't fire | ||
137 | * up while we kexec | ||
138 | */ | ||
139 | opal_shutdown(); | ||
140 | } | ||
141 | |||
129 | #ifdef CONFIG_KEXEC | 142 | #ifdef CONFIG_KEXEC |
130 | static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) | 143 | static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) |
131 | { | 144 | { |
@@ -187,6 +200,7 @@ define_machine(powernv) { | |||
187 | .init_IRQ = pnv_init_IRQ, | 200 | .init_IRQ = pnv_init_IRQ, |
188 | .show_cpuinfo = pnv_show_cpuinfo, | 201 | .show_cpuinfo = pnv_show_cpuinfo, |
189 | .progress = pnv_progress, | 202 | .progress = pnv_progress, |
203 | .machine_shutdown = pnv_shutdown, | ||
190 | .power_save = power7_idle, | 204 | .power_save = power7_idle, |
191 | .calibrate_decr = generic_calibrate_decr, | 205 | .calibrate_decr = generic_calibrate_decr, |
192 | #ifdef CONFIG_KEXEC | 206 | #ifdef CONFIG_KEXEC |
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 6a3ecca5b725..88c9459c3e07 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c | |||
@@ -71,18 +71,68 @@ int pnv_smp_kick_cpu(int nr) | |||
71 | 71 | ||
72 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 72 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
73 | 73 | ||
74 | /* On OPAL v2 the CPU are still spinning inside OPAL itself, | 74 | /* |
75 | * get them back now | 75 | * If we already started or OPALv2 is not supported, we just |
76 | * kick the CPU via the PACA | ||
76 | */ | 77 | */ |
77 | if (!paca[nr].cpu_start && firmware_has_feature(FW_FEATURE_OPALv2)) { | 78 | if (paca[nr].cpu_start || !firmware_has_feature(FW_FEATURE_OPALv2)) |
78 | pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", nr, pcpu); | 79 | goto kick; |
79 | rc = opal_start_cpu(pcpu, start_here); | 80 | |
81 | /* | ||
82 | * At this point, the CPU can either be spinning on the way in | ||
83 | * from kexec or be inside OPAL waiting to be started for the | ||
84 | * first time. OPAL v3 allows us to query OPAL to know if it | ||
85 | * has the CPUs, so we do that | ||
86 | */ | ||
87 | if (firmware_has_feature(FW_FEATURE_OPALv3)) { | ||
88 | uint8_t status; | ||
89 | |||
90 | rc = opal_query_cpu_status(pcpu, &status); | ||
80 | if (rc != OPAL_SUCCESS) { | 91 | if (rc != OPAL_SUCCESS) { |
81 | pr_warn("OPAL Error %ld starting CPU %d\n", | 92 | pr_warn("OPAL Error %ld querying CPU %d state\n", |
82 | rc, nr); | 93 | rc, nr); |
83 | return -ENODEV; | 94 | return -ENODEV; |
84 | } | 95 | } |
96 | |||
97 | /* | ||
98 | * Already started, just kick it, probably coming from | ||
99 | * kexec and spinning | ||
100 | */ | ||
101 | if (status == OPAL_THREAD_STARTED) | ||
102 | goto kick; | ||
103 | |||
104 | /* | ||
105 | * Available/inactive, let's kick it | ||
106 | */ | ||
107 | if (status == OPAL_THREAD_INACTIVE) { | ||
108 | pr_devel("OPAL: Starting CPU %d (HW 0x%x)...\n", | ||
109 | nr, pcpu); | ||
110 | rc = opal_start_cpu(pcpu, start_here); | ||
111 | if (rc != OPAL_SUCCESS) { | ||
112 | pr_warn("OPAL Error %ld starting CPU %d\n", | ||
113 | rc, nr); | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | } else { | ||
117 | /* | ||
118 | * An unavailable CPU (or any other unknown status) | ||
119 | * shouldn't be started. It should also | ||
120 | * not be in the possible map but currently it can | ||
121 | * happen | ||
122 | */ | ||
123 | pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable" | ||
124 | " (status %d)...\n", nr, pcpu, status); | ||
125 | return -ENODEV; | ||
126 | } | ||
127 | } else { | ||
128 | /* | ||
129 | * On OPAL v2, we just kick it and hope for the best, | ||
130 | * we must not test the error from opal_start_cpu() or | ||
131 | * we would fail to get CPUs from kexec. | ||
132 | */ | ||
133 | opal_start_cpu(pcpu, start_here); | ||
85 | } | 134 | } |
135 | kick: | ||
86 | return smp_generic_kick_cpu(nr); | 136 | return smp_generic_kick_cpu(nr); |
87 | } | 137 | } |
88 | 138 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 9a0941bc4d31..023b288f895b 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -18,6 +18,7 @@ config PPC_PSERIES | |||
18 | select PPC_PCI_CHOICE if EXPERT | 18 | select PPC_PCI_CHOICE if EXPERT |
19 | select ZLIB_DEFLATE | 19 | select ZLIB_DEFLATE |
20 | select PPC_DOORBELL | 20 | select PPC_DOORBELL |
21 | select HAVE_CONTEXT_TRACKING | ||
21 | default y | 22 | default y |
22 | 23 | ||
23 | config PPC_SPLPAR | 24 | config PPC_SPLPAR |
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 47226e04126d..5f997e79d570 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/cpu.h> | ||
19 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
20 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
21 | #include <linux/stat.h> | 22 | #include <linux/stat.h> |
@@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev, | |||
126 | struct device_attribute *attr, | 127 | struct device_attribute *attr, |
127 | const char *buf, size_t count) | 128 | const char *buf, size_t count) |
128 | { | 129 | { |
130 | cpumask_var_t offline_mask; | ||
129 | int rc; | 131 | int rc; |
130 | 132 | ||
131 | if (!capable(CAP_SYS_ADMIN)) | 133 | if (!capable(CAP_SYS_ADMIN)) |
132 | return -EPERM; | 134 | return -EPERM; |
133 | 135 | ||
136 | if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) | ||
137 | return -ENOMEM; | ||
138 | |||
134 | stream_id = simple_strtoul(buf, NULL, 16); | 139 | stream_id = simple_strtoul(buf, NULL, 16); |
135 | 140 | ||
136 | do { | 141 | do { |
@@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev, | |||
140 | } while (rc == -EAGAIN); | 145 | } while (rc == -EAGAIN); |
141 | 146 | ||
142 | if (!rc) { | 147 | if (!rc) { |
148 | /* All present CPUs must be online */ | ||
149 | cpumask_andnot(offline_mask, cpu_present_mask, | ||
150 | cpu_online_mask); | ||
151 | rc = rtas_online_cpus_mask(offline_mask); | ||
152 | if (rc) { | ||
153 | pr_err("%s: Could not bring present CPUs online.\n", | ||
154 | __func__); | ||
155 | goto out; | ||
156 | } | ||
157 | |||
143 | stop_topology_update(); | 158 | stop_topology_update(); |
144 | rc = pm_suspend(PM_SUSPEND_MEM); | 159 | rc = pm_suspend(PM_SUSPEND_MEM); |
145 | start_topology_update(); | 160 | start_topology_update(); |
161 | |||
162 | /* Take down CPUs not online prior to suspend */ | ||
163 | if (!rtas_offline_cpus_mask(offline_mask)) | ||
164 | pr_warn("%s: Could not restore CPUs to offline " | ||
165 | "state.\n", __func__); | ||
146 | } | 166 | } |
147 | 167 | ||
148 | stream_id = 0; | 168 | stream_id = 0; |
149 | 169 | ||
150 | if (!rc) | 170 | if (!rc) |
151 | rc = count; | 171 | rc = count; |
172 | out: | ||
173 | free_cpumask_var(offline_mask); | ||
152 | return rc; | 174 | return rc; |
153 | } | 175 | } |
154 | 176 | ||
diff --git a/arch/powerpc/platforms/wsp/ics.c b/arch/powerpc/platforms/wsp/ics.c index 97fe82ee8633..2d3b1dd9571d 100644 --- a/arch/powerpc/platforms/wsp/ics.c +++ b/arch/powerpc/platforms/wsp/ics.c | |||
@@ -361,7 +361,7 @@ static int wsp_chip_set_affinity(struct irq_data *d, | |||
361 | xive = xive_set_server(xive, get_irq_server(ics, hw_irq)); | 361 | xive = xive_set_server(xive, get_irq_server(ics, hw_irq)); |
362 | wsp_ics_set_xive(ics, hw_irq, xive); | 362 | wsp_ics_set_xive(ics, hw_irq, xive); |
363 | 363 | ||
364 | return 0; | 364 | return IRQ_SET_MASK_OK; |
365 | } | 365 | } |
366 | 366 | ||
367 | static struct irq_chip wsp_irq_chip = { | 367 | static struct irq_chip wsp_irq_chip = { |