Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Fix build error if __xchg() is not getting inlined.

If __xchg() is not getting inlined the outline version of the function
will have a reference to __xchg_called_with_bad_pointer() which does not
exist remaining. Fixed by using BUILD_BUG_ON() to check for allowable
operand sizes.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Patchwork: http://patchwork.linux-mips.org/patch/705/

+9 -6
+9 -6
arch/mips/include/asm/system.h
··· 12 12 #ifndef _ASM_SYSTEM_H 13 13 #define _ASM_SYSTEM_H 14 14 15 + #include <linux/kernel.h> 15 16 #include <linux/types.h> 16 17 #include <linux/irqflags.h> 17 18 ··· 194 193 #define __xchg_u64 __xchg_u64_unsupported_on_32bit_kernels 195 194 #endif 196 195 197 - /* This function doesn't exist, so you'll get a linker error 198 - if something tries to do an invalid xchg(). */ 199 - extern void __xchg_called_with_bad_pointer(void); 200 - 201 196 static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) 202 197 { 203 198 switch (size) { ··· 202 205 case 8: 203 206 return __xchg_u64(ptr, x); 204 207 } 205 - __xchg_called_with_bad_pointer(); 208 + 206 209 return x; 207 210 } 208 211 209 - #define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))) 212 + #define xchg(ptr, x) \ 213 + ({ \ 214 + BUILD_BUG_ON(sizeof(*(ptr)) & ~0xc); \ 215 + \ 216 + ((__typeof__(*(ptr))) \ 217 + __xchg((unsigned long)(x), (ptr), sizeof(*(ptr)))); \ 218 + }) 210 219 211 220 extern void set_handler(unsigned long offset, void *addr, unsigned long len); 212 221 extern void set_uncached_handler(unsigned long offset, void *addr, unsigned long len);