summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>2012-06-11 12:19:32 +0530
committerJohn W. Linville <linville@tuxdriver.com>2012-06-13 14:35:53 -0400
commit3863495b86d8ee8e7e70a328de5b88d555d7305a (patch)
tree1d74ca3fbb7774bed9cee07c4162b1ef2e52459b /drivers/net/wireless/ath
parent9dd9b0dc1de8031a31b3eaebc6a9c0ab60612026 (diff)
ath9k_hw: check GPM HW write pointer before chip reset
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@qca.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3
3 files changed, 22 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 13907f63bdc0..cbeff9c4b5d8 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 2a8c764281ba..45624e1d3960 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 6d893335f42b..8412128b842a 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);