diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2014-01-12 20:59:30 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-13 14:50:05 -0500 |
commit | 350e2dcb4647d144000db1505c94d586fcd57919 (patch) | |
tree | 42a54da4d37b0bf4985e87476ff0e71ff7255b5d | |
parent | c3b9f9e86b178fd3e94e2d6dd6da84ab38fa2ba7 (diff) |
ath9k: Add a debugfs file "node_recv"
This would be useful when debugging RX performance issues.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug.h | 34 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/debug_sta.c | 164 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 2 |
5 files changed, 203 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f622a986c8cc..cba7d772f7f3 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -146,7 +146,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, | |||
146 | 146 | ||
147 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) | 147 | #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) |
148 | 148 | ||
149 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) | 149 | #define IS_HT_RATE(rate) (rate & 0x80) |
150 | #define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) | ||
151 | #define IS_OFDM_RATE(rate) ((rate >= 0x8) && (rate <= 0xf)) | ||
150 | 152 | ||
151 | struct ath_txq { | 153 | struct ath_txq { |
152 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ | 154 | int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */ |
@@ -262,6 +264,10 @@ struct ath_node { | |||
262 | 264 | ||
263 | bool sleeping; | 265 | bool sleeping; |
264 | bool no_ps_filter; | 266 | bool no_ps_filter; |
267 | |||
268 | #ifdef CONFIG_ATH9K_STATION_STATISTICS | ||
269 | struct ath_rx_rate_stats rx_rate_stats; | ||
270 | #endif | ||
265 | }; | 271 | }; |
266 | 272 | ||
267 | struct ath_tx_control { | 273 | struct ath_tx_control { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index ec02d38ea8ea..b01b8c3ec570 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -27,11 +27,13 @@ struct fft_sample_tlv; | |||
27 | 27 | ||
28 | #ifdef CONFIG_ATH9K_DEBUGFS | 28 | #ifdef CONFIG_ATH9K_DEBUGFS |
29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ | 29 | #define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ |
30 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | ||
30 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ | 31 | #define RESET_STAT_INC(sc, type) sc->debug.stats.reset[type]++ |
31 | #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ | 32 | #define ANT_STAT_INC(i, c) sc->debug.stats.ant_stats[i].c++ |
32 | #define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; | 33 | #define ANT_LNA_INC(i, c) sc->debug.stats.ant_stats[i].lna_recv_cnt[c]++; |
33 | #else | 34 | #else |
34 | #define TX_STAT_INC(q, c) do { } while (0) | 35 | #define TX_STAT_INC(q, c) do { } while (0) |
36 | #define RX_STAT_INC(c) | ||
35 | #define RESET_STAT_INC(sc, type) do { } while (0) | 37 | #define RESET_STAT_INC(sc, type) do { } while (0) |
36 | #define ANT_STAT_INC(i, c) do { } while (0) | 38 | #define ANT_STAT_INC(i, c) do { } while (0) |
37 | #define ANT_LNA_INC(i, c) do { } while (0) | 39 | #define ANT_LNA_INC(i, c) do { } while (0) |
@@ -201,7 +203,23 @@ struct ath_tx_stats { | |||
201 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ | 203 | TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \ |
202 | } while(0) | 204 | } while(0) |
203 | 205 | ||
204 | #define RX_STAT_INC(c) (sc->debug.stats.rxstats.c++) | 206 | struct ath_rx_rate_stats { |
207 | struct { | ||
208 | u32 ht20_cnt; | ||
209 | u32 ht40_cnt; | ||
210 | u32 sgi_cnt; | ||
211 | u32 lgi_cnt; | ||
212 | } ht_stats[24]; | ||
213 | |||
214 | struct { | ||
215 | u32 ofdm_cnt; | ||
216 | } ofdm_stats[8]; | ||
217 | |||
218 | struct { | ||
219 | u32 cck_lp_cnt; | ||
220 | u32 cck_sp_cnt; | ||
221 | } cck_stats[4]; | ||
222 | }; | ||
205 | 223 | ||
206 | /** | 224 | /** |
207 | * struct ath_rx_stats - RX Statistics | 225 | * struct ath_rx_stats - RX Statistics |
@@ -299,8 +317,6 @@ void ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause); | |||
299 | 317 | ||
300 | #else | 318 | #else |
301 | 319 | ||
302 | #define RX_STAT_INC(c) /* NOP */ | ||
303 | |||
304 | static inline int ath9k_init_debug(struct ath_hw *ah) | 320 | static inline int ath9k_init_debug(struct ath_hw *ah) |
305 | { | 321 | { |
306 | return 0; | 322 | return 0; |
@@ -338,4 +354,16 @@ ath9k_debug_sync_cause(struct ath_softc *sc, u32 sync_cause) | |||
338 | 354 | ||
339 | #endif /* CONFIG_ATH9K_DEBUGFS */ | 355 | #endif /* CONFIG_ATH9K_DEBUGFS */ |
340 | 356 | ||
357 | #ifdef CONFIG_ATH9K_STATION_STATISTICS | ||
358 | void ath_debug_rate_stats(struct ath_softc *sc, | ||
359 | struct ath_rx_status *rs, | ||
360 | struct sk_buff *skb); | ||
361 | #else | ||
362 | static inline void ath_debug_rate_stats(struct ath_softc *sc, | ||
363 | struct ath_rx_status *rs, | ||
364 | struct sk_buff *skb) | ||
365 | { | ||
366 | } | ||
367 | #endif /* CONFIG_ATH9K_STATION_STATISTICS */ | ||
368 | |||
341 | #endif /* DEBUG_H */ | 369 | #endif /* DEBUG_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c index 3d119689d08a..d33cc88a5849 100644 --- a/drivers/net/wireless/ath/ath9k/debug_sta.c +++ b/drivers/net/wireless/ath/ath9k/debug_sta.c | |||
@@ -16,6 +16,10 @@ | |||
16 | 16 | ||
17 | #include "ath9k.h" | 17 | #include "ath9k.h" |
18 | 18 | ||
19 | /*************/ | ||
20 | /* node_aggr */ | ||
21 | /*************/ | ||
22 | |||
19 | static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, | 23 | static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf, |
20 | size_t count, loff_t *ppos) | 24 | size_t count, loff_t *ppos) |
21 | { | 25 | { |
@@ -95,11 +99,171 @@ static const struct file_operations fops_node_aggr = { | |||
95 | .llseek = default_llseek, | 99 | .llseek = default_llseek, |
96 | }; | 100 | }; |
97 | 101 | ||
102 | /*************/ | ||
103 | /* node_recv */ | ||
104 | /*************/ | ||
105 | |||
106 | void ath_debug_rate_stats(struct ath_softc *sc, | ||
107 | struct ath_rx_status *rs, | ||
108 | struct sk_buff *skb) | ||
109 | { | ||
110 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
111 | struct ath_hw *ah = sc->sc_ah; | ||
112 | struct ieee80211_rx_status *rxs; | ||
113 | struct ath_rx_rate_stats *rstats; | ||
114 | struct ieee80211_sta *sta; | ||
115 | struct ath_node *an; | ||
116 | |||
117 | if (!ieee80211_is_data(hdr->frame_control)) | ||
118 | return; | ||
119 | |||
120 | rcu_read_lock(); | ||
121 | |||
122 | sta = ieee80211_find_sta_by_ifaddr(sc->hw, hdr->addr2, NULL); | ||
123 | if (!sta) | ||
124 | goto exit; | ||
125 | |||
126 | an = (struct ath_node *) sta->drv_priv; | ||
127 | rstats = &an->rx_rate_stats; | ||
128 | rxs = IEEE80211_SKB_RXCB(skb); | ||
129 | |||
130 | if (IS_HT_RATE(rs->rs_rate)) { | ||
131 | if (rxs->rate_idx > ARRAY_SIZE(rstats->ht_stats)) | ||
132 | goto exit; | ||
133 | |||
134 | if (rxs->flag & RX_FLAG_40MHZ) | ||
135 | rstats->ht_stats[rxs->rate_idx].ht40_cnt++; | ||
136 | else | ||
137 | rstats->ht_stats[rxs->rate_idx].ht20_cnt++; | ||
138 | |||
139 | if (rxs->flag & RX_FLAG_SHORT_GI) | ||
140 | rstats->ht_stats[rxs->rate_idx].sgi_cnt++; | ||
141 | else | ||
142 | rstats->ht_stats[rxs->rate_idx].lgi_cnt++; | ||
143 | |||
144 | goto exit; | ||
145 | } | ||
146 | |||
147 | if (IS_CCK_RATE(rs->rs_rate)) { | ||
148 | if (rxs->flag & RX_FLAG_SHORTPRE) | ||
149 | rstats->cck_stats[rxs->rate_idx].cck_sp_cnt++; | ||
150 | else | ||
151 | rstats->cck_stats[rxs->rate_idx].cck_lp_cnt++; | ||
152 | |||
153 | goto exit; | ||
154 | } | ||
155 | |||
156 | if (IS_OFDM_RATE(rs->rs_rate)) { | ||
157 | if (ah->curchan->chan->band == IEEE80211_BAND_2GHZ) | ||
158 | rstats->ofdm_stats[rxs->rate_idx - 4].ofdm_cnt++; | ||
159 | else | ||
160 | rstats->ofdm_stats[rxs->rate_idx].ofdm_cnt++; | ||
161 | } | ||
162 | exit: | ||
163 | rcu_read_unlock(); | ||
164 | } | ||
165 | |||
166 | #define PRINT_CCK_RATE(str, i, sp) \ | ||
167 | do { \ | ||
168 | len += scnprintf(buf + len, size - len, \ | ||
169 | "%11s : %10u\n", \ | ||
170 | str, \ | ||
171 | (sp) ? rstats->cck_stats[i].cck_sp_cnt : \ | ||
172 | rstats->cck_stats[i].cck_lp_cnt); \ | ||
173 | } while (0) | ||
174 | |||
175 | #define PRINT_OFDM_RATE(str, i) \ | ||
176 | do { \ | ||
177 | len += scnprintf(buf + len, size - len, \ | ||
178 | "%11s : %10u\n", \ | ||
179 | str, \ | ||
180 | rstats->ofdm_stats[i].ofdm_cnt); \ | ||
181 | } while (0) | ||
182 | |||
183 | static ssize_t read_file_node_recv(struct file *file, char __user *user_buf, | ||
184 | size_t count, loff_t *ppos) | ||
185 | { | ||
186 | struct ath_node *an = file->private_data; | ||
187 | struct ath_softc *sc = an->sc; | ||
188 | struct ath_hw *ah = sc->sc_ah; | ||
189 | struct ath_rx_rate_stats *rstats; | ||
190 | struct ieee80211_sta *sta = an->sta; | ||
191 | enum ieee80211_band band; | ||
192 | u32 len = 0, size = 4096; | ||
193 | char *buf; | ||
194 | size_t retval; | ||
195 | int i; | ||
196 | |||
197 | buf = kzalloc(size, GFP_KERNEL); | ||
198 | if (buf == NULL) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | band = ah->curchan->chan->band; | ||
202 | rstats = &an->rx_rate_stats; | ||
203 | |||
204 | if (!sta->ht_cap.ht_supported) | ||
205 | goto legacy; | ||
206 | |||
207 | len += scnprintf(buf + len, size - len, | ||
208 | "%24s%10s%10s%10s\n", | ||
209 | "HT20", "HT40", "SGI", "LGI"); | ||
210 | |||
211 | for (i = 0; i < 24; i++) { | ||
212 | len += scnprintf(buf + len, size - len, | ||
213 | "%8s%3u : %10u%10u%10u%10u\n", | ||
214 | "MCS", i, | ||
215 | rstats->ht_stats[i].ht20_cnt, | ||
216 | rstats->ht_stats[i].ht40_cnt, | ||
217 | rstats->ht_stats[i].sgi_cnt, | ||
218 | rstats->ht_stats[i].lgi_cnt); | ||
219 | } | ||
220 | |||
221 | len += scnprintf(buf + len, size - len, "\n"); | ||
222 | |||
223 | legacy: | ||
224 | if (band == IEEE80211_BAND_2GHZ) { | ||
225 | PRINT_CCK_RATE("CCK-1M/LP", 0, false); | ||
226 | PRINT_CCK_RATE("CCK-2M/LP", 1, false); | ||
227 | PRINT_CCK_RATE("CCK-5.5M/LP", 2, false); | ||
228 | PRINT_CCK_RATE("CCK-11M/LP", 3, false); | ||
229 | |||
230 | PRINT_CCK_RATE("CCK-2M/SP", 1, true); | ||
231 | PRINT_CCK_RATE("CCK-5.5M/SP", 2, true); | ||
232 | PRINT_CCK_RATE("CCK-11M/SP", 3, true); | ||
233 | } | ||
234 | |||
235 | PRINT_OFDM_RATE("OFDM-6M", 0); | ||
236 | PRINT_OFDM_RATE("OFDM-9M", 1); | ||
237 | PRINT_OFDM_RATE("OFDM-12M", 2); | ||
238 | PRINT_OFDM_RATE("OFDM-18M", 3); | ||
239 | PRINT_OFDM_RATE("OFDM-24M", 4); | ||
240 | PRINT_OFDM_RATE("OFDM-36M", 5); | ||
241 | PRINT_OFDM_RATE("OFDM-48M", 6); | ||
242 | PRINT_OFDM_RATE("OFDM-54M", 7); | ||
243 | |||
244 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
245 | kfree(buf); | ||
246 | |||
247 | return retval; | ||
248 | } | ||
249 | |||
250 | #undef PRINT_OFDM_RATE | ||
251 | #undef PRINT_CCK_RATE | ||
252 | |||
253 | static const struct file_operations fops_node_recv = { | ||
254 | .read = read_file_node_recv, | ||
255 | .open = simple_open, | ||
256 | .owner = THIS_MODULE, | ||
257 | .llseek = default_llseek, | ||
258 | }; | ||
259 | |||
98 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, | 260 | void ath9k_sta_add_debugfs(struct ieee80211_hw *hw, |
99 | struct ieee80211_vif *vif, | 261 | struct ieee80211_vif *vif, |
100 | struct ieee80211_sta *sta, | 262 | struct ieee80211_sta *sta, |
101 | struct dentry *dir) | 263 | struct dentry *dir) |
102 | { | 264 | { |
103 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 265 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
266 | |||
104 | debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr); | 267 | debugfs_create_file("node_aggr", S_IRUGO, dir, an, &fops_node_aggr); |
268 | debugfs_create_file("node_recv", S_IRUGO, dir, an, &fops_node_recv); | ||
105 | } | 269 | } |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index f7cc5b37a18f..5bf3243dce0f 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1354,8 +1354,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1354 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1354 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1355 | 1355 | ||
1356 | ath9k_antenna_check(sc, &rs); | 1356 | ath9k_antenna_check(sc, &rs); |
1357 | |||
1358 | ath9k_apply_ampdu_details(sc, &rs, rxs); | 1357 | ath9k_apply_ampdu_details(sc, &rs, rxs); |
1358 | ath_debug_rate_stats(sc, &rs, skb); | ||
1359 | 1359 | ||
1360 | ieee80211_rx(hw, skb); | 1360 | ieee80211_rx(hw, skb); |
1361 | 1361 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e8d0e7fc77da..0a75e2f68c9d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -47,8 +47,6 @@ static u16 bits_per_symbol[][2] = { | |||
47 | { 260, 540 }, /* 7: 64-QAM 5/6 */ | 47 | { 260, 540 }, /* 7: 64-QAM 5/6 */ |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #define IS_HT_RATE(_rate) ((_rate) & 0x80) | ||
51 | |||
52 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | 50 | static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, |
53 | struct ath_atx_tid *tid, struct sk_buff *skb); | 51 | struct ath_atx_tid *tid, struct sk_buff *skb); |
54 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 52 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |