ath9k: fix counter overflow in survey channel time stats for the operating channel
[openwrt.git] / package / mac80211 / patches / 523-ath5k_use_common_counters.patch
1 --- a/drivers/net/wireless/ath/ath5k/ani.c
2 +++ b/drivers/net/wireless/ath/ath5k/ani.c
3 @@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw
4  
5  
6  /**
7 - * ath5k_hw_ani_get_listen_time() - Calculate time spent listening
8 + * ath5k_hw_ani_get_listen_time() - Update counters and return listening time
9   *
10   * Return an approximation of the time spent "listening" in milliseconds (ms)
11 - * since the last call of this function by deducting the cycles spent
12 - * transmitting and receiving from the total cycle count.
13 - * Save profile count values for debugging/statistics and because we might want
14 - * to use them later.
15 - *
16 - * We assume no one else clears these registers!
17 + * since the last call of this function.
18 + * Save a snapshot of the counter values for debugging/statistics.
19   */
20  static int
21  ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
22  {
23 +       struct ath_common *common = ath5k_hw_common(ah);
24         int listen;
25  
26 -       /* freeze */
27 -       ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC);
28 -       /* read */
29 -       as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE);
30 -       as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR);
31 -       as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX);
32 -       as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX);
33 -       /* clear */
34 -       ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
35 -       ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
36 -       ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
37 -       ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
38 -       /* un-freeze */
39 -       ath5k_hw_reg_write(ah, 0, AR5K_MIBC);
40 +       spin_lock_bh(&common->cc_lock);
41  
42 -       /* TODO: where does 44000 come from? (11g clock rate?) */
43 -       listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000;
44 +       ath_hw_cycle_counters_update(common);
45 +       memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc));
46 +
47 +       /* clears common->cc_ani */
48 +       listen = ath_hw_get_listen_time(common);
49 +
50 +       spin_unlock_bh(&common->cc_lock);
51  
52 -       if (as->pfc_cycles == 0 || listen < 0)
53 -               return 0;
54         return listen;
55  }
56  
57 --- a/drivers/net/wireless/ath/ath5k/ani.h
58 +++ b/drivers/net/wireless/ath/ath5k/ani.h
59 @@ -75,10 +75,7 @@ struct ath5k_ani_state {
60         unsigned int            cck_errors;
61  
62         /* debug/statistics only: numbers from last ANI calibration */
63 -       unsigned int            pfc_tx;
64 -       unsigned int            pfc_rx;
65 -       unsigned int            pfc_busy;
66 -       unsigned int            pfc_cycles;
67 +       struct ath_cycle_counters last_cc;
68         unsigned int            last_listen;
69         unsigned int            last_ofdm_errors;
70         unsigned int            last_cck_errors;
71 --- a/drivers/net/wireless/ath/ath5k/debug.c
72 +++ b/drivers/net/wireless/ath/ath5k/debug.c
73 @@ -715,20 +715,21 @@ static ssize_t read_file_ani(struct file
74         len += snprintf(buf+len, sizeof(buf)-len,
75                         "beacon RSSI average:\t%d\n",
76                         sc->ah->ah_beacon_rssi_avg.avg);
77 +
78 +#define CC_PRINT(_struct, _field) \
79 +       _struct._field, \
80 +       _struct.cycles > 0 ? \
81 +       _struct._field*100/_struct.cycles : 0
82 +
83         len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n",
84 -                       as->pfc_tx,
85 -                       as->pfc_cycles > 0 ?
86 -                       as->pfc_tx*100/as->pfc_cycles : 0);
87 +                       CC_PRINT(as->last_cc, tx_frame));
88         len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n",
89 -                       as->pfc_rx,
90 -                       as->pfc_cycles > 0 ?
91 -                       as->pfc_rx*100/as->pfc_cycles : 0);
92 +                       CC_PRINT(as->last_cc, rx_frame));
93         len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n",
94 -                       as->pfc_busy,
95 -                       as->pfc_cycles > 0 ?
96 -                       as->pfc_busy*100/as->pfc_cycles : 0);
97 +                       CC_PRINT(as->last_cc, rx_busy));
98 +#undef CC_PRINT
99         len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n",
100 -                       as->pfc_cycles);
101 +                       as->last_cc.cycles);
102         len += snprintf(buf+len, sizeof(buf)-len,
103                         "listen time\t\t%d\tlast: %d\n",
104                         as->listen_time, as->last_listen);