aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 01:59:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-26 01:59:39 -0400
commit184475029a724b6b900d88fc3a5f462a6107d5af (patch)
tree408320b46df221a2424bf94282b1b8e5b7aff7a1 /arch/powerpc/platforms/pseries
parent3b76eefe0f970c2e19f165d4a1650abc523d10bc (diff)
parentf1f4ee01c0d3dce0e3aa7d04e4332677db7af478 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (99 commits) drivers/virt: add missing linux/interrupt.h to fsl_hypervisor.c powerpc/85xx: fix mpic configuration in CAMP mode powerpc: Copy back TIF flags on return from softirq stack powerpc/64: Make server perfmon only built on ppc64 server devices powerpc/pseries: Fix hvc_vio.c build due to recent changes powerpc: Exporting boot_cpuid_phys powerpc: Add CFAR to oops output hvc_console: Add kdb support powerpc/pseries: Fix hvterm_raw_get_chars to accept < 16 chars, fixing xmon powerpc/irq: Quieten irq mapping printks powerpc: Enable lockup and hung task detectors in pseries and ppc64 defeconfigs powerpc: Add mpt2sas driver to pseries and ppc64 defconfig powerpc: Disable IRQs off tracer in ppc64 defconfig powerpc: Sync pseries and ppc64 defconfigs powerpc/pseries/hvconsole: Fix dropped console output hvc_console: Improve tty/console put_chars handling powerpc/kdump: Fix timeout in crash_kexec_wait_realmode powerpc/mm: Fix output of total_ram. powerpc/cpufreq: Add cpufreq driver for Momentum Maple boards powerpc: Correct annotations of pmu registration functions ... Fix up trivial Kconfig/Makefile conflicts in arch/powerpc, drivers, and drivers/cpufreq
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c10
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c10
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-memory.c16
-rw-r--r--arch/powerpc/platforms/pseries/hvconsole.c2
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c191
-rw-r--r--arch/powerpc/platforms/pseries/pseries.h3
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c28
-rw-r--r--arch/powerpc/platforms/pseries/setup.c5
-rw-r--r--arch/powerpc/platforms/pseries/smp.c2
9 files changed, 35 insertions, 232 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index 57ceb92b2288..e9be25bc571b 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -262,12 +262,11 @@ int dlpar_attach_node(struct device_node *dn)
262 if (!dn->parent) 262 if (!dn->parent)
263 return -ENOMEM; 263 return -ENOMEM;
264 264
265 rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, 265 rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
266 PSERIES_RECONFIG_ADD, dn); 266 if (rc) {
267 if (rc == NOTIFY_BAD) {
268 printk(KERN_ERR "Failed to add device node %s\n", 267 printk(KERN_ERR "Failed to add device node %s\n",
269 dn->full_name); 268 dn->full_name);
270 return -ENOMEM; /* For now, safe to assume kmalloc failure */ 269 return rc;
271 } 270 }
272 271
273 of_attach_node(dn); 272 of_attach_node(dn);
@@ -297,8 +296,7 @@ int dlpar_detach_node(struct device_node *dn)
297 remove_proc_entry(dn->pde->name, parent->pde); 296 remove_proc_entry(dn->pde->name, parent->pde);
298#endif 297#endif
299 298
300 blocking_notifier_call_chain(&pSeries_reconfig_chain, 299 pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
301 PSERIES_RECONFIG_REMOVE, dn);
302 of_detach_node(dn); 300 of_detach_node(dn);
303 of_node_put(dn); /* Must decrement the refcount */ 301 of_node_put(dn); /* Must decrement the refcount */
304 302
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 46f13a3c5d09..bc0288501f17 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -330,21 +330,17 @@ static void pseries_remove_processor(struct device_node *np)
330static int pseries_smp_notifier(struct notifier_block *nb, 330static int pseries_smp_notifier(struct notifier_block *nb,
331 unsigned long action, void *node) 331 unsigned long action, void *node)
332{ 332{
333 int err = NOTIFY_OK; 333 int err = 0;
334 334
335 switch (action) { 335 switch (action) {
336 case PSERIES_RECONFIG_ADD: 336 case PSERIES_RECONFIG_ADD:
337 if (pseries_add_processor(node)) 337 err = pseries_add_processor(node);
338 err = NOTIFY_BAD;
339 break; 338 break;
340 case PSERIES_RECONFIG_REMOVE: 339 case PSERIES_RECONFIG_REMOVE:
341 pseries_remove_processor(node); 340 pseries_remove_processor(node);
342 break; 341 break;
343 default:
344 err = NOTIFY_DONE;
345 break;
346 } 342 }
347 return err; 343 return notifier_from_errno(err);
348} 344}
349 345
350static struct notifier_block pseries_smp_nb = { 346static struct notifier_block pseries_smp_nb = {
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9d6a8effeda2..11d8e0544ac0 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -205,27 +205,21 @@ static int pseries_drconf_memory(unsigned long *base, unsigned int action)
205static int pseries_memory_notifier(struct notifier_block *nb, 205static int pseries_memory_notifier(struct notifier_block *nb,
206 unsigned long action, void *node) 206 unsigned long action, void *node)
207{ 207{
208 int err = NOTIFY_OK; 208 int err = 0;
209 209
210 switch (action) { 210 switch (action) {
211 case PSERIES_RECONFIG_ADD: 211 case PSERIES_RECONFIG_ADD:
212 if (pseries_add_memory(node)) 212 err = pseries_add_memory(node);
213 err = NOTIFY_BAD;
214 break; 213 break;
215 case PSERIES_RECONFIG_REMOVE: 214 case PSERIES_RECONFIG_REMOVE:
216 if (pseries_remove_memory(node)) 215 err = pseries_remove_memory(node);
217 err = NOTIFY_BAD;
218 break; 216 break;
219 case PSERIES_DRCONF_MEM_ADD: 217 case PSERIES_DRCONF_MEM_ADD:
220 case PSERIES_DRCONF_MEM_REMOVE: 218 case PSERIES_DRCONF_MEM_REMOVE:
221 if (pseries_drconf_memory(node, action)) 219 err = pseries_drconf_memory(node, action);
222 err = NOTIFY_BAD;
223 break;
224 default:
225 err = NOTIFY_DONE;
226 break; 220 break;
227 } 221 }
228 return err; 222 return notifier_from_errno(err);
229} 223}
230 224
231static struct notifier_block pseries_mem_nb = { 225static struct notifier_block pseries_mem_nb = {
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c
index 3f6a89b09816..041e87ca1893 100644
--- a/arch/powerpc/platforms/pseries/hvconsole.c
+++ b/arch/powerpc/platforms/pseries/hvconsole.c
@@ -73,7 +73,7 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
73 if (ret == H_SUCCESS) 73 if (ret == H_SUCCESS)
74 return count; 74 return count;
75 if (ret == H_BUSY) 75 if (ret == H_BUSY)
76 return 0; 76 return -EAGAIN;
77 return -EIO; 77 return -EIO;
78} 78}
79 79
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index 39e6e0a7b2fa..f7205d344efd 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -52,197 +52,6 @@ EXPORT_SYMBOL(plpar_hcall_norets);
52 52
53extern void pSeries_find_serial_port(void); 53extern void pSeries_find_serial_port(void);
54 54
55
56static int vtermno; /* virtual terminal# for udbg */
57
58#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
59static void udbg_hvsi_putc(char c)
60{
61 /* packet's seqno isn't used anyways */
62 uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
63 int rc;
64
65 if (c == '\n')
66 udbg_hvsi_putc('\r');
67
68 do {
69 rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
70 } while (rc == H_BUSY);
71}
72
73static long hvsi_udbg_buf_len;
74static uint8_t hvsi_udbg_buf[256];
75
76static int udbg_hvsi_getc_poll(void)
77{
78 unsigned char ch;
79 int rc, i;
80
81 if (hvsi_udbg_buf_len == 0) {
82 rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
83 if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
84 /* bad read or non-data packet */
85 hvsi_udbg_buf_len = 0;
86 } else {
87 /* remove the packet header */
88 for (i = 4; i < hvsi_udbg_buf_len; i++)
89 hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
90 hvsi_udbg_buf_len -= 4;
91 }
92 }
93
94 if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
95 /* no data ready */
96 hvsi_udbg_buf_len = 0;
97 return -1;
98 }
99
100 ch = hvsi_udbg_buf[0];
101 /* shift remaining data down */
102 for (i = 1; i < hvsi_udbg_buf_len; i++) {
103 hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
104 }
105 hvsi_udbg_buf_len--;
106
107 return ch;
108}
109
110static int udbg_hvsi_getc(void)
111{
112 int ch;
113 for (;;) {
114 ch = udbg_hvsi_getc_poll();
115 if (ch == -1) {
116 /* This shouldn't be needed...but... */
117 volatile unsigned long delay;
118 for (delay=0; delay < 2000000; delay++)
119 ;
120 } else {
121 return ch;
122 }
123 }
124}
125
126static void udbg_putcLP(char c)
127{
128 char buf[16];
129 unsigned long rc;
130
131 if (c == '\n')
132 udbg_putcLP('\r');
133
134 buf[0] = c;
135 do {
136 rc = plpar_put_term_char(vtermno, 1, buf);
137 } while(rc == H_BUSY);
138}
139
140/* Buffered chars getc */
141static long inbuflen;
142static long inbuf[2]; /* must be 2 longs */
143
144static int udbg_getc_pollLP(void)
145{
146 /* The interface is tricky because it may return up to 16 chars.
147 * We save them statically for future calls to udbg_getc().
148 */
149 char ch, *buf = (char *)inbuf;
150 int i;
151 long rc;
152 if (inbuflen == 0) {
153 /* get some more chars. */
154 inbuflen = 0;
155 rc = plpar_get_term_char(vtermno, &inbuflen, buf);
156 if (rc != H_SUCCESS)
157 inbuflen = 0; /* otherwise inbuflen is garbage */
158 }
159 if (inbuflen <= 0 || inbuflen > 16) {
160 /* Catch error case as well as other oddities (corruption) */
161 inbuflen = 0;
162 return -1;
163 }
164 ch = buf[0];
165 for (i = 1; i < inbuflen; i++) /* shuffle them down. */
166 buf[i-1] = buf[i];
167 inbuflen--;
168 return ch;
169}
170
171static int udbg_getcLP(void)
172{
173 int ch;
174 for (;;) {
175 ch = udbg_getc_pollLP();
176 if (ch == -1) {
177 /* This shouldn't be needed...but... */
178 volatile unsigned long delay;
179 for (delay=0; delay < 2000000; delay++)
180 ;
181 } else {
182 return ch;
183 }
184 }
185}
186
187/* call this from early_init() for a working debug console on
188 * vterm capable LPAR machines
189 */
190void __init udbg_init_debug_lpar(void)
191{
192 vtermno = 0;
193 udbg_putc = udbg_putcLP;
194 udbg_getc = udbg_getcLP;
195 udbg_getc_poll = udbg_getc_pollLP;
196
197 register_early_udbg_console();
198}
199
200/* returns 0 if couldn't find or use /chosen/stdout as console */
201void __init find_udbg_vterm(void)
202{
203 struct device_node *stdout_node;
204 const u32 *termno;
205 const char *name;
206
207 /* find the boot console from /chosen/stdout */
208 if (!of_chosen)
209 return;
210 name = of_get_property(of_chosen, "linux,stdout-path", NULL);
211 if (name == NULL)
212 return;
213 stdout_node = of_find_node_by_path(name);
214 if (!stdout_node)
215 return;
216 name = of_get_property(stdout_node, "name", NULL);
217 if (!name) {
218 printk(KERN_WARNING "stdout node missing 'name' property!\n");
219 goto out;
220 }
221
222 /* Check if it's a virtual terminal */
223 if (strncmp(name, "vty", 3) != 0)
224 goto out;
225 termno = of_get_property(stdout_node, "reg", NULL);
226 if (termno == NULL)
227 goto out;
228 vtermno = termno[0];
229
230 if (of_device_is_compatible(stdout_node, "hvterm1")) {
231 udbg_putc = udbg_putcLP;
232 udbg_getc = udbg_getcLP;
233 udbg_getc_poll = udbg_getc_pollLP;
234 add_preferred_console("hvc", termno[0] & 0xff, NULL);
235 } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
236 vtermno = termno[0];
237 udbg_putc = udbg_hvsi_putc;
238 udbg_getc = udbg_hvsi_getc;
239 udbg_getc_poll = udbg_hvsi_getc_poll;
240 add_preferred_console("hvsi", termno[0] & 0xff, NULL);
241 }
242out:
243 of_node_put(stdout_node);
244}
245
246void vpa_init(int cpu) 55void vpa_init(int cpu)
247{ 56{
248 int hwcpu = get_hard_smp_processor_id(cpu); 57 int hwcpu = get_hard_smp_processor_id(cpu);
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h
index e9f6d2859c3c..24c7162f11d9 100644
--- a/arch/powerpc/platforms/pseries/pseries.h
+++ b/arch/powerpc/platforms/pseries/pseries.h
@@ -47,7 +47,8 @@ extern void pSeries_final_fixup(void);
47/* Poweron flag used for enabling auto ups restart */ 47/* Poweron flag used for enabling auto ups restart */
48extern unsigned long rtas_poweron_auto; 48extern unsigned long rtas_poweron_auto;
49 49
50extern void find_udbg_vterm(void); 50/* Provided by HVC VIO */
51extern void hvc_vio_init_early(void);
51 52
52/* Dynamic logical Partitioning/Mobility */ 53/* Dynamic logical Partitioning/Mobility */
53extern void dlpar_free_cc_nodes(struct device_node *); 54extern void dlpar_free_cc_nodes(struct device_node *);
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 1de2cbb92303..168651acdd83 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -97,7 +97,7 @@ static struct device_node *derive_parent(const char *path)
97 return parent; 97 return parent;
98} 98}
99 99
100BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); 100static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
101 101
102int pSeries_reconfig_notifier_register(struct notifier_block *nb) 102int pSeries_reconfig_notifier_register(struct notifier_block *nb)
103{ 103{
@@ -109,6 +109,14 @@ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
109 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); 109 blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
110} 110}
111 111
112int pSeries_reconfig_notify(unsigned long action, void *p)
113{
114 int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
115 action, p);
116
117 return notifier_to_errno(err);
118}
119
112static int pSeries_reconfig_add_node(const char *path, struct property *proplist) 120static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
113{ 121{
114 struct device_node *np; 122 struct device_node *np;
@@ -132,11 +140,9 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
132 goto out_err; 140 goto out_err;
133 } 141 }
134 142
135 err = blocking_notifier_call_chain(&pSeries_reconfig_chain, 143 err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
136 PSERIES_RECONFIG_ADD, np); 144 if (err) {
137 if (err == NOTIFY_BAD) {
138 printk(KERN_ERR "Failed to add device node %s\n", path); 145 printk(KERN_ERR "Failed to add device node %s\n", path);
139 err = -ENOMEM; /* For now, safe to assume kmalloc failure */
140 goto out_err; 146 goto out_err;
141 } 147 }
142 148
@@ -173,8 +179,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
173 179
174 remove_node_proc_entries(np); 180 remove_node_proc_entries(np);
175 181
176 blocking_notifier_call_chain(&pSeries_reconfig_chain, 182 pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
177 PSERIES_RECONFIG_REMOVE, np);
178 of_detach_node(np); 183 of_detach_node(np);
179 184
180 of_node_put(parent); 185 of_node_put(parent);
@@ -472,11 +477,10 @@ static int do_update_property(char *buf, size_t bufsize)
472 else 477 else
473 action = PSERIES_DRCONF_MEM_REMOVE; 478 action = PSERIES_DRCONF_MEM_REMOVE;
474 479
475 rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, 480 rc = pSeries_reconfig_notify(action, value);
476 action, value); 481 if (rc) {
477 if (rc == NOTIFY_BAD) { 482 prom_update_property(np, oldprop, newprop);
478 rc = prom_update_property(np, oldprop, newprop); 483 return rc;
479 return -ENOMEM;
480 } 484 }
481 } 485 }
482 486
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 593acceeff96..d00e52926b71 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -512,9 +512,10 @@ static void __init pSeries_init_early(void)
512{ 512{
513 pr_debug(" -> pSeries_init_early()\n"); 513 pr_debug(" -> pSeries_init_early()\n");
514 514
515#ifdef CONFIG_HVC_CONSOLE
515 if (firmware_has_feature(FW_FEATURE_LPAR)) 516 if (firmware_has_feature(FW_FEATURE_LPAR))
516 find_udbg_vterm(); 517 hvc_vio_init_early();
517 518#endif
518 if (firmware_has_feature(FW_FEATURE_DABR)) 519 if (firmware_has_feature(FW_FEATURE_DABR))
519 ppc_md.set_dabr = pseries_set_dabr; 520 ppc_md.set_dabr = pseries_set_dabr;
520 else if (firmware_has_feature(FW_FEATURE_XDABR)) 521 else if (firmware_has_feature(FW_FEATURE_XDABR))
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c
index cd70be5ff27e..1672db2d1b0e 100644
--- a/arch/powerpc/platforms/pseries/smp.c
+++ b/arch/powerpc/platforms/pseries/smp.c
@@ -206,7 +206,7 @@ static struct smp_ops_t pSeries_mpic_smp_ops = {
206}; 206};
207 207
208static struct smp_ops_t pSeries_xics_smp_ops = { 208static struct smp_ops_t pSeries_xics_smp_ops = {
209 .message_pass = smp_muxed_ipi_message_pass, 209 .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
210 .cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */ 210 .cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
211 .probe = xics_smp_probe, 211 .probe = xics_smp_probe,
212 .kick_cpu = smp_pSeries_kick_cpu, 212 .kick_cpu = smp_pSeries_kick_cpu,