Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 506847ad authored by Rajkumar Manoharan's avatar Rajkumar Manoharan Committed by John W. Linville
Browse files

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: default avatarRajkumar Manoharan <rmanohar@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 64bc1239
Loading
Loading
Loading
Loading
+101 −97
Original line number Diff line number Diff line
@@ -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);
+5 −4
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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);

+3 −3
Original line number Diff line number Diff line
@@ -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,7 +488,7 @@ 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,
			offset = ar9003_mci_get_next_gpm_offset(ah, false,
								&more_data);

			if (offset == MCI_GPM_INVALID)