diff options
author | Sujith <Sujith.Manoharan@atheros.com> | 2009-01-30 04:02:09 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-09 15:03:44 -0500 |
commit | 7a7dec656252a5784218a22abf76ad1cdef115d0 (patch) | |
tree | a7496cdb999f27cb80082fd74f9790840f7c9fde | |
parent | c89424df441ea8d794682b9c5620d8e8b0315438 (diff) |
ath9k: Add debugfs files for printing TX rate details
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath9k/core.h | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/debug.c | 100 | ||||
-rw-r--r-- | drivers/net/wireless/ath9k/rc.c | 2 |
3 files changed, 119 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 8683fc8ddb3c..791f1acc0bb3 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -131,8 +131,18 @@ struct ath_interrupt_stats { | |||
131 | u32 dtim; | 131 | u32 dtim; |
132 | }; | 132 | }; |
133 | 133 | ||
134 | struct ath_legacy_rc_stats { | ||
135 | u32 success; | ||
136 | }; | ||
137 | |||
138 | struct ath_11n_rc_stats { | ||
139 | u32 success; | ||
140 | }; | ||
141 | |||
134 | struct ath_stats { | 142 | struct ath_stats { |
135 | struct ath_interrupt_stats istats; | 143 | struct ath_interrupt_stats istats; |
144 | struct ath_legacy_rc_stats legacy_rcstats[12]; /* max(11a,11b,11g) */ | ||
145 | struct ath_11n_rc_stats n_rcstats[16]; /* 0..15 MCS rates */ | ||
136 | }; | 146 | }; |
137 | 147 | ||
138 | struct ath9k_debug { | 148 | struct ath9k_debug { |
@@ -141,6 +151,7 @@ struct ath9k_debug { | |||
141 | struct dentry *debugfs_phy; | 151 | struct dentry *debugfs_phy; |
142 | struct dentry *debugfs_dma; | 152 | struct dentry *debugfs_dma; |
143 | struct dentry *debugfs_interrupt; | 153 | struct dentry *debugfs_interrupt; |
154 | struct dentry *debugfs_rcstat; | ||
144 | struct ath_stats stats; | 155 | struct ath_stats stats; |
145 | }; | 156 | }; |
146 | 157 | ||
@@ -148,6 +159,7 @@ void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); | |||
148 | int ath9k_init_debug(struct ath_softc *sc); | 159 | int ath9k_init_debug(struct ath_softc *sc); |
149 | void ath9k_exit_debug(struct ath_softc *sc); | 160 | void ath9k_exit_debug(struct ath_softc *sc); |
150 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); | 161 | void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); |
162 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); | ||
151 | 163 | ||
152 | #else | 164 | #else |
153 | 165 | ||
@@ -170,6 +182,11 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc, | |||
170 | { | 182 | { |
171 | } | 183 | } |
172 | 184 | ||
185 | static inline void ath_debug_stat_rc(struct ath_softc *sc, | ||
186 | struct sk_buff *skb) | ||
187 | { | ||
188 | } | ||
189 | |||
173 | #endif /* CONFIG_ATH9K_DEBUG */ | 190 | #endif /* CONFIG_ATH9K_DEBUG */ |
174 | 191 | ||
175 | struct ath_config { | 192 | struct ath_config { |
diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 1680164b4adb..6181e49eecba 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c | |||
@@ -222,6 +222,98 @@ static const struct file_operations fops_interrupt = { | |||
222 | .owner = THIS_MODULE | 222 | .owner = THIS_MODULE |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static void ath_debug_stat_11n_rc(struct ath_softc *sc, struct sk_buff *skb) | ||
226 | { | ||
227 | struct ath_tx_info_priv *tx_info_priv = NULL; | ||
228 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
229 | struct ieee80211_tx_rate *rates = tx_info->status.rates; | ||
230 | int final_ts_idx, idx; | ||
231 | |||
232 | tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
233 | final_ts_idx = tx_info_priv->tx.ts_rateindex; | ||
234 | idx = sc->cur_rate_table->info[rates[final_ts_idx].idx].dot11rate; | ||
235 | |||
236 | sc->sc_debug.stats.n_rcstats[idx].success++; | ||
237 | } | ||
238 | |||
239 | static void ath_debug_stat_legacy_rc(struct ath_softc *sc, struct sk_buff *skb) | ||
240 | { | ||
241 | struct ath_tx_info_priv *tx_info_priv = NULL; | ||
242 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
243 | struct ieee80211_tx_rate *rates = tx_info->status.rates; | ||
244 | int final_ts_idx, idx; | ||
245 | |||
246 | tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
247 | final_ts_idx = tx_info_priv->tx.ts_rateindex; | ||
248 | idx = rates[final_ts_idx].idx; | ||
249 | |||
250 | sc->sc_debug.stats.legacy_rcstats[idx].success++; | ||
251 | } | ||
252 | |||
253 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) | ||
254 | { | ||
255 | if (conf_is_ht(&sc->hw->conf)) | ||
256 | ath_debug_stat_11n_rc(sc, skb); | ||
257 | else | ||
258 | ath_debug_stat_legacy_rc(sc, skb); | ||
259 | } | ||
260 | |||
261 | static ssize_t ath_read_file_stat_11n_rc(struct file *file, | ||
262 | char __user *user_buf, | ||
263 | size_t count, loff_t *ppos) | ||
264 | { | ||
265 | struct ath_softc *sc = file->private_data; | ||
266 | char buf[512]; | ||
267 | unsigned int len = 0; | ||
268 | int i = 0; | ||
269 | |||
270 | len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); | ||
271 | |||
272 | for (i = 0; i <= 15; i++) { | ||
273 | len += snprintf(buf + len, sizeof(buf) - len, | ||
274 | "%5s%3d: %8u\n", "MCS", i, | ||
275 | sc->sc_debug.stats.n_rcstats[i].success); | ||
276 | } | ||
277 | |||
278 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
279 | } | ||
280 | |||
281 | static ssize_t ath_read_file_stat_legacy_rc(struct file *file, | ||
282 | char __user *user_buf, | ||
283 | size_t count, loff_t *ppos) | ||
284 | { | ||
285 | struct ath_softc *sc = file->private_data; | ||
286 | char buf[512]; | ||
287 | unsigned int len = 0; | ||
288 | int i = 0; | ||
289 | |||
290 | len += sprintf(buf, "%7s %13s\n\n", "Rate", "Success"); | ||
291 | |||
292 | for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { | ||
293 | len += snprintf(buf + len, sizeof(buf) - len, "%5u: %12u\n", | ||
294 | sc->cur_rate_table->info[i].ratekbps / 1000, | ||
295 | sc->sc_debug.stats.legacy_rcstats[i].success); | ||
296 | } | ||
297 | |||
298 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
299 | } | ||
300 | |||
301 | static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, | ||
302 | size_t count, loff_t *ppos) | ||
303 | { | ||
304 | struct ath_softc *sc = file->private_data; | ||
305 | |||
306 | if (conf_is_ht(&sc->hw->conf)) | ||
307 | return ath_read_file_stat_11n_rc(file, user_buf, count, ppos); | ||
308 | else | ||
309 | return ath_read_file_stat_legacy_rc(file, user_buf, count ,ppos); | ||
310 | } | ||
311 | |||
312 | static const struct file_operations fops_rcstat = { | ||
313 | .read = read_file_rcstat, | ||
314 | .open = ath9k_debugfs_open, | ||
315 | .owner = THIS_MODULE | ||
316 | }; | ||
225 | 317 | ||
226 | int ath9k_init_debug(struct ath_softc *sc) | 318 | int ath9k_init_debug(struct ath_softc *sc) |
227 | { | 319 | { |
@@ -248,6 +340,13 @@ int ath9k_init_debug(struct ath_softc *sc) | |||
248 | if (!sc->sc_debug.debugfs_interrupt) | 340 | if (!sc->sc_debug.debugfs_interrupt) |
249 | goto err; | 341 | goto err; |
250 | 342 | ||
343 | sc->sc_debug.debugfs_rcstat = debugfs_create_file("rcstat", | ||
344 | S_IRUGO, | ||
345 | sc->sc_debug.debugfs_phy, | ||
346 | sc, &fops_rcstat); | ||
347 | if (!sc->sc_debug.debugfs_rcstat) | ||
348 | goto err; | ||
349 | |||
251 | return 0; | 350 | return 0; |
252 | err: | 351 | err: |
253 | ath9k_exit_debug(sc); | 352 | ath9k_exit_debug(sc); |
@@ -256,6 +355,7 @@ err: | |||
256 | 355 | ||
257 | void ath9k_exit_debug(struct ath_softc *sc) | 356 | void ath9k_exit_debug(struct ath_softc *sc) |
258 | { | 357 | { |
358 | debugfs_remove(sc->sc_debug.debugfs_rcstat); | ||
259 | debugfs_remove(sc->sc_debug.debugfs_interrupt); | 359 | debugfs_remove(sc->sc_debug.debugfs_interrupt); |
260 | debugfs_remove(sc->sc_debug.debugfs_dma); | 360 | debugfs_remove(sc->sc_debug.debugfs_dma); |
261 | debugfs_remove(sc->sc_debug.debugfs_phy); | 361 | debugfs_remove(sc->sc_debug.debugfs_phy); |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index a8c4f9757eb1..704b62778142 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1544,6 +1544,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1544 | ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); | 1544 | ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); |
1545 | } | 1545 | } |
1546 | } | 1546 | } |
1547 | |||
1548 | ath_debug_stat_rc(sc, skb); | ||
1547 | exit: | 1549 | exit: |
1548 | kfree(tx_info_priv); | 1550 | kfree(tx_info_priv); |
1549 | } | 1551 | } |