aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c31
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c19
2 files changed, 44 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 174412fc81f8..5212e275f1c7 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -496,6 +496,8 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
496* Beacon control * 496* Beacon control *
497\****************/ 497\****************/
498 498
499#define ATH5K_MAX_TSF_READ 10
500
499/** 501/**
500 * ath5k_hw_get_tsf64 - Get the full 64bit TSF 502 * ath5k_hw_get_tsf64 - Get the full 64bit TSF
501 * 503 *
@@ -505,10 +507,35 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
505 */ 507 */
506u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) 508u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
507{ 509{
508 u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); 510 u32 tsf_lower, tsf_upper1, tsf_upper2;
511 int i;
512
513 /*
514 * While reading TSF upper and then lower part, the clock is still
515 * counting (or jumping in case of IBSS merge) so we might get
516 * inconsistent values. To avoid this, we read the upper part again
517 * and check it has not been changed. We make the hypothesis that a
518 * maximum of 3 changes can happens in a row (we use 10 as a safe
519 * value).
520 *
521 * Impact on performance is pretty small, since in most cases, only
522 * 3 register reads are needed.
523 */
524
525 tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
526 for (i = 0; i < ATH5K_MAX_TSF_READ; i++) {
527 tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
528 tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
529 if (tsf_upper2 == tsf_upper1)
530 break;
531 tsf_upper1 = tsf_upper2;
532 }
533
534 WARN_ON( i == ATH5K_MAX_TSF_READ );
535
509 ATH5K_TRACE(ah->ah_sc); 536 ATH5K_TRACE(ah->ah_sc);
510 537
511 return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); 538 return (((u64)tsf_upper1 << 32) | tsf_lower);
512} 539}
513 540
514/** 541/**
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 35f5cf40a990..894f5fc7489e 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2420,14 +2420,25 @@ void ath9k_hw_write_associd(struct ath_hw *ah)
2420} 2420}
2421EXPORT_SYMBOL(ath9k_hw_write_associd); 2421EXPORT_SYMBOL(ath9k_hw_write_associd);
2422 2422
2423#define ATH9K_MAX_TSF_READ 10
2424
2423u64 ath9k_hw_gettsf64(struct ath_hw *ah) 2425u64 ath9k_hw_gettsf64(struct ath_hw *ah)
2424{ 2426{
2425 u64 tsf; 2427 u32 tsf_lower, tsf_upper1, tsf_upper2;
2428 int i;
2429
2430 tsf_upper1 = REG_READ(ah, AR_TSF_U32);
2431 for (i = 0; i < ATH9K_MAX_TSF_READ; i++) {
2432 tsf_lower = REG_READ(ah, AR_TSF_L32);
2433 tsf_upper2 = REG_READ(ah, AR_TSF_U32);
2434 if (tsf_upper2 == tsf_upper1)
2435 break;
2436 tsf_upper1 = tsf_upper2;
2437 }
2426 2438
2427 tsf = REG_READ(ah, AR_TSF_U32); 2439 WARN_ON( i == ATH9K_MAX_TSF_READ );
2428 tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
2429 2440
2430 return tsf; 2441 return (((u64)tsf_upper1 << 32) | tsf_lower);
2431} 2442}
2432EXPORT_SYMBOL(ath9k_hw_gettsf64); 2443EXPORT_SYMBOL(ath9k_hw_gettsf64);
2433 2444