Search Linux Wireless

[PATCH v2 4/9] ath9k_hw: check GPM HW write pointer before chip reset

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Both "MAC Warm Reset" and "MCI Reset Rx" will reset GPM HW write_ptr.
We should check software cached write_ptr against HW write_ptr before
reset. Otherwise the pending DMA data will be lost.

Signed-off-by: Rajkumar Manoharan <rmanohar@xxxxxxxxxxxxxxxx>
---
 drivers/net/wireless/ath/ath9k/ar9003_mci.c |   18 ++++++++++++++++++
 drivers/net/wireless/ath/ath9k/ar9003_mci.h |    1 +
 drivers/net/wireless/ath/ath9k/hw.c         |    3 +++
 3 files changed, 22 insertions(+)

diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 13907f6..cbeff9c 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -893,6 +893,9 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
 		udelay(100);
 	}
 
+	/* Check pending GPM msg before MCI Reset Rx */
+	ar9003_mci_state(ah, MCI_STATE_CHECK_GPM_OFFSET, NULL);
+
 	regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
 	REG_WRITE(ah, AR_MCI_COMMAND2, regval);
 	udelay(1);
@@ -1190,6 +1193,21 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
 		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:
 		/*
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
index 2a8c764..45624e1 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h
@@ -190,6 +190,7 @@ enum mci_bt_state {
 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,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 6d89333..8412128 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1348,6 +1348,9 @@ 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);
+
 	REG_WRITE(ah, AR_RTC_RC, rst_flags);
 
 	REGWRITE_BUFFER_FLUSH(ah);
-- 
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux