--- /dev/null
+From 2a6515d8d708846591ef0c4bce0e226f75aa01a7 Mon Sep 17 00:00:00 2001
+From: David S. Miller <davem@davemloft.net>
+Date: Sun, 19 Sep 2010 17:50:44 -0700
+Subject: sparc64: Get rid of indirect p1275 PROM call buffer.
+
+From: David S. Miller <davem@davemloft.net>
+
+[ Upstream commit 25edd6946a1d74e5e77813c2324a0908c68bcf9e ]
+
+This is based upon a report by Meelis Roos showing that it's possible
+that we'll try to fetch a property that is 32K in size with some
+devices. With the current fixed 3K buffer we use for moving data in
+and out of the firmware during PROM calls, that simply won't work.
+
+In fact, it will scramble random kernel data during bootup.
+
+The reasoning behind the temporary buffer is entirely historical. It
+used to be the case that we had problems referencing dynamic kernel
+memory (including the stack) early in the boot process before we
+explicitly told the firwmare to switch us over to the kernel trap
+table.
+
+So what we did was always give the firmware buffers that were locked
+into the main kernel image.
+
+But we no longer have problems like that, so get rid of all of this
+indirect bounce buffering.
+
+Besides fixing Meelis's bug, this also makes the kernel data about 3K
+smaller.
+
+It was also discovered during these conversions that the
+implementation of prom_retain() was completely wrong, so that was
+fixed here as well. Currently that interface is not in use.
+
+Reported-by: Meelis Roos <mroos@linux.ee>
+Tested-by: Meelis Roos <mroos@linux.ee>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/include/asm/oplib_64.h | 27 ---
+ arch/sparc/prom/cif.S | 16 -
+ arch/sparc/prom/console_64.c | 48 ++++-
+ arch/sparc/prom/devops_64.c | 36 +++-
+ arch/sparc/prom/misc_64.c | 314 ++++++++++++++++++++++++++------------
+ arch/sparc/prom/p1275.c | 102 ------------
+ arch/sparc/prom/tree_64.c | 210 ++++++++++++++++++-------
+ 7 files changed, 456 insertions(+), 297 deletions(-)
+
+--- a/arch/sparc/include/asm/oplib_64.h
++++ b/arch/sparc/include/asm/oplib_64.h
+@@ -185,9 +185,8 @@ extern int prom_getunumber(int syndrome_
+ char *buf, int buflen);
+
+ /* Retain physical memory to the caller across soft resets. */
+-extern unsigned long prom_retain(const char *name,
+- unsigned long pa_low, unsigned long pa_high,
+- long size, long align);
++extern int prom_retain(const char *name, unsigned long size,
++ unsigned long align, unsigned long *paddr);
+
+ /* Load explicit I/D TLB entries into the calling processor. */
+ extern long prom_itlb_load(unsigned long index,
+@@ -287,26 +286,6 @@ extern void prom_sun4v_guest_soft_state(
+ extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
+
+ /* Client interface level routines. */
+-extern long p1275_cmd(const char *, long, ...);
+-
+-#if 0
+-#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
+-#else
+-#define P1275_SIZE(x) x
+-#endif
+-
+-/* We support at most 16 input and 1 output argument */
+-#define P1275_ARG_NUMBER 0
+-#define P1275_ARG_IN_STRING 1
+-#define P1275_ARG_OUT_BUF 2
+-#define P1275_ARG_OUT_32B 3
+-#define P1275_ARG_IN_FUNCTION 4
+-#define P1275_ARG_IN_BUF 5
+-#define P1275_ARG_IN_64B 6
+-
+-#define P1275_IN(x) ((x) & 0xf)
+-#define P1275_OUT(x) (((x) << 4) & 0xf0)
+-#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
+-#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
++extern void p1275_cmd_direct(unsigned long *);
+
+ #endif /* !(__SPARC64_OPLIB_H) */
+--- a/arch/sparc/prom/cif.S
++++ b/arch/sparc/prom/cif.S
+@@ -9,18 +9,18 @@
+ #include <asm/thread_info.h>
+
+ .text
+- .globl prom_cif_interface
+-prom_cif_interface:
+- sethi %hi(p1275buf), %o0
+- or %o0, %lo(p1275buf), %o0
+- ldx [%o0 + 0x010], %o1 ! prom_cif_stack
+- save %o1, -192, %sp
+- ldx [%i0 + 0x008], %l2 ! prom_cif_handler
++ .globl prom_cif_direct
++prom_cif_direct:
++ sethi %hi(p1275buf), %o1
++ or %o1, %lo(p1275buf), %o1
++ ldx [%o1 + 0x0010], %o2 ! prom_cif_stack
++ save %o2, -192, %sp
++ ldx [%i1 + 0x0008], %l2 ! prom_cif_handler
+ mov %g4, %l0
+ mov %g5, %l1
+ mov %g6, %l3
+ call %l2
+- add %i0, 0x018, %o0 ! prom_args
++ mov %i0, %o0 ! prom_args
+ mov %l0, %g4
+ mov %l1, %g5
+ mov %l3, %g6
+--- a/arch/sparc/prom/console_64.c
++++ b/arch/sparc/prom/console_64.c
+@@ -21,14 +21,22 @@ extern int prom_stdin, prom_stdout;
+ inline int
+ prom_nbgetchar(void)
+ {
++ unsigned long args[7];
+ char inc;
+
+- if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
+- P1275_INOUT(3,1),
+- prom_stdin, &inc, P1275_SIZE(1)) == 1)
++ args[0] = (unsigned long) "read";
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) prom_stdin;
++ args[4] = (unsigned long) &inc;
++ args[5] = 1;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ if (args[6] == 1)
+ return inc;
+- else
+- return -1;
++ return -1;
+ }
+
+ /* Non blocking put character to console device, returns -1 if
+@@ -37,12 +45,22 @@ prom_nbgetchar(void)
+ inline int
+ prom_nbputchar(char c)
+ {
++ unsigned long args[7];
+ char outc;
+
+ outc = c;
+- if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
+- P1275_INOUT(3,1),
+- prom_stdout, &outc, P1275_SIZE(1)) == 1)
++
++ args[0] = (unsigned long) "write";
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) prom_stdout;
++ args[4] = (unsigned long) &outc;
++ args[5] = 1;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ if (args[6] == 1)
+ return 0;
+ else
+ return -1;
+@@ -68,7 +86,15 @@ prom_putchar(char c)
+ void
+ prom_puts(const char *s, int len)
+ {
+- p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
+- P1275_INOUT(3,1),
+- prom_stdout, s, P1275_SIZE(len));
++ unsigned long args[7];
++
++ args[0] = (unsigned long) "write";
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) prom_stdout;
++ args[4] = (unsigned long) s;
++ args[5] = len;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
+ }
+--- a/arch/sparc/prom/devops_64.c
++++ b/arch/sparc/prom/devops_64.c
+@@ -18,16 +18,32 @@
+ int
+ prom_devopen(const char *dstr)
+ {
+- return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
+- P1275_INOUT(1,1),
+- dstr);
++ unsigned long args[5];
++
++ args[0] = (unsigned long) "open";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned long) dstr;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[4];
+ }
+
+ /* Close the device described by device handle 'dhandle'. */
+ int
+ prom_devclose(int dhandle)
+ {
+- p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
++ unsigned long args[4];
++
++ args[0] = (unsigned long) "close";
++ args[1] = 1;
++ args[2] = 0;
++ args[3] = (unsigned int) dhandle;
++
++ p1275_cmd_direct(args);
++
+ return 0;
+ }
+
+@@ -37,5 +53,15 @@ prom_devclose(int dhandle)
+ void
+ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
+ {
+- p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
++ unsigned long args[7];
++
++ args[0] = (unsigned long) "seek";
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) dhandle;
++ args[4] = seekhi;
++ args[5] = seeklo;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
+ }
+--- a/arch/sparc/prom/misc_64.c
++++ b/arch/sparc/prom/misc_64.c
+@@ -20,10 +20,17 @@
+
+ int prom_service_exists(const char *service_name)
+ {
+- int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_INOUT(1, 1), service_name);
++ unsigned long args[5];
+
+- if (err)
++ args[0] = (unsigned long) "test";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned long) service_name;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ if (args[4])
+ return 0;
+ return 1;
+ }
+@@ -31,30 +38,47 @@ int prom_service_exists(const char *serv
+ void prom_sun4v_guest_soft_state(void)
+ {
+ const char *svc = "SUNW,soft-state-supported";
++ unsigned long args[3];
+
+ if (!prom_service_exists(svc))
+ return;
+- p1275_cmd(svc, P1275_INOUT(0, 0));
++ args[0] = (unsigned long) svc;
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+ }
+
+ /* Reset and reboot the machine with the command 'bcommand'. */
+ void prom_reboot(const char *bcommand)
+ {
++ unsigned long args[4];
++
+ #ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_reboot(bcommand);
+ #endif
+- p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_INOUT(1, 0), bcommand);
++ args[0] = (unsigned long) "boot";
++ args[1] = 1;
++ args[2] = 0;
++ args[3] = (unsigned long) bcommand;
++
++ p1275_cmd_direct(args);
+ }
+
+ /* Forth evaluate the expression contained in 'fstring'. */
+ void prom_feval(const char *fstring)
+ {
++ unsigned long args[5];
++
+ if (!fstring || fstring[0] == 0)
+ return;
+- p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_INOUT(1, 1), fstring);
++ args[0] = (unsigned long) "interpret";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned long) fstring;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
+ }
+ EXPORT_SYMBOL(prom_feval);
+
+@@ -68,6 +92,7 @@ extern void smp_release(void);
+ */
+ void prom_cmdline(void)
+ {
++ unsigned long args[3];
+ unsigned long flags;
+
+ local_irq_save(flags);
+@@ -76,7 +101,11 @@ void prom_cmdline(void)
+ smp_capture();
+ #endif
+
+- p1275_cmd("enter", P1275_INOUT(0, 0));
++ args[0] = (unsigned long) "enter";
++ args[1] = 0;
++ args[2] = 0;
++
++ p1275_cmd_direct(args);
+
+ #ifdef CONFIG_SMP
+ smp_release();
+@@ -90,22 +119,32 @@ void prom_cmdline(void)
+ */
+ void notrace prom_halt(void)
+ {
++ unsigned long args[3];
++
+ #ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+ #endif
+ again:
+- p1275_cmd("exit", P1275_INOUT(0, 0));
++ args[0] = (unsigned long) "exit";
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+ goto again; /* PROM is out to get me -DaveM */
+ }
+
+ void prom_halt_power_off(void)
+ {
++ unsigned long args[3];
++
+ #ifdef CONFIG_SUN_LDOMS
+ if (ldom_domaining_enabled)
+ ldom_power_off();
+ #endif
+- p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
++ args[0] = (unsigned long) "SUNW,power-off";
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+
+ /* if nothing else helps, we just halt */
+ prom_halt();
+@@ -114,10 +153,15 @@ void prom_halt_power_off(void)
+ /* Set prom sync handler to call function 'funcp'. */
+ void prom_setcallback(callback_func_t funcp)
+ {
++ unsigned long args[5];
+ if (!funcp)
+ return;
+- p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
+- P1275_INOUT(1, 1), funcp);
++ args[0] = (unsigned long) "set-callback";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned long) funcp;
++ args[4] = (unsigned long) -1;
++ p1275_cmd_direct(args);
+ }
+
+ /* Get the idprom and stuff it into buffer 'idbuf'. Returns the
+@@ -173,57 +217,61 @@ static int prom_get_memory_ihandle(void)
+ }
+
+ /* Load explicit I/D TLB entries. */
++static long tlb_load(const char *type, unsigned long index,
++ unsigned long tte_data, unsigned long vaddr)
++{
++ unsigned long args[9];
++
++ args[0] = (unsigned long) prom_callmethod_name;
++ args[1] = 5;
++ args[2] = 1;
++ args[3] = (unsigned long) type;
++ args[4] = (unsigned int) prom_get_mmu_ihandle();
++ args[5] = vaddr;
++ args[6] = tte_data;
++ args[7] = index;
++ args[8] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (long) args[8];
++}
++
+ long prom_itlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+ {
+- return p1275_cmd(prom_callmethod_name,
+- (P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_ARG(2, P1275_ARG_IN_64B) |
+- P1275_ARG(3, P1275_ARG_IN_64B) |
+- P1275_INOUT(5, 1)),
+- "SUNW,itlb-load",
+- prom_get_mmu_ihandle(),
+- /* And then our actual args are pushed backwards. */
+- vaddr,
+- tte_data,
+- index);
++ return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
+ }
+
+ long prom_dtlb_load(unsigned long index,
+ unsigned long tte_data,
+ unsigned long vaddr)
+ {
+- return p1275_cmd(prom_callmethod_name,
+- (P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_ARG(2, P1275_ARG_IN_64B) |
+- P1275_ARG(3, P1275_ARG_IN_64B) |
+- P1275_INOUT(5, 1)),
+- "SUNW,dtlb-load",
+- prom_get_mmu_ihandle(),
+- /* And then our actual args are pushed backwards. */
+- vaddr,
+- tte_data,
+- index);
++ return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
+ }
+
+ int prom_map(int mode, unsigned long size,
+ unsigned long vaddr, unsigned long paddr)
+ {
+- int ret = p1275_cmd(prom_callmethod_name,
+- (P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_ARG(3, P1275_ARG_IN_64B) |
+- P1275_ARG(4, P1275_ARG_IN_64B) |
+- P1275_ARG(6, P1275_ARG_IN_64B) |
+- P1275_INOUT(7, 1)),
+- prom_map_name,
+- prom_get_mmu_ihandle(),
+- mode,
+- size,
+- vaddr,
+- 0,
+- paddr);
++ unsigned long args[11];
++ int ret;
+
++ args[0] = (unsigned long) prom_callmethod_name;
++ args[1] = 7;
++ args[2] = 1;
++ args[3] = (unsigned long) prom_map_name;
++ args[4] = (unsigned int) prom_get_mmu_ihandle();
++ args[5] = (unsigned int) mode;
++ args[6] = size;
++ args[7] = vaddr;
++ args[8] = 0;
++ args[9] = paddr;
++ args[10] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ ret = (int) args[10];
+ if (ret == 0)
+ ret = -1;
+ return ret;
+@@ -231,40 +279,51 @@ int prom_map(int mode, unsigned long siz
+
+ void prom_unmap(unsigned long size, unsigned long vaddr)
+ {
+- p1275_cmd(prom_callmethod_name,
+- (P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_ARG(2, P1275_ARG_IN_64B) |
+- P1275_ARG(3, P1275_ARG_IN_64B) |
+- P1275_INOUT(4, 0)),
+- prom_unmap_name,
+- prom_get_mmu_ihandle(),
+- size,
+- vaddr);
++ unsigned long args[7];
++
++ args[0] = (unsigned long) prom_callmethod_name;
++ args[1] = 4;
++ args[2] = 0;
++ args[3] = (unsigned long) prom_unmap_name;
++ args[4] = (unsigned int) prom_get_mmu_ihandle();
++ args[5] = size;
++ args[6] = vaddr;
++
++ p1275_cmd_direct(args);
+ }
+
+ /* Set aside physical memory which is not touched or modified
+ * across soft resets.
+ */
+-unsigned long prom_retain(const char *name,
+- unsigned long pa_low, unsigned long pa_high,
+- long size, long align)
+-{
+- /* XXX I don't think we return multiple values correctly.
+- * XXX OBP supposedly returns pa_low/pa_high here, how does
+- * XXX it work?
+- */
++int prom_retain(const char *name, unsigned long size,
++ unsigned long align, unsigned long *paddr)
++{
++ unsigned long args[11];
+
+- /* If align is zero, the pa_low/pa_high args are passed,
+- * else they are not.
++ args[0] = (unsigned long) prom_callmethod_name;
++ args[1] = 5;
++ args[2] = 3;
++ args[3] = (unsigned long) "SUNW,retain";
++ args[4] = (unsigned int) prom_get_memory_ihandle();
++ args[5] = align;
++ args[6] = size;
++ args[7] = (unsigned long) name;
++ args[8] = (unsigned long) -1;
++ args[9] = (unsigned long) -1;
++ args[10] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ if (args[8])
++ return (int) args[8];
++
++ /* Next we get "phys_high" then "phys_low". On 64-bit
++ * the phys_high cell is don't care since the phys_low
++ * cell has the full value.
+ */
+- if (align == 0)
+- return p1275_cmd("SUNW,retain",
+- (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
+- name, pa_low, pa_high, size, align);
+- else
+- return p1275_cmd("SUNW,retain",
+- (P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
+- name, size, align);
++ *paddr = args[10];
++
++ return 0;
+ }
+
+ /* Get "Unumber" string for the SIMM at the given
+@@ -277,62 +336,129 @@ int prom_getunumber(int syndrome_code,
+ unsigned long phys_addr,
+ char *buf, int buflen)
+ {
+- return p1275_cmd(prom_callmethod_name,
+- (P1275_ARG(0, P1275_ARG_IN_STRING) |
+- P1275_ARG(3, P1275_ARG_OUT_BUF) |
+- P1275_ARG(6, P1275_ARG_IN_64B) |
+- P1275_INOUT(8, 2)),
+- "SUNW,get-unumber", prom_get_memory_ihandle(),
+- buflen, buf, P1275_SIZE(buflen),
+- 0, phys_addr, syndrome_code);
++ unsigned long args[12];
++
++ args[0] = (unsigned long) prom_callmethod_name;
++ args[1] = 7;
++ args[2] = 2;
++ args[3] = (unsigned long) "SUNW,get-unumber";
++ args[4] = (unsigned int) prom_get_memory_ihandle();
++ args[5] = buflen;
++ args[6] = (unsigned long) buf;
++ args[7] = 0;
++ args[8] = phys_addr;
++ args[9] = (unsigned int) syndrome_code;
++ args[10] = (unsigned long) -1;
++ args[11] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[10];
+ }
+
+ /* Power management extensions. */
+ void prom_sleepself(void)
+ {
+- p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
++ unsigned long args[3];
++
++ args[0] = (unsigned long) "SUNW,sleep-self";
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+ }
+
+ int prom_sleepsystem(void)
+ {
+- return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
++ unsigned long args[4];
++
++ args[0] = (unsigned long) "SUNW,sleep-system";
++ args[1] = 0;
++ args[2] = 1;
++ args[3] = (unsigned long) -1;
++ p1275_cmd_direct(args);
++
++ return (int) args[3];
+ }
+
+ int prom_wakeupsystem(void)
+ {
+- return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
++ unsigned long args[4];
++
++ args[0] = (unsigned long) "SUNW,wakeup-system";
++ args[1] = 0;
++ args[2] = 1;
++ args[3] = (unsigned long) -1;
++ p1275_cmd_direct(args);
++
++ return (int) args[3];
+ }
+
+ #ifdef CONFIG_SMP
+ void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
+ {
+- p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
++ unsigned long args[6];
++
++ args[0] = (unsigned long) "SUNW,start-cpu";
++ args[1] = 3;
++ args[2] = 0;
++ args[3] = (unsigned int) cpunode;
++ args[4] = pc;
++ args[5] = arg;
++ p1275_cmd_direct(args);
+ }
+
+ void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
+ {
+- p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
+- cpuid, pc, arg);
++ unsigned long args[6];
++
++ args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
++ args[1] = 3;
++ args[2] = 0;
++ args[3] = (unsigned int) cpuid;
++ args[4] = pc;
++ args[5] = arg;
++ p1275_cmd_direct(args);
+ }
+
+ void prom_stopcpu_cpuid(int cpuid)
+ {
+- p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
+- cpuid);
++ unsigned long args[4];
++
++ args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
++ args[1] = 1;
++ args[2] = 0;
++ args[3] = (unsigned int) cpuid;
++ p1275_cmd_direct(args);
+ }
+
+ void prom_stopself(void)
+ {
+- p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
++ unsigned long args[3];
++
++ args[0] = (unsigned long) "SUNW,stop-self";
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+ }
+
+ void prom_idleself(void)
+ {
+- p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
++ unsigned long args[3];
++
++ args[0] = (unsigned long) "SUNW,idle-self";
++ args[1] = 0;
++ args[2] = 0;
++ p1275_cmd_direct(args);
+ }
+
+ void prom_resumecpu(int cpunode)
+ {
+- p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
++ unsigned long args[4];
++
++ args[0] = (unsigned long) "SUNW,resume-cpu";
++ args[1] = 1;
++ args[2] = 0;
++ args[3] = (unsigned int) cpunode;
++ p1275_cmd_direct(args);
+ }
+ #endif
+--- a/arch/sparc/prom/p1275.c
++++ b/arch/sparc/prom/p1275.c
+@@ -22,13 +22,11 @@ struct {
+ long prom_callback; /* 0x00 */
+ void (*prom_cif_handler)(long *); /* 0x08 */
+ unsigned long prom_cif_stack; /* 0x10 */
+- unsigned long prom_args [23]; /* 0x18 */
+- char prom_buffer [3000];
+ } p1275buf;
+
+ extern void prom_world(int);
+
+-extern void prom_cif_interface(void);
++extern void prom_cif_direct(unsigned long *args);
+ extern void prom_cif_callback(void);
+
+ /*
+@@ -36,114 +34,20 @@ extern void prom_cif_callback(void);
+ */
+ DEFINE_SPINLOCK(prom_entry_lock);
+
+-long p1275_cmd(const char *service, long fmt, ...)
++void p1275_cmd_direct(unsigned long *args)
+ {
+- char *p, *q;
+ unsigned long flags;
+- int nargs, nrets, i;
+- va_list list;
+- long attrs, x;
+-
+- p = p1275buf.prom_buffer;
+
+ raw_local_save_flags(flags);
+ raw_local_irq_restore(PIL_NMI);
+ spin_lock(&prom_entry_lock);
+
+- p1275buf.prom_args[0] = (unsigned long)p; /* service */
+- strcpy (p, service);
+- p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
+- p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */
+- p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */
+- attrs = fmt >> 8;
+- va_start(list, fmt);
+- for (i = 0; i < nargs; i++, attrs >>= 3) {
+- switch (attrs & 0x7) {
+- case P1275_ARG_NUMBER:
+- p1275buf.prom_args[i + 3] =
+- (unsigned)va_arg(list, long);
+- break;
+- case P1275_ARG_IN_64B:
+- p1275buf.prom_args[i + 3] =
+- va_arg(list, unsigned long);
+- break;
+- case P1275_ARG_IN_STRING:
+- strcpy (p, va_arg(list, char *));
+- p1275buf.prom_args[i + 3] = (unsigned long)p;
+- p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
+- break;
+- case P1275_ARG_OUT_BUF:
+- (void) va_arg(list, char *);
+- p1275buf.prom_args[i + 3] = (unsigned long)p;
+- x = va_arg(list, long);
+- i++; attrs >>= 3;
+- p = (char *)(((long)(p + (int)x + 7)) & ~7);
+- p1275buf.prom_args[i + 3] = x;
+- break;
+- case P1275_ARG_IN_BUF:
+- q = va_arg(list, char *);
+- p1275buf.prom_args[i + 3] = (unsigned long)p;
+- x = va_arg(list, long);
+- i++; attrs >>= 3;
+- memcpy (p, q, (int)x);
+- p = (char *)(((long)(p + (int)x + 7)) & ~7);
+- p1275buf.prom_args[i + 3] = x;
+- break;
+- case P1275_ARG_OUT_32B:
+- (void) va_arg(list, char *);
+- p1275buf.prom_args[i + 3] = (unsigned long)p;
+- p += 32;
+- break;
+- case P1275_ARG_IN_FUNCTION:
+- p1275buf.prom_args[i + 3] =
+- (unsigned long)prom_cif_callback;
+- p1275buf.prom_callback = va_arg(list, long);
+- break;
+- }
+- }
+- va_end(list);
+-
+ prom_world(1);
+- prom_cif_interface();
++ prom_cif_direct(args);
+ prom_world(0);
+
+- attrs = fmt >> 8;
+- va_start(list, fmt);
+- for (i = 0; i < nargs; i++, attrs >>= 3) {
+- switch (attrs & 0x7) {
+- case P1275_ARG_NUMBER:
+- (void) va_arg(list, long);
+- break;
+- case P1275_ARG_IN_STRING:
+- (void) va_arg(list, char *);
+- break;
+- case P1275_ARG_IN_FUNCTION:
+- (void) va_arg(list, long);
+- break;
+- case P1275_ARG_IN_BUF:
+- (void) va_arg(list, char *);
+- (void) va_arg(list, long);
+- i++; attrs >>= 3;
+- break;
+- case P1275_ARG_OUT_BUF:
+- p = va_arg(list, char *);
+- x = va_arg(list, long);
+- memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
+- i++; attrs >>= 3;
+- break;
+- case P1275_ARG_OUT_32B:
+- p = va_arg(list, char *);
+- memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
+- break;
+- }
+- }
+- va_end(list);
+- x = p1275buf.prom_args [nargs + 3];
+-
+ spin_unlock(&prom_entry_lock);
+ raw_local_irq_restore(flags);
+-
+- return x;
+ }
+
+ void prom_cif_init(void *cif_handler, void *cif_stack)
+--- a/arch/sparc/prom/tree_64.c
++++ b/arch/sparc/prom/tree_64.c
+@@ -16,22 +16,39 @@
+ #include <asm/oplib.h>
+ #include <asm/ldc.h>
+
++static int prom_node_to_node(const char *type, int node)
++{
++ unsigned long args[5];
++
++ args[0] = (unsigned long) type;
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[4];
++}
++
+ /* Return the child of node 'node' or zero if no this node has no
+ * direct descendent.
+ */
+ inline int __prom_getchild(int node)
+ {
+- return p1275_cmd ("child", P1275_INOUT(1, 1), node);
++ return prom_node_to_node("child", node);
+ }
+
+ inline int prom_getchild(int node)
+ {
+ int cnode;
+
+- if(node == -1) return 0;
++ if (node == -1)
++ return 0;
+ cnode = __prom_getchild(node);
+- if(cnode == -1) return 0;
+- return (int)cnode;
++ if (cnode == -1)
++ return 0;
++ return cnode;
+ }
+ EXPORT_SYMBOL(prom_getchild);
+
+@@ -39,10 +56,12 @@ inline int prom_getparent(int node)
+ {
+ int cnode;
+
+- if(node == -1) return 0;
+- cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
+- if(cnode == -1) return 0;
+- return (int)cnode;
++ if (node == -1)
++ return 0;
++ cnode = prom_node_to_node("parent", node);
++ if (cnode == -1)
++ return 0;
++ return cnode;
+ }
+
+ /* Return the next sibling of node 'node' or zero if no more siblings
+@@ -50,7 +69,7 @@ inline int prom_getparent(int node)
+ */
+ inline int __prom_getsibling(int node)
+ {
+- return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
++ return prom_node_to_node(prom_peer_name, node);
+ }
+
+ inline int prom_getsibling(int node)
+@@ -72,11 +91,21 @@ EXPORT_SYMBOL(prom_getsibling);
+ */
+ inline int prom_getproplen(int node, const char *prop)
+ {
+- if((!node) || (!prop)) return -1;
+- return p1275_cmd ("getproplen",
+- P1275_ARG(1,P1275_ARG_IN_STRING)|
+- P1275_INOUT(2, 1),
+- node, prop);
++ unsigned long args[6];
++
++ if (!node || !prop)
++ return -1;
++
++ args[0] = (unsigned long) "getproplen";
++ args[1] = 2;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = (unsigned long) prop;
++ args[5] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[5];
+ }
+ EXPORT_SYMBOL(prom_getproplen);
+
+@@ -87,19 +116,25 @@ EXPORT_SYMBOL(prom_getproplen);
+ inline int prom_getproperty(int node, const char *prop,
+ char *buffer, int bufsize)
+ {
++ unsigned long args[8];
+ int plen;
+
+ plen = prom_getproplen(node, prop);
+- if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
++ if ((plen > bufsize) || (plen == 0) || (plen == -1))
+ return -1;
+- } else {
+- /* Ok, things seem all right. */
+- return p1275_cmd(prom_getprop_name,
+- P1275_ARG(1,P1275_ARG_IN_STRING)|
+- P1275_ARG(2,P1275_ARG_OUT_BUF)|
+- P1275_INOUT(4, 1),
+- node, prop, buffer, P1275_SIZE(plen));
+- }
++
++ args[0] = (unsigned long) prom_getprop_name;
++ args[1] = 4;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = (unsigned long) prop;
++ args[5] = (unsigned long) buffer;
++ args[6] = bufsize;
++ args[7] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[7];
+ }
+ EXPORT_SYMBOL(prom_getproperty);
+
+@@ -110,7 +145,7 @@ inline int prom_getint(int node, const c
+ {
+ int intprop;
+
+- if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
++ if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
+ return intprop;
+
+ return -1;
+@@ -126,7 +161,8 @@ int prom_getintdefault(int node, const c
+ int retval;
+
+ retval = prom_getint(node, property);
+- if(retval == -1) return deflt;
++ if (retval == -1)
++ return deflt;
+
+ return retval;
+ }
+@@ -138,7 +174,8 @@ int prom_getbool(int node, const char *p
+ int retval;
+
+ retval = prom_getproplen(node, prop);
+- if(retval == -1) return 0;
++ if (retval == -1)
++ return 0;
+ return 1;
+ }
+ EXPORT_SYMBOL(prom_getbool);
+@@ -152,7 +189,8 @@ void prom_getstring(int node, const char
+ int len;
+
+ len = prom_getproperty(node, prop, user_buf, ubuf_size);
+- if(len != -1) return;
++ if (len != -1)
++ return;
+ user_buf[0] = 0;
+ return;
+ }
+@@ -165,7 +203,8 @@ int prom_nodematch(int node, const char
+ {
+ char namebuf[128];
+ prom_getproperty(node, "name", namebuf, sizeof(namebuf));
+- if(strcmp(namebuf, name) == 0) return 1;
++ if (strcmp(namebuf, name) == 0)
++ return 1;
+ return 0;
+ }
+
+@@ -191,16 +230,29 @@ int prom_searchsiblings(int node_start,
+ }
+ EXPORT_SYMBOL(prom_searchsiblings);
+
++static const char *prom_nextprop_name = "nextprop";
++
+ /* Return the first property type for node 'node'.
+ * buffer should be at least 32B in length
+ */
+ inline char *prom_firstprop(int node, char *buffer)
+ {
++ unsigned long args[7];
++
+ *buffer = 0;
+- if(node == -1) return buffer;
+- p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
+- P1275_INOUT(3, 0),
+- node, (char *) 0x0, buffer);
++ if (node == -1)
++ return buffer;
++
++ args[0] = (unsigned long) prom_nextprop_name;
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = 0;
++ args[5] = (unsigned long) buffer;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
+ return buffer;
+ }
+ EXPORT_SYMBOL(prom_firstprop);
+@@ -211,9 +263,10 @@ EXPORT_SYMBOL(prom_firstprop);
+ */
+ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
+ {
++ unsigned long args[7];
+ char buf[32];
+
+- if(node == -1) {
++ if (node == -1) {
+ *buffer = 0;
+ return buffer;
+ }
+@@ -221,10 +274,17 @@ inline char *prom_nextprop(int node, con
+ strcpy (buf, oprop);
+ oprop = buf;
+ }
+- p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
+- P1275_ARG(2,P1275_ARG_OUT_32B)|
+- P1275_INOUT(3, 0),
+- node, oprop, buffer);
++
++ args[0] = (unsigned long) prom_nextprop_name;
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = (unsigned long) oprop;
++ args[5] = (unsigned long) buffer;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
+ return buffer;
+ }
+ EXPORT_SYMBOL(prom_nextprop);
+@@ -232,12 +292,19 @@ EXPORT_SYMBOL(prom_nextprop);
+ int
+ prom_finddevice(const char *name)
+ {
++ unsigned long args[5];
++
+ if (!name)
+ return 0;
+- return p1275_cmd(prom_finddev_name,
+- P1275_ARG(0,P1275_ARG_IN_STRING)|
+- P1275_INOUT(1, 1),
+- name);
++ args[0] = (unsigned long) "finddevice";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned long) name;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[4];
+ }
+ EXPORT_SYMBOL(prom_finddevice);
+
+@@ -248,7 +315,7 @@ int prom_node_has_property(int node, con
+ *buf = 0;
+ do {
+ prom_nextprop(node, buf, buf);
+- if(!strcmp(buf, prop))
++ if (!strcmp(buf, prop))
+ return 1;
+ } while (*buf);
+ return 0;
+@@ -261,6 +328,8 @@ EXPORT_SYMBOL(prom_node_has_property);
+ int
+ prom_setprop(int node, const char *pname, char *value, int size)
+ {
++ unsigned long args[8];
++
+ if (size == 0)
+ return 0;
+ if ((pname == 0) || (value == 0))
+@@ -272,19 +341,37 @@ prom_setprop(int node, const char *pname
+ return 0;
+ }
+ #endif
+- return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
+- P1275_ARG(2,P1275_ARG_IN_BUF)|
+- P1275_INOUT(4, 1),
+- node, pname, value, P1275_SIZE(size));
++ args[0] = (unsigned long) "setprop";
++ args[1] = 4;
++ args[2] = 1;
++ args[3] = (unsigned int) node;
++ args[4] = (unsigned long) pname;
++ args[5] = (unsigned long) value;
++ args[6] = size;
++ args[7] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[7];
+ }
+ EXPORT_SYMBOL(prom_setprop);
+
+ inline int prom_inst2pkg(int inst)
+ {
++ unsigned long args[5];
+ int node;
+
+- node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
+- if (node == -1) return 0;
++ args[0] = (unsigned long) "instance-to-package";
++ args[1] = 1;
++ args[2] = 1;
++ args[3] = (unsigned int) inst;
++ args[4] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ node = (int) args[4];
++ if (node == -1)
++ return 0;
+ return node;
+ }
+
+@@ -297,17 +384,28 @@ prom_pathtoinode(const char *path)
+ int node, inst;
+
+ inst = prom_devopen (path);
+- if (inst == 0) return 0;
+- node = prom_inst2pkg (inst);
+- prom_devclose (inst);
+- if (node == -1) return 0;
++ if (inst == 0)
++ return 0;
++ node = prom_inst2pkg(inst);
++ prom_devclose(inst);
++ if (node == -1)
++ return 0;
+ return node;
+ }
+
+ int prom_ihandle2path(int handle, char *buffer, int bufsize)
+ {
+- return p1275_cmd("instance-to-path",
+- P1275_ARG(1,P1275_ARG_OUT_BUF)|
+- P1275_INOUT(3, 1),
+- handle, buffer, P1275_SIZE(bufsize));
++ unsigned long args[7];
++
++ args[0] = (unsigned long) "instance-to-path";
++ args[1] = 3;
++ args[2] = 1;
++ args[3] = (unsigned int) handle;
++ args[4] = (unsigned long) buffer;
++ args[5] = bufsize;
++ args[6] = (unsigned long) -1;
++
++ p1275_cmd_direct(args);
++
++ return (int) args[6];
+ }