0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/module.h>
0016 #include <linux/kernel.h>
0017 #include <linux/slab.h>
0018 #include <linux/types.h>
0019 #include <linux/proc_fs.h>
0020 #include <linux/workqueue.h>
0021 #include <linux/pci.h>
0022 #include <linux/pci_hotplug.h>
0023 #include <linux/mutex.h>
0024 #include <linux/debugfs.h>
0025 #include "cpqphp.h"
0026
0027 static DEFINE_MUTEX(cpqphp_mutex);
0028 static int show_ctrl(struct controller *ctrl, char *buf)
0029 {
0030 char *out = buf;
0031 int index;
0032 struct pci_resource *res;
0033
0034 out += sprintf(buf, "Free resources: memory\n");
0035 index = 11;
0036 res = ctrl->mem_head;
0037 while (res && index--) {
0038 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0039 res = res->next;
0040 }
0041 out += sprintf(out, "Free resources: prefetchable memory\n");
0042 index = 11;
0043 res = ctrl->p_mem_head;
0044 while (res && index--) {
0045 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0046 res = res->next;
0047 }
0048 out += sprintf(out, "Free resources: IO\n");
0049 index = 11;
0050 res = ctrl->io_head;
0051 while (res && index--) {
0052 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0053 res = res->next;
0054 }
0055 out += sprintf(out, "Free resources: bus numbers\n");
0056 index = 11;
0057 res = ctrl->bus_head;
0058 while (res && index--) {
0059 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0060 res = res->next;
0061 }
0062
0063 return out - buf;
0064 }
0065
0066 static int show_dev(struct controller *ctrl, char *buf)
0067 {
0068 char *out = buf;
0069 int index;
0070 struct pci_resource *res;
0071 struct pci_func *new_slot;
0072 struct slot *slot;
0073
0074 slot = ctrl->slot;
0075
0076 while (slot) {
0077 new_slot = cpqhp_slot_find(slot->bus, slot->device, 0);
0078 if (!new_slot)
0079 break;
0080 out += sprintf(out, "assigned resources: memory\n");
0081 index = 11;
0082 res = new_slot->mem_head;
0083 while (res && index--) {
0084 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0085 res = res->next;
0086 }
0087 out += sprintf(out, "assigned resources: prefetchable memory\n");
0088 index = 11;
0089 res = new_slot->p_mem_head;
0090 while (res && index--) {
0091 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0092 res = res->next;
0093 }
0094 out += sprintf(out, "assigned resources: IO\n");
0095 index = 11;
0096 res = new_slot->io_head;
0097 while (res && index--) {
0098 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0099 res = res->next;
0100 }
0101 out += sprintf(out, "assigned resources: bus numbers\n");
0102 index = 11;
0103 res = new_slot->bus_head;
0104 while (res && index--) {
0105 out += sprintf(out, "start = %8.8x, length = %8.8x\n", res->base, res->length);
0106 res = res->next;
0107 }
0108 slot = slot->next;
0109 }
0110
0111 return out - buf;
0112 }
0113
0114 static int spew_debug_info(struct controller *ctrl, char *data, int size)
0115 {
0116 int used;
0117
0118 used = size - show_ctrl(ctrl, data);
0119 used = (size - used) - show_dev(ctrl, &data[used]);
0120 return used;
0121 }
0122
0123 struct ctrl_dbg {
0124 int size;
0125 char *data;
0126 struct controller *ctrl;
0127 };
0128
0129 #define MAX_OUTPUT (4*PAGE_SIZE)
0130
0131 static int open(struct inode *inode, struct file *file)
0132 {
0133 struct controller *ctrl = inode->i_private;
0134 struct ctrl_dbg *dbg;
0135 int retval = -ENOMEM;
0136
0137 mutex_lock(&cpqphp_mutex);
0138 dbg = kmalloc(sizeof(*dbg), GFP_KERNEL);
0139 if (!dbg)
0140 goto exit;
0141 dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL);
0142 if (!dbg->data) {
0143 kfree(dbg);
0144 goto exit;
0145 }
0146 dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT);
0147 file->private_data = dbg;
0148 retval = 0;
0149 exit:
0150 mutex_unlock(&cpqphp_mutex);
0151 return retval;
0152 }
0153
0154 static loff_t lseek(struct file *file, loff_t off, int whence)
0155 {
0156 struct ctrl_dbg *dbg = file->private_data;
0157 return fixed_size_llseek(file, off, whence, dbg->size);
0158 }
0159
0160 static ssize_t read(struct file *file, char __user *buf,
0161 size_t nbytes, loff_t *ppos)
0162 {
0163 struct ctrl_dbg *dbg = file->private_data;
0164 return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size);
0165 }
0166
0167 static int release(struct inode *inode, struct file *file)
0168 {
0169 struct ctrl_dbg *dbg = file->private_data;
0170
0171 kfree(dbg->data);
0172 kfree(dbg);
0173 return 0;
0174 }
0175
0176 static const struct file_operations debug_ops = {
0177 .owner = THIS_MODULE,
0178 .open = open,
0179 .llseek = lseek,
0180 .read = read,
0181 .release = release,
0182 };
0183
0184 static struct dentry *root;
0185
0186 void cpqhp_initialize_debugfs(void)
0187 {
0188 if (!root)
0189 root = debugfs_create_dir("cpqhp", NULL);
0190 }
0191
0192 void cpqhp_shutdown_debugfs(void)
0193 {
0194 debugfs_remove(root);
0195 }
0196
0197 void cpqhp_create_debugfs_files(struct controller *ctrl)
0198 {
0199 ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev),
0200 S_IRUGO, root, ctrl, &debug_ops);
0201 }
0202
0203 void cpqhp_remove_debugfs_files(struct controller *ctrl)
0204 {
0205 debugfs_remove(ctrl->dentry);
0206 ctrl->dentry = NULL;
0207 }
0208