Skip to content

Commit

Permalink
ath9k: fix TSF after reset on AR913x
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Jun 30, 2010
1 parent 4e9e58c commit f860d52
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;

/* For chips on which RTC reset is done, save TSF before it gets cleared */
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
if (AR_SREV_9100(ah) ||
(AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
tsf = ath9k_hw_gettsf64(ah);

saveLedState = REG_READ(ah, AR_CFG_LED) &
Expand Down Expand Up @@ -1300,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
}

/* Restore TSF */
if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
if (tsf)
ath9k_hw_settsf64(ah, tsf);

if (AR_SREV_9280_10_OR_LATER(ah))
Expand All @@ -1313,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (r)
return r;

/*
* Some AR91xx SoC devices frequently fail to accept TSF writes
* right after the chip reset. When that happens, write a new
* value after the initvals have been applied, with an offset
* based on measured time difference
*/
if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
tsf += 1500;
ath9k_hw_settsf64(ah, tsf);
}

/* Setup MFP options for CCMP */
if (AR_SREV_9280_20_OR_LATER(ah)) {
/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
Expand Down

0 comments on commit f860d52

Please sign in to comment.