diff options
Diffstat (limited to 'arch/blackfin/include')
| -rw-r--r-- | arch/blackfin/include/asm/atomic.h | 119 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/bfin-global.h | 5 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/bitops.h | 189 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/cache.h | 29 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/cacheflush.h | 20 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/context.S | 6 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/cpu.h | 42 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/l1layout.h | 3 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/mutex-dec.h | 112 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/mutex.h | 63 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/pda.h | 70 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/percpu.h | 12 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/processor.h | 7 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/rwlock.h | 6 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/smp.h | 42 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/spinlock.h | 87 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/spinlock_types.h | 22 | ||||
| -rw-r--r-- | arch/blackfin/include/asm/system.h | 116 |
18 files changed, 829 insertions, 121 deletions
diff --git a/arch/blackfin/include/asm/atomic.h b/arch/blackfin/include/asm/atomic.h index 25776c19064b..d76275e5638c 100644 --- a/arch/blackfin/include/asm/atomic.h +++ b/arch/blackfin/include/asm/atomic.h | |||
| @@ -15,11 +15,80 @@ | |||
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #define ATOMIC_INIT(i) { (i) } | 17 | #define ATOMIC_INIT(i) { (i) } |
| 18 | |||
| 19 | #define atomic_read(v) ((v)->counter) | ||
| 20 | #define atomic_set(v, i) (((v)->counter) = i) | 18 | #define atomic_set(v, i) (((v)->counter) = i) |
| 21 | 19 | ||
| 22 | static __inline__ void atomic_add(int i, atomic_t * v) | 20 | #ifdef CONFIG_SMP |
| 21 | |||
| 22 | #define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter) | ||
| 23 | |||
| 24 | asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr); | ||
| 25 | |||
| 26 | asmlinkage int __raw_atomic_update_asm(volatile int *ptr, int value); | ||
| 27 | |||
| 28 | asmlinkage int __raw_atomic_clear_asm(volatile int *ptr, int value); | ||
| 29 | |||
| 30 | asmlinkage int __raw_atomic_set_asm(volatile int *ptr, int value); | ||
| 31 | |||
| 32 | asmlinkage int __raw_atomic_xor_asm(volatile int *ptr, int value); | ||
| 33 | |||
| 34 | asmlinkage int __raw_atomic_test_asm(const volatile int *ptr, int value); | ||
| 35 | |||
| 36 | static inline void atomic_add(int i, atomic_t *v) | ||
| 37 | { | ||
| 38 | __raw_atomic_update_asm(&v->counter, i); | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void atomic_sub(int i, atomic_t *v) | ||
| 42 | { | ||
| 43 | __raw_atomic_update_asm(&v->counter, -i); | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline int atomic_add_return(int i, atomic_t *v) | ||
| 47 | { | ||
| 48 | return __raw_atomic_update_asm(&v->counter, i); | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline int atomic_sub_return(int i, atomic_t *v) | ||
| 52 | { | ||
| 53 | return __raw_atomic_update_asm(&v->counter, -i); | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline void atomic_inc(volatile atomic_t *v) | ||
| 57 | { | ||
| 58 | __raw_atomic_update_asm(&v->counter, 1); | ||
| 59 | } | ||
| 60 | |||
| 61 | static inline void atomic_dec(volatile atomic_t *v) | ||
| 62 | { | ||
| 63 | __raw_atomic_update_asm(&v->counter, -1); | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline void atomic_clear_mask(int mask, atomic_t *v) | ||
| 67 | { | ||
| 68 | __raw_atomic_clear_asm(&v->counter, mask); | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void atomic_set_mask(int mask, atomic_t *v) | ||
| 72 | { | ||
| 73 | __raw_atomic_set_asm(&v->counter, mask); | ||
| 74 | } | ||
| 75 | |||
| 76 | static inline int atomic_test_mask(int mask, atomic_t *v) | ||
| 77 | { | ||
| 78 | return __raw_atomic_test_asm(&v->counter, mask); | ||
| 79 | } | ||
| 80 | |||
| 81 | /* Atomic operations are already serializing */ | ||
| 82 | #define smp_mb__before_atomic_dec() barrier() | ||
| 83 | #define smp_mb__after_atomic_dec() barrier() | ||
| 84 | #define smp_mb__before_atomic_inc() barrier() | ||
| 85 | #define smp_mb__after_atomic_inc() barrier() | ||
| 86 | |||
| 87 | #else /* !CONFIG_SMP */ | ||
| 88 | |||
| 89 | #define atomic_read(v) ((v)->counter) | ||
| 90 | |||
| 91 | static inline void atomic_add(int i, atomic_t *v) | ||
| 23 | { | 92 | { |
| 24 | long flags; | 93 | long flags; |
| 25 | 94 | ||
| @@ -28,7 +97,7 @@ static __inline__ void atomic_add(int i, atomic_t * v) | |||
| 28 | local_irq_restore(flags); | 97 | local_irq_restore(flags); |
| 29 | } | 98 | } |
| 30 | 99 | ||
| 31 | static __inline__ void atomic_sub(int i, atomic_t * v) | 100 | static inline void atomic_sub(int i, atomic_t *v) |
| 32 | { | 101 | { |
| 33 | long flags; | 102 | long flags; |
| 34 | 103 | ||
| @@ -38,7 +107,7 @@ static __inline__ void atomic_sub(int i, atomic_t * v) | |||
| 38 | 107 | ||
| 39 | } | 108 | } |
| 40 | 109 | ||
| 41 | static inline int atomic_add_return(int i, atomic_t * v) | 110 | static inline int atomic_add_return(int i, atomic_t *v) |
| 42 | { | 111 | { |
| 43 | int __temp = 0; | 112 | int __temp = 0; |
| 44 | long flags; | 113 | long flags; |
| @@ -52,8 +121,7 @@ static inline int atomic_add_return(int i, atomic_t * v) | |||
| 52 | return __temp; | 121 | return __temp; |
| 53 | } | 122 | } |
| 54 | 123 | ||
| 55 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) | 124 | static inline int atomic_sub_return(int i, atomic_t *v) |
| 56 | static inline int atomic_sub_return(int i, atomic_t * v) | ||
| 57 | { | 125 | { |
| 58 | int __temp = 0; | 126 | int __temp = 0; |
| 59 | long flags; | 127 | long flags; |
| @@ -66,7 +134,7 @@ static inline int atomic_sub_return(int i, atomic_t * v) | |||
| 66 | return __temp; | 134 | return __temp; |
| 67 | } | 135 | } |
| 68 | 136 | ||
| 69 | static __inline__ void atomic_inc(volatile atomic_t * v) | 137 | static inline void atomic_inc(volatile atomic_t *v) |
| 70 | { | 138 | { |
| 71 | long flags; | 139 | long flags; |
| 72 | 140 | ||
| @@ -75,20 +143,7 @@ static __inline__ void atomic_inc(volatile atomic_t * v) | |||
| 75 | local_irq_restore(flags); | 143 | local_irq_restore(flags); |
| 76 | } | 144 | } |
| 77 | 145 | ||
| 78 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | 146 | static inline void atomic_dec(volatile atomic_t *v) |
| 79 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
| 80 | |||
| 81 | #define atomic_add_unless(v, a, u) \ | ||
| 82 | ({ \ | ||
| 83 | int c, old; \ | ||
| 84 | c = atomic_read(v); \ | ||
| 85 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
| 86 | c = old; \ | ||
| 87 | c != (u); \ | ||
| 88 | }) | ||
| 89 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
| 90 | |||
| 91 | static __inline__ void atomic_dec(volatile atomic_t * v) | ||
| 92 | { | 147 | { |
| 93 | long flags; | 148 | long flags; |
| 94 | 149 | ||
| @@ -97,7 +152,7 @@ static __inline__ void atomic_dec(volatile atomic_t * v) | |||
| 97 | local_irq_restore(flags); | 152 | local_irq_restore(flags); |
| 98 | } | 153 | } |
| 99 | 154 | ||
| 100 | static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v) | 155 | static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) |
| 101 | { | 156 | { |
| 102 | long flags; | 157 | long flags; |
| 103 | 158 | ||
| @@ -106,7 +161,7 @@ static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t * v) | |||
| 106 | local_irq_restore(flags); | 161 | local_irq_restore(flags); |
| 107 | } | 162 | } |
| 108 | 163 | ||
| 109 | static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v) | 164 | static inline void atomic_set_mask(unsigned int mask, atomic_t *v) |
| 110 | { | 165 | { |
| 111 | long flags; | 166 | long flags; |
| 112 | 167 | ||
| @@ -121,9 +176,25 @@ static __inline__ void atomic_set_mask(unsigned int mask, atomic_t * v) | |||
| 121 | #define smp_mb__before_atomic_inc() barrier() | 176 | #define smp_mb__before_atomic_inc() barrier() |
| 122 | #define smp_mb__after_atomic_inc() barrier() | 177 | #define smp_mb__after_atomic_inc() barrier() |
| 123 | 178 | ||
| 179 | #endif /* !CONFIG_SMP */ | ||
| 180 | |||
| 181 | #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) | ||
| 124 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) | 182 | #define atomic_dec_return(v) atomic_sub_return(1,(v)) |
| 125 | #define atomic_inc_return(v) atomic_add_return(1,(v)) | 183 | #define atomic_inc_return(v) atomic_add_return(1,(v)) |
| 126 | 184 | ||
| 185 | #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n))) | ||
| 186 | #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) | ||
| 187 | |||
| 188 | #define atomic_add_unless(v, a, u) \ | ||
| 189 | ({ \ | ||
| 190 | int c, old; \ | ||
| 191 | c = atomic_read(v); \ | ||
| 192 | while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ | ||
| 193 | c = old; \ | ||
| 194 | c != (u); \ | ||
| 195 | }) | ||
| 196 | #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) | ||
| 197 | |||
| 127 | /* | 198 | /* |
| 128 | * atomic_inc_and_test - increment and test | 199 | * atomic_inc_and_test - increment and test |
| 129 | * @v: pointer of type atomic_t | 200 | * @v: pointer of type atomic_t |
diff --git a/arch/blackfin/include/asm/bfin-global.h b/arch/blackfin/include/asm/bfin-global.h index 77295666c34b..1dd08058bc90 100644 --- a/arch/blackfin/include/asm/bfin-global.h +++ b/arch/blackfin/include/asm/bfin-global.h | |||
| @@ -47,6 +47,9 @@ | |||
| 47 | # define DMA_UNCACHED_REGION (0) | 47 | # define DMA_UNCACHED_REGION (0) |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | extern void bfin_setup_caches(unsigned int cpu); | ||
| 51 | extern void bfin_setup_cpudata(unsigned int cpu); | ||
| 52 | |||
| 50 | extern unsigned long get_cclk(void); | 53 | extern unsigned long get_cclk(void); |
| 51 | extern unsigned long get_sclk(void); | 54 | extern unsigned long get_sclk(void); |
| 52 | extern unsigned long sclk_to_usecs(unsigned long sclk); | 55 | extern unsigned long sclk_to_usecs(unsigned long sclk); |
| @@ -58,8 +61,6 @@ extern void dump_bfin_trace_buffer(void); | |||
| 58 | 61 | ||
| 59 | /* init functions only */ | 62 | /* init functions only */ |
| 60 | extern int init_arch_irq(void); | 63 | extern int init_arch_irq(void); |
| 61 | extern void bfin_icache_init(void); | ||
| 62 | extern void bfin_dcache_init(void); | ||
| 63 | extern void init_exception_vectors(void); | 64 | extern void init_exception_vectors(void); |
| 64 | extern void program_IAR(void); | 65 | extern void program_IAR(void); |
| 65 | 66 | ||
diff --git a/arch/blackfin/include/asm/bitops.h b/arch/blackfin/include/asm/bitops.h index c428e4106f89..9964e17232e9 100644 --- a/arch/blackfin/include/asm/bitops.h +++ b/arch/blackfin/include/asm/bitops.h | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
| 9 | #include <asm/byteorder.h> /* swab32 */ | 9 | #include <asm/byteorder.h> /* swab32 */ |
| 10 | #include <asm/system.h> /* save_flags */ | ||
| 11 | 10 | ||
| 12 | #ifdef __KERNEL__ | 11 | #ifdef __KERNEL__ |
| 13 | 12 | ||
| @@ -20,36 +19,71 @@ | |||
| 20 | #include <asm-generic/bitops/sched.h> | 19 | #include <asm-generic/bitops/sched.h> |
| 21 | #include <asm-generic/bitops/ffz.h> | 20 | #include <asm-generic/bitops/ffz.h> |
| 22 | 21 | ||
| 23 | static __inline__ void set_bit(int nr, volatile unsigned long *addr) | 22 | #ifdef CONFIG_SMP |
| 23 | |||
| 24 | #include <linux/linkage.h> | ||
| 25 | |||
| 26 | asmlinkage int __raw_bit_set_asm(volatile unsigned long *addr, int nr); | ||
| 27 | |||
| 28 | asmlinkage int __raw_bit_clear_asm(volatile unsigned long *addr, int nr); | ||
| 29 | |||
| 30 | asmlinkage int __raw_bit_toggle_asm(volatile unsigned long *addr, int nr); | ||
| 31 | |||
| 32 | asmlinkage int __raw_bit_test_set_asm(volatile unsigned long *addr, int nr); | ||
| 33 | |||
| 34 | asmlinkage int __raw_bit_test_clear_asm(volatile unsigned long *addr, int nr); | ||
| 35 | |||
| 36 | asmlinkage int __raw_bit_test_toggle_asm(volatile unsigned long *addr, int nr); | ||
| 37 | |||
| 38 | asmlinkage int __raw_bit_test_asm(const volatile unsigned long *addr, int nr); | ||
| 39 | |||
| 40 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
| 24 | { | 41 | { |
| 25 | int *a = (int *)addr; | 42 | volatile unsigned long *a = addr + (nr >> 5); |
| 26 | int mask; | 43 | __raw_bit_set_asm(a, nr & 0x1f); |
| 27 | unsigned long flags; | 44 | } |
| 28 | 45 | ||
| 29 | a += nr >> 5; | 46 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
| 30 | mask = 1 << (nr & 0x1f); | 47 | { |
| 31 | local_irq_save(flags); | 48 | volatile unsigned long *a = addr + (nr >> 5); |
| 32 | *a |= mask; | 49 | __raw_bit_clear_asm(a, nr & 0x1f); |
| 33 | local_irq_restore(flags); | ||
| 34 | } | 50 | } |
| 35 | 51 | ||
| 36 | static __inline__ void __set_bit(int nr, volatile unsigned long *addr) | 52 | static inline void change_bit(int nr, volatile unsigned long *addr) |
| 37 | { | 53 | { |
| 38 | int *a = (int *)addr; | 54 | volatile unsigned long *a = addr + (nr >> 5); |
| 39 | int mask; | 55 | __raw_bit_toggle_asm(a, nr & 0x1f); |
| 56 | } | ||
| 40 | 57 | ||
| 41 | a += nr >> 5; | 58 | static inline int test_bit(int nr, const volatile unsigned long *addr) |
| 42 | mask = 1 << (nr & 0x1f); | 59 | { |
| 43 | *a |= mask; | 60 | volatile const unsigned long *a = addr + (nr >> 5); |
| 61 | return __raw_bit_test_asm(a, nr & 0x1f) != 0; | ||
| 44 | } | 62 | } |
| 45 | 63 | ||
| 46 | /* | 64 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
| 47 | * clear_bit() doesn't provide any barrier for the compiler. | 65 | { |
| 48 | */ | 66 | volatile unsigned long *a = addr + (nr >> 5); |
| 49 | #define smp_mb__before_clear_bit() barrier() | 67 | return __raw_bit_test_set_asm(a, nr & 0x1f); |
| 50 | #define smp_mb__after_clear_bit() barrier() | 68 | } |
| 51 | 69 | ||
| 52 | static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | 70 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
| 71 | { | ||
| 72 | volatile unsigned long *a = addr + (nr >> 5); | ||
| 73 | return __raw_bit_test_clear_asm(a, nr & 0x1f); | ||
| 74 | } | ||
| 75 | |||
| 76 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) | ||
| 77 | { | ||
| 78 | volatile unsigned long *a = addr + (nr >> 5); | ||
| 79 | return __raw_bit_test_toggle_asm(a, nr & 0x1f); | ||
| 80 | } | ||
| 81 | |||
| 82 | #else /* !CONFIG_SMP */ | ||
| 83 | |||
| 84 | #include <asm/system.h> /* save_flags */ | ||
| 85 | |||
| 86 | static inline void set_bit(int nr, volatile unsigned long *addr) | ||
| 53 | { | 87 | { |
| 54 | int *a = (int *)addr; | 88 | int *a = (int *)addr; |
| 55 | int mask; | 89 | int mask; |
| @@ -57,21 +91,23 @@ static __inline__ void clear_bit(int nr, volatile unsigned long *addr) | |||
| 57 | a += nr >> 5; | 91 | a += nr >> 5; |
| 58 | mask = 1 << (nr & 0x1f); | 92 | mask = 1 << (nr & 0x1f); |
| 59 | local_irq_save(flags); | 93 | local_irq_save(flags); |
| 60 | *a &= ~mask; | 94 | *a |= mask; |
| 61 | local_irq_restore(flags); | 95 | local_irq_restore(flags); |
| 62 | } | 96 | } |
| 63 | 97 | ||
| 64 | static __inline__ void __clear_bit(int nr, volatile unsigned long *addr) | 98 | static inline void clear_bit(int nr, volatile unsigned long *addr) |
| 65 | { | 99 | { |
| 66 | int *a = (int *)addr; | 100 | int *a = (int *)addr; |
| 67 | int mask; | 101 | int mask; |
| 68 | 102 | unsigned long flags; | |
| 69 | a += nr >> 5; | 103 | a += nr >> 5; |
| 70 | mask = 1 << (nr & 0x1f); | 104 | mask = 1 << (nr & 0x1f); |
| 105 | local_irq_save(flags); | ||
| 71 | *a &= ~mask; | 106 | *a &= ~mask; |
| 107 | local_irq_restore(flags); | ||
| 72 | } | 108 | } |
| 73 | 109 | ||
| 74 | static __inline__ void change_bit(int nr, volatile unsigned long *addr) | 110 | static inline void change_bit(int nr, volatile unsigned long *addr) |
| 75 | { | 111 | { |
| 76 | int mask, flags; | 112 | int mask, flags; |
| 77 | unsigned long *ADDR = (unsigned long *)addr; | 113 | unsigned long *ADDR = (unsigned long *)addr; |
| @@ -83,17 +119,7 @@ static __inline__ void change_bit(int nr, volatile unsigned long *addr) | |||
| 83 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
| 84 | } | 120 | } |
| 85 | 121 | ||
| 86 | static __inline__ void __change_bit(int nr, volatile unsigned long *addr) | 122 | static inline int test_and_set_bit(int nr, volatile unsigned long *addr) |
| 87 | { | ||
| 88 | int mask; | ||
| 89 | unsigned long *ADDR = (unsigned long *)addr; | ||
| 90 | |||
| 91 | ADDR += nr >> 5; | ||
| 92 | mask = 1 << (nr & 31); | ||
| 93 | *ADDR ^= mask; | ||
| 94 | } | ||
| 95 | |||
| 96 | static __inline__ int test_and_set_bit(int nr, void *addr) | ||
| 97 | { | 123 | { |
| 98 | int mask, retval; | 124 | int mask, retval; |
| 99 | volatile unsigned int *a = (volatile unsigned int *)addr; | 125 | volatile unsigned int *a = (volatile unsigned int *)addr; |
| @@ -109,19 +135,23 @@ static __inline__ int test_and_set_bit(int nr, void *addr) | |||
| 109 | return retval; | 135 | return retval; |
| 110 | } | 136 | } |
| 111 | 137 | ||
| 112 | static __inline__ int __test_and_set_bit(int nr, volatile unsigned long *addr) | 138 | static inline int test_and_clear_bit(int nr, volatile unsigned long *addr) |
| 113 | { | 139 | { |
| 114 | int mask, retval; | 140 | int mask, retval; |
| 115 | volatile unsigned int *a = (volatile unsigned int *)addr; | 141 | volatile unsigned int *a = (volatile unsigned int *)addr; |
| 142 | unsigned long flags; | ||
| 116 | 143 | ||
| 117 | a += nr >> 5; | 144 | a += nr >> 5; |
| 118 | mask = 1 << (nr & 0x1f); | 145 | mask = 1 << (nr & 0x1f); |
| 146 | local_irq_save(flags); | ||
| 119 | retval = (mask & *a) != 0; | 147 | retval = (mask & *a) != 0; |
| 120 | *a |= mask; | 148 | *a &= ~mask; |
| 149 | local_irq_restore(flags); | ||
| 150 | |||
| 121 | return retval; | 151 | return retval; |
| 122 | } | 152 | } |
| 123 | 153 | ||
| 124 | static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | 154 | static inline int test_and_change_bit(int nr, volatile unsigned long *addr) |
| 125 | { | 155 | { |
| 126 | int mask, retval; | 156 | int mask, retval; |
| 127 | volatile unsigned int *a = (volatile unsigned int *)addr; | 157 | volatile unsigned int *a = (volatile unsigned int *)addr; |
| @@ -131,13 +161,50 @@ static __inline__ int test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
| 131 | mask = 1 << (nr & 0x1f); | 161 | mask = 1 << (nr & 0x1f); |
| 132 | local_irq_save(flags); | 162 | local_irq_save(flags); |
| 133 | retval = (mask & *a) != 0; | 163 | retval = (mask & *a) != 0; |
| 134 | *a &= ~mask; | 164 | *a ^= mask; |
| 135 | local_irq_restore(flags); | 165 | local_irq_restore(flags); |
| 136 | |||
| 137 | return retval; | 166 | return retval; |
| 138 | } | 167 | } |
| 139 | 168 | ||
| 140 | static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | 169 | #endif /* CONFIG_SMP */ |
| 170 | |||
| 171 | /* | ||
| 172 | * clear_bit() doesn't provide any barrier for the compiler. | ||
| 173 | */ | ||
| 174 | #define smp_mb__before_clear_bit() barrier() | ||
| 175 | #define smp_mb__after_clear_bit() barrier() | ||
| 176 | |||
| 177 | static inline void __set_bit(int nr, volatile unsigned long *addr) | ||
| 178 | { | ||
| 179 | int *a = (int *)addr; | ||
| 180 | int mask; | ||
| 181 | |||
| 182 | a += nr >> 5; | ||
| 183 | mask = 1 << (nr & 0x1f); | ||
| 184 | *a |= mask; | ||
| 185 | } | ||
| 186 | |||
| 187 | static inline void __clear_bit(int nr, volatile unsigned long *addr) | ||
| 188 | { | ||
| 189 | int *a = (int *)addr; | ||
| 190 | int mask; | ||
| 191 | |||
| 192 | a += nr >> 5; | ||
| 193 | mask = 1 << (nr & 0x1f); | ||
| 194 | *a &= ~mask; | ||
| 195 | } | ||
| 196 | |||
| 197 | static inline void __change_bit(int nr, volatile unsigned long *addr) | ||
| 198 | { | ||
| 199 | int mask; | ||
| 200 | unsigned long *ADDR = (unsigned long *)addr; | ||
| 201 | |||
| 202 | ADDR += nr >> 5; | ||
| 203 | mask = 1 << (nr & 31); | ||
| 204 | *ADDR ^= mask; | ||
| 205 | } | ||
| 206 | |||
| 207 | static inline int __test_and_set_bit(int nr, volatile unsigned long *addr) | ||
| 141 | { | 208 | { |
| 142 | int mask, retval; | 209 | int mask, retval; |
| 143 | volatile unsigned int *a = (volatile unsigned int *)addr; | 210 | volatile unsigned int *a = (volatile unsigned int *)addr; |
| @@ -145,26 +212,23 @@ static __inline__ int __test_and_clear_bit(int nr, volatile unsigned long *addr) | |||
| 145 | a += nr >> 5; | 212 | a += nr >> 5; |
| 146 | mask = 1 << (nr & 0x1f); | 213 | mask = 1 << (nr & 0x1f); |
| 147 | retval = (mask & *a) != 0; | 214 | retval = (mask & *a) != 0; |
| 148 | *a &= ~mask; | 215 | *a |= mask; |
| 149 | return retval; | 216 | return retval; |
| 150 | } | 217 | } |
| 151 | 218 | ||
| 152 | static __inline__ int test_and_change_bit(int nr, volatile unsigned long *addr) | 219 | static inline int __test_and_clear_bit(int nr, volatile unsigned long *addr) |
| 153 | { | 220 | { |
| 154 | int mask, retval; | 221 | int mask, retval; |
| 155 | volatile unsigned int *a = (volatile unsigned int *)addr; | 222 | volatile unsigned int *a = (volatile unsigned int *)addr; |
| 156 | unsigned long flags; | ||
| 157 | 223 | ||
| 158 | a += nr >> 5; | 224 | a += nr >> 5; |
| 159 | mask = 1 << (nr & 0x1f); | 225 | mask = 1 << (nr & 0x1f); |
| 160 | local_irq_save(flags); | ||
| 161 | retval = (mask & *a) != 0; | 226 | retval = (mask & *a) != 0; |
| 162 | *a ^= mask; | 227 | *a &= ~mask; |
| 163 | local_irq_restore(flags); | ||
| 164 | return retval; | 228 | return retval; |
| 165 | } | 229 | } |
| 166 | 230 | ||
| 167 | static __inline__ int __test_and_change_bit(int nr, | 231 | static inline int __test_and_change_bit(int nr, |
| 168 | volatile unsigned long *addr) | 232 | volatile unsigned long *addr) |
| 169 | { | 233 | { |
| 170 | int mask, retval; | 234 | int mask, retval; |
| @@ -177,16 +241,7 @@ static __inline__ int __test_and_change_bit(int nr, | |||
| 177 | return retval; | 241 | return retval; |
| 178 | } | 242 | } |
| 179 | 243 | ||
| 180 | /* | 244 | static inline int __test_bit(int nr, const void *addr) |
| 181 | * This routine doesn't need to be atomic. | ||
| 182 | */ | ||
| 183 | static __inline__ int __constant_test_bit(int nr, const void *addr) | ||
| 184 | { | ||
| 185 | return ((1UL << (nr & 31)) & | ||
| 186 | (((const volatile unsigned int *)addr)[nr >> 5])) != 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static __inline__ int __test_bit(int nr, const void *addr) | ||
| 190 | { | 245 | { |
| 191 | int *a = (int *)addr; | 246 | int *a = (int *)addr; |
| 192 | int mask; | 247 | int mask; |
| @@ -196,10 +251,16 @@ static __inline__ int __test_bit(int nr, const void *addr) | |||
| 196 | return ((mask & *a) != 0); | 251 | return ((mask & *a) != 0); |
| 197 | } | 252 | } |
| 198 | 253 | ||
| 199 | #define test_bit(nr,addr) \ | 254 | #ifndef CONFIG_SMP |
| 200 | (__builtin_constant_p(nr) ? \ | 255 | /* |
| 201 | __constant_test_bit((nr),(addr)) : \ | 256 | * This routine doesn't need irq save and restore ops in UP |
| 202 | __test_bit((nr),(addr))) | 257 | * context. |
| 258 | */ | ||
| 259 | static inline int test_bit(int nr, const void *addr) | ||
| 260 | { | ||
| 261 | return __test_bit(nr, addr); | ||
| 262 | } | ||
| 263 | #endif | ||
| 203 | 264 | ||
| 204 | #include <asm-generic/bitops/find.h> | 265 | #include <asm-generic/bitops/find.h> |
| 205 | #include <asm-generic/bitops/hweight.h> | 266 | #include <asm-generic/bitops/hweight.h> |
diff --git a/arch/blackfin/include/asm/cache.h b/arch/blackfin/include/asm/cache.h index 023d72133b5a..86637814cf25 100644 --- a/arch/blackfin/include/asm/cache.h +++ b/arch/blackfin/include/asm/cache.h | |||
| @@ -12,6 +12,11 @@ | |||
| 12 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 12 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
| 13 | #define SMP_CACHE_BYTES L1_CACHE_BYTES | 13 | #define SMP_CACHE_BYTES L1_CACHE_BYTES |
| 14 | 14 | ||
| 15 | #ifdef CONFIG_SMP | ||
| 16 | #define __cacheline_aligned | ||
| 17 | #else | ||
| 18 | #define ____cacheline_aligned | ||
| 19 | |||
| 15 | /* | 20 | /* |
| 16 | * Put cacheline_aliged data to L1 data memory | 21 | * Put cacheline_aliged data to L1 data memory |
| 17 | */ | 22 | */ |
| @@ -21,9 +26,33 @@ | |||
| 21 | __section__(".data_l1.cacheline_aligned"))) | 26 | __section__(".data_l1.cacheline_aligned"))) |
| 22 | #endif | 27 | #endif |
| 23 | 28 | ||
| 29 | #endif | ||
| 30 | |||
| 24 | /* | 31 | /* |
| 25 | * largest L1 which this arch supports | 32 | * largest L1 which this arch supports |
| 26 | */ | 33 | */ |
| 27 | #define L1_CACHE_SHIFT_MAX 5 | 34 | #define L1_CACHE_SHIFT_MAX 5 |
| 28 | 35 | ||
| 36 | #if defined(CONFIG_SMP) && \ | ||
| 37 | !defined(CONFIG_BFIN_CACHE_COHERENT) && \ | ||
| 38 | defined(CONFIG_BFIN_DCACHE) | ||
| 39 | #define __ARCH_SYNC_CORE_DCACHE | ||
| 40 | #ifndef __ASSEMBLY__ | ||
| 41 | asmlinkage void __raw_smp_mark_barrier_asm(void); | ||
| 42 | asmlinkage void __raw_smp_check_barrier_asm(void); | ||
| 43 | |||
| 44 | static inline void smp_mark_barrier(void) | ||
| 45 | { | ||
| 46 | __raw_smp_mark_barrier_asm(); | ||
| 47 | } | ||
| 48 | static inline void smp_check_barrier(void) | ||
| 49 | { | ||
| 50 | __raw_smp_check_barrier_asm(); | ||
| 51 | } | ||
| 52 | |||
| 53 | void resync_core_dcache(void); | ||
| 54 | #endif | ||
| 55 | #endif | ||
| 56 | |||
| 57 | |||
| 29 | #endif | 58 | #endif |
diff --git a/arch/blackfin/include/asm/cacheflush.h b/arch/blackfin/include/asm/cacheflush.h index 4403415583fa..1b040f5b4feb 100644 --- a/arch/blackfin/include/asm/cacheflush.h +++ b/arch/blackfin/include/asm/cacheflush.h | |||
| @@ -35,6 +35,7 @@ extern void blackfin_icache_flush_range(unsigned long start_address, unsigned lo | |||
| 35 | extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); | 35 | extern void blackfin_dcache_flush_range(unsigned long start_address, unsigned long end_address); |
| 36 | extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); | 36 | extern void blackfin_dcache_invalidate_range(unsigned long start_address, unsigned long end_address); |
| 37 | extern void blackfin_dflush_page(void *page); | 37 | extern void blackfin_dflush_page(void *page); |
| 38 | extern void blackfin_invalidate_entire_dcache(void); | ||
| 38 | 39 | ||
| 39 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 40 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
| 40 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) | 41 | #define flush_dcache_mmap_unlock(mapping) do { } while (0) |
| @@ -44,12 +45,20 @@ extern void blackfin_dflush_page(void *page); | |||
| 44 | #define flush_cache_vmap(start, end) do { } while (0) | 45 | #define flush_cache_vmap(start, end) do { } while (0) |
| 45 | #define flush_cache_vunmap(start, end) do { } while (0) | 46 | #define flush_cache_vunmap(start, end) do { } while (0) |
| 46 | 47 | ||
| 48 | #ifdef CONFIG_SMP | ||
| 49 | #define flush_icache_range_others(start, end) \ | ||
| 50 | smp_icache_flush_range_others((start), (end)) | ||
| 51 | #else | ||
| 52 | #define flush_icache_range_others(start, end) do { } while (0) | ||
| 53 | #endif | ||
| 54 | |||
| 47 | static inline void flush_icache_range(unsigned start, unsigned end) | 55 | static inline void flush_icache_range(unsigned start, unsigned end) |
| 48 | { | 56 | { |
| 49 | #if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) | 57 | #if defined(CONFIG_BFIN_DCACHE) && defined(CONFIG_BFIN_ICACHE) |
| 50 | 58 | ||
| 51 | # if defined(CONFIG_BFIN_WT) | 59 | # if defined(CONFIG_BFIN_WT) |
| 52 | blackfin_icache_flush_range((start), (end)); | 60 | blackfin_icache_flush_range((start), (end)); |
| 61 | flush_icache_range_others(start, end); | ||
| 53 | # else | 62 | # else |
| 54 | blackfin_icache_dcache_flush_range((start), (end)); | 63 | blackfin_icache_dcache_flush_range((start), (end)); |
| 55 | # endif | 64 | # endif |
| @@ -58,6 +67,7 @@ static inline void flush_icache_range(unsigned start, unsigned end) | |||
| 58 | 67 | ||
| 59 | # if defined(CONFIG_BFIN_ICACHE) | 68 | # if defined(CONFIG_BFIN_ICACHE) |
| 60 | blackfin_icache_flush_range((start), (end)); | 69 | blackfin_icache_flush_range((start), (end)); |
| 70 | flush_icache_range_others(start, end); | ||
| 61 | # endif | 71 | # endif |
| 62 | # if defined(CONFIG_BFIN_DCACHE) | 72 | # if defined(CONFIG_BFIN_DCACHE) |
| 63 | blackfin_dcache_flush_range((start), (end)); | 73 | blackfin_dcache_flush_range((start), (end)); |
| @@ -66,10 +76,12 @@ static inline void flush_icache_range(unsigned start, unsigned end) | |||
| 66 | #endif | 76 | #endif |
| 67 | } | 77 | } |
| 68 | 78 | ||
| 69 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ | 79 | #define copy_to_user_page(vma, page, vaddr, dst, src, len) \ |
| 70 | do { memcpy(dst, src, len); \ | 80 | do { memcpy(dst, src, len); \ |
| 71 | flush_icache_range ((unsigned) (dst), (unsigned) (dst) + (len)); \ | 81 | flush_icache_range((unsigned) (dst), (unsigned) (dst) + (len)); \ |
| 82 | flush_icache_range_others((unsigned long) (dst), (unsigned long) (dst) + (len));\ | ||
| 72 | } while (0) | 83 | } while (0) |
| 84 | |||
| 73 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) | 85 | #define copy_from_user_page(vma, page, vaddr, dst, src, len) memcpy(dst, src, len) |
| 74 | 86 | ||
| 75 | #if defined(CONFIG_BFIN_DCACHE) | 87 | #if defined(CONFIG_BFIN_DCACHE) |
| @@ -82,7 +94,7 @@ do { memcpy(dst, src, len); \ | |||
| 82 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) | 94 | # define flush_dcache_page(page) blackfin_dflush_page(page_address(page)) |
| 83 | #else | 95 | #else |
| 84 | # define flush_dcache_range(start,end) do { } while (0) | 96 | # define flush_dcache_range(start,end) do { } while (0) |
| 85 | # define flush_dcache_page(page) do { } while (0) | 97 | # define flush_dcache_page(page) do { } while (0) |
| 86 | #endif | 98 | #endif |
| 87 | 99 | ||
| 88 | extern unsigned long reserved_mem_dcache_on; | 100 | extern unsigned long reserved_mem_dcache_on; |
diff --git a/arch/blackfin/include/asm/context.S b/arch/blackfin/include/asm/context.S index c0e630edfb9a..40d20b4a9b1f 100644 --- a/arch/blackfin/include/asm/context.S +++ b/arch/blackfin/include/asm/context.S | |||
| @@ -303,9 +303,14 @@ | |||
| 303 | RETI = [sp++]; | 303 | RETI = [sp++]; |
| 304 | RETS = [sp++]; | 304 | RETS = [sp++]; |
| 305 | 305 | ||
| 306 | #ifdef CONFIG_SMP | ||
| 307 | GET_PDA(p0, r0); | ||
| 308 | r0 = [p0 + PDA_IRQFLAGS]; | ||
| 309 | #else | ||
| 306 | p0.h = _irq_flags; | 310 | p0.h = _irq_flags; |
| 307 | p0.l = _irq_flags; | 311 | p0.l = _irq_flags; |
| 308 | r0 = [p0]; | 312 | r0 = [p0]; |
| 313 | #endif | ||
| 309 | sti r0; | 314 | sti r0; |
| 310 | 315 | ||
| 311 | sp += 4; /* Skip Reserved */ | 316 | sp += 4; /* Skip Reserved */ |
| @@ -352,4 +357,3 @@ | |||
| 352 | SYSCFG = [sp++]; | 357 | SYSCFG = [sp++]; |
| 353 | csync; | 358 | csync; |
| 354 | .endm | 359 | .endm |
| 355 | |||
diff --git a/arch/blackfin/include/asm/cpu.h b/arch/blackfin/include/asm/cpu.h new file mode 100644 index 000000000000..9b7aefe7eb2d --- /dev/null +++ b/arch/blackfin/include/asm/cpu.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * File: arch/blackfin/include/asm/cpu.h. | ||
| 3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
| 4 | * | ||
| 5 | * Copyright 2007 Analog Devices Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, see the file COPYING, or write | ||
| 19 | * to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef __ASM_BLACKFIN_CPU_H | ||
| 24 | #define __ASM_BLACKFIN_CPU_H | ||
| 25 | |||
| 26 | #include <linux/percpu.h> | ||
| 27 | |||
| 28 | struct task_struct; | ||
| 29 | |||
| 30 | struct blackfin_cpudata { | ||
| 31 | struct cpu cpu; | ||
| 32 | struct task_struct *idle; | ||
| 33 | unsigned long cclk; | ||
| 34 | unsigned int imemctl; | ||
| 35 | unsigned int dmemctl; | ||
| 36 | unsigned long loops_per_jiffy; | ||
| 37 | unsigned long dcache_invld_count; | ||
| 38 | }; | ||
| 39 | |||
| 40 | DECLARE_PER_CPU(struct blackfin_cpudata, cpu_data); | ||
| 41 | |||
| 42 | #endif | ||
diff --git a/arch/blackfin/include/asm/l1layout.h b/arch/blackfin/include/asm/l1layout.h index c13ded777828..06bb37f6c788 100644 --- a/arch/blackfin/include/asm/l1layout.h +++ b/arch/blackfin/include/asm/l1layout.h | |||
| @@ -24,7 +24,8 @@ struct l1_scratch_task_info | |||
| 24 | }; | 24 | }; |
| 25 | 25 | ||
| 26 | /* A pointer to the structure in memory. */ | 26 | /* A pointer to the structure in memory. */ |
| 27 | #define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START) | 27 | #define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)\ |
| 28 | get_l1_scratch_start()) | ||
| 28 | 29 | ||
| 29 | #endif | 30 | #endif |
| 30 | 31 | ||
diff --git a/arch/blackfin/include/asm/mutex-dec.h b/arch/blackfin/include/asm/mutex-dec.h new file mode 100644 index 000000000000..0134151656af --- /dev/null +++ b/arch/blackfin/include/asm/mutex-dec.h | |||
| @@ -0,0 +1,112 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-generic/mutex-dec.h | ||
| 3 | * | ||
| 4 | * Generic implementation of the mutex fastpath, based on atomic | ||
| 5 | * decrement/increment. | ||
| 6 | */ | ||
| 7 | #ifndef _ASM_GENERIC_MUTEX_DEC_H | ||
| 8 | #define _ASM_GENERIC_MUTEX_DEC_H | ||
| 9 | |||
| 10 | /** | ||
| 11 | * __mutex_fastpath_lock - try to take the lock by moving the count | ||
| 12 | * from 1 to a 0 value | ||
| 13 | * @count: pointer of type atomic_t | ||
| 14 | * @fail_fn: function to call if the original value was not 1 | ||
| 15 | * | ||
| 16 | * Change the count from 1 to a value lower than 1, and call <fail_fn> if | ||
| 17 | * it wasn't 1 originally. This function MUST leave the value lower than | ||
| 18 | * 1 even when the "1" assertion wasn't true. | ||
| 19 | */ | ||
| 20 | static inline void | ||
| 21 | __mutex_fastpath_lock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) | ||
| 22 | { | ||
| 23 | if (unlikely(atomic_dec_return(count) < 0)) | ||
| 24 | fail_fn(count); | ||
| 25 | else | ||
| 26 | smp_mb(); | ||
| 27 | } | ||
| 28 | |||
| 29 | /** | ||
| 30 | * __mutex_fastpath_lock_retval - try to take the lock by moving the count | ||
| 31 | * from 1 to a 0 value | ||
| 32 | * @count: pointer of type atomic_t | ||
| 33 | * @fail_fn: function to call if the original value was not 1 | ||
| 34 | * | ||
| 35 | * Change the count from 1 to a value lower than 1, and call <fail_fn> if | ||
| 36 | * it wasn't 1 originally. This function returns 0 if the fastpath succeeds, | ||
| 37 | * or anything the slow path function returns. | ||
| 38 | */ | ||
| 39 | static inline int | ||
| 40 | __mutex_fastpath_lock_retval(atomic_t *count, fastcall int (*fail_fn)(atomic_t *)) | ||
| 41 | { | ||
| 42 | if (unlikely(atomic_dec_return(count) < 0)) | ||
| 43 | return fail_fn(count); | ||
| 44 | else { | ||
| 45 | smp_mb(); | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | /** | ||
| 51 | * __mutex_fastpath_unlock - try to promote the count from 0 to 1 | ||
| 52 | * @count: pointer of type atomic_t | ||
| 53 | * @fail_fn: function to call if the original value was not 0 | ||
| 54 | * | ||
| 55 | * Try to promote the count from 0 to 1. If it wasn't 0, call <fail_fn>. | ||
| 56 | * In the failure case, this function is allowed to either set the value to | ||
| 57 | * 1, or to set it to a value lower than 1. | ||
| 58 | * | ||
| 59 | * If the implementation sets it to a value of lower than 1, then the | ||
| 60 | * __mutex_slowpath_needs_to_unlock() macro needs to return 1, it needs | ||
| 61 | * to return 0 otherwise. | ||
| 62 | */ | ||
| 63 | static inline void | ||
| 64 | __mutex_fastpath_unlock(atomic_t *count, fastcall void (*fail_fn)(atomic_t *)) | ||
| 65 | { | ||
| 66 | smp_mb(); | ||
| 67 | if (unlikely(atomic_inc_return(count) <= 0)) | ||
| 68 | fail_fn(count); | ||
| 69 | } | ||
| 70 | |||
| 71 | #define __mutex_slowpath_needs_to_unlock() 1 | ||
| 72 | |||
| 73 | /** | ||
| 74 | * __mutex_fastpath_trylock - try to acquire the mutex, without waiting | ||
| 75 | * | ||
| 76 | * @count: pointer of type atomic_t | ||
| 77 | * @fail_fn: fallback function | ||
| 78 | * | ||
| 79 | * Change the count from 1 to a value lower than 1, and return 0 (failure) | ||
| 80 | * if it wasn't 1 originally, or return 1 (success) otherwise. This function | ||
| 81 | * MUST leave the value lower than 1 even when the "1" assertion wasn't true. | ||
| 82 | * Additionally, if the value was < 0 originally, this function must not leave | ||
| 83 | * it to 0 on failure. | ||
| 84 | * | ||
| 85 | * If the architecture has no effective trylock variant, it should call the | ||
| 86 | * <fail_fn> spinlock-based trylock variant unconditionally. | ||
| 87 | */ | ||
| 88 | static inline int | ||
| 89 | __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
| 90 | { | ||
| 91 | /* | ||
| 92 | * We have two variants here. The cmpxchg based one is the best one | ||
| 93 | * because it never induce a false contention state. It is included | ||
| 94 | * here because architectures using the inc/dec algorithms over the | ||
| 95 | * xchg ones are much more likely to support cmpxchg natively. | ||
| 96 | * | ||
| 97 | * If not we fall back to the spinlock based variant - that is | ||
| 98 | * just as efficient (and simpler) as a 'destructive' probing of | ||
| 99 | * the mutex state would be. | ||
| 100 | */ | ||
| 101 | #ifdef __HAVE_ARCH_CMPXCHG | ||
| 102 | if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { | ||
| 103 | smp_mb(); | ||
| 104 | return 1; | ||
| 105 | } | ||
| 106 | return 0; | ||
| 107 | #else | ||
| 108 | return fail_fn(count); | ||
| 109 | #endif | ||
| 110 | } | ||
| 111 | |||
| 112 | #endif | ||
diff --git a/arch/blackfin/include/asm/mutex.h b/arch/blackfin/include/asm/mutex.h index 458c1f7fbc18..5d399256bf06 100644 --- a/arch/blackfin/include/asm/mutex.h +++ b/arch/blackfin/include/asm/mutex.h | |||
| @@ -6,4 +6,67 @@ | |||
| 6 | * implementation. (see asm-generic/mutex-xchg.h for details) | 6 | * implementation. (see asm-generic/mutex-xchg.h for details) |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #ifndef _ASM_MUTEX_H | ||
| 10 | #define _ASM_MUTEX_H | ||
| 11 | |||
| 12 | #ifndef CONFIG_SMP | ||
| 9 | #include <asm-generic/mutex-dec.h> | 13 | #include <asm-generic/mutex-dec.h> |
| 14 | #else | ||
| 15 | |||
| 16 | static inline void | ||
| 17 | __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
| 18 | { | ||
| 19 | if (unlikely(atomic_dec_return(count) < 0)) | ||
| 20 | fail_fn(count); | ||
| 21 | else | ||
| 22 | smp_mb(); | ||
| 23 | } | ||
| 24 | |||
| 25 | static inline int | ||
| 26 | __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
| 27 | { | ||
| 28 | if (unlikely(atomic_dec_return(count) < 0)) | ||
| 29 | return fail_fn(count); | ||
| 30 | else { | ||
| 31 | smp_mb(); | ||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | static inline void | ||
| 37 | __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) | ||
| 38 | { | ||
| 39 | smp_mb(); | ||
| 40 | if (unlikely(atomic_inc_return(count) <= 0)) | ||
| 41 | fail_fn(count); | ||
| 42 | } | ||
| 43 | |||
| 44 | #define __mutex_slowpath_needs_to_unlock() 1 | ||
| 45 | |||
| 46 | static inline int | ||
| 47 | __mutex_fastpath_trylock(atomic_t *count, int (*fail_fn)(atomic_t *)) | ||
| 48 | { | ||
| 49 | /* | ||
| 50 | * We have two variants here. The cmpxchg based one is the best one | ||
| 51 | * because it never induce a false contention state. It is included | ||
| 52 | * here because architectures using the inc/dec algorithms over the | ||
| 53 | * xchg ones are much more likely to support cmpxchg natively. | ||
| 54 | * | ||
| 55 | * If not we fall back to the spinlock based variant - that is | ||
| 56 | * just as efficient (and simpler) as a 'destructive' probing of | ||
| 57 | * the mutex state would be. | ||
| 58 | */ | ||
| 59 | #ifdef __HAVE_ARCH_CMPXCHG | ||
| 60 | if (likely(atomic_cmpxchg(count, 1, 0) == 1)) { | ||
| 61 | smp_mb(); | ||
| 62 | return 1; | ||
| 63 | } | ||
| 64 | return 0; | ||
| 65 | #else | ||
| 66 | return fail_fn(count); | ||
| 67 | #endif | ||
| 68 | } | ||
| 69 | |||
| 70 | #endif | ||
| 71 | |||
| 72 | #endif | ||
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h new file mode 100644 index 000000000000..a24d130c30f0 --- /dev/null +++ b/arch/blackfin/include/asm/pda.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * File: arch/blackfin/include/asm/pda.h | ||
| 3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
| 4 | * | ||
| 5 | * Copyright 2007 Analog Devices Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, see the file COPYING, or write | ||
| 19 | * to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef _ASM_BLACKFIN_PDA_H | ||
| 24 | #define _ASM_BLACKFIN_PDA_H | ||
| 25 | |||
| 26 | #include <asm/mem_map.h> | ||
| 27 | |||
| 28 | #ifndef __ASSEMBLY__ | ||
| 29 | |||
| 30 | struct blackfin_pda { /* Per-processor Data Area */ | ||
| 31 | struct blackfin_pda *next; | ||
| 32 | |||
| 33 | unsigned long syscfg; | ||
| 34 | #ifdef CONFIG_SMP | ||
| 35 | unsigned long imask; /* Current IMASK value */ | ||
| 36 | #endif | ||
| 37 | |||
| 38 | unsigned long *ipdt; /* Start of switchable I-CPLB table */ | ||
| 39 | unsigned long *ipdt_swapcount; /* Number of swaps in ipdt */ | ||
| 40 | unsigned long *dpdt; /* Start of switchable D-CPLB table */ | ||
| 41 | unsigned long *dpdt_swapcount; /* Number of swaps in dpdt */ | ||
| 42 | |||
| 43 | /* | ||
| 44 | * Single instructions can have multiple faults, which | ||
| 45 | * need to be handled by traps.c, in irq5. We store | ||
| 46 | * the exception cause to ensure we don't miss a | ||
| 47 | * double fault condition | ||
| 48 | */ | ||
| 49 | unsigned long ex_iptr; | ||
| 50 | unsigned long ex_optr; | ||
| 51 | unsigned long ex_buf[4]; | ||
| 52 | unsigned long ex_imask; /* Saved imask from exception */ | ||
| 53 | unsigned long *ex_stack; /* Exception stack space */ | ||
| 54 | |||
| 55 | #ifdef ANOMALY_05000261 | ||
| 56 | unsigned long last_cplb_fault_retx; | ||
| 57 | #endif | ||
| 58 | unsigned long dcplb_fault_addr; | ||
| 59 | unsigned long icplb_fault_addr; | ||
| 60 | unsigned long retx; | ||
| 61 | unsigned long seqstat; | ||
| 62 | }; | ||
| 63 | |||
| 64 | extern struct blackfin_pda cpu_pda[]; | ||
| 65 | |||
| 66 | void reserve_pda(void); | ||
| 67 | |||
| 68 | #endif /* __ASSEMBLY__ */ | ||
| 69 | |||
| 70 | #endif /* _ASM_BLACKFIN_PDA_H */ | ||
diff --git a/arch/blackfin/include/asm/percpu.h b/arch/blackfin/include/asm/percpu.h index 78dd61f6b39f..797c0c165069 100644 --- a/arch/blackfin/include/asm/percpu.h +++ b/arch/blackfin/include/asm/percpu.h | |||
| @@ -3,4 +3,14 @@ | |||
| 3 | 3 | ||
| 4 | #include <asm-generic/percpu.h> | 4 | #include <asm-generic/percpu.h> |
| 5 | 5 | ||
| 6 | #endif /* __ARCH_BLACKFIN_PERCPU__ */ | 6 | #ifdef CONFIG_MODULES |
| 7 | #define PERCPU_MODULE_RESERVE 8192 | ||
| 8 | #else | ||
| 9 | #define PERCPU_MODULE_RESERVE 0 | ||
| 10 | #endif | ||
| 11 | |||
| 12 | #define PERCPU_ENOUGH_ROOM \ | ||
| 13 | (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ | ||
| 14 | PERCPU_MODULE_RESERVE) | ||
| 15 | |||
| 16 | #endif /* __ARCH_BLACKFIN_PERCPU__ */ | ||
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index e3e9b41fa8db..30703c75030c 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h | |||
| @@ -106,7 +106,8 @@ unsigned long get_wchan(struct task_struct *p); | |||
| 106 | eip; }) | 106 | eip; }) |
| 107 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) | 107 | #define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) |
| 108 | 108 | ||
| 109 | #define cpu_relax() barrier() | 109 | #define cpu_relax() smp_mb() |
| 110 | |||
| 110 | 111 | ||
| 111 | /* Get the Silicon Revision of the chip */ | 112 | /* Get the Silicon Revision of the chip */ |
| 112 | static inline uint32_t __pure bfin_revid(void) | 113 | static inline uint32_t __pure bfin_revid(void) |
| @@ -137,7 +138,11 @@ static inline uint32_t __pure bfin_revid(void) | |||
| 137 | static inline uint16_t __pure bfin_cpuid(void) | 138 | static inline uint16_t __pure bfin_cpuid(void) |
| 138 | { | 139 | { |
| 139 | return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; | 140 | return (bfin_read_CHIPID() & CHIPID_FAMILY) >> 12; |
| 141 | } | ||
| 140 | 142 | ||
| 143 | static inline uint32_t __pure bfin_dspid(void) | ||
| 144 | { | ||
| 145 | return bfin_read_DSPID(); | ||
| 141 | } | 146 | } |
| 142 | 147 | ||
| 143 | static inline uint32_t __pure bfin_compiled_revid(void) | 148 | static inline uint32_t __pure bfin_compiled_revid(void) |
diff --git a/arch/blackfin/include/asm/rwlock.h b/arch/blackfin/include/asm/rwlock.h new file mode 100644 index 000000000000..4a724b378971 --- /dev/null +++ b/arch/blackfin/include/asm/rwlock.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef _ASM_BLACKFIN_RWLOCK_H | ||
| 2 | #define _ASM_BLACKFIN_RWLOCK_H | ||
| 3 | |||
| 4 | #define RW_LOCK_BIAS 0x01000000 | ||
| 5 | |||
| 6 | #endif | ||
diff --git a/arch/blackfin/include/asm/smp.h b/arch/blackfin/include/asm/smp.h new file mode 100644 index 000000000000..233cb8c3cfb7 --- /dev/null +++ b/arch/blackfin/include/asm/smp.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * File: arch/blackfin/include/asm/smp.h | ||
| 3 | * Author: Philippe Gerum <rpm@xenomai.org> | ||
| 4 | * | ||
| 5 | * Copyright 2007 Analog Devices Inc. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, see the file COPYING, or write | ||
| 19 | * to the Free Software Foundation, Inc., | ||
| 20 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef __ASM_BLACKFIN_SMP_H | ||
| 24 | #define __ASM_BLACKFIN_SMP_H | ||
| 25 | |||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/threads.h> | ||
| 28 | #include <linux/cpumask.h> | ||
| 29 | #include <linux/cache.h> | ||
| 30 | #include <asm/blackfin.h> | ||
| 31 | #include <mach/smp.h> | ||
| 32 | |||
| 33 | #define raw_smp_processor_id() blackfin_core_id() | ||
| 34 | |||
| 35 | struct corelock_slot { | ||
| 36 | int lock; | ||
| 37 | }; | ||
| 38 | |||
| 39 | void smp_icache_flush_range_others(unsigned long start, | ||
| 40 | unsigned long end); | ||
| 41 | |||
| 42 | #endif /* !__ASM_BLACKFIN_SMP_H */ | ||
diff --git a/arch/blackfin/include/asm/spinlock.h b/arch/blackfin/include/asm/spinlock.h index 64e908a50646..0249ac319476 100644 --- a/arch/blackfin/include/asm/spinlock.h +++ b/arch/blackfin/include/asm/spinlock.h | |||
| @@ -1,6 +1,89 @@ | |||
| 1 | #ifndef __BFIN_SPINLOCK_H | 1 | #ifndef __BFIN_SPINLOCK_H |
| 2 | #define __BFIN_SPINLOCK_H | 2 | #define __BFIN_SPINLOCK_H |
| 3 | 3 | ||
| 4 | #error blackfin architecture does not support SMP spin lock yet | 4 | #include <asm/atomic.h> |
| 5 | 5 | ||
| 6 | #endif | 6 | asmlinkage int __raw_spin_is_locked_asm(volatile int *ptr); |
| 7 | asmlinkage void __raw_spin_lock_asm(volatile int *ptr); | ||
| 8 | asmlinkage int __raw_spin_trylock_asm(volatile int *ptr); | ||
| 9 | asmlinkage void __raw_spin_unlock_asm(volatile int *ptr); | ||
| 10 | asmlinkage void __raw_read_lock_asm(volatile int *ptr); | ||
| 11 | asmlinkage int __raw_read_trylock_asm(volatile int *ptr); | ||
| 12 | asmlinkage void __raw_read_unlock_asm(volatile int *ptr); | ||
| 13 | asmlinkage void __raw_write_lock_asm(volatile int *ptr); | ||
| 14 | asmlinkage int __raw_write_trylock_asm(volatile int *ptr); | ||
| 15 | asmlinkage void __raw_write_unlock_asm(volatile int *ptr); | ||
| 16 | |||
| 17 | static inline int __raw_spin_is_locked(raw_spinlock_t *lock) | ||
| 18 | { | ||
| 19 | return __raw_spin_is_locked_asm(&lock->lock); | ||
| 20 | } | ||
| 21 | |||
| 22 | static inline void __raw_spin_lock(raw_spinlock_t *lock) | ||
| 23 | { | ||
| 24 | __raw_spin_lock_asm(&lock->lock); | ||
| 25 | } | ||
| 26 | |||
| 27 | #define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock) | ||
| 28 | |||
| 29 | static inline int __raw_spin_trylock(raw_spinlock_t *lock) | ||
| 30 | { | ||
| 31 | return __raw_spin_trylock_asm(&lock->lock); | ||
| 32 | } | ||
| 33 | |||
| 34 | static inline void __raw_spin_unlock(raw_spinlock_t *lock) | ||
| 35 | { | ||
| 36 | __raw_spin_unlock_asm(&lock->lock); | ||
| 37 | } | ||
| 38 | |||
| 39 | static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock) | ||
| 40 | { | ||
| 41 | while (__raw_spin_is_locked(lock)) | ||
| 42 | cpu_relax(); | ||
| 43 | } | ||
| 44 | |||
| 45 | static inline int __raw_read_can_lock(raw_rwlock_t *rw) | ||
| 46 | { | ||
| 47 | return __raw_uncached_fetch_asm(&rw->lock) > 0; | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline int __raw_write_can_lock(raw_rwlock_t *rw) | ||
| 51 | { | ||
| 52 | return __raw_uncached_fetch_asm(&rw->lock) == RW_LOCK_BIAS; | ||
| 53 | } | ||
| 54 | |||
| 55 | static inline void __raw_read_lock(raw_rwlock_t *rw) | ||
| 56 | { | ||
| 57 | __raw_read_lock_asm(&rw->lock); | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline int __raw_read_trylock(raw_rwlock_t *rw) | ||
| 61 | { | ||
| 62 | return __raw_read_trylock_asm(&rw->lock); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void __raw_read_unlock(raw_rwlock_t *rw) | ||
| 66 | { | ||
| 67 | __raw_read_unlock_asm(&rw->lock); | ||
| 68 | } | ||
| 69 | |||
| 70 | static inline void __raw_write_lock(raw_rwlock_t *rw) | ||
| 71 | { | ||
| 72 | __raw_write_lock_asm(&rw->lock); | ||
| 73 | } | ||
| 74 | |||
| 75 | static inline int __raw_write_trylock(raw_rwlock_t *rw) | ||
| 76 | { | ||
| 77 | return __raw_write_trylock_asm(&rw->lock); | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void __raw_write_unlock(raw_rwlock_t *rw) | ||
| 81 | { | ||
| 82 | __raw_write_unlock_asm(&rw->lock); | ||
| 83 | } | ||
| 84 | |||
| 85 | #define _raw_spin_relax(lock) cpu_relax() | ||
| 86 | #define _raw_read_relax(lock) cpu_relax() | ||
| 87 | #define _raw_write_relax(lock) cpu_relax() | ||
| 88 | |||
| 89 | #endif /* !__BFIN_SPINLOCK_H */ | ||
diff --git a/arch/blackfin/include/asm/spinlock_types.h b/arch/blackfin/include/asm/spinlock_types.h new file mode 100644 index 000000000000..b1e3c4c7b382 --- /dev/null +++ b/arch/blackfin/include/asm/spinlock_types.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | #ifndef __ASM_SPINLOCK_TYPES_H | ||
| 2 | #define __ASM_SPINLOCK_TYPES_H | ||
| 3 | |||
| 4 | #ifndef __LINUX_SPINLOCK_TYPES_H | ||
| 5 | # error "please don't include this file directly" | ||
| 6 | #endif | ||
| 7 | |||
| 8 | #include <asm/rwlock.h> | ||
| 9 | |||
| 10 | typedef struct { | ||
| 11 | volatile unsigned int lock; | ||
| 12 | } raw_spinlock_t; | ||
| 13 | |||
| 14 | #define __RAW_SPIN_LOCK_UNLOCKED { 0 } | ||
| 15 | |||
| 16 | typedef struct { | ||
| 17 | volatile unsigned int lock; | ||
| 18 | } raw_rwlock_t; | ||
| 19 | |||
| 20 | #define __RAW_RW_LOCK_UNLOCKED { RW_LOCK_BIAS } | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index 8f1627d8bf09..6b368faf30c3 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h | |||
| @@ -37,20 +37,16 @@ | |||
| 37 | #include <linux/linkage.h> | 37 | #include <linux/linkage.h> |
| 38 | #include <linux/compiler.h> | 38 | #include <linux/compiler.h> |
| 39 | #include <mach/anomaly.h> | 39 | #include <mach/anomaly.h> |
| 40 | #include <asm/pda.h> | ||
| 41 | #include <asm/processor.h> | ||
| 42 | |||
| 43 | /* Forward decl needed due to cdef inter dependencies */ | ||
| 44 | static inline uint32_t __pure bfin_dspid(void); | ||
| 45 | #define blackfin_core_id() (bfin_dspid() & 0xff) | ||
| 40 | 46 | ||
| 41 | /* | 47 | /* |
| 42 | * Interrupt configuring macros. | 48 | * Interrupt configuring macros. |
| 43 | */ | 49 | */ |
| 44 | |||
| 45 | extern unsigned long irq_flags; | ||
| 46 | |||
| 47 | #define local_irq_enable() \ | ||
| 48 | __asm__ __volatile__( \ | ||
| 49 | "sti %0;" \ | ||
| 50 | : \ | ||
| 51 | : "d" (irq_flags) \ | ||
| 52 | ) | ||
| 53 | |||
| 54 | #define local_irq_disable() \ | 50 | #define local_irq_disable() \ |
| 55 | do { \ | 51 | do { \ |
| 56 | int __tmp_dummy; \ | 52 | int __tmp_dummy; \ |
| @@ -66,6 +62,18 @@ extern unsigned long irq_flags; | |||
| 66 | # define NOP_PAD_ANOMALY_05000244 | 62 | # define NOP_PAD_ANOMALY_05000244 |
| 67 | #endif | 63 | #endif |
| 68 | 64 | ||
| 65 | #ifdef CONFIG_SMP | ||
| 66 | # define irq_flags cpu_pda[blackfin_core_id()].imask | ||
| 67 | #else | ||
| 68 | extern unsigned long irq_flags; | ||
| 69 | #endif | ||
| 70 | |||
| 71 | #define local_irq_enable() \ | ||
| 72 | __asm__ __volatile__( \ | ||
| 73 | "sti %0;" \ | ||
| 74 | : \ | ||
| 75 | : "d" (irq_flags) \ | ||
| 76 | ) | ||
| 69 | #define idle_with_irq_disabled() \ | 77 | #define idle_with_irq_disabled() \ |
| 70 | __asm__ __volatile__( \ | 78 | __asm__ __volatile__( \ |
| 71 | NOP_PAD_ANOMALY_05000244 \ | 79 | NOP_PAD_ANOMALY_05000244 \ |
| @@ -129,22 +137,85 @@ extern unsigned long irq_flags; | |||
| 129 | #define rmb() asm volatile ("" : : :"memory") | 137 | #define rmb() asm volatile ("" : : :"memory") |
| 130 | #define wmb() asm volatile ("" : : :"memory") | 138 | #define wmb() asm volatile ("" : : :"memory") |
| 131 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) | 139 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) |
| 132 | |||
| 133 | #define read_barrier_depends() do { } while(0) | 140 | #define read_barrier_depends() do { } while(0) |
| 134 | 141 | ||
| 135 | #ifdef CONFIG_SMP | 142 | #ifdef CONFIG_SMP |
| 136 | #define smp_mb() mb() | 143 | asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value); |
| 137 | #define smp_rmb() rmb() | 144 | asmlinkage unsigned long __raw_xchg_2_asm(volatile void *ptr, unsigned long value); |
| 138 | #define smp_wmb() wmb() | 145 | asmlinkage unsigned long __raw_xchg_4_asm(volatile void *ptr, unsigned long value); |
| 139 | #define smp_read_barrier_depends() read_barrier_depends() | 146 | asmlinkage unsigned long __raw_cmpxchg_1_asm(volatile void *ptr, |
| 147 | unsigned long new, unsigned long old); | ||
| 148 | asmlinkage unsigned long __raw_cmpxchg_2_asm(volatile void *ptr, | ||
| 149 | unsigned long new, unsigned long old); | ||
| 150 | asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr, | ||
| 151 | unsigned long new, unsigned long old); | ||
| 152 | |||
| 153 | #ifdef __ARCH_SYNC_CORE_DCACHE | ||
| 154 | # define smp_mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0) | ||
| 155 | # define smp_rmb() do { barrier(); smp_check_barrier(); } while (0) | ||
| 156 | # define smp_wmb() do { barrier(); smp_mark_barrier(); } while (0) | ||
| 140 | #else | 157 | #else |
| 158 | # define smp_mb() barrier() | ||
| 159 | # define smp_rmb() barrier() | ||
| 160 | # define smp_wmb() barrier() | ||
| 161 | #endif | ||
| 162 | |||
| 163 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | ||
| 164 | int size) | ||
| 165 | { | ||
| 166 | unsigned long tmp; | ||
| 167 | |||
| 168 | switch (size) { | ||
| 169 | case 1: | ||
| 170 | tmp = __raw_xchg_1_asm(ptr, x); | ||
| 171 | break; | ||
| 172 | case 2: | ||
| 173 | tmp = __raw_xchg_2_asm(ptr, x); | ||
| 174 | break; | ||
| 175 | case 4: | ||
| 176 | tmp = __raw_xchg_4_asm(ptr, x); | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | |||
| 180 | return tmp; | ||
| 181 | } | ||
| 182 | |||
| 183 | /* | ||
| 184 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | ||
| 185 | * store NEW in MEM. Return the initial value in MEM. Success is | ||
| 186 | * indicated by comparing RETURN with OLD. | ||
| 187 | */ | ||
| 188 | static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | ||
| 189 | unsigned long new, int size) | ||
| 190 | { | ||
| 191 | unsigned long tmp; | ||
| 192 | |||
| 193 | switch (size) { | ||
| 194 | case 1: | ||
| 195 | tmp = __raw_cmpxchg_1_asm(ptr, new, old); | ||
| 196 | break; | ||
| 197 | case 2: | ||
| 198 | tmp = __raw_cmpxchg_2_asm(ptr, new, old); | ||
| 199 | break; | ||
| 200 | case 4: | ||
| 201 | tmp = __raw_cmpxchg_4_asm(ptr, new, old); | ||
| 202 | break; | ||
| 203 | } | ||
| 204 | |||
| 205 | return tmp; | ||
| 206 | } | ||
| 207 | #define cmpxchg(ptr, o, n) \ | ||
| 208 | ((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o), \ | ||
| 209 | (unsigned long)(n), sizeof(*(ptr)))) | ||
| 210 | |||
| 211 | #define smp_read_barrier_depends() smp_check_barrier() | ||
| 212 | |||
| 213 | #else /* !CONFIG_SMP */ | ||
| 214 | |||
| 141 | #define smp_mb() barrier() | 215 | #define smp_mb() barrier() |
| 142 | #define smp_rmb() barrier() | 216 | #define smp_rmb() barrier() |
| 143 | #define smp_wmb() barrier() | 217 | #define smp_wmb() barrier() |
| 144 | #define smp_read_barrier_depends() do { } while(0) | 218 | #define smp_read_barrier_depends() do { } while(0) |
| 145 | #endif | ||
| 146 | |||
| 147 | #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) | ||
| 148 | 219 | ||
| 149 | struct __xchg_dummy { | 220 | struct __xchg_dummy { |
| 150 | unsigned long a[100]; | 221 | unsigned long a[100]; |
| @@ -194,9 +265,12 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | |||
| 194 | (unsigned long)(n), sizeof(*(ptr)))) | 265 | (unsigned long)(n), sizeof(*(ptr)))) |
| 195 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | 266 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) |
| 196 | 267 | ||
| 197 | #ifndef CONFIG_SMP | ||
| 198 | #include <asm-generic/cmpxchg.h> | 268 | #include <asm-generic/cmpxchg.h> |
| 199 | #endif | 269 | |
| 270 | #endif /* !CONFIG_SMP */ | ||
| 271 | |||
| 272 | #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) | ||
| 273 | #define tas(ptr) ((void)xchg((ptr), 1)) | ||
| 200 | 274 | ||
| 201 | #define prepare_to_switch() do { } while(0) | 275 | #define prepare_to_switch() do { } while(0) |
| 202 | 276 | ||
| @@ -218,4 +292,4 @@ do { \ | |||
| 218 | (last) = resume (prev, next); \ | 292 | (last) = resume (prev, next); \ |
| 219 | } while (0) | 293 | } while (0) |
| 220 | 294 | ||
| 221 | #endif /* _BLACKFIN_SYSTEM_H */ | 295 | #endif /* _BLACKFIN_SYSTEM_H */ |
