ath9k: Add HW callbacks for MAC/BB hang checks

This is required for adding separate hang check
routines for AR9002 and AR9003.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Sujith Manoharan 2013-12-24 10:44:19 +05:30 committed by John W. Linville
parent 4598702d1b
commit 990de2b2e4
4 changed files with 85 additions and 70 deletions

View File

@ -892,6 +892,77 @@ static void ar9003_hw_init_hang_checks(struct ath_hw *ah)
ah->bb_watchdog_timeout_ms = 25;
}
static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states,
int *hang_state, int *hang_pos)
{
static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */
u32 chain_state, dcs_pos, i;
for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) {
chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f;
for (i = 0; i < 3; i++) {
if (chain_state == dcu_chain_state[i]) {
*hang_state = chain_state;
*hang_pos = dcs_pos;
return true;
}
}
}
return false;
}
#define DCU_COMPLETE_STATE 1
#define DCU_COMPLETE_STATE_MASK 0x3
#define NUM_STATUS_READS 50
static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah)
{
u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4;
u32 i, hang_pos, hang_state, num_state = 6;
comp_state = REG_READ(ah, AR_DMADBG_6);
if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) {
ath_dbg(ath9k_hw_common(ah), RESET,
"MAC Hang signature not found at DCU complete\n");
return false;
}
chain_state = REG_READ(ah, dcs_reg);
if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
goto hang_check_iter;
dcs_reg = AR_DMADBG_5;
num_state = 4;
chain_state = REG_READ(ah, dcs_reg);
if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
goto hang_check_iter;
ath_dbg(ath9k_hw_common(ah), RESET,
"MAC Hang signature 1 not found\n");
return false;
hang_check_iter:
ath_dbg(ath9k_hw_common(ah), RESET,
"DCU registers: chain %08x complete %08x Hang: state %d pos %d\n",
chain_state, comp_state, hang_state, hang_pos);
for (i = 0; i < NUM_STATUS_READS; i++) {
chain_state = REG_READ(ah, dcs_reg);
chain_state = (chain_state >> (5 * hang_pos)) & 0x1f;
comp_state = REG_READ(ah, AR_DMADBG_6);
if (((comp_state & DCU_COMPLETE_STATE_MASK) !=
DCU_COMPLETE_STATE) ||
(chain_state != hang_state))
return false;
}
ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n");
return true;
}
/* Sets up the AR9003 hardware familiy callbacks */
void ar9003_hw_attach_ops(struct ath_hw *ah)
{
@ -901,6 +972,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
ar9003_hw_init_mode_regs(ah);
priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
priv_ops->init_hang_checks = ar9003_hw_init_hang_checks;
priv_ops->detect_mac_hang = ar9003_hw_detect_mac_hang;
ops->config_pci_powersave = ar9003_hw_configpcipowersave;

View File

@ -112,6 +112,16 @@ static inline void ath9k_hw_init_hang_checks(struct ath_hw *ah)
ath9k_hw_private_ops(ah)->init_hang_checks(ah);
}
static inline bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->detect_mac_hang(ah);
}
static inline bool ath9k_hw_detect_bb_hang(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->detect_bb_hang(ah);
}
/* PHY ops */
static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,

View File

@ -1529,76 +1529,6 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
}
}
static bool ath9k_hw_check_dcs(u32 dma_dbg, u32 num_dcu_states,
int *hang_state, int *hang_pos)
{
static u32 dcu_chain_state[] = {5, 6, 9}; /* DCU chain stuck states */
u32 chain_state, dcs_pos, i;
for (dcs_pos = 0; dcs_pos < num_dcu_states; dcs_pos++) {
chain_state = (dma_dbg >> (5 * dcs_pos)) & 0x1f;
for (i = 0; i < 3; i++) {
if (chain_state == dcu_chain_state[i]) {
*hang_state = chain_state;
*hang_pos = dcs_pos;
return true;
}
}
}
return false;
}
#define DCU_COMPLETE_STATE 1
#define DCU_COMPLETE_STATE_MASK 0x3
#define NUM_STATUS_READS 50
static bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
{
u32 chain_state, comp_state, dcs_reg = AR_DMADBG_4;
u32 i, hang_pos, hang_state, num_state = 6;
comp_state = REG_READ(ah, AR_DMADBG_6);
if ((comp_state & DCU_COMPLETE_STATE_MASK) != DCU_COMPLETE_STATE) {
ath_dbg(ath9k_hw_common(ah), RESET,
"MAC Hang signature not found at DCU complete\n");
return false;
}
chain_state = REG_READ(ah, dcs_reg);
if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
goto hang_check_iter;
dcs_reg = AR_DMADBG_5;
num_state = 4;
chain_state = REG_READ(ah, dcs_reg);
if (ath9k_hw_check_dcs(chain_state, num_state, &hang_state, &hang_pos))
goto hang_check_iter;
ath_dbg(ath9k_hw_common(ah), RESET,
"MAC Hang signature 1 not found\n");
return false;
hang_check_iter:
ath_dbg(ath9k_hw_common(ah), RESET,
"DCU registers: chain %08x complete %08x Hang: state %d pos %d\n",
chain_state, comp_state, hang_state, hang_pos);
for (i = 0; i < NUM_STATUS_READS; i++) {
chain_state = REG_READ(ah, dcs_reg);
chain_state = (chain_state >> (5 * hang_pos)) & 0x1f;
comp_state = REG_READ(ah, AR_DMADBG_6);
if (((comp_state & DCU_COMPLETE_STATE_MASK) !=
DCU_COMPLETE_STATE) ||
(chain_state != hang_state))
return false;
}
ath_dbg(ath9k_hw_common(ah), RESET, "MAC Hang signature 1 found\n");
return true;
}
void ath9k_hw_check_nav(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);

View File

@ -585,6 +585,9 @@ struct ath_hw_radar_conf {
*/
struct ath_hw_private_ops {
void (*init_hang_checks)(struct ath_hw *ah);
bool (*detect_mac_hang)(struct ath_hw *ah);
bool (*detect_bb_hang)(struct ath_hw *ah);
/* Calibration ops */
void (*init_cal_settings)(struct ath_hw *ah);
bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);