aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanohar@qca.qualcomm.com>2012-06-11 02:49:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-13 14:35:53 -0400
commit3863495b86d8ee8e7e70a328de5b88d555d7305a (patch)
tree1d74ca3fbb7774bed9cee07c4162b1ef2e52459b
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>
-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,
893 udelay(100); 893 udelay(100);
894 } 894 }
895 895
896 /* Check pending GPM msg before MCI Reset Rx */
897 ar9003_mci_state(ah, MCI_STATE_CHECK_GPM_OFFSET, NULL);
898
896 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX); 899 regval |= SM(1, AR_MCI_COMMAND2_RESET_RX);
897 REG_WRITE(ah, AR_MCI_COMMAND2, regval); 900 REG_WRITE(ah, AR_MCI_COMMAND2, regval);
898 udelay(1); 901 udelay(1);
@@ -1190,6 +1193,21 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
1190 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR); 1193 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1191 mci->gpm_idx = value; 1194 mci->gpm_idx = value;
1192 break; 1195 break;
1196 case MCI_STATE_CHECK_GPM_OFFSET:
1197 /*
1198 * This should only be called before "MAC Warm Reset" or
1199 * "MCI Reset Rx".
1200 */
1201 value = MS(REG_READ(ah, AR_MCI_GPM_1), AR_MCI_GPM_WRITE_PTR);
1202 if (mci->gpm_idx == value)
1203 break;
1204 ath_dbg(common, MCI,
1205 "GPM cached write pointer mismatch %d %d\n",
1206 mci->gpm_idx, value);
1207 mci->query_bt = true;
1208 mci->need_flush_btinfo = true;
1209 mci->gpm_idx = 0;
1210 break;
1193 case MCI_STATE_NEXT_GPM_OFFSET: 1211 case MCI_STATE_NEXT_GPM_OFFSET:
1194 case MCI_STATE_LAST_GPM_OFFSET: 1212 case MCI_STATE_LAST_GPM_OFFSET:
1195 /* 1213 /*
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 {
190enum mci_state_type { 190enum mci_state_type {
191 MCI_STATE_ENABLE, 191 MCI_STATE_ENABLE,
192 MCI_STATE_INIT_GPM_OFFSET, 192 MCI_STATE_INIT_GPM_OFFSET,
193 MCI_STATE_CHECK_GPM_OFFSET,
193 MCI_STATE_NEXT_GPM_OFFSET, 194 MCI_STATE_NEXT_GPM_OFFSET,
194 MCI_STATE_LAST_GPM_OFFSET, 195 MCI_STATE_LAST_GPM_OFFSET,
195 MCI_STATE_BT, 196 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)
1348 } 1348 }
1349 } 1349 }
1350 1350
1351 if (ath9k_hw_mci_is_enabled(ah))
1352 ar9003_mci_state(ah, MCI_STATE_CHECK_GPM_OFFSET, NULL);
1353
1351 REG_WRITE(ah, AR_RTC_RC, rst_flags); 1354 REG_WRITE(ah, AR_RTC_RC, rst_flags);
1352 1355
1353 REGWRITE_BUFFER_FLUSH(ah); 1356 REGWRITE_BUFFER_FLUSH(ah);