aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-10-08 16:13:53 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-11 15:04:20 -0400
commitb5bfc5683db44a121ad47ec0a9f4efd4aac040e0 (patch)
treeb9d182f42cbbfdea95ad7ab425302617c5f40db9
parent9d119f3ebd074bde0b801f476a44ca60d222efb2 (diff)
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>
-rw-r--r--drivers/net/wireless/ath/ath.h14
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c64
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h11
-rw-r--r--drivers/net/wireless/ath/hw.c59
-rw-r--r--drivers/net/wireless/ath/reg.h11
9 files changed, 101 insertions, 87 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index b36d9d770ff1..501050c0296f 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -19,6 +19,7 @@
19 19
20#include <linux/skbuff.h> 20#include <linux/skbuff.h>
21#include <linux/if_ether.h> 21#include <linux/if_ether.h>
22#include <linux/spinlock.h>
22#include <net/mac80211.h> 23#include <net/mac80211.h>
23 24
24/* 25/*
@@ -42,6 +43,13 @@ struct ath_ani {
42 struct timer_list timer; 43 struct timer_list timer;
43}; 44};
44 45
46struct ath_cycle_counters {
47 u32 cycles;
48 u32 rx_busy;
49 u32 rx_frame;
50 u32 tx_frame;
51};
52
45enum ath_device_state { 53enum ath_device_state {
46 ATH_HW_UNAVAILABLE, 54 ATH_HW_UNAVAILABLE,
47 ATH_HW_INITIALIZED, 55 ATH_HW_INITIALIZED,
@@ -147,6 +155,10 @@ struct ath_common {
147 155
148 unsigned int clockrate; 156 unsigned int clockrate;
149 157
158 spinlock_t cc_lock;
159 struct ath_cycle_counters cc_ani;
160 struct ath_cycle_counters cc_survey;
161
150 struct ath_regulatory regulatory; 162 struct ath_regulatory regulatory;
151 const struct ath_ops *ops; 163 const struct ath_ops *ops;
152 const struct ath_bus_ops *bus_ops; 164 const struct ath_bus_ops *bus_ops;
@@ -163,5 +175,7 @@ int ath_key_config(struct ath_common *common,
163 struct ieee80211_sta *sta, 175 struct ieee80211_sta *sta,
164 struct ieee80211_key_conf *key); 176 struct ieee80211_key_conf *key);
165bool ath_hw_keyreset(struct ath_common *common, u16 entry); 177bool ath_hw_keyreset(struct ath_common *common, u16 entry);
178void ath_hw_cycle_counters_update(struct ath_common *common);
179int32_t ath_hw_get_listen_time(struct ath_common *common);
166 180
167#endif /* ATH_H */ 181#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index f2aa68405d2f..3aa8fb1ad77f 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -465,18 +465,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
465 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); 465 ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
466} 466}
467 467
468static 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
480static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) 468static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
481{ 469{
482 struct ar5416AniState *aniState; 470 struct ar5416AniState *aniState;
@@ -655,7 +643,9 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
655 u32 phyCnt1, phyCnt2; 643 u32 phyCnt1, phyCnt2;
656 int32_t listenTime; 644 int32_t listenTime;
657 645
658 listenTime = ath9k_hw_ani_get_listen_time(ah); 646 ath_hw_cycle_counters_update(common);
647 listenTime = ath_hw_get_listen_time(common);
648
659 if (listenTime < 0) { 649 if (listenTime < 0) {
660 ah->stats.ast_ani_lneg++; 650 ah->stats.ast_ani_lneg++;
661 ath9k_ani_restart(ah); 651 ath9k_ani_restart(ah);
@@ -796,54 +786,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
796} 786}
797EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); 787EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
798 788
799void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
800{
801 struct ath_cycle_counters cc;
802 bool clear;
803
804 memcpy(&cc, &ah->cc, sizeof(cc));
805
806 /* freeze counters */
807 REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
808
809 ah->cc.cycles = REG_READ(ah, AR_CCCNT);
810 if (ah->cc.cycles < cc.cycles) {
811 clear = true;
812 goto skip;
813 }
814
815 ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
816 ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
817 ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);
818
819 /* prevent wraparound */
820 if (ah->cc.cycles & BIT(31))
821 clear = true;
822
823#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
824 CC_DELTA(cycles, AR_CCCNT);
825 CC_DELTA(rx_frame, AR_RFCNT);
826 CC_DELTA(rx_clear, AR_RCCNT);
827 CC_DELTA(tx_frame, AR_TFCNT);
828#undef CC_DELTA
829
830 ah->listen_time += (ah->cc.cycles - cc.cycles) -
831 ((ah->cc.rx_frame - cc.rx_frame) +
832 (ah->cc.tx_frame - cc.tx_frame));
833
834skip:
835 if (clear) {
836 REG_WRITE(ah, AR_CCCNT, 0);
837 REG_WRITE(ah, AR_RFCNT, 0);
838 REG_WRITE(ah, AR_RCCNT, 0);
839 REG_WRITE(ah, AR_TFCNT, 0);
840 memset(&ah->cc, 0, sizeof(ah->cc));
841 }
842
843 /* unfreeze counters */
844 REG_WRITE(ah, AR_MIBC, 0);
845}
846
847/* 789/*
848 * Process a MIB interrupt. We may potentially be invoked because 790 * Process a MIB interrupt. We may potentially be invoked because
849 * any of the MIB counters overflow/trigger so don't assume we're 791 * any of the MIB counters overflow/trigger so don't assume we're
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index 98cfd8154c71..0cd6783de883 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -93,13 +93,6 @@ struct ath9k_mib_stats {
93 u32 beacons; 93 u32 beacons;
94}; 94};
95 95
96struct ath_cycle_counters {
97 u32 cycles;
98 u32 rx_frame;
99 u32 rx_clear;
100 u32 tx_frame;
101};
102
103/* INI default values for ANI registers */ 96/* INI default values for ANI registers */
104struct ath9k_ani_default { 97struct ath9k_ani_default {
105 u16 m1ThreshLow; 98 u16 m1ThreshLow;
@@ -164,7 +157,6 @@ struct ar5416Stats {
164 157
165void ath9k_enable_mib_counters(struct ath_hw *ah); 158void ath9k_enable_mib_counters(struct ath_hw *ah);
166void ath9k_hw_disable_mib_counters(struct ath_hw *ah); 159void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
167void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
168void ath9k_hw_ani_setup(struct ath_hw *ah); 160void ath9k_hw_ani_setup(struct ath_hw *ah);
169void ath9k_hw_ani_init(struct ath_hw *ah); 161void ath9k_hw_ani_init(struct ath_hw *ah);
170int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, 162int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index efb05599b84c..669b777729b3 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
1254 "** BB mode: BB_gen_controls=0x%08x **\n", 1254 "** BB mode: BB_gen_controls=0x%08x **\n",
1255 REG_READ(ah, AR_PHY_GEN_CTRL)); 1255 REG_READ(ah, AR_PHY_GEN_CTRL));
1256 1256
1257 ath9k_hw_update_cycle_counters(ah); 1257#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
1258#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles) 1258 if (common->cc_survey.cycles)
1259 if (ah->cc_delta.cycles)
1260 ath_print(common, ATH_DBG_RESET, 1259 ath_print(common, ATH_DBG_RESET,
1261 "** BB busy times: rx_clear=%d%%, " 1260 "** BB busy times: rx_clear=%d%%, "
1262 "rx_frame=%d%%, tx_frame=%d%% **\n", 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 ath_print(common, ATH_DBG_RESET, 1264 ath_print(common, ATH_DBG_RESET,
1266 "==== BB update: done ====\n\n"); 1265 "==== BB update: done ====\n\n");
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 87627dd63463..7f696c82ca0a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -740,8 +740,6 @@ struct ath_hw {
740 int coarse_low[5]; 740 int coarse_low[5];
741 int firpwr[5]; 741 int firpwr[5];
742 enum ath9k_ani_cmd ani_function; 742 enum ath9k_ani_cmd ani_function;
743 struct ath_cycle_counters cc, cc_delta;
744 int32_t listen_time;
745 743
746 /* Bluetooth coexistance */ 744 /* Bluetooth coexistance */
747 struct ath_btcoex_hw btcoex_hw; 745 struct ath_btcoex_hw btcoex_hw;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 74c2dc8a8b8a..360c6f5e843a 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -399,6 +399,7 @@ void ath_ani_calibrate(unsigned long data)
399 bool aniflag = false; 399 bool aniflag = false;
400 unsigned int timestamp = jiffies_to_msecs(jiffies); 400 unsigned int timestamp = jiffies_to_msecs(jiffies);
401 u32 cal_interval, short_cal_interval, long_cal_interval; 401 u32 cal_interval, short_cal_interval, long_cal_interval;
402 unsigned long flags;
402 403
403 if (ah->caldata && ah->caldata->nfcal_interference) 404 if (ah->caldata && ah->caldata->nfcal_interference)
404 long_cal_interval = ATH_LONG_CALINTERVAL_INT; 405 long_cal_interval = ATH_LONG_CALINTERVAL_INT;
@@ -449,8 +450,11 @@ void ath_ani_calibrate(unsigned long data)
449 /* Skip all processing if there's nothing to do. */ 450 /* Skip all processing if there's nothing to do. */
450 if (longcal || shortcal || aniflag) { 451 if (longcal || shortcal || aniflag) {
451 /* Call ANI routine if necessary */ 452 /* Call ANI routine if necessary */
452 if (aniflag) 453 if (aniflag) {
454 spin_lock_irqsave(&common->cc_lock, flags);
453 ath9k_hw_ani_monitor(ah, ah->curchan); 455 ath9k_hw_ani_monitor(ah, ah->curchan);
456 spin_unlock_irqrestore(&common->cc_lock, flags);
457 }
454 458
455 /* Perform calibration if necessary */ 459 /* Perform calibration if necessary */
456 if (longcal || shortcal) { 460 if (longcal || shortcal) {
@@ -635,6 +639,7 @@ irqreturn_t ath_isr(int irq, void *dev)
635 639
636 struct ath_softc *sc = dev; 640 struct ath_softc *sc = dev;
637 struct ath_hw *ah = sc->sc_ah; 641 struct ath_hw *ah = sc->sc_ah;
642 struct ath_common *common = ath9k_hw_common(ah);
638 enum ath9k_int status; 643 enum ath9k_int status;
639 bool sched = false; 644 bool sched = false;
640 645
@@ -684,7 +689,12 @@ irqreturn_t ath_isr(int irq, void *dev)
684 689
685 if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && 690 if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
686 (status & ATH9K_INT_BB_WATCHDOG)) { 691 (status & ATH9K_INT_BB_WATCHDOG)) {
692
693 spin_lock(&common->cc_lock);
694 ath_hw_cycle_counters_update(common);
687 ar9003_hw_bb_watchdog_dbg_info(ah); 695 ar9003_hw_bb_watchdog_dbg_info(ah);
696 spin_unlock(&common->cc_lock);
697
688 goto chip_reset; 698 goto chip_reset;
689 } 699 }
690 700
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 6d01e501b9b4..017617894533 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -107,12 +107,6 @@
107#define AR_RXCFG_DMASZ_256B 6 107#define AR_RXCFG_DMASZ_256B 6
108#define AR_RXCFG_DMASZ_512B 7 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#define AR_TOPS 0x0044 110#define AR_TOPS 0x0044
117#define AR_TOPS_MASK 0x0000FFFF 111#define AR_TOPS_MASK 0x0000FFFF
118 112
@@ -1524,11 +1518,6 @@ enum {
1524#define AR_TPC_CHIRP 0x003f0000 1518#define AR_TPC_CHIRP 0x003f0000
1525#define AR_TPC_CHIRP_S 0x16 1519#define AR_TPC_CHIRP_S 0x16
1526 1520
1527#define AR_TFCNT 0x80ec
1528#define AR_RFCNT 0x80f0
1529#define AR_RCCNT 0x80f4
1530#define AR_CCCNT 0x80f8
1531
1532#define AR_QUIET1 0x80fc 1521#define AR_QUIET1 0x80fc
1533#define AR_QUIET1_NEXT_QUIET_S 0 1522#define AR_QUIET1_NEXT_QUIET_S 0
1534#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff 1523#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index a8f81ea09f14..183c28281385 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_common *common)
124 REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); 124 REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
125} 125}
126EXPORT_SYMBOL(ath_hw_setbssidmask); 126EXPORT_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 */
137void 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}
171EXPORT_SYMBOL(ath_hw_cycle_counters_update);
172
173int32_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}
185EXPORT_SYMBOL(ath_hw_get_listen_time);
diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h
index e798ef476581..298e53f3fa48 100644
--- a/drivers/net/wireless/ath/reg.h
+++ b/drivers/net/wireless/ath/reg.h
@@ -17,6 +17,12 @@
17#ifndef ATH_REGISTERS_H 17#ifndef ATH_REGISTERS_H
18#define ATH_REGISTERS_H 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 * BSSID mask registers. See ath_hw_set_bssid_mask() 27 * BSSID mask registers. See ath_hw_set_bssid_mask()
22 * for detailed documentation about these registers. 28 * for detailed documentation about these registers.
@@ -24,6 +30,11 @@
24#define AR_BSSMSKL 0x80e0 30#define AR_BSSMSKL 0x80e0
25#define AR_BSSMSKU 0x80e4 31#define AR_BSSMSKU 0x80e4
26 32
33#define AR_TFCNT 0x80ec
34#define AR_RFCNT 0x80f0
35#define AR_RCCNT 0x80f4
36#define AR_CCCNT 0x80f8
37
27#define AR_KEYTABLE_0 0x8800 38#define AR_KEYTABLE_0 0x8800
28#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) 39#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32))
29#define AR_KEY_CACHE_SIZE 128 40#define AR_KEY_CACHE_SIZE 128