mmiowb.h 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_GENERIC_MMIOWB_H
  3. #define __ASM_GENERIC_MMIOWB_H
  4. /*
  5. * Generic implementation of mmiowb() tracking for spinlocks.
  6. *
  7. * If your architecture doesn't ensure that writes to an I/O peripheral
  8. * within two spinlocked sections on two different CPUs are seen by the
  9. * peripheral in the order corresponding to the lock handover, then you
  10. * need to follow these FIVE easy steps:
  11. *
  12. * 1. Implement mmiowb() (and arch_mmiowb_state() if you're fancy)
  13. * in asm/mmiowb.h, then #include this file
  14. * 2. Ensure your I/O write accessors call mmiowb_set_pending()
  15. * 3. Select ARCH_HAS_MMIOWB
  16. * 4. Untangle the resulting mess of header files
  17. * 5. Complain to your architects
  18. */
  19. #ifdef CONFIG_MMIOWB
  20. #include <linux/compiler.h>
  21. #include <asm-generic/mmiowb_types.h>
  22. #ifndef arch_mmiowb_state
  23. #include <asm/percpu.h>
  24. #include <asm/smp.h>
  25. DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
  26. #define __mmiowb_state() raw_cpu_ptr(&__mmiowb_state)
  27. #else
  28. #define __mmiowb_state() arch_mmiowb_state()
  29. #endif /* arch_mmiowb_state */
  30. static inline void mmiowb_set_pending(void)
  31. {
  32. struct mmiowb_state *ms = __mmiowb_state();
  33. if (likely(ms->nesting_count))
  34. ms->mmiowb_pending = ms->nesting_count;
  35. }
  36. static inline void mmiowb_spin_lock(void)
  37. {
  38. struct mmiowb_state *ms = __mmiowb_state();
  39. ms->nesting_count++;
  40. }
  41. static inline void mmiowb_spin_unlock(void)
  42. {
  43. struct mmiowb_state *ms = __mmiowb_state();
  44. if (unlikely(ms->mmiowb_pending)) {
  45. ms->mmiowb_pending = 0;
  46. mmiowb();
  47. }
  48. ms->nesting_count--;
  49. }
  50. #else
  51. #define mmiowb_set_pending() do { } while (0)
  52. #define mmiowb_spin_lock() do { } while (0)
  53. #define mmiowb_spin_unlock() do { } while (0)
  54. #endif /* CONFIG_MMIOWB */
  55. #endif /* __ASM_GENERIC_MMIOWB_H */