diff options
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 @@ /* - * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com> + * Copyright (c) 2007-2008 Bruno Randolf <bruno@thinktube.com> * * This file is free software: you may copy, redistribute and/or modify it * 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, { struct ath5k_softc *sc = file->private_data; char buf[100]; - snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); + snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); return simple_read_from_buffer(user_buf, count, ppos, buf, 19); } @@ -209,7 +209,12 @@ static ssize_t write_file_tsf(struct file *file, size_t count, loff_t *ppos) { struct ath5k_softc *sc = file->private_data; - if (strncmp(userbuf, "reset", 5) == 0) { + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + if (strncmp(buf, "reset", 5) == 0) { ath5k_hw_reset_tsf(sc->ah); printk(KERN_INFO "debugfs reset TSF\n"); } @@ -231,8 +236,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; - char buf[1000]; - int len = 0; + char buf[500]; + unsigned int len = 0; unsigned int v; u64 tsf; @@ -277,11 +282,15 @@ static ssize_t write_file_beacon(struct file *file, { struct ath5k_softc *sc = file->private_data; struct ath5k_hw *ah = sc->ah; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; - if (strncmp(userbuf, "disable", 7) == 0) { + if (strncmp(buf, "disable", 7) == 0) { AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs disable beacons\n"); - } else if (strncmp(userbuf, "enable", 6) == 0) { + } else if (strncmp(buf, "enable", 6) == 0) { AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); printk(KERN_INFO "debugfs enable beacons\n"); } @@ -314,6 +323,82 @@ static const struct file_operations fops_reset = { }; +/* debugfs: debug level */ + +static struct { + enum ath5k_debug_level level; + const char *name; + const char *desc; +} dbg_info[] = { + { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, + { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, + { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, + { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, + { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, + { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, + { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, + { ATH5K_DEBUG_LED, "led", "LED mamagement" }, + { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, + { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, + { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" }, + { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, + { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, +}; + +static ssize_t read_file_debug(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + unsigned int i; + + len += snprintf(buf+len, sizeof(buf)-len, + "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); + + for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level & dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + } + len += snprintf(buf+len, sizeof(buf)-len, + "%10s %c 0x%08x - %s\n", dbg_info[i].name, + sc->debug.level == dbg_info[i].level ? '+' : ' ', + dbg_info[i].level, dbg_info[i].desc); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_debug(struct file *file, + const char __user *userbuf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + unsigned int i; + char buf[20]; + + if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) + return -EFAULT; + + for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { + if (strncmp(buf, dbg_info[i].name, + strlen(dbg_info[i].name)) == 0) { + sc->debug.level ^= dbg_info[i].level; /* toggle bit */ + break; + } + } + return count; +} + +static const struct file_operations fops_debug = { + .read = read_file_debug, + .write = write_file_debug, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + + /* init */ void @@ -326,26 +411,24 @@ void ath5k_debug_init_device(struct ath5k_softc *sc) { sc->debug.level = ath5k_debug; + sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); - sc->debug.debugfs_debug = debugfs_create_u32("debug", - 0666, sc->debug.debugfs_phydir, &sc->debug.level); + ath5k_global_debugfs); + + sc->debug.debugfs_debug = debugfs_create_file("debug", 0666, + sc->debug.debugfs_phydir, sc, &fops_debug); sc->debug.debugfs_registers = debugfs_create_file("registers", 0444, - sc->debug.debugfs_phydir, - sc, &fops_registers); + sc->debug.debugfs_phydir, sc, &fops_registers); sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666, - sc->debug.debugfs_phydir, - sc, &fops_tsf); + sc->debug.debugfs_phydir, sc, &fops_tsf); sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666, - sc->debug.debugfs_phydir, - sc, &fops_beacon); + sc->debug.debugfs_phydir, sc, &fops_beacon); sc->debug.debugfs_reset = debugfs_create_file("reset", 0222, - sc->debug.debugfs_phydir, - sc, &fops_reset); + sc->debug.debugfs_phydir, sc, &fops_reset); } void @@ -415,8 +498,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) struct ath5k_buf *bf; int status; - if (likely(!(sc->debug.level & - (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL)))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; printk(KERN_DEBUG "rx queue %x, link %p\n", @@ -426,7 +508,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) list_for_each_entry(bf, &sc->rxbuf, list) { ds = bf->desc; status = ah->ah_proc_rx_desc(ah, ds); - if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL)) + if (!status) ath5k_debug_printrxbuf(bf, status == 0); } spin_unlock_bh(&sc->rxbuflock); |