[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.)
This commit is contained in:
adrian 2016-01-02 17:14:22 +00:00
parent bebb40faf6
commit cd342db2ce
2 changed files with 33 additions and 2 deletions

View File

@ -291,6 +291,7 @@ ath_hal_reg_write(struct ath_hal *ah, u_int32_t reg, u_int32_t val)
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_int32_t reg)
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_int32_t reg, u_int32_t val)
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_int32_t reg)
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);

View File

@ -109,6 +109,27 @@ struct ath_hal;
#define OS_REG_WRITE_BUFFER_FLUSH(_ah) \
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
@ -123,11 +144,17 @@ extern void ath_hal_reg_write(struct ath_hal *ah, u_int reg, u_int32_t val);
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