svn commit: r293050 - head/sys/dev/ath
Adrian Chadd
adrian at FreeBSD.org
Sat Jan 2 17:14:23 UTC 2016
Author: adrian
Date: Sat Jan 2 17:14:22 2016
New Revision: 293050
URL: https://svnweb.freebsd.org/changeset/base/293050
Log:
[ath] add explicit bus barriers.
The ath hal and driver code all assume the world is an x86 or the
bus layer does an explicit bus flush after each operation (eg netbsd.)
However, we don't do that.
So, to be "correct" on platforms like sparc64, mips and ppc (and maybe
ARM, I am not sure), just do explicit barriers after each operation.
Now, this does slow things down a tad on embedded platforms but I'd
rather things be "correct" versus "fast." At some later point if someone
wishes it to be fast then we should add the barrier calls to the HAL and
driver.
Tested:
* carambola 2 (AR9331.)
Modified:
head/sys/dev/ath/ah_osdep.c
head/sys/dev/ath/ah_osdep.h
Modified: head/sys/dev/ath/ah_osdep.c
==============================================================================
--- head/sys/dev/ath/ah_osdep.c Sat Jan 2 16:40:37 2016 (r293049)
+++ head/sys/dev/ath/ah_osdep.c Sat Jan 2 17:14:22 2016 (r293050)
@@ -291,6 +291,7 @@ ath_hal_reg_write(struct ath_hal *ah, u_
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
bus_space_write_4(tag, h, reg, val);
+ OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
if (ah->ah_config.ah_serialise_reg_war)
mtx_unlock_spin(&ah_regser_mtx);
}
@@ -311,6 +312,7 @@ ath_hal_reg_read(struct ath_hal *ah, u_i
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
+ OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
val = bus_space_read_4(tag, h, reg);
if (ah->ah_config.ah_serialise_reg_war)
mtx_unlock_spin(&ah_regser_mtx);
@@ -371,6 +373,7 @@ ath_hal_reg_write(struct ath_hal *ah, u_
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
bus_space_write_4(tag, h, reg, val);
+ OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_WRITE);
if (ah->ah_config.ah_serialise_reg_war)
mtx_unlock_spin(&ah_regser_mtx);
}
@@ -391,6 +394,7 @@ ath_hal_reg_read(struct ath_hal *ah, u_i
if (ah->ah_config.ah_serialise_reg_war)
mtx_lock_spin(&ah_regser_mtx);
+ OS_BUS_BARRIER_REG(ah, reg, OS_BUS_BARRIER_READ);
val = bus_space_read_4(tag, h, reg);
if (ah->ah_config.ah_serialise_reg_war)
mtx_unlock_spin(&ah_regser_mtx);
Modified: head/sys/dev/ath/ah_osdep.h
==============================================================================
--- head/sys/dev/ath/ah_osdep.h Sat Jan 2 16:40:37 2016 (r293049)
+++ head/sys/dev/ath/ah_osdep.h Sat Jan 2 17:14:22 2016 (r293050)
@@ -110,6 +110,27 @@ struct ath_hal;
do { } while (0)
/*
+ * Read and write barriers. Some platforms require more strongly ordered
+ * operations and unfortunately most of the HAL is written assuming everything
+ * is either an x86 or the bus layer will do the barriers for you.
+ *
+ * Read barriers should occur before each read, and write barriers
+ * occur after each write.
+ *
+ * Later on for SDIO/USB parts we will methodize this and make them no-ops;
+ * register accesses will go via USB commands.
+ */
+#define OS_BUS_BARRIER_READ BUS_SPACE_BARRIER_READ
+#define OS_BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE
+#define OS_BUS_BARRIER_RW \
+ (BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+#define OS_BUS_BARRIER(_ah, _start, _len, _t) \
+ bus_space_barrier((bus_space_tag_t)(_ah)->ah_st, \
+ (bus_space_handle_t)(_ah)->ah_sh, (_start), (_len), (_t))
+#define OS_BUS_BARRIER_REG(_ah, _reg, _t) \
+ OS_BUS_BARRIER((_ah), (_reg), 4, (_t))
+
+/*
* Register read/write operations are either handled through
* platform-dependent routines (or when debugging is enabled
* with AH_DEBUG); or they are inline expanded using the macros
@@ -123,11 +144,17 @@ extern void ath_hal_reg_write(struct ath
extern u_int32_t ath_hal_reg_read(struct ath_hal *ah, u_int reg);
#else
#define OS_REG_WRITE(_ah, _reg, _val) \
+ do { \
bus_space_write_4((bus_space_tag_t)(_ah)->ah_st, \
- (bus_space_handle_t)(_ah)->ah_sh, (_reg), (_val))
+ (bus_space_handle_t)(_ah)->ah_sh, (_reg), (_val)); \
+ OS_BUS_BARRIER_REG((_ah), (_reg), OS_BUS_BARRIER_WRITE); \
+ } while (0)
#define OS_REG_READ(_ah, _reg) \
+ do { \
+ OS_BUS_BARRIER_REG((_ah), (_reg), OS_BUS_BARRIER_READ); \
bus_space_read_4((bus_space_tag_t)(_ah)->ah_st, \
- (bus_space_handle_t)(_ah)->ah_sh, (_reg))
+ (bus_space_handle_t)(_ah)->ah_sh, (_reg)); \
+ } while (0)
#endif
#ifdef AH_DEBUG_ALQ
More information about the svn-src-all
mailing list