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

sh: Fix up T-bit error handling in SH-4A mutex fastpath.

This corrects a deadlock encountered on ap325 in the cases where the
mutex is contended and the slow-path needs to be fallen back upon.

Signed-off-by: Takashi YOSHII <yoshii.takashi@renesas.com>
Signed-off-by: Kuninori Morimoto <morimoto.kuninori@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Takashi Yoshii and committed by
Paul Mundt
c20f326a 03f07876

+9 -12
+9 -12
arch/sh/include/asm/mutex-llsc.h
··· 21 21 static inline void 22 22 __mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *)) 23 23 { 24 - int __ex_flag, __res; 24 + int __done, __res; 25 25 26 26 __asm__ __volatile__ ( 27 27 "movli.l @%2, %0 \n" 28 28 "add #-1, %0 \n" 29 29 "movco.l %0, @%2 \n" 30 30 "movt %1 \n" 31 - : "=&z" (__res), "=&r" (__ex_flag) 31 + : "=&z" (__res), "=&r" (__done) 32 32 : "r" (&(count)->counter) 33 33 : "t"); 34 34 35 - __res |= !__ex_flag; 36 - if (unlikely(__res != 0)) 35 + if (unlikely(!__done || __res != 0)) 37 36 fail_fn(count); 38 37 } 39 38 40 39 static inline int 41 40 __mutex_fastpath_lock_retval(atomic_t *count, int (*fail_fn)(atomic_t *)) 42 41 { 43 - int __ex_flag, __res; 42 + int __done, __res; 44 43 45 44 __asm__ __volatile__ ( 46 45 "movli.l @%2, %0 \n" 47 46 "add #-1, %0 \n" 48 47 "movco.l %0, @%2 \n" 49 48 "movt %1 \n" 50 - : "=&z" (__res), "=&r" (__ex_flag) 49 + : "=&z" (__res), "=&r" (__done) 51 50 : "r" (&(count)->counter) 52 51 : "t"); 53 52 54 - __res |= !__ex_flag; 55 - if (unlikely(__res != 0)) 53 + if (unlikely(!__done || __res != 0)) 56 54 __res = fail_fn(count); 57 55 58 56 return __res; ··· 59 61 static inline void 60 62 __mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *)) 61 63 { 62 - int __ex_flag, __res; 64 + int __done, __res; 63 65 64 66 __asm__ __volatile__ ( 65 67 "movli.l @%2, %0 \n\t" 66 68 "add #1, %0 \n\t" 67 69 "movco.l %0, @%2 \n\t" 68 70 "movt %1 \n\t" 69 - : "=&z" (__res), "=&r" (__ex_flag) 71 + : "=&z" (__res), "=&r" (__done) 70 72 : "r" (&(count)->counter) 71 73 : "t"); 72 74 73 - __res |= !__ex_flag; 74 - if (unlikely(__res <= 0)) 75 + if (unlikely(!__done || __res <= 0)) 75 76 fail_fn(count); 76 77 } 77 78