diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-14 22:03:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-04-14 22:03:27 -0400 |
commit | e38f5b745075828ac51b12c8c95c85a7be4a3ec7 (patch) | |
tree | 603387de83d221f62be764de28a841ef84105413 | |
parent | e6d28318344535331d9473548b210dd267fe7b7e (diff) | |
parent | 8d50de9ee77b38a239dc5b1d6a63ad92a78f119d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/vapier/blackfin:
Blackfin: SMP: fix cache flush loop
Blackfin: time-ts: ack gptimer sooner to avoid missing short ints
Blackfin: gptimers: fix thinko when disabling timers
Blackfin: SMP: make all barriers handle cache issues
-rw-r--r-- | arch/blackfin/include/asm/system.h | 36 | ||||
-rw-r--r-- | arch/blackfin/kernel/gptimers.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/time-ts.c | 8 | ||||
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 19 |
4 files changed, 42 insertions, 23 deletions
diff --git a/arch/blackfin/include/asm/system.h b/arch/blackfin/include/asm/system.h index 19e2c7c3e63a..44bd0cced725 100644 --- a/arch/blackfin/include/asm/system.h +++ b/arch/blackfin/include/asm/system.h | |||
@@ -19,11 +19,11 @@ | |||
19 | * Force strict CPU ordering. | 19 | * Force strict CPU ordering. |
20 | */ | 20 | */ |
21 | #define nop() __asm__ __volatile__ ("nop;\n\t" : : ) | 21 | #define nop() __asm__ __volatile__ ("nop;\n\t" : : ) |
22 | #define mb() __asm__ __volatile__ ("" : : : "memory") | 22 | #define smp_mb() mb() |
23 | #define rmb() __asm__ __volatile__ ("" : : : "memory") | 23 | #define smp_rmb() rmb() |
24 | #define wmb() __asm__ __volatile__ ("" : : : "memory") | 24 | #define smp_wmb() wmb() |
25 | #define set_mb(var, value) do { (void) xchg(&var, value); } while (0) | 25 | #define set_mb(var, value) do { var = value; mb(); } while (0) |
26 | #define read_barrier_depends() do { } while(0) | 26 | #define smp_read_barrier_depends() read_barrier_depends() |
27 | 27 | ||
28 | #ifdef CONFIG_SMP | 28 | #ifdef CONFIG_SMP |
29 | asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value); | 29 | asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value); |
@@ -37,16 +37,16 @@ asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr, | |||
37 | unsigned long new, unsigned long old); | 37 | unsigned long new, unsigned long old); |
38 | 38 | ||
39 | #ifdef __ARCH_SYNC_CORE_DCACHE | 39 | #ifdef __ARCH_SYNC_CORE_DCACHE |
40 | # define smp_mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0) | 40 | /* Force Core data cache coherence */ |
41 | # define smp_rmb() do { barrier(); smp_check_barrier(); } while (0) | 41 | # define mb() do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0) |
42 | # define smp_wmb() do { barrier(); smp_mark_barrier(); } while (0) | 42 | # define rmb() do { barrier(); smp_check_barrier(); } while (0) |
43 | #define smp_read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0) | 43 | # define wmb() do { barrier(); smp_mark_barrier(); } while (0) |
44 | 44 | # define read_barrier_depends() do { barrier(); smp_check_barrier(); } while (0) | |
45 | #else | 45 | #else |
46 | # define smp_mb() barrier() | 46 | # define mb() barrier() |
47 | # define smp_rmb() barrier() | 47 | # define rmb() barrier() |
48 | # define smp_wmb() barrier() | 48 | # define wmb() barrier() |
49 | #define smp_read_barrier_depends() barrier() | 49 | # define read_barrier_depends() do { } while (0) |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, | 52 | static inline unsigned long __xchg(unsigned long x, volatile void *ptr, |
@@ -99,10 +99,10 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, | |||
99 | 99 | ||
100 | #else /* !CONFIG_SMP */ | 100 | #else /* !CONFIG_SMP */ |
101 | 101 | ||
102 | #define smp_mb() barrier() | 102 | #define mb() barrier() |
103 | #define smp_rmb() barrier() | 103 | #define rmb() barrier() |
104 | #define smp_wmb() barrier() | 104 | #define wmb() barrier() |
105 | #define smp_read_barrier_depends() do { } while(0) | 105 | #define read_barrier_depends() do { } while (0) |
106 | 106 | ||
107 | struct __xchg_dummy { | 107 | struct __xchg_dummy { |
108 | unsigned long a[100]; | 108 | unsigned long a[100]; |
diff --git a/arch/blackfin/kernel/gptimers.c b/arch/blackfin/kernel/gptimers.c index cdbe075de1dc..8b81dc04488a 100644 --- a/arch/blackfin/kernel/gptimers.c +++ b/arch/blackfin/kernel/gptimers.c | |||
@@ -268,7 +268,7 @@ void disable_gptimers(uint16_t mask) | |||
268 | _disable_gptimers(mask); | 268 | _disable_gptimers(mask); |
269 | for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) | 269 | for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i) |
270 | if (mask & (1 << i)) | 270 | if (mask & (1 << i)) |
271 | group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i]; | 271 | group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i]; |
272 | SSYNC(); | 272 | SSYNC(); |
273 | } | 273 | } |
274 | EXPORT_SYMBOL(disable_gptimers); | 274 | EXPORT_SYMBOL(disable_gptimers); |
diff --git a/arch/blackfin/kernel/time-ts.c b/arch/blackfin/kernel/time-ts.c index 8c9a43daf80f..cdb4beb6bc8f 100644 --- a/arch/blackfin/kernel/time-ts.c +++ b/arch/blackfin/kernel/time-ts.c | |||
@@ -206,8 +206,14 @@ irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id) | |||
206 | { | 206 | { |
207 | struct clock_event_device *evt = dev_id; | 207 | struct clock_event_device *evt = dev_id; |
208 | smp_mb(); | 208 | smp_mb(); |
209 | evt->event_handler(evt); | 209 | /* |
210 | * We want to ACK before we handle so that we can handle smaller timer | ||
211 | * intervals. This way if the timer expires again while we're handling | ||
212 | * things, we're more likely to see that 2nd int rather than swallowing | ||
213 | * it by ACKing the int at the end of this handler. | ||
214 | */ | ||
210 | bfin_gptmr0_ack(); | 215 | bfin_gptmr0_ack(); |
216 | evt->event_handler(evt); | ||
211 | return IRQ_HANDLED; | 217 | return IRQ_HANDLED; |
212 | } | 218 | } |
213 | 219 | ||
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 6e17a265c4d3..8bce5ed031e4 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -109,10 +109,23 @@ static void ipi_flush_icache(void *info) | |||
109 | struct blackfin_flush_data *fdata = info; | 109 | struct blackfin_flush_data *fdata = info; |
110 | 110 | ||
111 | /* Invalidate the memory holding the bounds of the flushed region. */ | 111 | /* Invalidate the memory holding the bounds of the flushed region. */ |
112 | invalidate_dcache_range((unsigned long)fdata, | 112 | blackfin_dcache_invalidate_range((unsigned long)fdata, |
113 | (unsigned long)fdata + sizeof(*fdata)); | 113 | (unsigned long)fdata + sizeof(*fdata)); |
114 | |||
115 | /* Make sure all write buffers in the data side of the core | ||
116 | * are flushed before trying to invalidate the icache. This | ||
117 | * needs to be after the data flush and before the icache | ||
118 | * flush so that the SSYNC does the right thing in preventing | ||
119 | * the instruction prefetcher from hitting things in cached | ||
120 | * memory at the wrong time -- it runs much further ahead than | ||
121 | * the pipeline. | ||
122 | */ | ||
123 | SSYNC(); | ||
114 | 124 | ||
115 | flush_icache_range(fdata->start, fdata->end); | 125 | /* ipi_flaush_icache is invoked by generic flush_icache_range, |
126 | * so call blackfin arch icache flush directly here. | ||
127 | */ | ||
128 | blackfin_icache_flush_range(fdata->start, fdata->end); | ||
116 | } | 129 | } |
117 | 130 | ||
118 | static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) | 131 | static void ipi_call_function(unsigned int cpu, struct ipi_message *msg) |