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

parisc: Improve interrupt handling in arch_spin_lock_flags()

Rewrite arch_spin_lock() and arch_spin_lock_flags() to not re-enable and
disable the PSW_SM_I interrupt flag too often.

Signed-off-by: Helge Deller <deller@gmx.de>

+19 -10
+19 -10
arch/parisc/include/asm/spinlock.h
··· 10 10 static inline int arch_spin_is_locked(arch_spinlock_t *x) 11 11 { 12 12 volatile unsigned int *a = __ldcw_align(x); 13 + smp_mb(); 13 14 return *a == 0; 14 15 } 15 16 16 - #define arch_spin_lock(lock) arch_spin_lock_flags(lock, 0) 17 - 18 - static inline void arch_spin_lock_flags(arch_spinlock_t *x, 19 - unsigned long flags) 17 + static inline void arch_spin_lock(arch_spinlock_t *x) 20 18 { 21 19 volatile unsigned int *a; 22 20 23 21 a = __ldcw_align(x); 24 22 while (__ldcw(a) == 0) 25 23 while (*a == 0) 26 - if (flags & PSW_SM_I) { 27 - local_irq_enable(); 28 - cpu_relax(); 29 - local_irq_disable(); 30 - } else 31 - cpu_relax(); 24 + cpu_relax(); 25 + } 26 + 27 + static inline void arch_spin_lock_flags(arch_spinlock_t *x, 28 + unsigned long flags) 29 + { 30 + volatile unsigned int *a; 31 + unsigned long flags_dis; 32 + 33 + a = __ldcw_align(x); 34 + while (__ldcw(a) == 0) { 35 + local_save_flags(flags_dis); 36 + local_irq_restore(flags); 37 + while (*a == 0) 38 + cpu_relax(); 39 + local_irq_restore(flags_dis); 40 + } 32 41 } 33 42 #define arch_spin_lock_flags arch_spin_lock_flags 34 43