diff options
Diffstat (limited to 'drivers/pci/hotplug/cpqphp_sysfs.c')
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 138 |
1 files changed, 116 insertions, 22 deletions
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 4c11048..bbfeed7 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -33,22 +33,15 @@ #include <linux/proc_fs.h> #include <linux/workqueue.h> #include <linux/pci.h> +#include <linux/debugfs.h> #include "cpqphp.h" - -/* A few routines that create sysfs entries for the hot plug controller */ - -static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf) +static int show_ctrl (struct controller *ctrl, char *buf) { - struct pci_dev *pci_dev; - struct controller *ctrl; - char * out = buf; + char *out = buf; int index; struct pci_resource *res; - pci_dev = container_of (dev, struct pci_dev, dev); - ctrl = pci_get_drvdata(pci_dev); - out += sprintf(buf, "Free resources: memory\n"); index = 11; res = ctrl->mem_head; @@ -80,22 +73,16 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha return out - buf; } -static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); -static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf) +static int show_dev (struct controller *ctrl, char *buf) { - struct pci_dev *pci_dev; - struct controller *ctrl; char * out = buf; int index; struct pci_resource *res; struct pci_func *new_slot; struct slot *slot; - pci_dev = container_of (dev, struct pci_dev, dev); - ctrl = pci_get_drvdata(pci_dev); - - slot=ctrl->slot; + slot = ctrl->slot; while (slot) { new_slot = cpqhp_slot_find(slot->bus, slot->device, 0); @@ -134,10 +121,117 @@ static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char return out - buf; } -static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL); -void cpqhp_create_ctrl_files (struct controller *ctrl) +static int spew_debug_info(struct controller *ctrl, char *data, int size) { - device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); - device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev); + int used; + + used = size - show_ctrl(ctrl, data); + used = (size - used) - show_dev(ctrl, &data[used]); + return used; +} + +struct ctrl_dbg { + int size; + char *data; + struct controller *ctrl; +}; + +#define MAX_OUTPUT (4*PAGE_SIZE) + +static int open(struct inode *inode, struct file *file) +{ + struct controller *ctrl = inode->u.generic_ip; + struct ctrl_dbg *dbg; + int retval = -ENOMEM; + + lock_kernel(); + dbg = kmalloc(sizeof(*dbg), GFP_KERNEL); + if (!dbg) + goto exit; + dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); + if (!dbg->data) { + kfree(dbg); + goto exit; + } + dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT); + file->private_data = dbg; + retval = 0; +exit: + unlock_kernel(); + return retval; +} + +static loff_t lseek(struct file *file, loff_t off, int whence) +{ + struct ctrl_dbg *dbg; + loff_t new = -1; + + lock_kernel(); + dbg = file->private_data; + + switch (whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + } + if (new < 0 || new > dbg->size) { + unlock_kernel(); + return -EINVAL; + } + unlock_kernel(); + return (file->f_pos = new); } + +static ssize_t read(struct file *file, char __user *buf, + size_t nbytes, loff_t *ppos) +{ + struct ctrl_dbg *dbg = file->private_data; + return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size); +} + +static int release(struct inode *inode, struct file *file) +{ + struct ctrl_dbg *dbg = file->private_data; + + kfree(dbg->data); + kfree(dbg); + return 0; +} + +static struct file_operations debug_ops = { + .owner = THIS_MODULE, + .open = open, + .llseek = lseek, + .read = read, + .release = release, +}; + +static struct dentry *root; + +void cpqhp_initialize_debugfs(void) +{ + if (!root) + root = debugfs_create_dir("cpqhp", NULL); +} + +void cpqhp_shutdown_debugfs(void) +{ + debugfs_remove(root); +} + +void cpqhp_create_debugfs_files(struct controller *ctrl) +{ + ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops); +} + +void cpqhp_remove_debugfs_files(struct controller *ctrl) +{ + if (ctrl->dentry) + debugfs_remove(ctrl->dentry); + ctrl->dentry = NULL; +} + |