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 4c11048ad51b..bbfeed767ff1 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c | |||
@@ -33,22 +33,15 @@ | |||
33 | #include <linux/proc_fs.h> | 33 | #include <linux/proc_fs.h> |
34 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/debugfs.h> | ||
36 | #include "cpqphp.h" | 37 | #include "cpqphp.h" |
37 | 38 | ||
38 | 39 | static int show_ctrl (struct controller *ctrl, char *buf) | |
39 | /* A few routines that create sysfs entries for the hot plug controller */ | ||
40 | |||
41 | static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf) | ||
42 | { | 40 | { |
43 | struct pci_dev *pci_dev; | 41 | char *out = buf; |
44 | struct controller *ctrl; | ||
45 | char * out = buf; | ||
46 | int index; | 42 | int index; |
47 | struct pci_resource *res; | 43 | struct pci_resource *res; |
48 | 44 | ||
49 | pci_dev = container_of (dev, struct pci_dev, dev); | ||
50 | ctrl = pci_get_drvdata(pci_dev); | ||
51 | |||
52 | out += sprintf(buf, "Free resources: memory\n"); | 45 | out += sprintf(buf, "Free resources: memory\n"); |
53 | index = 11; | 46 | index = 11; |
54 | res = ctrl->mem_head; | 47 | res = ctrl->mem_head; |
@@ -80,22 +73,16 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha | |||
80 | 73 | ||
81 | return out - buf; | 74 | return out - buf; |
82 | } | 75 | } |
83 | static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); | ||
84 | 76 | ||
85 | static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf) | 77 | static int show_dev (struct controller *ctrl, char *buf) |
86 | { | 78 | { |
87 | struct pci_dev *pci_dev; | ||
88 | struct controller *ctrl; | ||
89 | char * out = buf; | 79 | char * out = buf; |
90 | int index; | 80 | int index; |
91 | struct pci_resource *res; | 81 | struct pci_resource *res; |
92 | struct pci_func *new_slot; | 82 | struct pci_func *new_slot; |
93 | struct slot *slot; | 83 | struct slot *slot; |
94 | 84 | ||
95 | pci_dev = container_of (dev, struct pci_dev, dev); | 85 | slot = ctrl->slot; |
96 | ctrl = pci_get_drvdata(pci_dev); | ||
97 | |||
98 | slot=ctrl->slot; | ||
99 | 86 | ||
100 | while (slot) { | 87 | while (slot) { |
101 | new_slot = cpqhp_slot_find(slot->bus, slot->device, 0); | 88 | 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 | |||
134 | 121 | ||
135 | return out - buf; | 122 | return out - buf; |
136 | } | 123 | } |
137 | static DEVICE_ATTR (dev, S_IRUGO, show_dev, NULL); | ||
138 | 124 | ||
139 | void cpqhp_create_ctrl_files (struct controller *ctrl) | 125 | static int spew_debug_info(struct controller *ctrl, char *data, int size) |
140 | { | 126 | { |
141 | device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); | 127 | int used; |
142 | device_create_file (&ctrl->pci_dev->dev, &dev_attr_dev); | 128 | |
129 | used = size - show_ctrl(ctrl, data); | ||
130 | used = (size - used) - show_dev(ctrl, &data[used]); | ||
131 | return used; | ||
132 | } | ||
133 | |||
134 | struct ctrl_dbg { | ||
135 | int size; | ||
136 | char *data; | ||
137 | struct controller *ctrl; | ||
138 | }; | ||
139 | |||
140 | #define MAX_OUTPUT (4*PAGE_SIZE) | ||
141 | |||
142 | static int open(struct inode *inode, struct file *file) | ||
143 | { | ||
144 | struct controller *ctrl = inode->u.generic_ip; | ||
145 | struct ctrl_dbg *dbg; | ||
146 | int retval = -ENOMEM; | ||
147 | |||
148 | lock_kernel(); | ||
149 | dbg = kmalloc(sizeof(*dbg), GFP_KERNEL); | ||
150 | if (!dbg) | ||
151 | goto exit; | ||
152 | dbg->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); | ||
153 | if (!dbg->data) { | ||
154 | kfree(dbg); | ||
155 | goto exit; | ||
156 | } | ||
157 | dbg->size = spew_debug_info(ctrl, dbg->data, MAX_OUTPUT); | ||
158 | file->private_data = dbg; | ||
159 | retval = 0; | ||
160 | exit: | ||
161 | unlock_kernel(); | ||
162 | return retval; | ||
163 | } | ||
164 | |||
165 | static loff_t lseek(struct file *file, loff_t off, int whence) | ||
166 | { | ||
167 | struct ctrl_dbg *dbg; | ||
168 | loff_t new = -1; | ||
169 | |||
170 | lock_kernel(); | ||
171 | dbg = file->private_data; | ||
172 | |||
173 | switch (whence) { | ||
174 | case 0: | ||
175 | new = off; | ||
176 | break; | ||
177 | case 1: | ||
178 | new = file->f_pos + off; | ||
179 | break; | ||
180 | } | ||
181 | if (new < 0 || new > dbg->size) { | ||
182 | unlock_kernel(); | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | unlock_kernel(); | ||
186 | return (file->f_pos = new); | ||
143 | } | 187 | } |
188 | |||
189 | static ssize_t read(struct file *file, char __user *buf, | ||
190 | size_t nbytes, loff_t *ppos) | ||
191 | { | ||
192 | struct ctrl_dbg *dbg = file->private_data; | ||
193 | return simple_read_from_buffer(buf, nbytes, ppos, dbg->data, dbg->size); | ||
194 | } | ||
195 | |||
196 | static int release(struct inode *inode, struct file *file) | ||
197 | { | ||
198 | struct ctrl_dbg *dbg = file->private_data; | ||
199 | |||
200 | kfree(dbg->data); | ||
201 | kfree(dbg); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static struct file_operations debug_ops = { | ||
206 | .owner = THIS_MODULE, | ||
207 | .open = open, | ||
208 | .llseek = lseek, | ||
209 | .read = read, | ||
210 | .release = release, | ||
211 | }; | ||
212 | |||
213 | static struct dentry *root; | ||
214 | |||
215 | void cpqhp_initialize_debugfs(void) | ||
216 | { | ||
217 | if (!root) | ||
218 | root = debugfs_create_dir("cpqhp", NULL); | ||
219 | } | ||
220 | |||
221 | void cpqhp_shutdown_debugfs(void) | ||
222 | { | ||
223 | debugfs_remove(root); | ||
224 | } | ||
225 | |||
226 | void cpqhp_create_debugfs_files(struct controller *ctrl) | ||
227 | { | ||
228 | ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops); | ||
229 | } | ||
230 | |||
231 | void cpqhp_remove_debugfs_files(struct controller *ctrl) | ||
232 | { | ||
233 | if (ctrl->dentry) | ||
234 | debugfs_remove(ctrl->dentry); | ||
235 | ctrl->dentry = NULL; | ||
236 | } | ||
237 | |||