summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@debian.org>2003-09-08 23:38:49 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-09-08 23:38:49 -0700
commit36eaa6e4c0e0b6950136b956b72fd08155b92ca3 (patch)
treebcdb3628f3d6256b5603cf7c3788d606ed16bac0 /include
parent8b318c7cccb30852fc5b4b34f936dcccafdf7889 (diff)
[PATCH] PA-RISC update for 2.6.0-test5
PA-RISC updates for 2.6.0-test5. Contributions from Paul Bame, James Bottomley, Randolph Chung, Helge Deller, Grant Grundler, LaMont Jones, Matthew Wilcox
Diffstat (limited to 'include')
-rw-r--r--include/asm-parisc/atomic.h17
-rw-r--r--include/asm-parisc/bitops.h109
-rw-r--r--include/asm-parisc/byteorder.h50
-rw-r--r--include/asm-parisc/cacheflush.h5
-rw-r--r--include/asm-parisc/elf.h1
-rw-r--r--include/asm-parisc/hil.h26
-rw-r--r--include/asm-parisc/io.h7
-rw-r--r--include/asm-parisc/local.h40
-rw-r--r--include/asm-parisc/sections.h7
-rw-r--r--include/asm-parisc/uaccess.h17
10 files changed, 177 insertions, 102 deletions
diff --git a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h
index d50c506dd8a4..808373512d6c 100644
--- a/include/asm-parisc/atomic.h
+++ b/include/asm-parisc/atomic.h
@@ -49,27 +49,14 @@ extern spinlock_t __atomic_hash[ATOMIC_HASH_SIZE];
* Cache-line alignment would conflict with, for example, linux/module.h
*/
-typedef struct {
- volatile int counter;
-} atomic_t;
+typedef struct { volatile long counter; } atomic_t;
-/*
-** xchg/cmpxchg moved from asm/system.h - ggg
-*/
-
-#if 1
/* This should get optimized out since it's never called.
** Or get a link error if xchg is used "wrong".
*/
extern void __xchg_called_with_bad_pointer(void);
-#else
-static inline void __xchg_called_with_bad_pointer(void)
-{
- extern void panic(const char * fmt, ...);
- panic("xchg called with bad pointer");
-}
-#endif
+
/* __xchg32/64 defined in arch/parisc/lib/bitops.c */
extern unsigned long __xchg8(char, char *);
diff --git a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
index 711e7d154afa..51f4871ac6ce 100644
--- a/include/asm-parisc/bitops.h
+++ b/include/asm-parisc/bitops.h
@@ -203,55 +203,102 @@ static __inline__ int test_bit(int nr, const void *address)
return !!(*addr & mask);
}
-extern __inline__ unsigned long ffz(unsigned long word)
-{
- unsigned long result;
-
- result = 0;
- while (word & 1) {
- result++;
- word >>= 1;
- }
-
- return result;
-}
-
#ifdef __KERNEL__
/**
- * __ffs - find first bit in word.
+ * __ffs - find first bit in word. returns 0 to "BITS_PER_LONG-1".
* @word: The word to search
*
- * Undefined if no bit exists, so code should check against 0 first.
+ * __ffs() return is undefined if no bit is set.
+ *
+ * 32-bit fast __ffs by LaMont Jones "lamont At hp com".
+ * 64-bit enhancement by Grant Grundler "grundler At parisc-linux org".
+ * (with help from willy/jejb to get the semantics right)
+ *
+ * This algorithm avoids branches by making use of nullification.
+ * One side effect of "extr" instructions is it sets PSW[N] bit.
+ * How PSW[N] (nullify next insn) gets set is determined by the
+ * "condition" field (eg "<>" or "TR" below) in the extr* insn.
+ * Only the 1st and one of either the 2cd or 3rd insn will get executed.
+ * Each set of 3 insn will get executed in 2 cycles on PA8x00 vs 16 or so
+ * cycles for each mispredicted branch.
*/
-static __inline__ unsigned long __ffs(unsigned long word)
-{
- unsigned long result = 0;
- while (!(word & 1UL)) {
- result++;
- word >>= 1;
- }
- return result;
+static __inline__ unsigned long __ffs(unsigned long x)
+{
+ unsigned long ret;
+
+ __asm__(
+#if BITS_PER_LONG > 32
+ " ldi 63,%1\n"
+ " extrd,u,*<> %0,63,32,%%r0\n"
+ " extrd,u,*TR %0,31,32,%0\n"
+ " addi -32,%1,%1\n"
+#else
+ " ldi 31,%1\n"
+#endif
+ " extru,<> %0,31,16,%%r0\n"
+ " extru,TR %0,15,16,%0\n"
+ " addi -16,%1,%1\n"
+ " extru,<> %0,31,8,%%r0\n"
+ " extru,TR %0,23,8,%0\n"
+ " addi -8,%1,%1\n"
+ " extru,<> %0,31,4,%%r0\n"
+ " extru,TR %0,27,4,%0\n"
+ " addi -4,%1,%1\n"
+ " extru,<> %0,31,2,%%r0\n"
+ " extru,TR %0,29,2,%0\n"
+ " addi -2,%1,%1\n"
+ " extru,= %0,31,1,%%r0\n"
+ " addi -1,%1,%1\n"
+ : "+r" (x), "=r" (ret) );
+ return ret;
}
+/* Undefined if no bit is zero. */
+#define ffz(x) __ffs(~x)
+
/*
- * ffs: find first bit set. This is defined the same way as
- * the libc and compiler builtin ffs routines, therefore
- * differs in spirit from the above ffz (man ffs).
+ * ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set)
+ * This is defined the same way as the libc and compiler builtin
+ * ffs routines, therefore differs in spirit from the above ffz (man ffs).
*/
static __inline__ int ffs(int x)
{
- if (!x)
- return 0;
- return __ffs((unsigned long)x);
+ return x ? (__ffs((unsigned long)x) + 1) : 0;
}
/*
- * fls: find last bit set.
+ * fls: find last (most significant) bit set.
+ * fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
-#define fls(x) generic_fls(x)
+static __inline__ int fls(int x)
+{
+ int ret;
+ if (!x)
+ return 0;
+
+ __asm__(
+ " ldi 1,%1\n"
+ " extru,<> %0,15,16,%%r0\n"
+ " zdep,TR %0,15,16,%0\n" /* xxxx0000 */
+ " addi 16,%1,%1\n"
+ " extru,<> %0,7,8,%%r0\n"
+ " zdep,TR %0,23,24,%0\n" /* xx000000 */
+ " addi 8,%1,%1\n"
+ " extru,<> %0,3,4,%%r0\n"
+ " zdep,TR %0,27,28,%0\n" /* x0000000 */
+ " addi 4,%1,%1\n"
+ " extru,<> %0,1,2,%%r0\n"
+ " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0 */
+ " addi 2,%1,%1\n"
+ " extru,= %0,0,1,%%r0\n"
+ " addi 1,%1,%1\n" /* if y & 8, add 1 */
+ : "+r" (x), "=r" (ret) );
+
+ return ret;
+}
/*
* hweightN: returns the hamming weight (i.e. the number
diff --git a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h
index 9ddeab1777a5..352b3146f7b0 100644
--- a/include/asm-parisc/byteorder.h
+++ b/include/asm-parisc/byteorder.h
@@ -5,6 +5,25 @@
#ifdef __GNUC__
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+ __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
+ "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
+ : "=r" (x)
+ : "0" (x));
+ return x;
+}
+
+static __inline__ __const__ __u32 ___arch__swab24(__u32 x)
+{
+ __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
+ "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
+ "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */
+ : "=r" (x)
+ : "0" (x));
+ return x;
+}
+
static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
{
unsigned int temp;
@@ -39,34 +58,21 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
return x;
}
#define __arch__swab64(x) ___arch__swab64(x)
-#else
+#define __BYTEORDER_HAS_U64__
+#elif !defined(__STRICT_ANSI__)
static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
{
- __u32 t1 = (__u32) x;
- __u32 t2 = (__u32) ((x) >> 32);
- ___arch__swab32(t1);
- ___arch__swab32(t2);
- return (((__u64) t1 << 32) + ((__u64) t2));
+ __u32 t1 = ___arch__swab32((__u32) x);
+ __u32 t2 = ___arch__swab32((__u32) (x >> 32));
+ return (((__u64) t1 << 32) | t2);
}
+#define __arch__swab64(x) ___arch__swab64(x)
+#define __BYTEORDER_HAS_U64__
#endif
-
-static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
-{
- __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
- "shd %r0, %0, 8, %0" /* shift 000000ab -> 00ba */
- : "=r" (x)
- : "0" (x));
- return x;
-}
-
-#define __arch__swab32(x) ___arch__swab32(x)
#define __arch__swab16(x) ___arch__swab16(x)
-
-#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-# define __BYTEORDER_HAS_U64__
-# define __SWAB_64_THRU_32__
-#endif
+#define __arch__swab24(x) ___arch__swab24(x)
+#define __arch__swab32(x) ___arch__swab32(x)
#endif /* __GNUC__ */
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 5392339e549b..b88200337cca 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -78,8 +78,9 @@ static inline void flush_dcache_page(struct page *page)
#define flush_icache_range(s,e) do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0)
-#define flush_icache_user_range(vma, page, addr, len) \
- flush_icache_page((vma), (page))
+#define flush_icache_user_range(vma, page, addr, len) do { \
+ flush_user_dcache_range(addr, addr + len); \
+ flush_user_icache_range(addr, addr + len); } while (0)
static inline void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
index b9f6090b78f2..a01e946dfc57 100644
--- a/include/asm-parisc/elf.h
+++ b/include/asm-parisc/elf.h
@@ -283,6 +283,7 @@ struct pt_regs; /* forward declaration... */
*/
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_PARISC
+#define ELF_OSABI ELFOSABI_LINUX
/* %r23 is set by ld.so to a pointer to a function which might be
registered using atexit. This provides a mean for the dynamic
diff --git a/include/asm-parisc/hil.h b/include/asm-parisc/hil.h
deleted file mode 100644
index 97cd5553f22f..000000000000
--- a/include/asm-parisc/hil.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _ASM_HIL_H
-#define _ASM_HIL_H
-
-/*
- * linux/asm-parisc/hil.h
- *
- * (c) 1999 Matthew Wilcox
- */
-
-extern unsigned long hil_base; /* declared in drivers/parisc/hil.c */
-extern unsigned int hil_irq;
-
-#define HILBASE hil_base /* 0xf0821000 (old) or 0xf0201000 (new) */
-#define HIL_DATA 0x800
-#define HIL_CMD 0x801
-
-#define HIL_IRQ hil_irq
-
-#define hil_busy() (gsc_readb(HILBASE + HIL_CMD) & HIL_BUSY)
-#define hil_data_available() (gsc_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
-#define hil_status() (gsc_readb(HILBASE + HIL_CMD))
-#define hil_command(x) do { gsc_writeb((x), HILBASE + HIL_CMD); } while (0)
-#define hil_read_data() (gsc_readb(HILBASE + HIL_DATA))
-#define hil_write_data(x) do { gsc_writeb((x), HILBASE + HIL_DATA); } while (0)
-
-#endif
diff --git a/include/asm-parisc/io.h b/include/asm-parisc/io.h
index 69933ab23159..0350f0198995 100644
--- a/include/asm-parisc/io.h
+++ b/include/asm-parisc/io.h
@@ -291,4 +291,11 @@ extern void outsl (unsigned long port, const void *src, unsigned long count);
#define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
#define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0)
+/* PA machines have an MM I/O space from 0xf0000000-0xffffffff in 32
+ * bit mode and from 0xfffffffff0000000-0xfffffffffffffff in 64 bit
+ * mode (essentially just sign extending. This macro takes in a 32
+ * bit I/O address (still with the leading f) and outputs the correct
+ * value for either 32 or 64 bit mode */
+#define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL)))
+
#endif
diff --git a/include/asm-parisc/local.h b/include/asm-parisc/local.h
new file mode 100644
index 000000000000..892b3b2c4962
--- /dev/null
+++ b/include/asm-parisc/local.h
@@ -0,0 +1,40 @@
+#ifndef _ARCH_PARISC_LOCAL_H
+#define _ARCH_PARISC_LOCAL_H
+
+#include <linux/percpu.h>
+#include <asm/atomic.h>
+
+typedef atomic_t local_t;
+
+#define LOCAL_INIT(i) ATOMIC_INIT(i)
+#define local_read(v) atomic_read(v)
+#define local_set(v,i) atomic_set(v,i)
+
+#define local_inc(v) atomic_inc(v)
+#define local_dec(v) atomic_dec(v)
+#define local_add(i, v) atomic_add(i, v)
+#define local_sub(i, v) atomic_sub(i, v)
+
+#define __local_inc(v) ((v)->counter++)
+#define __local_dec(v) ((v)->counter--)
+#define __local_add(i,v) ((v)->counter+=(i))
+#define __local_sub(i,v) ((v)->counter-=(i))
+
+/* Use these for per-cpu local_t variables: on some archs they are
+ * much more efficient than these naive implementations. Note they take
+ * a variable, not an address.
+ */
+#define cpu_local_read(v) local_read(&__get_cpu_var(v))
+#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i))
+
+#define cpu_local_inc(v) local_inc(&__get_cpu_var(v))
+#define cpu_local_dec(v) local_dec(&__get_cpu_var(v))
+#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v))
+#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v))
+
+#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v))
+#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v))
+#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v))
+#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v))
+
+#endif /* _ARCH_PARISC_LOCAL_H */
diff --git a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h
new file mode 100644
index 000000000000..fdd43ec42ec5
--- /dev/null
+++ b/include/asm-parisc/sections.h
@@ -0,0 +1,7 @@
+#ifndef _PARISC_SECTIONS_H
+#define _PARISC_SECTIONS_H
+
+/* nothing to see, move along */
+#include <asm-generic/sections.h>
+
+#endif
diff --git a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
index 8bd1067c4a50..cc9e311cabd1 100644
--- a/include/asm-parisc/uaccess.h
+++ b/include/asm-parisc/uaccess.h
@@ -28,6 +28,11 @@
* that put_user is the same as __put_user, etc.
*/
+extern int __get_kernel_bad(void);
+extern int __get_user_bad(void);
+extern int __put_kernel_bad(void);
+extern int __put_user_bad(void);
+
#define access_ok(type,addr,size) (1)
#define verify_area(type,addr,size) (0)
@@ -35,8 +40,8 @@
#define get_user __get_user
#if BITS_PER_LONG == 32
-#define LDD_KERNEL(ptr) BUG()
-#define LDD_USER(ptr) BUG()
+#define LDD_KERNEL(ptr) __get_kernel_bad();
+#define LDD_USER(ptr) __get_user_bad();
#define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr)
#define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr)
#else
@@ -72,7 +77,7 @@ struct exception_table_entry {
case 2: __get_kernel_asm("ldh",ptr); break; \
case 4: __get_kernel_asm("ldw",ptr); break; \
case 8: LDD_KERNEL(ptr); break; \
- default: BUG(); break; \
+ default: __get_kernel_bad(); break; \
} \
} \
else { \
@@ -81,7 +86,7 @@ struct exception_table_entry {
case 2: __get_user_asm("ldh",ptr); break; \
case 4: __get_user_asm("ldw",ptr); break; \
case 8: LDD_USER(ptr); break; \
- default: BUG(); break; \
+ default: __get_user_bad(); break; \
} \
} \
\
@@ -141,7 +146,7 @@ struct exception_table_entry {
case 2: __put_kernel_asm("sth",x,ptr); break; \
case 4: __put_kernel_asm("stw",x,ptr); break; \
case 8: STD_KERNEL(x,ptr); break; \
- default: BUG(); break; \
+ default: __put_kernel_bad(); break; \
} \
} \
else { \
@@ -150,7 +155,7 @@ struct exception_table_entry {
case 2: __put_user_asm("sth",x,ptr); break; \
case 4: __put_user_asm("stw",x,ptr); break; \
case 8: STD_USER(x,ptr); break; \
- default: BUG(); break; \
+ default: __put_user_bad(); break; \
} \
} \
\