Merge branch 'master' into for_paulus
[linux-drm-fsl-dcu.git] / drivers / pci / hotplug / cpqphp_sysfs.c
index 4c11048ad51b432f41bc7c965b8666debf4144b2..a13abf55d7844adba846c7c99c2e23d376e05fec 100644 (file)
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/workqueue.h>
 #include <linux/pci.h>
+#include <linux/pci_hotplug.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->i_private;
+       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 const 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;
+}
+