aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-04-05 15:42:04 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-04-18 22:14:29 -0400
commit7e3bfc7cfc402458b0386086ab650ce811720927 (patch)
treed7512049fad83d13a909a9ad8085c33f9d44b13f
parentbb12d612d4b2e6dc260fab081f69df783b74289f (diff)
[MIPS] Handle IDE PIO cache aliases on SMP.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/mm/c-r3k.c5
-rw-r--r--arch/mips/mm/c-r4k.c1
-rw-r--r--arch/mips/mm/c-sb1.c1
-rw-r--r--arch/mips/mm/c-tx39.c7
-rw-r--r--arch/mips/mm/cache.c1
-rw-r--r--include/asm-mips/cacheflush.h1
-rw-r--r--include/asm-mips/mach-generic/ide.h46
7 files changed, 60 insertions, 2 deletions
diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
index 9dd1352d5748..bb041a22f20a 100644
--- a/arch/mips/mm/c-r3k.c
+++ b/arch/mips/mm/c-r3k.c
@@ -260,6 +260,10 @@ static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page,
260{ 260{
261} 261}
262 262
263static void local_r3k_flush_data_cache_page(unsigned long addr)
264{
265}
266
263static void r3k_flush_data_cache_page(unsigned long addr) 267static void r3k_flush_data_cache_page(unsigned long addr)
264{ 268{
265} 269}
@@ -335,6 +339,7 @@ void __init r3k_cache_init(void)
335 flush_icache_range = r3k_flush_icache_range; 339 flush_icache_range = r3k_flush_icache_range;
336 340
337 flush_cache_sigtramp = r3k_flush_cache_sigtramp; 341 flush_cache_sigtramp = r3k_flush_cache_sigtramp;
342 local_flush_data_cache_page = local_r3k_flush_data_cache_page;
338 flush_data_cache_page = r3k_flush_data_cache_page; 343 flush_data_cache_page = r3k_flush_data_cache_page;
339 344
340 _dma_cache_wback_inv = r3k_dma_cache_wback_inv; 345 _dma_cache_wback_inv = r3k_dma_cache_wback_inv;
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index c4c208449d87..d88c6686413a 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1199,6 +1199,7 @@ void __init r4k_cache_init(void)
1199 1199
1200 flush_cache_sigtramp = r4k_flush_cache_sigtramp; 1200 flush_cache_sigtramp = r4k_flush_cache_sigtramp;
1201 flush_icache_all = r4k_flush_icache_all; 1201 flush_icache_all = r4k_flush_icache_all;
1202 local_flush_data_cache_page = local_r4k_flush_data_cache_page;
1202 flush_data_cache_page = r4k_flush_data_cache_page; 1203 flush_data_cache_page = r4k_flush_data_cache_page;
1203 flush_icache_range = r4k_flush_icache_range; 1204 flush_icache_range = r4k_flush_icache_range;
1204 1205
diff --git a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
index 2f08b535f20e..f9b129491b1e 100644
--- a/arch/mips/mm/c-sb1.c
+++ b/arch/mips/mm/c-sb1.c
@@ -528,6 +528,7 @@ void sb1_cache_init(void)
528 flush_cache_page = sb1_flush_cache_page; 528 flush_cache_page = sb1_flush_cache_page;
529 529
530 flush_cache_sigtramp = sb1_flush_cache_sigtramp; 530 flush_cache_sigtramp = sb1_flush_cache_sigtramp;
531 local_flush_data_cache_page = (void *) sb1_nop;
531 flush_data_cache_page = (void *) sb1_nop; 532 flush_data_cache_page = (void *) sb1_nop;
532 533
533 /* Full flush */ 534 /* Full flush */
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index fe232e3988e3..5dfc9b1901f6 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -216,6 +216,11 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
216 tx39_blast_icache_page_indexed(page); 216 tx39_blast_icache_page_indexed(page);
217} 217}
218 218
219static void local_tx39_flush_data_cache_page(void * addr)
220{
221 tx39_blast_dcache_page(addr);
222}
223
219static void tx39_flush_data_cache_page(unsigned long addr) 224static void tx39_flush_data_cache_page(unsigned long addr)
220{ 225{
221 tx39_blast_dcache_page(addr); 226 tx39_blast_dcache_page(addr);
@@ -381,6 +386,7 @@ void __init tx39_cache_init(void)
381 flush_icache_range = (void *) tx39h_flush_icache_all; 386 flush_icache_range = (void *) tx39h_flush_icache_all;
382 387
383 flush_cache_sigtramp = (void *) tx39h_flush_icache_all; 388 flush_cache_sigtramp = (void *) tx39h_flush_icache_all;
389 local_flush_data_cache_page = (void *) tx39h_flush_icache_all;
384 flush_data_cache_page = (void *) tx39h_flush_icache_all; 390 flush_data_cache_page = (void *) tx39h_flush_icache_all;
385 391
386 _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; 392 _dma_cache_wback_inv = tx39h_dma_cache_wback_inv;
@@ -406,6 +412,7 @@ void __init tx39_cache_init(void)
406 flush_icache_range = tx39_flush_icache_range; 412 flush_icache_range = tx39_flush_icache_range;
407 413
408 flush_cache_sigtramp = tx39_flush_cache_sigtramp; 414 flush_cache_sigtramp = tx39_flush_cache_sigtramp;
415 local_flush_data_cache_page = local_tx39_flush_data_cache_page;
409 flush_data_cache_page = tx39_flush_data_cache_page; 416 flush_data_cache_page = tx39_flush_data_cache_page;
410 417
411 _dma_cache_wback_inv = tx39_dma_cache_wback_inv; 418 _dma_cache_wback_inv = tx39_dma_cache_wback_inv;
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 591c22b080e4..83a56296be86 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -30,6 +30,7 @@ void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
30 30
31/* MIPS specific cache operations */ 31/* MIPS specific cache operations */
32void (*flush_cache_sigtramp)(unsigned long addr); 32void (*flush_cache_sigtramp)(unsigned long addr);
33void (*local_flush_data_cache_page)(void * addr);
33void (*flush_data_cache_page)(unsigned long addr); 34void (*flush_data_cache_page)(unsigned long addr);
34void (*flush_icache_all)(void); 35void (*flush_icache_all)(void);
35 36
diff --git a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
index aeae9fabf4a9..47bc8f6c20d2 100644
--- a/include/asm-mips/cacheflush.h
+++ b/include/asm-mips/cacheflush.h
@@ -74,6 +74,7 @@ static inline void copy_from_user_page(struct vm_area_struct *vma,
74 74
75extern void (*flush_cache_sigtramp)(unsigned long addr); 75extern void (*flush_cache_sigtramp)(unsigned long addr);
76extern void (*flush_icache_all)(void); 76extern void (*flush_icache_all)(void);
77extern void (*local_flush_data_cache_page)(void * addr);
77extern void (*flush_data_cache_page)(unsigned long addr); 78extern void (*flush_data_cache_page)(unsigned long addr);
78 79
79/* 80/*
diff --git a/include/asm-mips/mach-generic/ide.h b/include/asm-mips/mach-generic/ide.h
index 550979a9ea9d..e3315359500a 100644
--- a/include/asm-mips/mach-generic/ide.h
+++ b/include/asm-mips/mach-generic/ide.h
@@ -104,65 +104,107 @@ static __inline__ unsigned long ide_default_io_base(int index)
104#endif 104#endif
105 105
106/* MIPS port and memory-mapped I/O string operations. */ 106/* MIPS port and memory-mapped I/O string operations. */
107static inline void __ide_flush_prologue(void)
108{
109#ifdef CONFIG_SMP
110 if (cpu_has_dc_aliases)
111 preempt_disable();
112#endif
113}
114
115static inline void __ide_flush_epilogue(void)
116{
117#ifdef CONFIG_SMP
118 if (cpu_has_dc_aliases)
119 preempt_enable();
120#endif
121}
107 122
108static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size) 123static inline void __ide_flush_dcache_range(unsigned long addr, unsigned long size)
109{ 124{
110 if (cpu_has_dc_aliases) { 125 if (cpu_has_dc_aliases) {
111 unsigned long end = addr + size; 126 unsigned long end = addr + size;
112 for (; addr < end; addr += PAGE_SIZE) 127
113 flush_dcache_page(virt_to_page(addr)); 128 while (addr < end) {
129 local_flush_data_cache_page((void *)addr);
130 addr += PAGE_SIZE;
131 }
114 } 132 }
115} 133}
116 134
135/*
136 * insw() and gang might be called with interrupts disabled, so we can't
137 * send IPIs for flushing due to the potencial of deadlocks, see the comment
138 * above smp_call_function() in arch/mips/kernel/smp.c. We work around the
139 * problem by disabling preemption so we know we actually perform the flush
140 * on the processor that actually has the lines to be flushed which hopefully
141 * is even better for performance anyway.
142 */
117static inline void __ide_insw(unsigned long port, void *addr, 143static inline void __ide_insw(unsigned long port, void *addr,
118 unsigned int count) 144 unsigned int count)
119{ 145{
146 __ide_flush_prologue();
120 insw(port, addr, count); 147 insw(port, addr, count);
121 __ide_flush_dcache_range((unsigned long)addr, count * 2); 148 __ide_flush_dcache_range((unsigned long)addr, count * 2);
149 __ide_flush_epilogue();
122} 150}
123 151
124static inline void __ide_insl(unsigned long port, void *addr, unsigned int count) 152static inline void __ide_insl(unsigned long port, void *addr, unsigned int count)
125{ 153{
154 __ide_flush_prologue();
126 insl(port, addr, count); 155 insl(port, addr, count);
127 __ide_flush_dcache_range((unsigned long)addr, count * 4); 156 __ide_flush_dcache_range((unsigned long)addr, count * 4);
157 __ide_flush_epilogue();
128} 158}
129 159
130static inline void __ide_outsw(unsigned long port, const void *addr, 160static inline void __ide_outsw(unsigned long port, const void *addr,
131 unsigned long count) 161 unsigned long count)
132{ 162{
163 __ide_flush_prologue();
133 outsw(port, addr, count); 164 outsw(port, addr, count);
134 __ide_flush_dcache_range((unsigned long)addr, count * 2); 165 __ide_flush_dcache_range((unsigned long)addr, count * 2);
166 __ide_flush_epilogue();
135} 167}
136 168
137static inline void __ide_outsl(unsigned long port, const void *addr, 169static inline void __ide_outsl(unsigned long port, const void *addr,
138 unsigned long count) 170 unsigned long count)
139{ 171{
172 __ide_flush_prologue();
140 outsl(port, addr, count); 173 outsl(port, addr, count);
141 __ide_flush_dcache_range((unsigned long)addr, count * 4); 174 __ide_flush_dcache_range((unsigned long)addr, count * 4);
175 __ide_flush_epilogue();
142} 176}
143 177
144static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count) 178static inline void __ide_mm_insw(void __iomem *port, void *addr, u32 count)
145{ 179{
180 __ide_flush_prologue();
146 readsw(port, addr, count); 181 readsw(port, addr, count);
147 __ide_flush_dcache_range((unsigned long)addr, count * 2); 182 __ide_flush_dcache_range((unsigned long)addr, count * 2);
183 __ide_flush_epilogue();
148} 184}
149 185
150static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count) 186static inline void __ide_mm_insl(void __iomem *port, void *addr, u32 count)
151{ 187{
188 __ide_flush_prologue();
152 readsl(port, addr, count); 189 readsl(port, addr, count);
153 __ide_flush_dcache_range((unsigned long)addr, count * 4); 190 __ide_flush_dcache_range((unsigned long)addr, count * 4);
191 __ide_flush_epilogue();
154} 192}
155 193
156static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count) 194static inline void __ide_mm_outsw(void __iomem *port, void *addr, u32 count)
157{ 195{
196 __ide_flush_prologue();
158 writesw(port, addr, count); 197 writesw(port, addr, count);
159 __ide_flush_dcache_range((unsigned long)addr, count * 2); 198 __ide_flush_dcache_range((unsigned long)addr, count * 2);
199 __ide_flush_epilogue();
160} 200}
161 201
162static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count) 202static inline void __ide_mm_outsl(void __iomem * port, void *addr, u32 count)
163{ 203{
204 __ide_flush_prologue();
164 writesl(port, addr, count); 205 writesl(port, addr, count);
165 __ide_flush_dcache_range((unsigned long)addr, count * 4); 206 __ide_flush_dcache_range((unsigned long)addr, count * 4);
207 __ide_flush_epilogue();
166} 208}
167 209
168/* ide_insw calls insw, not __ide_insw. Why? */ 210/* ide_insw calls insw, not __ide_insw. Why? */