[PATCH] PCI Hotplug: fix up the sysfs file in the compaq pci hotplug driver
Greg Kroah-Hartman [Wed, 14 Dec 2005 17:37:26 +0000 (09:37 -0800)]
The Compaq PCI Hotplug driver was creating 2 sysfs files that contained
nothing but debug information, and had way more than "one value" in
them.  This patch converts the code to use debugfs for these files
instead.

Compile tested only.

Cc: Kay Sievers <kay.sievers@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

drivers/pci/hotplug/cpqphp.h
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_sysfs.c

index 092491e..cb88404 100644 (file)
@@ -317,6 +317,7 @@ struct controller {
        u16 vendor_id;
        struct work_struct int_task_event;
        wait_queue_head_t queue;        /* sleep & wake process */
+       struct dentry *dentry;          /* debugfs dentry */
 };
 
 struct irq_mapping {
@@ -399,8 +400,11 @@ struct resource_lists {
 #define msg_button_ignore      "PCI slot #%d - button press ignored.  (action in progress...)\n"
 
 
-/* sysfs functions for the hotplug controller info */
-extern void cpqhp_create_ctrl_files            (struct controller *ctrl);
+/* debugfs functions for the hotplug controller info */
+extern void cpqhp_initialize_debugfs           (void);
+extern void cpqhp_shutdown_debugfs             (void);
+extern void cpqhp_create_debugfs_files         (struct controller *ctrl);
+extern void cpqhp_remove_debugfs_files         (struct controller *ctrl);
 
 /* controller functions */
 extern void    cpqhp_pushbutton_thread         (unsigned long event_pointer);
index d364470..b3659ff 100644 (file)
@@ -479,6 +479,8 @@ static int ctrl_slot_cleanup (struct controller * ctrl)
                old_slot = next_slot;
        }
 
+       cpqhp_remove_debugfs_files(ctrl);
+
        //Free IRQ associated with hot plug device
        free_irq(ctrl->interrupt, ctrl);
        //Unmap the memory
@@ -1275,7 +1277,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        // Done with exclusive hardware access
        up(&ctrl->crit_sect);
 
-       cpqhp_create_ctrl_files(ctrl);
+       cpqhp_create_debugfs_files(ctrl);
 
        return 0;
 
@@ -1515,6 +1517,7 @@ static int __init cpqhpc_init(void)
        cpqhp_debug = debug;
 
        info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+       cpqhp_initialize_debugfs();
        result = pci_register_driver(&cpqhpc_driver);
        dbg("pci_register_driver = %d\n", result);
        return result;
@@ -1528,6 +1531,7 @@ static void __exit cpqhpc_cleanup(void)
 
        dbg("pci_unregister_driver\n");
        pci_unregister_driver(&cpqhpc_driver);
+       cpqhp_shutdown_debugfs();
 }
 
 
index 4c11048..bbfeed7 100644 (file)
 #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;
+}
+