📄 debugfs.c
字号:
fappend("\nUsed Baseband attenuation values:\n"); for (i = 0; i < lo->bbatt_list.len; i++) { fappend("%u, ", lo->bbatt_list.list[i].att); } fappend("\n");out: return err ? err : count;}#undef fappendstatic int b43_debugfs_open(struct inode *inode, struct file *file){ file->private_data = inode->i_private; return 0;}static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, size_t count, loff_t *ppos){ struct b43_wldev *dev; struct b43_debugfs_fops *dfops; struct b43_dfs_file *dfile; ssize_t ret; char *buf; const size_t bufsize = 1024 * 128; const size_t buforder = get_order(bufsize); int err = 0; if (!count) return 0; dev = file->private_data; if (!dev) return -ENODEV; mutex_lock(&dev->wl->mutex); if (b43_status(dev) < B43_STAT_INITIALIZED) { err = -ENODEV; goto out_unlock; } dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); if (!dfops->read) { err = -ENOSYS; goto out_unlock; } dfile = fops_to_dfs_file(dev, dfops); if (!dfile->buffer) { buf = (char *)__get_free_pages(GFP_KERNEL, buforder); if (!buf) { err = -ENOMEM; goto out_unlock; } /* Sparse warns about the following memset, because it has a big * size value. That warning is bogus, so I will ignore it. --mb */ memset(buf, 0, bufsize); if (dfops->take_irqlock) { spin_lock_irq(&dev->wl->irq_lock); ret = dfops->read(dev, buf, bufsize); spin_unlock_irq(&dev->wl->irq_lock); } else ret = dfops->read(dev, buf, bufsize); if (ret <= 0) { free_pages((unsigned long)buf, buforder); err = ret; goto out_unlock; } dfile->data_len = ret; dfile->buffer = buf; } ret = simple_read_from_buffer(userbuf, count, ppos, dfile->buffer, dfile->data_len); if (*ppos >= dfile->data_len) { free_pages((unsigned long)dfile->buffer, buforder); dfile->buffer = NULL; dfile->data_len = 0; }out_unlock: mutex_unlock(&dev->wl->mutex); return err ? err : ret;}static ssize_t b43_debugfs_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos){ struct b43_wldev *dev; struct b43_debugfs_fops *dfops; char *buf; int err = 0; if (!count) return 0; if (count > PAGE_SIZE) return -E2BIG; dev = file->private_data; if (!dev) return -ENODEV; mutex_lock(&dev->wl->mutex); if (b43_status(dev) < B43_STAT_INITIALIZED) { err = -ENODEV; goto out_unlock; } dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); if (!dfops->write) { err = -ENOSYS; goto out_unlock; } buf = (char *)get_zeroed_page(GFP_KERNEL); if (!buf) { err = -ENOMEM; goto out_unlock; } if (copy_from_user(buf, userbuf, count)) { err = -EFAULT; goto out_freepage; } if (dfops->take_irqlock) { spin_lock_irq(&dev->wl->irq_lock); err = dfops->write(dev, buf, count); spin_unlock_irq(&dev->wl->irq_lock); } else err = dfops->write(dev, buf, count); if (err) goto out_freepage;out_freepage: free_page((unsigned long)buf);out_unlock: mutex_unlock(&dev->wl->mutex); return err ? err : count;}#define B43_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \ static struct b43_debugfs_fops fops_##name = { \ .read = _read, \ .write = _write, \ .fops = { \ .open = b43_debugfs_open, \ .read = b43_debugfs_read, \ .write = b43_debugfs_write, \ }, \ .file_struct_offset = offsetof(struct b43_dfsentry, \ file_##name), \ .take_irqlock = _take_irqlock, \ }B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1);B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1);B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL, 0);int b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature){ return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]);}static void b43_remove_dynamic_debug(struct b43_wldev *dev){ struct b43_dfsentry *e = dev->dfsentry; int i; for (i = 0; i < __B43_NR_DYNDBG; i++) debugfs_remove(e->dyn_debug_dentries[i]);}static void b43_add_dynamic_debug(struct b43_wldev *dev){ struct b43_dfsentry *e = dev->dfsentry; struct dentry *d;#define add_dyn_dbg(name, id, initstate) do { \ e->dyn_debug[id] = (initstate); \ d = debugfs_create_bool(name, 0600, e->subdir, \ &(e->dyn_debug[id])); \ if (!IS_ERR(d)) \ e->dyn_debug_dentries[id] = d; \ } while (0) add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, 0); add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, 0); add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);#undef add_dyn_dbg}void b43_debugfs_add_device(struct b43_wldev *dev){ struct b43_dfsentry *e; struct b43_txstatus_log *log; char devdir[16]; B43_WARN_ON(!dev); e = kzalloc(sizeof(*e), GFP_KERNEL); if (!e) { b43err(dev->wl, "debugfs: add device OOM\n"); return; } e->dev = dev; log = &e->txstatlog; log->log = kcalloc(B43_NR_LOGGED_TXSTATUS, sizeof(struct b43_txstatus), GFP_KERNEL); if (!log->log) { b43err(dev->wl, "debugfs: add device txstatus OOM\n"); kfree(e); return; } log->end = -1; spin_lock_init(&log->lock); dev->dfsentry = e; snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy)); e->subdir = debugfs_create_dir(devdir, rootdir); if (!e->subdir || IS_ERR(e->subdir)) { if (e->subdir == ERR_PTR(-ENODEV)) { b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not " "enabled in kernel config\n"); } else { b43err(dev->wl, "debugfs: cannot create %s directory\n", devdir); } dev->dfsentry = NULL; kfree(log->log); kfree(e); return; }#define ADD_FILE(name, mode) \ do { \ struct dentry *d; \ d = debugfs_create_file(__stringify(name), \ mode, e->subdir, dev, \ &fops_##name.fops); \ e->file_##name.dentry = NULL; \ if (!IS_ERR(d)) \ e->file_##name.dentry = d; \ } while (0) ADD_FILE(tsf, 0600); ADD_FILE(ucode_regs, 0400); ADD_FILE(shm, 0400); ADD_FILE(txstat, 0400); ADD_FILE(txpower_g, 0600); ADD_FILE(restart, 0200); ADD_FILE(loctls, 0400);#undef ADD_FILE b43_add_dynamic_debug(dev);}void b43_debugfs_remove_device(struct b43_wldev *dev){ struct b43_dfsentry *e; if (!dev) return; e = dev->dfsentry; if (!e) return; b43_remove_dynamic_debug(dev); debugfs_remove(e->file_tsf.dentry); debugfs_remove(e->file_ucode_regs.dentry); debugfs_remove(e->file_shm.dentry); debugfs_remove(e->file_txstat.dentry); debugfs_remove(e->file_txpower_g.dentry); debugfs_remove(e->file_restart.dentry); debugfs_remove(e->file_loctls.dentry); debugfs_remove(e->subdir); kfree(e->txstatlog.log); kfree(e);}void b43_debugfs_log_txstat(struct b43_wldev *dev, const struct b43_txstatus *status){ struct b43_dfsentry *e = dev->dfsentry; struct b43_txstatus_log *log; struct b43_txstatus *cur; int i; if (!e) return; log = &e->txstatlog; B43_WARN_ON(!irqs_disabled()); spin_lock(&log->lock); i = log->end + 1; if (i == B43_NR_LOGGED_TXSTATUS) i = 0; log->end = i; cur = &(log->log[i]); memcpy(cur, status, sizeof(*cur)); spin_unlock(&log->lock);}void b43_debugfs_init(void){ rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); if (IS_ERR(rootdir)) rootdir = NULL;}void b43_debugfs_exit(void){ debugfs_remove(rootdir);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -