Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ath9k_hw: move the cycle counter tracking to ath

Instead of keeping track of wraparound, clear the counters on every
access and keep separate deltas for ANI and later survey use.
Also moves the function for calculating the 'listen time' for ANI

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Felix Fietkau and committed by
John W. Linville
b5bfc568 9d119f3e

+101 -87
+14
drivers/net/wireless/ath/ath.h
··· 19 19 20 20 #include <linux/skbuff.h> 21 21 #include <linux/if_ether.h> 22 + #include <linux/spinlock.h> 22 23 #include <net/mac80211.h> 23 24 24 25 /* ··· 41 40 unsigned int resetcal_timer; 42 41 unsigned int checkani_timer; 43 42 struct timer_list timer; 43 + }; 44 + 45 + struct ath_cycle_counters { 46 + u32 cycles; 47 + u32 rx_busy; 48 + u32 rx_frame; 49 + u32 tx_frame; 44 50 }; 45 51 46 52 enum ath_device_state { ··· 155 147 156 148 unsigned int clockrate; 157 149 150 + spinlock_t cc_lock; 151 + struct ath_cycle_counters cc_ani; 152 + struct ath_cycle_counters cc_survey; 153 + 158 154 struct ath_regulatory regulatory; 159 155 const struct ath_ops *ops; 160 156 const struct ath_bus_ops *bus_ops; ··· 175 163 struct ieee80211_sta *sta, 176 164 struct ieee80211_key_conf *key); 177 165 bool ath_hw_keyreset(struct ath_common *common, u16 entry); 166 + void ath_hw_cycle_counters_update(struct ath_common *common); 167 + int32_t ath_hw_get_listen_time(struct ath_common *common); 178 168 179 169 #endif /* ATH_H */
+3 -61
drivers/net/wireless/ath/ath9k/ani.c
··· 465 465 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); 466 466 } 467 467 468 - static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) 469 - { 470 - struct ath_common *common = ath9k_hw_common(ah); 471 - int32_t listen_time; 472 - 473 - ath9k_hw_update_cycle_counters(ah); 474 - listen_time = ah->listen_time / (common->clockrate * 1000); 475 - ah->listen_time = 0; 476 - 477 - return listen_time; 478 - } 479 - 480 468 static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) 481 469 { 482 470 struct ar5416AniState *aniState; ··· 643 655 u32 phyCnt1, phyCnt2; 644 656 int32_t listenTime; 645 657 646 - listenTime = ath9k_hw_ani_get_listen_time(ah); 658 + ath_hw_cycle_counters_update(common); 659 + listenTime = ath_hw_get_listen_time(common); 660 + 647 661 if (listenTime < 0) { 648 662 ah->stats.ast_ani_lneg++; 649 663 ath9k_ani_restart(ah); ··· 785 795 REG_WRITE(ah, AR_FILT_CCK, 0); 786 796 } 787 797 EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); 788 - 789 - void ath9k_hw_update_cycle_counters(struct ath_hw *ah) 790 - { 791 - struct ath_cycle_counters cc; 792 - bool clear; 793 - 794 - memcpy(&cc, &ah->cc, sizeof(cc)); 795 - 796 - /* freeze counters */ 797 - REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); 798 - 799 - ah->cc.cycles = REG_READ(ah, AR_CCCNT); 800 - if (ah->cc.cycles < cc.cycles) { 801 - clear = true; 802 - goto skip; 803 - } 804 - 805 - ah->cc.rx_clear = REG_READ(ah, AR_RCCNT); 806 - ah->cc.rx_frame = REG_READ(ah, AR_RFCNT); 807 - ah->cc.tx_frame = REG_READ(ah, AR_TFCNT); 808 - 809 - /* prevent wraparound */ 810 - if (ah->cc.cycles & BIT(31)) 811 - clear = true; 812 - 813 - #define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field 814 - CC_DELTA(cycles, AR_CCCNT); 815 - CC_DELTA(rx_frame, AR_RFCNT); 816 - CC_DELTA(rx_clear, AR_RCCNT); 817 - CC_DELTA(tx_frame, AR_TFCNT); 818 - #undef CC_DELTA 819 - 820 - ah->listen_time += (ah->cc.cycles - cc.cycles) - 821 - ((ah->cc.rx_frame - cc.rx_frame) + 822 - (ah->cc.tx_frame - cc.tx_frame)); 823 - 824 - skip: 825 - if (clear) { 826 - REG_WRITE(ah, AR_CCCNT, 0); 827 - REG_WRITE(ah, AR_RFCNT, 0); 828 - REG_WRITE(ah, AR_RCCNT, 0); 829 - REG_WRITE(ah, AR_TFCNT, 0); 830 - memset(&ah->cc, 0, sizeof(ah->cc)); 831 - } 832 - 833 - /* unfreeze counters */ 834 - REG_WRITE(ah, AR_MIBC, 0); 835 - } 836 798 837 799 /* 838 800 * Process a MIB interrupt. We may potentially be invoked because
-8
drivers/net/wireless/ath/ath9k/ani.h
··· 93 93 u32 beacons; 94 94 }; 95 95 96 - struct ath_cycle_counters { 97 - u32 cycles; 98 - u32 rx_frame; 99 - u32 rx_clear; 100 - u32 tx_frame; 101 - }; 102 - 103 96 /* INI default values for ANI registers */ 104 97 struct ath9k_ani_default { 105 98 u16 m1ThreshLow; ··· 157 164 158 165 void ath9k_enable_mib_counters(struct ath_hw *ah); 159 166 void ath9k_hw_disable_mib_counters(struct ath_hw *ah); 160 - void ath9k_hw_update_cycle_counters(struct ath_hw *ah); 161 167 void ath9k_hw_ani_setup(struct ath_hw *ah); 162 168 void ath9k_hw_ani_init(struct ath_hw *ah); 163 169 int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
+3 -4
drivers/net/wireless/ath/ath9k/ar9003_phy.c
··· 1254 1254 "** BB mode: BB_gen_controls=0x%08x **\n", 1255 1255 REG_READ(ah, AR_PHY_GEN_CTRL)); 1256 1256 1257 - ath9k_hw_update_cycle_counters(ah); 1258 - #define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles) 1259 - if (ah->cc_delta.cycles) 1257 + #define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles) 1258 + if (common->cc_survey.cycles) 1260 1259 ath_print(common, ATH_DBG_RESET, 1261 1260 "** BB busy times: rx_clear=%d%%, " 1262 1261 "rx_frame=%d%%, tx_frame=%d%% **\n", 1263 - PCT(rx_clear), PCT(rx_frame), PCT(tx_frame)); 1262 + PCT(rx_busy), PCT(rx_frame), PCT(tx_frame)); 1264 1263 1265 1264 ath_print(common, ATH_DBG_RESET, 1266 1265 "==== BB update: done ====\n\n");
-2
drivers/net/wireless/ath/ath9k/hw.h
··· 740 740 int coarse_low[5]; 741 741 int firpwr[5]; 742 742 enum ath9k_ani_cmd ani_function; 743 - struct ath_cycle_counters cc, cc_delta; 744 - int32_t listen_time; 745 743 746 744 /* Bluetooth coexistance */ 747 745 struct ath_btcoex_hw btcoex_hw;
+11 -1
drivers/net/wireless/ath/ath9k/main.c
··· 399 399 bool aniflag = false; 400 400 unsigned int timestamp = jiffies_to_msecs(jiffies); 401 401 u32 cal_interval, short_cal_interval, long_cal_interval; 402 + unsigned long flags; 402 403 403 404 if (ah->caldata && ah->caldata->nfcal_interference) 404 405 long_cal_interval = ATH_LONG_CALINTERVAL_INT; ··· 450 449 /* Skip all processing if there's nothing to do. */ 451 450 if (longcal || shortcal || aniflag) { 452 451 /* Call ANI routine if necessary */ 453 - if (aniflag) 452 + if (aniflag) { 453 + spin_lock_irqsave(&common->cc_lock, flags); 454 454 ath9k_hw_ani_monitor(ah, ah->curchan); 455 + spin_unlock_irqrestore(&common->cc_lock, flags); 456 + } 455 457 456 458 /* Perform calibration if necessary */ 457 459 if (longcal || shortcal) { ··· 639 635 640 636 struct ath_softc *sc = dev; 641 637 struct ath_hw *ah = sc->sc_ah; 638 + struct ath_common *common = ath9k_hw_common(ah); 642 639 enum ath9k_int status; 643 640 bool sched = false; 644 641 ··· 689 684 690 685 if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && 691 686 (status & ATH9K_INT_BB_WATCHDOG)) { 687 + 688 + spin_lock(&common->cc_lock); 689 + ath_hw_cycle_counters_update(common); 692 690 ar9003_hw_bb_watchdog_dbg_info(ah); 691 + spin_unlock(&common->cc_lock); 692 + 693 693 goto chip_reset; 694 694 } 695 695
-11
drivers/net/wireless/ath/ath9k/reg.h
··· 107 107 #define AR_RXCFG_DMASZ_256B 6 108 108 #define AR_RXCFG_DMASZ_512B 7 109 109 110 - #define AR_MIBC 0x0040 111 - #define AR_MIBC_COW 0x00000001 112 - #define AR_MIBC_FMC 0x00000002 113 - #define AR_MIBC_CMC 0x00000004 114 - #define AR_MIBC_MCS 0x00000008 115 - 116 110 #define AR_TOPS 0x0044 117 111 #define AR_TOPS_MASK 0x0000FFFF 118 112 ··· 1517 1523 #define AR_TPC_CTS_S 0x08 1518 1524 #define AR_TPC_CHIRP 0x003f0000 1519 1525 #define AR_TPC_CHIRP_S 0x16 1520 - 1521 - #define AR_TFCNT 0x80ec 1522 - #define AR_RFCNT 0x80f0 1523 - #define AR_RCCNT 0x80f4 1524 - #define AR_CCCNT 0x80f8 1525 1526 1526 1527 #define AR_QUIET1 0x80fc 1527 1528 #define AR_QUIET1_NEXT_QUIET_S 0
+59
drivers/net/wireless/ath/hw.c
··· 124 124 REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); 125 125 } 126 126 EXPORT_SYMBOL(ath_hw_setbssidmask); 127 + 128 + 129 + /** 130 + * ath_hw_cycle_counters_update - common function to update cycle counters 131 + * 132 + * @common: the ath_common struct for the device. 133 + * 134 + * This function is used to update all cycle counters in one place. 135 + * It has to be called while holding common->cc_lock! 136 + */ 137 + void ath_hw_cycle_counters_update(struct ath_common *common) 138 + { 139 + u32 cycles, busy, rx, tx; 140 + void *ah = common->ah; 141 + 142 + /* freeze */ 143 + REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC); 144 + 145 + /* read */ 146 + cycles = REG_READ(ah, AR_CCCNT); 147 + busy = REG_READ(ah, AR_RCCNT); 148 + rx = REG_READ(ah, AR_RFCNT); 149 + tx = REG_READ(ah, AR_TFCNT); 150 + 151 + /* clear */ 152 + REG_WRITE(ah, 0, AR_CCCNT); 153 + REG_WRITE(ah, 0, AR_RFCNT); 154 + REG_WRITE(ah, 0, AR_RCCNT); 155 + REG_WRITE(ah, 0, AR_TFCNT); 156 + 157 + /* unfreeze */ 158 + REG_WRITE(ah, 0, AR_MIBC); 159 + 160 + /* update all cycle counters here */ 161 + common->cc_ani.cycles += cycles; 162 + common->cc_ani.rx_busy += busy; 163 + common->cc_ani.rx_frame += rx; 164 + common->cc_ani.tx_frame += tx; 165 + 166 + common->cc_survey.cycles += cycles; 167 + common->cc_survey.rx_busy += busy; 168 + common->cc_survey.rx_frame += rx; 169 + common->cc_survey.tx_frame += tx; 170 + } 171 + EXPORT_SYMBOL(ath_hw_cycle_counters_update); 172 + 173 + int32_t ath_hw_get_listen_time(struct ath_common *common) 174 + { 175 + struct ath_cycle_counters *cc = &common->cc_ani; 176 + int32_t listen_time; 177 + 178 + listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) / 179 + (common->clockrate * 1000); 180 + 181 + memset(cc, 0, sizeof(*cc)); 182 + 183 + return listen_time; 184 + } 185 + EXPORT_SYMBOL(ath_hw_get_listen_time);
+11
drivers/net/wireless/ath/reg.h
··· 17 17 #ifndef ATH_REGISTERS_H 18 18 #define ATH_REGISTERS_H 19 19 20 + #define AR_MIBC 0x0040 21 + #define AR_MIBC_COW 0x00000001 22 + #define AR_MIBC_FMC 0x00000002 23 + #define AR_MIBC_CMC 0x00000004 24 + #define AR_MIBC_MCS 0x00000008 25 + 20 26 /* 21 27 * BSSID mask registers. See ath_hw_set_bssid_mask() 22 28 * for detailed documentation about these registers. 23 29 */ 24 30 #define AR_BSSMSKL 0x80e0 25 31 #define AR_BSSMSKU 0x80e4 32 + 33 + #define AR_TFCNT 0x80ec 34 + #define AR_RFCNT 0x80f0 35 + #define AR_RCCNT 0x80f4 36 + #define AR_CCCNT 0x80f8 26 37 27 38 #define AR_KEYTABLE_0 0x8800 28 39 #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))