diff options
-rw-r--r-- | drivers/pci/hotplug/cpqphp.h | 8 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_core.c | 6 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_sysfs.c | 138 |
3 files changed, 127 insertions, 25 deletions
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 092491e25ef2..cb88404c89fe 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h | |||
@@ -317,6 +317,7 @@ struct controller { | |||
317 | u16 vendor_id; | 317 | u16 vendor_id; |
318 | struct work_struct int_task_event; | 318 | struct work_struct int_task_event; |
319 | wait_queue_head_t queue; /* sleep & wake process */ | 319 | wait_queue_head_t queue; /* sleep & wake process */ |
320 | struct dentry *dentry; /* debugfs dentry */ | ||
320 | }; | 321 | }; |
321 | 322 | ||
322 | struct irq_mapping { | 323 | struct irq_mapping { |
@@ -399,8 +400,11 @@ struct resource_lists { | |||
399 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" | 400 | #define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" |
400 | 401 | ||
401 | 402 | ||
402 | /* sysfs functions for the hotplug controller info */ | 403 | /* debugfs functions for the hotplug controller info */ |
403 | extern void cpqhp_create_ctrl_files (struct controller *ctrl); | 404 | extern void cpqhp_initialize_debugfs (void); |
405 | extern void cpqhp_shutdown_debugfs (void); | ||
406 | extern void cpqhp_create_debugfs_files (struct controller *ctrl); | ||
407 | extern void cpqhp_remove_debugfs_files (struct controller *ctrl); | ||
404 | 408 | ||
405 | /* controller functions */ | 409 | /* controller functions */ |
406 | extern void cpqhp_pushbutton_thread (unsigned long event_pointer); | 410 | extern void cpqhp_pushbutton_thread (unsigned long event_pointer); |
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index d3644709a035..b3659ffccac9 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c | |||
@@ -479,6 +479,8 @@ static int ctrl_slot_cleanup (struct controller * ctrl) | |||
479 | old_slot = next_slot; | 479 | old_slot = next_slot; |
480 | } | 480 | } |
481 | 481 | ||
482 | cpqhp_remove_debugfs_files(ctrl); | ||
483 | |||
482 | //Free IRQ associated with hot plug device | 484 | //Free IRQ associated with hot plug device |
483 | free_irq(ctrl->interrupt, ctrl); | 485 | free_irq(ctrl->interrupt, ctrl); |
484 | //Unmap the memory | 486 | //Unmap the memory |
@@ -1275,7 +1277,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1275 | // Done with exclusive hardware access | 1277 | // Done with exclusive hardware access |
1276 | up(&ctrl->crit_sect); | 1278 | up(&ctrl->crit_sect); |
1277 | 1279 | ||
1278 | cpqhp_create_ctrl_files(ctrl); | 1280 | cpqhp_create_debugfs_files(ctrl); |
1279 | 1281 | ||
1280 | return 0; | 1282 | return 0; |
1281 | 1283 | ||
@@ -1515,6 +1517,7 @@ static int __init cpqhpc_init(void) | |||
1515 | cpqhp_debug = debug; | 1517 | cpqhp_debug = debug; |
1516 | 1518 | ||
1517 | info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 1519 | info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
1520 | cpqhp_initialize_debugfs(); | ||
1518 | result = pci_register_driver(&cpqhpc_driver); | 1521 | result = pci_register_driver(&cpqhpc_driver); |
1519 | dbg("pci_register_driver = %d\n", result); | 1522 | dbg("pci_register_driver = %d\n", result); |
1520 | return result; | 1523 | return result; |
@@ -1528,6 +1531,7 @@ static void __exit cpqhpc_cleanup(void) | |||
1528 | 1531 | ||
1529 | dbg("pci_unregister_driver\n"); | 1532 | dbg("pci_unregister_driver\n"); |
1530 | pci_unregister_driver(&cpqhpc_driver); | 1533 | pci_unregister_driver(&cpqhpc_driver); |
1534 | cpqhp_shutdown_debugfs(); | ||
1531 | } | 1535 | } |
1532 | 1536 | ||
1533 | 1537 | ||
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 | |||