diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-24 10:10:13 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-24 10:10:13 -0700 |
commit | 1a7c55368c7c8749aa9326c29a50e79a4eba5d26 (patch) | |
tree | abbbfe79f7362a2f2d2fa478c57f943514338ae2 | |
parent | bd45fe539f0e26ff8d76b4cb954195ab8a6467af (diff) | |
parent | 25edd6946a1d74e5e77813c2324a0908c68bcf9e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6:
sparc64: Get rid of indirect p1275 PROM call buffer.
sparc64: Fill a missing delay slot.
sparc64: Make lock backoff really a NOP on UP builds.
sparc64: simple microoptimizations for atomic functions
sparc64: Make rwsems 64-bit.
sparc64: Really fix atomic64_t interface types.
-rw-r--r-- | arch/sparc/include/asm/atomic_64.h | 8 | ||||
-rw-r--r-- | arch/sparc/include/asm/backoff.h | 11 | ||||
-rw-r--r-- | arch/sparc/include/asm/oplib_64.h | 27 | ||||
-rw-r--r-- | arch/sparc/include/asm/rwsem-const.h | 12 | ||||
-rw-r--r-- | arch/sparc/include/asm/rwsem.h | 120 | ||||
-rw-r--r-- | arch/sparc/include/asm/system_64.h | 1 | ||||
-rw-r--r-- | arch/sparc/lib/Makefile | 2 | ||||
-rw-r--r-- | arch/sparc/lib/atomic_64.S | 36 | ||||
-rw-r--r-- | arch/sparc/lib/bitops.S | 12 | ||||
-rw-r--r-- | arch/sparc/lib/rwsem_64.S | 163 | ||||
-rw-r--r-- | arch/sparc/prom/cif.S | 16 | ||||
-rw-r--r-- | arch/sparc/prom/console_64.c | 48 | ||||
-rw-r--r-- | arch/sparc/prom/devops_64.c | 36 | ||||
-rw-r--r-- | arch/sparc/prom/misc_64.c | 314 | ||||
-rw-r--r-- | arch/sparc/prom/p1275.c | 102 | ||||
-rw-r--r-- | arch/sparc/prom/tree_64.c | 210 |
16 files changed, 595 insertions, 523 deletions
diff --git a/arch/sparc/include/asm/atomic_64.h b/arch/sparc/include/asm/atomic_64.h index f0c74227c73..bdb2ff880bd 100644 --- a/arch/sparc/include/asm/atomic_64.h +++ b/arch/sparc/include/asm/atomic_64.h @@ -20,14 +20,14 @@ #define atomic64_set(v, i) (((v)->counter) = i) extern void atomic_add(int, atomic_t *); -extern void atomic64_add(int, atomic64_t *); +extern void atomic64_add(long, atomic64_t *); extern void atomic_sub(int, atomic_t *); -extern void atomic64_sub(int, atomic64_t *); +extern void atomic64_sub(long, atomic64_t *); extern int atomic_add_ret(int, atomic_t *); -extern long atomic64_add_ret(int, atomic64_t *); +extern long atomic64_add_ret(long, atomic64_t *); extern int atomic_sub_ret(int, atomic_t *); -extern long atomic64_sub_ret(int, atomic64_t *); +extern long atomic64_sub_ret(long, atomic64_t *); #define atomic_dec_return(v) atomic_sub_ret(1, v) #define atomic64_dec_return(v) atomic64_sub_ret(1, v) diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h index fa1fdf67e35..db3af0d30fb 100644 --- a/arch/sparc/include/asm/backoff.h +++ b/arch/sparc/include/asm/backoff.h @@ -8,6 +8,9 @@ #define BACKOFF_SETUP(reg) \ mov 1, reg +#define BACKOFF_LABEL(spin_label, continue_label) \ + spin_label + #define BACKOFF_SPIN(reg, tmp, label) \ mov reg, tmp; \ 88: brnz,pt tmp, 88b; \ @@ -22,9 +25,11 @@ #else #define BACKOFF_SETUP(reg) -#define BACKOFF_SPIN(reg, tmp, label) \ - ba,pt %xcc, label; \ - nop; + +#define BACKOFF_LABEL(spin_label, continue_label) \ + continue_label + +#define BACKOFF_SPIN(reg, tmp, label) #endif diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index a5db0317b5f..3e0b2d62303 100644 --- 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_code, 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(void); 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) */ diff --git a/arch/sparc/include/asm/rwsem-const.h b/arch/sparc/include/asm/rwsem-const.h deleted file mode 100644 index e4c61a18bb2..00000000000 --- a/arch/sparc/include/asm/rwsem-const.h +++ /dev/null @@ -1,12 +0,0 @@ -/* rwsem-const.h: RW semaphore counter constants. */ -#ifndef _SPARC64_RWSEM_CONST_H -#define _SPARC64_RWSEM_CONST_H - -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) -#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) - -#endif /* _SPARC64_RWSEM_CONST_H */ diff --git a/arch/sparc/include/asm/rwsem.h b/arch/sparc/include/asm/rwsem.h index 6e5621006f8..a2b4302869b 100644 --- a/arch/sparc/include/asm/rwsem.h +++ b/arch/sparc/include/asm/rwsem.h @@ -15,16 +15,21 @@ #include <linux/list.h> #include <linux/spinlock.h> -#include <asm/rwsem-const.h> struct rwsem_waiter; struct rw_semaphore { - signed int count; - spinlock_t wait_lock; - struct list_head wait_list; + signed long count; +#define RWSEM_UNLOCKED_VALUE 0x00000000L +#define RWSEM_ACTIVE_BIAS 0x00000001L +#define RWSEM_ACTIVE_MASK 0xffffffffL +#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) +#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS +#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) + spinlock_t wait_lock; + struct list_head wait_list; #ifdef CONFIG_DEBUG_LOCK_ALLOC - struct lockdep_map dep_map; + struct lockdep_map dep_map; #endif }; @@ -41,6 +46,11 @@ struct rw_semaphore { #define DECLARE_RWSEM(name) \ struct rw_semaphore name = __RWSEM_INITIALIZER(name) +extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); + extern void __init_rwsem(struct rw_semaphore *sem, const char *name, struct lock_class_key *key); @@ -51,27 +61,103 @@ do { \ __init_rwsem((sem), #sem, &__key); \ } while (0) -extern void __down_read(struct rw_semaphore *sem); -extern int __down_read_trylock(struct rw_semaphore *sem); -extern void __down_write(struct rw_semaphore *sem); -extern int __down_write_trylock(struct rw_semaphore *sem); -extern void __up_read(struct rw_semaphore *sem); -extern void __up_write(struct rw_semaphore *sem); -extern void __downgrade_write(struct rw_semaphore *sem); +/* + * lock for reading + */ +static inline void __down_read(struct rw_semaphore *sem) +{ + if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L)) + rwsem_down_read_failed(sem); +} + +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + long tmp; + + while ((tmp = sem->count) >= 0L) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + return 1; + } + } + return 0; +} +/* + * lock for writing + */ static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) { - __down_write(sem); + long tmp; + + tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic64_t *)(&sem->count)); + if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) + rwsem_down_write_failed(sem); } -static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) +static inline void __down_write(struct rw_semaphore *sem) { - return atomic_add_return(delta, (atomic_t *)(&sem->count)); + __down_write_nested(sem, 0); +} + +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + long tmp; + + tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + return tmp == RWSEM_UNLOCKED_VALUE; } -static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) +/* + * unlock after reading + */ +static inline void __up_read(struct rw_semaphore *sem) +{ + long tmp; + + tmp = atomic64_dec_return((atomic64_t *)(&sem->count)); + if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L)) + rwsem_wake(sem); +} + +/* + * unlock after writing + */ +static inline void __up_write(struct rw_semaphore *sem) +{ + if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic64_t *)(&sem->count)) < 0L)) + rwsem_wake(sem); +} + +/* + * implement atomic add functionality + */ +static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem) +{ + atomic64_add(delta, (atomic64_t *)(&sem->count)); +} + +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + long tmp; + + tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count)); + if (tmp < 0L) + rwsem_downgrade_wake(sem); +} + +/* + * implement exchange and add functionality + */ +static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem) { - atomic_add(delta, (atomic_t *)(&sem->count)); + return atomic64_add_return(delta, (atomic64_t *)(&sem->count)); } static inline int rwsem_is_locked(struct rw_semaphore *sem) diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index d24cfe16afc..e3b65d8cf41 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h @@ -106,6 +106,7 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ */ #define write_pic(__p) \ __asm__ __volatile__("ba,pt %%xcc, 99f\n\t" \ + " nop\n\t" \ ".align 64\n" \ "99:wr %0, 0x0, %%pic\n\t" \ "rd %%pic, %%g0" : : "r" (__p)) diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index c4b5e03af11..846d1c4374e 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -15,7 +15,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o lib-$(CONFIG_SPARC32) += copy_user.o locks.o lib-y += atomic_$(BITS).o lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o -lib-y += rwsem_$(BITS).o +lib-$(CONFIG_SPARC32) += rwsem_32.o lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o diff --git a/arch/sparc/lib/atomic_64.S b/arch/sparc/lib/atomic_64.S index 0268210ca16..59186e0fcf3 100644 --- a/arch/sparc/lib/atomic_64.S +++ b/arch/sparc/lib/atomic_64.S @@ -21,7 +21,7 @@ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */ add %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 2f + bne,pn %icc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -36,7 +36,7 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */ sub %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 2f + bne,pn %icc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -51,11 +51,10 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ add %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 2f - add %g7, %o0, %g7 - sra %g7, 0, %o0 + bne,pn %icc, BACKOFF_LABEL(2f, 1b) + add %g1, %o0, %g1 retl - nop + sra %g1, 0, %o0 2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_add_ret, .-atomic_add_ret @@ -67,11 +66,10 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ sub %g1, %o0, %g7 cas [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %icc, 2f - sub %g7, %o0, %g7 - sra %g7, 0, %o0 + bne,pn %icc, BACKOFF_LABEL(2f, 1b) + sub %g1, %o0, %g1 retl - nop + sra %g1, 0, %o0 2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic_sub_ret, .-atomic_sub_ret @@ -83,7 +81,7 @@ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */ add %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -98,7 +96,7 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */ sub %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -113,11 +111,10 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */ add %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 2f - add %g7, %o0, %g7 - mov %g7, %o0 - retl + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop + retl + add %g1, %o0, %o0 2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_add_ret, .-atomic64_add_ret @@ -129,10 +126,9 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */ sub %g1, %o0, %g7 casx [%o1], %g1, %g7 cmp %g1, %g7 - bne,pn %xcc, 2f - sub %g7, %o0, %g7 - mov %g7, %o0 - retl + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop + retl + sub %g1, %o0, %o0 2: BACKOFF_SPIN(%o2, %o3, 1b) .size atomic64_sub_ret, .-atomic64_sub_ret diff --git a/arch/sparc/lib/bitops.S b/arch/sparc/lib/bitops.S index 2b7228cb8c2..3dc61d5537c 100644 --- a/arch/sparc/lib/bitops.S +++ b/arch/sparc/lib/bitops.S @@ -22,7 +22,7 @@ test_and_set_bit: /* %o0=nr, %o1=addr */ or %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 @@ -45,7 +45,7 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */ andn %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 @@ -68,7 +68,7 @@ test_and_change_bit: /* %o0=nr, %o1=addr */ xor %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) and %g7, %o2, %g2 clr %o0 movrne %g2, 1, %o0 @@ -91,7 +91,7 @@ set_bit: /* %o0=nr, %o1=addr */ or %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -112,7 +112,7 @@ clear_bit: /* %o0=nr, %o1=addr */ andn %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop retl nop @@ -133,7 +133,7 @@ change_bit: /* %o0=nr, %o1=addr */ xor %g7, %o2, %g1 casx [%o1], %g7, %g1 cmp %g7, %g1 - bne,pn %xcc, 2f + bne,pn %xcc, BACKOFF_LABEL(2f, 1b) nop retl nop diff --git a/arch/sparc/lib/rwsem_64.S b/arch/sparc/lib/rwsem_64.S deleted file mode 100644 index 91a7d29a79d..00000000000 --- a/arch/sparc/lib/rwsem_64.S +++ /dev/null @@ -1,163 +0,0 @@ -/* rwsem.S: RW semaphore assembler. - * - * Written by David S. Miller (davem@redhat.com), 2001. - * Derived from asm-i386/rwsem.h - */ - -#include <asm/rwsem-const.h> - - .section .sched.text, "ax" - - .globl __down_read -__down_read: -1: lduw [%o0], %g1 - add %g1, 1, %g7 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - add %g7, 1, %g7 - cmp %g7, 0 - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_down_read_failed - mov %i0, %o0 - ret - restore - .size __down_read, .-__down_read - - .globl __down_read_trylock -__down_read_trylock: -1: lduw [%o0], %g1 - add %g1, 1, %g7 - cmp %g7, 0 - bl,pn %icc, 2f - mov 0, %o1 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - mov 1, %o1 -2: retl - mov %o1, %o0 - .size __down_read_trylock, .-__down_read_trylock - - .globl __down_write -__down_write: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - add %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - cmp %g7, 0 - bne,pn %icc, 3f - nop -2: retl - nop -3: - save %sp, -192, %sp - call rwsem_down_write_failed - mov %i0, %o0 - ret - restore - .size __down_write, .-__down_write - - .globl __down_write_trylock -__down_write_trylock: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - cmp %g3, 0 - bne,pn %icc, 2f - mov 0, %o1 - add %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - mov 1, %o1 -2: retl - mov %o1, %o0 - .size __down_write_trylock, .-__down_write_trylock - - .globl __up_read -__up_read: -1: - lduw [%o0], %g1 - sub %g1, 1, %g7 - cas [%o0], %g1, %g7 - cmp %g1, %g7 - bne,pn %icc, 1b - cmp %g7, 0 - bl,pn %icc, 3f - nop -2: retl - nop -3: sethi %hi(RWSEM_ACTIVE_MASK), %g1 - sub %g7, 1, %g7 - or %g1, %lo(RWSEM_ACTIVE_MASK), %g1 - andcc %g7, %g1, %g0 - bne,pn %icc, 2b - nop - save %sp, -192, %sp - call rwsem_wake - mov %i0, %o0 - ret - restore - .size __up_read, .-__up_read - - .globl __up_write -__up_write: - sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1 - or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1 -1: - lduw [%o0], %g3 - sub %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - sub %g7, %g1, %g7 - cmp %g7, 0 - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_wake - mov %i0, %o0 - ret - restore - .size __up_write, .-__up_write - - .globl __downgrade_write -__downgrade_write: - sethi %hi(RWSEM_WAITING_BIAS), %g1 - or %g1, %lo(RWSEM_WAITING_BIAS), %g1 -1: - lduw [%o0], %g3 - sub %g3, %g1, %g7 - cas [%o0], %g3, %g7 - cmp %g3, %g7 - bne,pn %icc, 1b - sub %g7, %g1, %g7 - cmp %g7, 0 - bl,pn %icc, 3f - nop -2: - retl - nop -3: - save %sp, -192, %sp - call rwsem_downgrade_wake - mov %i0, %o0 - ret - restore - .size __downgrade_write, .-__downgrade_write diff --git a/arch/sparc/prom/cif.S b/arch/sparc/prom/cif.S index 5f27ad779c0..9c86b4b7d42 100644 --- 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 diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index f55d58a8a15..10322dc2f55 100644 --- 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; @@ -67,7 +85,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); } diff --git a/arch/sparc/prom/devops_64.c b/arch/sparc/prom/devops_64.c index 9dbd803e46e..a017119e7ef 100644 --- 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); } diff --git a/arch/sparc/prom/misc_64.c b/arch/sparc/prom/misc_64.c index 39fc6af21b7..6cb1581d6ae 100644 --- 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 *service_name) 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 size, 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(); + ar |