diff options
author | Bruno Randolf <bruno@thinktube.com> | 2008-01-22 20:27:51 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-31 22:26:35 -0500 |
commit | be9b72590c05daf34c2b55cd5b7c68375a4a795b (patch) | |
tree | b14df772e982996effc400fce57268f3547d0bc3 /drivers/net/wireless/ath5k/debug.c | |
parent | 691ba2346d5b88cec62fe8db0bf336a58a07b926 (diff) |
ath5k: debug level improvements
* use only one debug level for beacon debugging: unify ATH5K_DEBUG_BEACON and
ATH5K_DEBUG_BEACON_PROC.
* remove debug level ATH5K_DEBUG_FATAL. doesn't make sense as a debug level -
if it's fatal it should be logged as an error.
* fancier printing of debug levels. cat /debugfs/ath5k/phy0/debug.
* allow debug levels to be changed by echoing their name into
/debugfs/ath5k/phy0/debug. this will toggle the state, when it was off it will
be turned on and vice versa.
* use copy_from_user() when reading from the debug files. use unsigned int for
better optimization. reduce buffer sizes on stack.
drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD
drivers/net/wireless/ath5k/debug.c: Changes-licensed-under: GPL
drivers/net/wireless/ath5k/debug.h: Changes-licensed-under: GPL
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
Acked-by: Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
Acked-by: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/ath5k/debug.c')
-rw-r--r-- | drivers/net/wireless/ath5k/debug.c | 124 |
1 files changed, 103 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 4ba649e20269..bb581ef6d1ef 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> | 2 | * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com> |
3 | * | 3 | * |
4 | * This file is free software: you may copy, redistribute and/or modify it | 4 | * This file is free software: you may copy, redistribute and/or modify it |
5 | * under the terms of the GNU General Public License as published by the | 5 | * under the terms of the GNU General Public License as published by the |
@@ -200,7 +200,7 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf, | |||
200 | { | 200 | { |
201 | struct ath5k_softc *sc = file->private_data; | 201 | struct ath5k_softc *sc = file->private_data; |
202 | char buf[100]; | 202 | char buf[100]; |
203 | snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); | 203 | snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); |
204 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); | 204 | return simple_read_from_buffer(user_buf, count, ppos, buf, 19); |
205 | } | 205 | } |
206 | 206 | ||
@@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file, | |||
209 | size_t count, loff_t *ppos) | 209 | size_t count, loff_t *ppos) |
210 | { | 210 | { |
211 | struct ath5k_softc *sc = file->private_data; | 211 | struct ath5k_softc *sc = file->private_data; |
212 | if (strncmp(userbuf, "reset", 5) == 0) { | 212 | char buf[20]; |
213 | |||
214 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
215 | return -EFAULT; | ||
216 | |||
217 | if (strncmp(buf, "reset", 5) == 0) { | ||
213 | ath5k_hw_reset_tsf(sc->ah); | 218 | ath5k_hw_reset_tsf(sc->ah); |
214 | printk(KERN_INFO "debugfs reset TSF\n"); | 219 | printk(KERN_INFO "debugfs reset TSF\n"); |
215 | } | 220 | } |
@@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, | |||
231 | { | 236 | { |
232 | struct ath5k_softc *sc = file->private_data; | 237 | struct ath5k_softc *sc = file->private_data; |
233 | struct ath5k_hw *ah = sc->ah; | 238 | struct ath5k_hw *ah = sc->ah; |
234 | char buf[1000]; | 239 | char buf[500]; |
235 | int len = 0; | 240 | unsigned int len = 0; |
236 | unsigned int v; | 241 | unsigned int v; |
237 | u64 tsf; | 242 | u64 tsf; |
238 | 243 | ||
@@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file, | |||
277 | { | 282 | { |
278 | struct ath5k_softc *sc = file->private_data; | 283 | struct ath5k_softc *sc = file->private_data; |
279 | struct ath5k_hw *ah = sc->ah; | 284 | struct ath5k_hw *ah = sc->ah; |
285 | char buf[20]; | ||
286 | |||
287 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
288 | return -EFAULT; | ||
280 | 289 | ||
281 | if (strncmp(userbuf, "disable", 7) == 0) { | 290 | if (strncmp(buf, "disable", 7) == 0) { |
282 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | 291 | AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
283 | printk(KERN_INFO "debugfs disable beacons\n"); | 292 | printk(KERN_INFO "debugfs disable beacons\n"); |
284 | } else if (strncmp(userbuf, "enable", 6) == 0) { | 293 | } else if (strncmp(buf, "enable", 6) == 0) { |
285 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); | 294 | AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); |
286 | printk(KERN_INFO "debugfs enable beacons\n"); | 295 | printk(KERN_INFO "debugfs enable beacons\n"); |
287 | } | 296 | } |
@@ -314,6 +323,82 @@ static const struct file_operations fops_reset = { | |||
314 | }; | 323 | }; |
315 | 324 | ||
316 | 325 | ||
326 | /* debugfs: debug level */ | ||
327 | |||
328 | static struct { | ||
329 | enum ath5k_debug_level level; | ||
330 | const char *name; | ||
331 | const char *desc; | ||
332 | } dbg_info[] = { | ||
333 | { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, | ||
334 | { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, | ||
335 | { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, | ||
336 | { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, | ||
337 | { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, | ||
338 | { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, | ||
339 | { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, | ||
340 | { ATH5K_DEBUG_LED, "led", "LED mamagement" }, | ||
341 | { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, | ||
342 | { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, | ||
343 | { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" }, | ||
344 | { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, | ||
345 | { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, | ||
346 | }; | ||
347 | |||
348 | static ssize_t read_file_debug(struct file *file, char __user *user_buf, | ||
349 | size_t count, loff_t *ppos) | ||
350 | { | ||
351 | struct ath5k_softc *sc = file->private_data; | ||
352 | char buf[700]; | ||
353 | unsigned int len = 0; | ||
354 | unsigned int i; | ||
355 | |||
356 | len += snprintf(buf+len, sizeof(buf)-len, | ||
357 | "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); | ||
358 | |||
359 | for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { | ||
360 | len += snprintf(buf+len, sizeof(buf)-len, | ||
361 | "%10s %c 0x%08x - %s\n", dbg_info[i].name, | ||
362 | sc->debug.level & dbg_info[i].level ? '+' : ' ', | ||
363 | dbg_info[i].level, dbg_info[i].desc); | ||
364 | } | ||
365 | len += snprintf(buf+len, sizeof(buf)-len, | ||
366 | "%10s %c 0x%08x - %s\n", dbg_info[i].name, | ||
367 | sc->debug.level == dbg_info[i].level ? '+' : ' ', | ||
368 | dbg_info[i].level, dbg_info[i].desc); | ||
369 | |||
370 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
371 | } | ||
372 | |||
373 | static ssize_t write_file_debug(struct file *file, | ||
374 | const char __user *userbuf, | ||
375 | size_t count, loff_t *ppos) | ||
376 | { | ||
377 | struct ath5k_softc *sc = file->private_data; | ||
378 | unsigned int i; | ||
379 | char buf[20]; | ||
380 | |||
381 | if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) | ||
382 | return -EFAULT; | ||
383 | |||
384 | for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { | ||
385 | if (strncmp(buf, dbg_info[i].name, | ||
386 | strlen(dbg_info[i].name)) == 0) { | ||
387 | sc->debug.level ^= dbg_info[i].level; /* toggle bit */ | ||
388 | break; | ||
389 | } | ||
390 | } | ||
391 | return count; | ||
392 | } | ||
393 | |||
394 | static const struct file_operations fops_debug = { | ||
395 | .read = read_file_debug, | ||
396 | .write = write_file_debug, | ||
397 | .open = ath5k_debugfs_open, | ||
398 | .owner = THIS_MODULE, | ||
399 | }; | ||
400 | |||
401 | |||
317 | /* init */ | 402 | /* init */ |
318 | 403 | ||
319 | void | 404 | void |
@@ -326,26 +411,24 @@ void | |||
326 | ath5k_debug_init_device(struct ath5k_softc *sc) | 411 | ath5k_debug_init_device(struct ath5k_softc *sc) |
327 | { | 412 | { |
328 | sc->debug.level = ath5k_debug; | 413 | sc->debug.level = ath5k_debug; |
414 | |||
329 | sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), | 415 | sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), |
330 | ath5k_global_debugfs); | 416 | ath5k_global_debugfs); |
331 | sc->debug.debugfs_debug = debugfs_create_u32("debug", | 417 | |
332 | 0666, sc->debug.debugfs_phydir, &sc->debug.level); | 418 | sc->debug.debugfs_debug = debugfs_create_file("debug", 0666, |
419 | sc->debug.debugfs_phydir, sc, &fops_debug); | ||
333 | 420 | ||
334 | sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, | 421 | sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, |
335 | sc->debug.debugfs_phydir, | 422 | sc->debug.debugfs_phydir, sc, &fops_registers); |
336 | sc, &fops_registers); | ||
337 | 423 | ||
338 | sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, | 424 | sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, |
339 | sc->debug.debugfs_phydir, | 425 | sc->debug.debugfs_phydir, sc, &fops_tsf); |
340 | sc, &fops_tsf); | ||
341 | 426 | ||
342 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, | 427 | sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, |
343 | sc->debug.debugfs_phydir, | 428 | sc->debug.debugfs_phydir, sc, &fops_beacon); |
344 | sc, &fops_beacon); | ||
345 | 429 | ||
346 | sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, | 430 | sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, |
347 | sc->debug.debugfs_phydir, | 431 | sc->debug.debugfs_phydir, sc, &fops_reset); |
348 | sc, &fops_reset); | ||
349 | } | 432 | } |
350 | 433 | ||
351 | void | 434 | void |
@@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
415 | struct ath5k_buf *bf; | 498 | struct ath5k_buf *bf; |
416 | int status; | 499 | int status; |
417 | 500 | ||
418 | if (likely(!(sc->debug.level & | 501 | if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) |
419 | (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) | ||
420 | return; | 502 | return; |
421 | 503 | ||
422 | printk(KERN_DEBUG "rx queue %x, link %p\n", | 504 | printk(KERN_DEBUG "rx queue %x, link %p\n", |
@@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) | |||
426 | list_for_each_entry(bf, &sc->rxbuf, list) { | 508 | list_for_each_entry(bf, &sc->rxbuf, list) { |
427 | ds = bf->desc; | 509 | ds = bf->desc; |
428 | status = ah->ah_proc_rx_desc(ah, ds); | 510 | status = ah->ah_proc_rx_desc(ah, ds); |
429 | if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) | 511 | if (!status) |
430 | ath5k_debug_printrxbuf(bf, status == 0); | 512 | ath5k_debug_printrxbuf(bf, status == 0); |
431 | } | 513 | } |
432 | spin_unlock_bh(&sc->rxbuflock); | 514 | spin_unlock_bh(&sc->rxbuflock); |