ath9k_hw: cleanup MCI gpm offset state
Add utility functions to get and test GPM offset and remove MCI_STATE*_GPM_OFFSET states. Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Родитель
64bc1239c7
Коммит
506847ad34
|
@ -593,8 +593,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
|
|||
if (!time_out)
|
||||
break;
|
||||
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
|
||||
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
continue;
|
||||
|
@ -658,8 +657,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
|
|||
time_out = 0;
|
||||
|
||||
while (more_data == MCI_GPM_MORE) {
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false, &more_data);
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
break;
|
||||
|
||||
|
@ -894,7 +892,7 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
}
|
||||
|
||||
/* Check pending GPM msg before MCI Reset Rx */
|
||||
ar9003_mci_state(ah, MCI_STATE_CHECK_GPM_OFFSET, NULL);
|
||||
ar9003_mci_check_gpm_offset(ah);
|
||||
|
||||
regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
|
||||
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
|
||||
|
@ -902,7 +900,7 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
regval &= ~SM(1, AR_MCI_COMMAND2_RESET_RX);
|
||||
REG_WRITE(ah, AR_MCI_COMMAND2, regval);
|
||||
|
||||
ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
|
||||
ar9003_mci_get_next_gpm_offset(ah, true, NULL);
|
||||
|
||||
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE,
|
||||
(SM(0xe801, AR_MCI_MSG_ATTRIBUTES_TABLE_INVALID_HDR) |
|
||||
|
@ -1170,7 +1168,7 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 value = 0, more_gpm = 0, gpm_ptr;
|
||||
u32 value = 0;
|
||||
u8 query_type;
|
||||
|
||||
switch (state_type) {
|
||||
|
@ -1182,96 +1180,6 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
|
|||
value = 0;
|
||||
}
|
||||
value &= AR_BTCOEX_CTRL_MCI_MODE_EN;
|
||||
break;
|
||||
case MCI_STATE_INIT_GPM_OFFSET:
|
||||
value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
mci->gpm_idx = value;
|
||||
break;
|
||||
case MCI_STATE_CHECK_GPM_OFFSET:
|
||||
/*
|
||||
* This should only be called before "MAC Warm Reset" or
|
||||
* "MCI Reset Rx".
|
||||
*/
|
||||
value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
if (mci->gpm_idx == value)
|
||||
break;
|
||||
ath_dbg(common, MCI,
|
||||
"GPM cached write pointer mismatch %d %d\n",
|
||||
mci->gpm_idx, value);
|
||||
mci->query_bt = true;
|
||||
mci->need_flush_btinfo = true;
|
||||
mci->gpm_idx = 0;
|
||||
break;
|
||||
case MCI_STATE_NEXT_GPM_OFFSET:
|
||||
case MCI_STATE_LAST_GPM_OFFSET:
|
||||
/*
|
||||
* This could be useful to avoid new GPM message interrupt which
|
||||
* may lead to spurious interrupt after power sleep, or multiple
|
||||
* entry of ath_mci_intr().
|
||||
* Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
|
||||
* alleviate this effect, but clearing GPM RX interrupt bit is
|
||||
* safe, because whether this is called from hw or driver code
|
||||
* there must be an interrupt bit set/triggered initially
|
||||
*/
|
||||
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
|
||||
AR_MCI_INTERRUPT_RX_MSG_GPM);
|
||||
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
value = gpm_ptr;
|
||||
|
||||
if (value == 0)
|
||||
value = mci->gpm_len - 1;
|
||||
else if (value >= mci->gpm_len) {
|
||||
if (value != 0xFFFF)
|
||||
value = 0;
|
||||
} else {
|
||||
value--;
|
||||
}
|
||||
|
||||
if (value == 0xFFFF) {
|
||||
value = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
} else if (state_type == MCI_STATE_NEXT_GPM_OFFSET) {
|
||||
if (gpm_ptr == mci->gpm_idx) {
|
||||
value = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
} else {
|
||||
for (;;) {
|
||||
u32 temp_index;
|
||||
|
||||
/* skip reserved GPM if any */
|
||||
|
||||
if (value != mci->gpm_idx)
|
||||
more_gpm = MCI_GPM_MORE;
|
||||
else
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
|
||||
temp_index = mci->gpm_idx;
|
||||
mci->gpm_idx++;
|
||||
|
||||
if (mci->gpm_idx >=
|
||||
mci->gpm_len)
|
||||
mci->gpm_idx = 0;
|
||||
|
||||
if (ar9003_mci_is_gpm_valid(ah,
|
||||
temp_index)) {
|
||||
value = temp_index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (more_gpm == MCI_GPM_NOMORE) {
|
||||
value = MCI_GPM_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (p_data)
|
||||
*p_data = more_gpm;
|
||||
}
|
||||
|
||||
if (value != MCI_GPM_INVALID)
|
||||
value <<= 4;
|
||||
|
||||
break;
|
||||
case MCI_STATE_LAST_SCHD_MSG_OFFSET:
|
||||
value = MS(REG_READ(ah, AR_MCI_RX_STATUS),
|
||||
|
@ -1450,3 +1358,99 @@ void ar9003_mci_set_power_awake(struct ath_hw *ah)
|
|||
udelay(50);
|
||||
}
|
||||
}
|
||||
|
||||
void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 offset;
|
||||
|
||||
/*
|
||||
* This should only be called before "MAC Warm Reset" or "MCI Reset Rx".
|
||||
*/
|
||||
offset = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
if (mci->gpm_idx == offset)
|
||||
return;
|
||||
ath_dbg(common, MCI, "GPM cached write pointer mismatch %d %d\n",
|
||||
mci->gpm_idx, offset);
|
||||
mci->query_bt = true;
|
||||
mci->need_flush_btinfo = true;
|
||||
mci->gpm_idx = 0;
|
||||
}
|
||||
|
||||
u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 offset, more_gpm = 0, gpm_ptr;
|
||||
|
||||
if (first) {
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
mci->gpm_idx = gpm_ptr;
|
||||
return gpm_ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This could be useful to avoid new GPM message interrupt which
|
||||
* may lead to spurious interrupt after power sleep, or multiple
|
||||
* entry of ath_mci_intr().
|
||||
* Adding empty GPM check by returning HAL_MCI_GPM_INVALID can
|
||||
* alleviate this effect, but clearing GPM RX interrupt bit is
|
||||
* safe, because whether this is called from hw or driver code
|
||||
* there must be an interrupt bit set/triggered initially
|
||||
*/
|
||||
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
|
||||
AR_MCI_INTERRUPT_RX_MSG_GPM);
|
||||
|
||||
gpm_ptr = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
|
||||
offset = gpm_ptr;
|
||||
|
||||
if (!offset)
|
||||
offset = mci->gpm_len - 1;
|
||||
else if (offset >= mci->gpm_len) {
|
||||
if (offset != 0xFFFF)
|
||||
offset = 0;
|
||||
} else {
|
||||
offset--;
|
||||
}
|
||||
|
||||
if ((offset == 0xFFFF) || (gpm_ptr == mci->gpm_idx)) {
|
||||
offset = MCI_GPM_INVALID;
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
goto out;
|
||||
}
|
||||
for (;;) {
|
||||
u32 temp_index;
|
||||
|
||||
/* skip reserved GPM if any */
|
||||
|
||||
if (offset != mci->gpm_idx)
|
||||
more_gpm = MCI_GPM_MORE;
|
||||
else
|
||||
more_gpm = MCI_GPM_NOMORE;
|
||||
|
||||
temp_index = mci->gpm_idx;
|
||||
mci->gpm_idx++;
|
||||
|
||||
if (mci->gpm_idx >= mci->gpm_len)
|
||||
mci->gpm_idx = 0;
|
||||
|
||||
if (ar9003_mci_is_gpm_valid(ah, temp_index)) {
|
||||
offset = temp_index;
|
||||
break;
|
||||
}
|
||||
|
||||
if (more_gpm == MCI_GPM_NOMORE) {
|
||||
offset = MCI_GPM_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset != MCI_GPM_INVALID)
|
||||
offset <<= 4;
|
||||
out:
|
||||
if (more)
|
||||
*more = more_gpm;
|
||||
|
||||
return offset;
|
||||
}
|
||||
EXPORT_SYMBOL(ar9003_mci_get_next_gpm_offset);
|
||||
|
|
|
@ -189,10 +189,6 @@ enum mci_bt_state {
|
|||
/* Type of state query */
|
||||
enum mci_state_type {
|
||||
MCI_STATE_ENABLE,
|
||||
MCI_STATE_INIT_GPM_OFFSET,
|
||||
MCI_STATE_CHECK_GPM_OFFSET,
|
||||
MCI_STATE_NEXT_GPM_OFFSET,
|
||||
MCI_STATE_LAST_GPM_OFFSET,
|
||||
MCI_STATE_BT,
|
||||
MCI_STATE_SET_BT_SLEEP,
|
||||
MCI_STATE_SET_BT_AWAKE,
|
||||
|
@ -266,6 +262,7 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
|
|||
void ar9003_mci_cleanup(struct ath_hw *ah);
|
||||
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
|
||||
u32 *rx_msg_intr);
|
||||
u32 ar9003_mci_get_next_gpm_offset(struct ath_hw *ah, bool first, u32 *more);
|
||||
/*
|
||||
* These functions are used by ath9k_hw.
|
||||
*/
|
||||
|
@ -286,6 +283,7 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
|
||||
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
|
||||
void ar9003_mci_set_power_awake(struct ath_hw *ah);
|
||||
void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
|
||||
|
||||
#else
|
||||
|
||||
|
@ -329,6 +327,9 @@ static inline void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah)
|
|||
static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1349,7 +1349,7 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
|
|||
}
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_state(ah, MCI_STATE_CHECK_GPM_OFFSET, NULL);
|
||||
ar9003_mci_check_gpm_offset(ah);
|
||||
|
||||
REG_WRITE(ah, AR_RTC_RC, rst_flags);
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
|
||||
|
||||
if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
|
||||
ar9003_mci_state(ah, MCI_STATE_INIT_GPM_OFFSET, NULL);
|
||||
ar9003_mci_get_next_gpm_offset(ah, true, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -488,8 +488,8 @@ void ath_mci_intr(struct ath_softc *sc)
|
|||
while (more_data == MCI_GPM_MORE) {
|
||||
|
||||
pgpm = mci->gpm_buf.bf_addr;
|
||||
offset = ar9003_mci_state(ah, MCI_STATE_NEXT_GPM_OFFSET,
|
||||
&more_data);
|
||||
offset = ar9003_mci_get_next_gpm_offset(ah, false,
|
||||
&more_data);
|
||||
|
||||
if (offset == MCI_GPM_INVALID)
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче