aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-06-29 20:07:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-30 15:00:53 -0400
commitf860d526eb2939a1c37128900b5af2b6f3ff7f20 (patch)
treefc9cc9a7cfb66c44a0c0970eb2c04b66a593735f /drivers/net
parent4e9e58c6bf6512a1812556188b67bada6a09c0e8 (diff)
ath9k: fix TSF after reset on AR913x
When issuing a reset, the TSF value is lost in the hardware because of the 913x specific cold reset. As with some AR9280 cards, the TSF needs to be preserved in software here. Additionally, there's an issue that frequently prevents a successful TSF write directly after the chip reset. In this case, repeating the TSF write after the initval-writes usually works. This patch detects failed TSF writes and recovers from them, taking into account the delay caused by the initval writes. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Reported-by: Björn Smedman <bjorn.smedman@venatech.se> Cc: stable@kernel.org Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 6e87af42b30a..6bf7e7ac9874 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1268,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1268 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; 1268 macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
1269 1269
1270 /* For chips on which RTC reset is done, save TSF before it gets cleared */ 1270 /* For chips on which RTC reset is done, save TSF before it gets cleared */
1271 if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 1271 if (AR_SREV_9100(ah) ||
1272 (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
1272 tsf = ath9k_hw_gettsf64(ah); 1273 tsf = ath9k_hw_gettsf64(ah);
1273 1274
1274 saveLedState = REG_READ(ah, AR_CFG_LED) & 1275 saveLedState = REG_READ(ah, AR_CFG_LED) &
@@ -1300,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1300 } 1301 }
1301 1302
1302 /* Restore TSF */ 1303 /* Restore TSF */
1303 if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) 1304 if (tsf)
1304 ath9k_hw_settsf64(ah, tsf); 1305 ath9k_hw_settsf64(ah, tsf);
1305 1306
1306 if (AR_SREV_9280_10_OR_LATER(ah)) 1307 if (AR_SREV_9280_10_OR_LATER(ah))
@@ -1313,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1313 if (r) 1314 if (r)
1314 return r; 1315 return r;
1315 1316
1317 /*
1318 * Some AR91xx SoC devices frequently fail to accept TSF writes
1319 * right after the chip reset. When that happens, write a new
1320 * value after the initvals have been applied, with an offset
1321 * based on measured time difference
1322 */
1323 if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
1324 tsf += 1500;
1325 ath9k_hw_settsf64(ah, tsf);
1326 }
1327
1316 /* Setup MFP options for CCMP */ 1328 /* Setup MFP options for CCMP */
1317 if (AR_SREV_9280_20_OR_LATER(ah)) { 1329 if (AR_SREV_9280_20_OR_LATER(ah)) {
1318 /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt 1330 /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt