Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __ASM_GENERIC_MMIOWB_H
0003 #define __ASM_GENERIC_MMIOWB_H
0004 
0005 /*
0006  * Generic implementation of mmiowb() tracking for spinlocks.
0007  *
0008  * If your architecture doesn't ensure that writes to an I/O peripheral
0009  * within two spinlocked sections on two different CPUs are seen by the
0010  * peripheral in the order corresponding to the lock handover, then you
0011  * need to follow these FIVE easy steps:
0012  *
0013  *  1. Implement mmiowb() (and arch_mmiowb_state() if you're fancy)
0014  *     in asm/mmiowb.h, then #include this file
0015  *  2. Ensure your I/O write accessors call mmiowb_set_pending()
0016  *  3. Select ARCH_HAS_MMIOWB
0017  *  4. Untangle the resulting mess of header files
0018  *  5. Complain to your architects
0019  */
0020 #ifdef CONFIG_MMIOWB
0021 
0022 #include <linux/compiler.h>
0023 #include <asm-generic/mmiowb_types.h>
0024 
0025 #ifndef arch_mmiowb_state
0026 #include <asm/percpu.h>
0027 #include <asm/smp.h>
0028 
0029 DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
0030 #define __mmiowb_state()    raw_cpu_ptr(&__mmiowb_state)
0031 #else
0032 #define __mmiowb_state()    arch_mmiowb_state()
0033 #endif  /* arch_mmiowb_state */
0034 
0035 static inline void mmiowb_set_pending(void)
0036 {
0037     struct mmiowb_state *ms = __mmiowb_state();
0038 
0039     if (likely(ms->nesting_count))
0040         ms->mmiowb_pending = ms->nesting_count;
0041 }
0042 
0043 static inline void mmiowb_spin_lock(void)
0044 {
0045     struct mmiowb_state *ms = __mmiowb_state();
0046     ms->nesting_count++;
0047 }
0048 
0049 static inline void mmiowb_spin_unlock(void)
0050 {
0051     struct mmiowb_state *ms = __mmiowb_state();
0052 
0053     if (unlikely(ms->mmiowb_pending)) {
0054         ms->mmiowb_pending = 0;
0055         mmiowb();
0056     }
0057 
0058     ms->nesting_count--;
0059 }
0060 #else
0061 #define mmiowb_set_pending()        do { } while (0)
0062 #define mmiowb_spin_lock()      do { } while (0)
0063 #define mmiowb_spin_unlock()        do { } while (0)
0064 #endif  /* CONFIG_MMIOWB */
0065 #endif  /* __ASM_GENERIC_MMIOWB_H */