aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-mips
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 /include/asm-mips
parentbb12d612d4b2e6dc260fab081f69df783b74289f (diff)
[MIPS] Handle IDE PIO cache aliases on SMP.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'include/asm-mips')
-rw-r--r--include/asm-mips/cacheflush.h1
-rw-r--r--include/asm-mips/mach-generic/ide.h46
2 files changed, 45 insertions, 2 deletions
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? */