summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-25 22:59:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-25 22:59:39 -0700
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)
if (!dn->parent)
return -ENOMEM;
- rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_ADD, dn);
- if (rc == NOTIFY_BAD) {
+ rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn);
+ if (rc) {
printk(KERN_ERR "Failed to add device node %s\n",
dn->full_name);
- return -ENOMEM; /* For now, safe to assume kmalloc failure */
+ return rc;
}
of_attach_node(dn);
@@ -297,8 +296,7 @@ int dlpar_detach_node(struct device_node *dn)
remove_proc_entry(dn->pde->name, parent->pde);
#endif
- blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_REMOVE, dn);
+ pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, dn);
of_detach_node(dn);
of_node_put(dn); /* Must decrement the refcount */
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)
static int pseries_smp_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
- int err = NOTIFY_OK;
+ int err = 0;
switch (action) {
case PSERIES_RECONFIG_ADD:
- if (pseries_add_processor(node))
- err = NOTIFY_BAD;
+ err = pseries_add_processor(node);
break;
case PSERIES_RECONFIG_REMOVE:
pseries_remove_processor(node);
break;
- default:
- err = NOTIFY_DONE;
- break;
}
- return err;
+ return notifier_from_errno(err);
}
static 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)
static int pseries_memory_notifier(struct notifier_block *nb,
unsigned long action, void *node)
{
- int err = NOTIFY_OK;
+ int err = 0;
switch (action) {
case PSERIES_RECONFIG_ADD:
- if (pseries_add_memory(node))
- err = NOTIFY_BAD;
+ err = pseries_add_memory(node);
break;
case PSERIES_RECONFIG_REMOVE:
- if (pseries_remove_memory(node))
- err = NOTIFY_BAD;
+ err = pseries_remove_memory(node);
break;
case PSERIES_DRCONF_MEM_ADD:
case PSERIES_DRCONF_MEM_REMOVE:
- if (pseries_drconf_memory(node, action))
- err = NOTIFY_BAD;
- break;
- default:
- err = NOTIFY_DONE;
+ err = pseries_drconf_memory(node, action);
break;
}
- return err;
+ return notifier_from_errno(err);
}
static 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)
if (ret == H_SUCCESS)
return count;
if (ret == H_BUSY)
- return 0;
+ return -EAGAIN;
return -EIO;
}
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);
extern void pSeries_find_serial_port(void);
-
-static int vtermno; /* virtual terminal# for udbg */
-
-#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
-static void udbg_hvsi_putc(char c)
-{
- /* packet's seqno isn't used anyways */
- uint8_t packet[] __ALIGNED__ = { 0xff, 5, 0, 0, c };
- int rc;
-
- if (c == '\n')
- udbg_hvsi_putc('\r');
-
- do {
- rc = plpar_put_term_char(vtermno, sizeof(packet), packet);
- } while (rc == H_BUSY);
-}
-
-static long hvsi_udbg_buf_len;
-static uint8_t hvsi_udbg_buf[256];
-
-static int udbg_hvsi_getc_poll(void)
-{
- unsigned char ch;
- int rc, i;
-
- if (hvsi_udbg_buf_len == 0) {
- rc = plpar_get_term_char(vtermno, &hvsi_udbg_buf_len, hvsi_udbg_buf);
- if (rc != H_SUCCESS || hvsi_udbg_buf[0] != 0xff) {
- /* bad read or non-data packet */
- hvsi_udbg_buf_len = 0;
- } else {
- /* remove the packet header */
- for (i = 4; i < hvsi_udbg_buf_len; i++)
- hvsi_udbg_buf[i-4] = hvsi_udbg_buf[i];
- hvsi_udbg_buf_len -= 4;
- }
- }
-
- if (hvsi_udbg_buf_len <= 0 || hvsi_udbg_buf_len > 256) {
- /* no data ready */
- hvsi_udbg_buf_len = 0;
- return -1;
- }
-
- ch = hvsi_udbg_buf[0];
- /* shift remaining data down */
- for (i = 1; i < hvsi_udbg_buf_len; i++) {
- hvsi_udbg_buf[i-1] = hvsi_udbg_buf[i];
- }
- hvsi_udbg_buf_len--;
-
- return ch;
-}
-
-static int udbg_hvsi_getc(void)
-{
- int ch;
- for (;;) {
- ch = udbg_hvsi_getc_poll();
- if (ch == -1) {
- /* This shouldn't be needed...but... */
- volatile unsigned long delay;
- for (delay=0; delay < 2000000; delay++)
- ;
- } else {
- return ch;
- }
- }
-}
-
-static void udbg_putcLP(char c)
-{
- char buf[16];
- unsigned long rc;
-
- if (c == '\n')
- udbg_putcLP('\r');
-
- buf[0] = c;
- do {
- rc = plpar_put_term_char(vtermno, 1, buf);
- } while(rc == H_BUSY);
-}
-
-/* Buffered chars getc */
-static long inbuflen;
-static long inbuf[2]; /* must be 2 longs */
-
-static int udbg_getc_pollLP(void)
-{
- /* The interface is tricky because it may return up to 16 chars.
- * We save them statically for future calls to udbg_getc().
- */
- char ch, *buf = (char *)inbuf;
- int i;
- long rc;
- if (inbuflen == 0) {
- /* get some more chars. */
- inbuflen = 0;
- rc = plpar_get_term_char(vtermno, &inbuflen, buf);
- if (rc != H_SUCCESS)
- inbuflen = 0; /* otherwise inbuflen is garbage */
- }
- if (inbuflen <= 0 || inbuflen > 16) {
- /* Catch error case as well as other oddities (corruption) */
- inbuflen = 0;
- return -1;
- }
- ch = buf[0];
- for (i = 1; i < inbuflen; i++) /* shuffle them down. */
- buf[i-1] = buf[i];
- inbuflen--;
- return ch;
-}
-
-static int udbg_getcLP(void)
-{
- int ch;
- for (;;) {
- ch = udbg_getc_pollLP();
- if (ch == -1) {
- /* This shouldn't be needed...but... */
- volatile unsigned long delay;
- for (delay=0; delay < 2000000; delay++)
- ;
- } else {
- return ch;
- }
- }
-}
-
-/* call this from early_init() for a working debug console on
- * vterm capable LPAR machines
- */
-void __init udbg_init_debug_lpar(void)
-{
- vtermno = 0;
- udbg_putc = udbg_putcLP;
- udbg_getc = udbg_getcLP;
- udbg_getc_poll = udbg_getc_pollLP;
-
- register_early_udbg_console();
-}
-
-/* returns 0 if couldn't find or use /chosen/stdout as console */
-void __init find_udbg_vterm(void)
-{
- struct device_node *stdout_node;
- const u32 *termno;
- const char *name;
-
- /* find the boot console from /chosen/stdout */
- if (!of_chosen)
- return;
- name = of_get_property(of_chosen, "linux,stdout-path", NULL);
- if (name == NULL)
- return;
- stdout_node = of_find_node_by_path(name);
- if (!stdout_node)
- return;
- name = of_get_property(stdout_node, "name", NULL);
- if (!name) {
- printk(KERN_WARNING "stdout node missing 'name' property!\n");
- goto out;
- }
-
- /* Check if it's a virtual terminal */
- if (strncmp(name, "vty", 3) != 0)
- goto out;
- termno = of_get_property(stdout_node, "reg", NULL);
- if (termno == NULL)
- goto out;
- vtermno = termno[0];
-
- if (of_device_is_compatible(stdout_node, "hvterm1")) {
- udbg_putc = udbg_putcLP;
- udbg_getc = udbg_getcLP;
- udbg_getc_poll = udbg_getc_pollLP;
- add_preferred_console("hvc", termno[0] & 0xff, NULL);
- } else if (of_device_is_compatible(stdout_node, "hvterm-protocol")) {
- vtermno = termno[0];
- udbg_putc = udbg_hvsi_putc;
- udbg_getc = udbg_hvsi_getc;
- udbg_getc_poll = udbg_hvsi_getc_poll;
- add_preferred_console("hvsi", termno[0] & 0xff, NULL);
- }
-out:
- of_node_put(stdout_node);
-}
-
void vpa_init(int cpu)
{
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);
/* Poweron flag used for enabling auto ups restart */
extern unsigned long rtas_poweron_auto;
-extern void find_udbg_vterm(void);
+/* Provided by HVC VIO */
+extern void hvc_vio_init_early(void);
/* Dynamic logical Partitioning/Mobility */
extern 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)
return parent;
}
-BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
+static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
int pSeries_reconfig_notifier_register(struct notifier_block *nb)
{
@@ -109,6 +109,14 @@ void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
}
+int pSeries_reconfig_notify(unsigned long action, void *p)
+{
+ int err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
+ action, p);
+
+ return notifier_to_errno(err);
+}
+
static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
{
struct device_node *np;
@@ -132,11 +140,9 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
goto out_err;
}
- err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_ADD, np);
- if (err == NOTIFY_BAD) {
+ err = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, np);
+ if (err) {
printk(KERN_ERR "Failed to add device node %s\n", path);
- err = -ENOMEM; /* For now, safe to assume kmalloc failure */
goto out_err;
}
@@ -173,8 +179,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
remove_node_proc_entries(np);
- blocking_notifier_call_chain(&pSeries_reconfig_chain,
- PSERIES_RECONFIG_REMOVE, np);
+ pSeries_reconfig_notify(PSERIES_RECONFIG_REMOVE, np);
of_detach_node(np);
of_node_put(parent);
@@ -472,11 +477,10 @@ static int do_update_property(char *buf, size_t bufsize)
else
action = PSERIES_DRCONF_MEM_REMOVE;
- rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
- action, value);
- if (rc == NOTIFY_BAD) {
- rc = prom_update_property(np, oldprop, newprop);
- return -ENOMEM;
+ rc = pSeries_reconfig_notify(action, value);
+ if (rc) {
+ prom_update_property(np, oldprop, newprop);
+ return rc;
}
}
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)
{
pr_debug(" -> pSeries_init_early()\n");
+#ifdef CONFIG_HVC_CONSOLE
if (firmware_has_feature(FW_FEATURE_LPAR))
- find_udbg_vterm();
-
+ hvc_vio_init_early();
+#endif
if (firmware_has_feature(FW_FEATURE_DABR))
ppc_md.set_dabr = pseries_set_dabr;
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 = {
};
static struct smp_ops_t pSeries_xics_smp_ops = {
- .message_pass = smp_muxed_ipi_message_pass,
+ .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */
.cause_ipi = NULL, /* Filled at runtime by xics_smp_probe() */
.probe = xics_smp_probe,
.kick_cpu = smp_pSeries_kick_cpu,