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