[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:
parent
bebb40faf6
commit
cd342db2ce
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user