1 /*
2 * PCI HotPlug Controller Core
3 *
4 * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com)
5 * Copyright (C) 2001-2002 IBM Corp.
6 *
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or (at
12 * your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
17 * NON INFRINGEMENT. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 * Send feedback to <greg@kroah.com>
25 *
26 * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs
27 *
28 */
29
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/kernel.h>
33 #include <linux/types.h>
34 #include <linux/list.h>
35 #include <linux/pagemap.h>
36 #include <linux/slab.h>
37 #include <linux/smp_lock.h>
38 #include <linux/init.h>
39 #include <linux/pci.h>
40 #include <linux/dnotify.h>
41 #include <linux/proc_fs.h>
42 #include <asm/uaccess.h>
43 #include "pci_hotplug.h"
44
45
46 #if !defined(CONFIG_HOTPLUG_PCI_MODULE)
47 #define MY_NAME "pci_hotplug"
48 #else
49 #define MY_NAME THIS_MODULE->name
50 #endif
51
52 #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __FUNCTION__ , ## arg); } while (0)
53 #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
54 #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
55 #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
56
57
58 /* local variables */
59 static int debug;
60
61 #define DRIVER_VERSION "0.5"
62 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
63 #define DRIVER_DESC "PCI Hot Plug PCI Core"
64
65
66 //////////////////////////////////////////////////////////////////
67
68 /* Random magic number */
69 #define PCIHPFS_MAGIC 0x52454541
70
71 struct hotplug_slot_core {
72 struct dentry *dir_dentry;
73 struct dentry *power_dentry;
74 struct dentry *attention_dentry;
75 struct dentry *latch_dentry;
76 struct dentry *adapter_dentry;
77 struct dentry *address_dentry;
78 struct dentry *test_dentry;
79 struct dentry *max_bus_speed_dentry;
80 struct dentry *cur_bus_speed_dentry;
81 };
82
83 static struct super_operations pcihpfs_ops;
84 static struct file_operations default_file_operations;
85 static struct inode_operations pcihpfs_dir_inode_operations;
86 static struct vfsmount *pcihpfs_mount; /* one of the mounts of our fs for reference counting */
87 static int pcihpfs_mount_count; /* times we have mounted our fs */
88 static spinlock_t mount_lock; /* protects our mount_count */
89 static spinlock_t list_lock;
90
91 LIST_HEAD(pci_hotplug_slot_list);
92
93 /* these strings match up with the values in pci_bus_speed */
94 static char *pci_bus_speed_strings[] = {
95 "33 MHz PCI", /* 0x00 */
96 "66 MHz PCI", /* 0x01 */
97 "66 MHz PCIX", /* 0x02 */
98 "100 MHz PCIX", /* 0x03 */
99 "133 MHz PCIX", /* 0x04 */
100 NULL, /* 0x05 */
101 NULL, /* 0x06 */
102 NULL, /* 0x07 */
103 NULL, /* 0x08 */
104 "66 MHz PCIX 266", /* 0x09 */
105 "100 MHz PCIX 266", /* 0x0a */
106 "133 MHz PCIX 266", /* 0x0b */
107 NULL, /* 0x0c */
108 NULL, /* 0x0d */
109 NULL, /* 0x0e */
110 NULL, /* 0x0f */
111 NULL, /* 0x10 */
112 "66 MHz PCIX 533", /* 0x11 */
113 "100 MHz PCIX 533", /* 0x12 */
114 "133 MHz PCIX 533", /* 0x13 */
115 "25 GBps PCI-E", /* 0x14 */
116 };
117
pcihpfs_statfs(struct super_block * sb,struct statfs * buf)118 static int pcihpfs_statfs (struct super_block *sb, struct statfs *buf)
119 {
120 buf->f_type = PCIHPFS_MAGIC;
121 buf->f_bsize = PAGE_CACHE_SIZE;
122 buf->f_namelen = 255;
123 return 0;
124 }
125
pcihpfs_lookup(struct inode * dir,struct dentry * dentry)126 static struct dentry *pcihpfs_lookup (struct inode *dir, struct dentry *dentry)
127 {
128 d_add(dentry, NULL);
129 return NULL;
130 }
131
132 #ifdef CONFIG_PROC_FS
133 extern struct proc_dir_entry *proc_bus_pci_dir;
134 static struct proc_dir_entry *slotdir = NULL;
135 static const char *slotdir_name = "slots";
136 #endif
137
pcihpfs_get_inode(struct super_block * sb,int mode,int dev)138 static struct inode *pcihpfs_get_inode (struct super_block *sb, int mode, int dev)
139 {
140 struct inode *inode = new_inode(sb);
141
142 if (inode) {
143 inode->i_mode = mode;
144 inode->i_uid = current->fsuid;
145 inode->i_gid = current->fsgid;
146 inode->i_blksize = PAGE_CACHE_SIZE;
147 inode->i_blocks = 0;
148 inode->i_rdev = NODEV;
149 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
150 switch (mode & S_IFMT) {
151 default:
152 init_special_inode(inode, mode, dev);
153 break;
154 case S_IFREG:
155 inode->i_fop = &default_file_operations;
156 break;
157 case S_IFDIR:
158 inode->i_op = &pcihpfs_dir_inode_operations;
159 inode->i_fop = &dcache_dir_ops;
160 break;
161 }
162 }
163 return inode;
164 }
165
pcihpfs_mknod(struct inode * dir,struct dentry * dentry,int mode,int dev)166 static int pcihpfs_mknod (struct inode *dir, struct dentry *dentry, int mode, int dev)
167 {
168 struct inode *inode = pcihpfs_get_inode(dir->i_sb, mode, dev);
169 int error = -ENOSPC;
170
171 if (inode) {
172 d_instantiate(dentry, inode);
173 dget(dentry);
174 error = 0;
175 }
176 return error;
177 }
178
pcihpfs_mkdir(struct inode * dir,struct dentry * dentry,int mode)179 static int pcihpfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
180 {
181 return pcihpfs_mknod (dir, dentry, mode | S_IFDIR, 0);
182 }
183
pcihpfs_create(struct inode * dir,struct dentry * dentry,int mode)184 static int pcihpfs_create (struct inode *dir, struct dentry *dentry, int mode)
185 {
186 return pcihpfs_mknod (dir, dentry, mode | S_IFREG, 0);
187 }
188
pcihpfs_positive(struct dentry * dentry)189 static inline int pcihpfs_positive (struct dentry *dentry)
190 {
191 return dentry->d_inode && !d_unhashed(dentry);
192 }
193
pcihpfs_empty(struct dentry * dentry)194 static int pcihpfs_empty (struct dentry *dentry)
195 {
196 struct list_head *list;
197
198 spin_lock(&dcache_lock);
199
200 list_for_each(list, &dentry->d_subdirs) {
201 struct dentry *de = list_entry(list, struct dentry, d_child);
202 if (pcihpfs_positive(de)) {
203 spin_unlock(&dcache_lock);
204 return 0;
205 }
206 }
207
208 spin_unlock(&dcache_lock);
209 return 1;
210 }
211
pcihpfs_unlink(struct inode * dir,struct dentry * dentry)212 static int pcihpfs_unlink (struct inode *dir, struct dentry *dentry)
213 {
214 int error = -ENOTEMPTY;
215
216 if (pcihpfs_empty(dentry)) {
217 struct inode *inode = dentry->d_inode;
218
219 inode->i_nlink--;
220 dput(dentry);
221 error = 0;
222 }
223 return error;
224 }
225
226 #define pcihpfs_rmdir pcihpfs_unlink
227
228 /* default file operations */
default_read_file(struct file * file,char * buf,size_t count,loff_t * ppos)229 static ssize_t default_read_file (struct file *file, char *buf, size_t count, loff_t *ppos)
230 {
231 dbg ("\n");
232 return 0;
233 }
234
default_write_file(struct file * file,const char * buf,size_t count,loff_t * ppos)235 static ssize_t default_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos)
236 {
237 dbg ("\n");
238 return count;
239 }
240
default_file_lseek(struct file * file,loff_t offset,int orig)241 static loff_t default_file_lseek (struct file *file, loff_t offset, int orig)
242 {
243 loff_t retval = -EINVAL;
244
245 switch(orig) {
246 case 0:
247 if (offset > 0) {
248 file->f_pos = offset;
249 retval = file->f_pos;
250 }
251 break;
252 case 1:
253 if ((offset + file->f_pos) > 0) {
254 file->f_pos += offset;
255 retval = file->f_pos;
256 }
257 break;
258 default:
259 break;
260 }
261 return retval;
262 }
263
default_open(struct inode * inode,struct file * filp)264 static int default_open (struct inode *inode, struct file *filp)
265 {
266 if (inode->u.generic_ip)
267 filp->private_data = inode->u.generic_ip;
268
269 return 0;
270 }
271
272 static struct file_operations default_file_operations = {
273 read: default_read_file,
274 write: default_write_file,
275 open: default_open,
276 llseek: default_file_lseek,
277 };
278
279 /* file ops for the "power" files */
280 static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
281 static ssize_t power_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
282 static struct file_operations power_file_operations = {
283 read: power_read_file,
284 write: power_write_file,
285 open: default_open,
286 llseek: default_file_lseek,
287 };
288
289 /* file ops for the "attention" files */
290 static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
291 static ssize_t attention_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
292 static struct file_operations attention_file_operations = {
293 read: attention_read_file,
294 write: attention_write_file,
295 open: default_open,
296 llseek: default_file_lseek,
297 };
298
299 /* file ops for the "latch" files */
300 static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
301 static struct file_operations latch_file_operations = {
302 read: latch_read_file,
303 write: default_write_file,
304 open: default_open,
305 llseek: default_file_lseek,
306 };
307
308 /* file ops for the "presence" files */
309 static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
310 static struct file_operations presence_file_operations = {
311 read: presence_read_file,
312 write: default_write_file,
313 open: default_open,
314 llseek: default_file_lseek,
315 };
316
317 /* file ops for the "address" files */
318 static ssize_t address_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
319 static struct file_operations address_file_operations = {
320 read: address_read_file,
321 write: default_write_file,
322 open: default_open,
323 llseek: default_file_lseek,
324 };
325
326 /* file ops for the "max bus speed" files */
327 static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
328 static struct file_operations max_bus_speed_file_operations = {
329 read: max_bus_speed_read_file,
330 write: default_write_file,
331 open: default_open,
332 llseek: default_file_lseek,
333 };
334
335 /* file ops for the "current bus speed" files */
336 static ssize_t cur_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset);
337 static struct file_operations cur_bus_speed_file_operations = {
338 read: cur_bus_speed_read_file,
339 write: default_write_file,
340 open: default_open,
341 llseek: default_file_lseek,
342 };
343
344 /* file ops for the "test" files */
345 static ssize_t test_write_file (struct file *file, const char *buf, size_t count, loff_t *ppos);
346 static struct file_operations test_file_operations = {
347 read: default_read_file,
348 write: test_write_file,
349 open: default_open,
350 llseek: default_file_lseek,
351 };
352
353 static struct inode_operations pcihpfs_dir_inode_operations = {
354 create: pcihpfs_create,
355 lookup: pcihpfs_lookup,
356 unlink: pcihpfs_unlink,
357 mkdir: pcihpfs_mkdir,
358 rmdir: pcihpfs_rmdir,
359 mknod: pcihpfs_mknod,
360 };
361
362 static struct super_operations pcihpfs_ops = {
363 statfs: pcihpfs_statfs,
364 put_inode: force_delete,
365 };
366
pcihpfs_read_super(struct super_block * sb,void * data,int silent)367 static struct super_block *pcihpfs_read_super (struct super_block *sb, void *data, int silent)
368 {
369 struct inode *inode;
370 struct dentry *root;
371
372 sb->s_blocksize = PAGE_CACHE_SIZE;
373 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
374 sb->s_magic = PCIHPFS_MAGIC;
375 sb->s_op = &pcihpfs_ops;
376 inode = pcihpfs_get_inode(sb, S_IFDIR | 0755, 0);
377
378 if (!inode) {
379 dbg("%s: could not get inode!\n",__FUNCTION__);
380 return NULL;
381 }
382
383 root = d_alloc_root(inode);
384 if (!root) {
385 dbg("%s: could not get root dentry!\n",__FUNCTION__);
386 iput(inode);
387 return NULL;
388 }
389 sb->s_root = root;
390 return sb;
391 }
392
393 static DECLARE_FSTYPE(pcihpfs_fs_type, "pcihpfs", pcihpfs_read_super, FS_SINGLE | FS_LITTER);
394
get_mount(void)395 static int get_mount (void)
396 {
397 struct vfsmount *mnt;
398
399 spin_lock (&mount_lock);
400 if (pcihpfs_mount) {
401 mntget(pcihpfs_mount);
402 ++pcihpfs_mount_count;
403 spin_unlock (&mount_lock);
404 goto go_ahead;
405 }
406
407 spin_unlock (&mount_lock);
408 mnt = kern_mount (&pcihpfs_fs_type);
409 if (IS_ERR(mnt)) {
410 err ("could not mount the fs...erroring out!\n");
411 return -ENODEV;
412 }
413 spin_lock (&mount_lock);
414 if (!pcihpfs_mount) {
415 pcihpfs_mount = mnt;
416 ++pcihpfs_mount_count;
417 spin_unlock (&mount_lock);
418 goto go_ahead;
419 }
420 mntget(pcihpfs_mount);
421 ++pcihpfs_mount_count;
422 spin_unlock (&mount_lock);
423 mntput(mnt);
424
425 go_ahead:
426 dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);
427 return 0;
428 }
429
remove_mount(void)430 static void remove_mount (void)
431 {
432 struct vfsmount *mnt;
433
434 spin_lock (&mount_lock);
435 mnt = pcihpfs_mount;
436 --pcihpfs_mount_count;
437 if (!pcihpfs_mount_count)
438 pcihpfs_mount = NULL;
439
440 spin_unlock (&mount_lock);
441 mntput(mnt);
442 dbg("pcihpfs_mount_count = %d\n", pcihpfs_mount_count);
443 }
444
445
446 /**
447 * pcihpfs_create_by_name - create a file, given a name
448 * @name: name of file
449 * @mode: type of file
450 * @parent: dentry of directory to create it in
451 * @dentry: resulting dentry of file
452 *
453 * There is a bit of overhead in creating a file - basically, we
454 * have to hash the name of the file, then look it up. This will
455 * prevent files of the same name.
456 * We then call the proper vfs_ function to take care of all the
457 * file creation details.
458 * This function handles both regular files and directories.
459 */
pcihpfs_create_by_name(const char * name,mode_t mode,struct dentry * parent,struct dentry ** dentry)460 static int pcihpfs_create_by_name (const char *name, mode_t mode,
461 struct dentry *parent, struct dentry **dentry)
462 {
463 struct dentry *d = NULL;
464 struct qstr qstr;
465 int error;
466
467 /* If the parent is not specified, we create it in the root.
468 * We need the root dentry to do this, which is in the super
469 * block. A pointer to that is in the struct vfsmount that we
470 * have around.
471 */
472 if (!parent ) {
473 if (pcihpfs_mount && pcihpfs_mount->mnt_sb) {
474 parent = pcihpfs_mount->mnt_sb->s_root;
475 }
476 }
477
478 if (!parent) {
479 dbg("Ah! can not find a parent!\n");
480 return -EINVAL;
481 }
482
483 *dentry = NULL;
484 qstr.name = name;
485 qstr.len = strlen(name);
486 qstr.hash = full_name_hash(name,qstr.len);
487
488 parent = dget(parent);
489
490 down(&parent->d_inode->i_sem);
491
492 d = lookup_hash(&qstr,parent);
493
494 error = PTR_ERR(d);
495 if (!IS_ERR(d)) {
496 switch(mode & S_IFMT) {
497 case 0:
498 case S_IFREG:
499 error = vfs_create(parent->d_inode,d,mode);
500 break;
501 case S_IFDIR:
502 error = vfs_mkdir(parent->d_inode,d,mode);
503 break;
504 default:
505 err("cannot create special files\n");
506 }
507 *dentry = d;
508 }
509 up(&parent->d_inode->i_sem);
510
511 dput(parent);
512 return error;
513 }
514
fs_create_file(const char * name,mode_t mode,struct dentry * parent,void * data,struct file_operations * fops)515 static struct dentry *fs_create_file (const char *name, mode_t mode,
516 struct dentry *parent, void *data,
517 struct file_operations *fops)
518 {
519 struct dentry *dentry;
520 int error;
521
522 dbg("creating file '%s'\n",name);
523
524 error = pcihpfs_create_by_name(name,mode,parent,&dentry);
525 if (error) {
526 dentry = NULL;
527 } else {
528 if (dentry->d_inode) {
529 if (data)
530 dentry->d_inode->u.generic_ip = data;
531 if (fops)
532 dentry->d_inode->i_fop = fops;
533 }
534 }
535
536 return dentry;
537 }
538
fs_remove_file(struct dentry * dentry)539 static void fs_remove_file (struct dentry *dentry)
540 {
541 struct dentry *parent = dentry->d_parent;
542
543 if (!parent || !parent->d_inode)
544 return;
545
546 down(&parent->d_inode->i_sem);
547 if (pcihpfs_positive(dentry)) {
548 if (dentry->d_inode) {
549 if (S_ISDIR(dentry->d_inode->i_mode))
550 vfs_rmdir(parent->d_inode,dentry);
551 else
552 vfs_unlink(parent->d_inode,dentry);
553 }
554
555 dput(dentry);
556 }
557 up(&parent->d_inode->i_sem);
558 }
559
560 #define GET_STATUS(name,type) \
561 static int get_##name (struct hotplug_slot *slot, type *value) \
562 { \
563 struct hotplug_slot_ops *ops = slot->ops; \
564 int retval = 0; \
565 if (ops->owner) \
566 __MOD_INC_USE_COUNT(ops->owner); \
567 if (ops->get_##name) \
568 retval = ops->get_##name (slot, value); \
569 else \
570 *value = slot->info->name; \
571 if (ops->owner) \
572 __MOD_DEC_USE_COUNT(ops->owner); \
573 return retval; \
574 }
575
GET_STATUS(power_status,u8)576 GET_STATUS(power_status, u8)
577 GET_STATUS(attention_status, u8)
578 GET_STATUS(latch_status, u8)
579 GET_STATUS(adapter_status, u8)
580 GET_STATUS(address, u32)
581 GET_STATUS(max_bus_speed, enum pci_bus_speed)
582 GET_STATUS(cur_bus_speed, enum pci_bus_speed)
583
584 static ssize_t power_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
585 {
586 struct hotplug_slot *slot = file->private_data;
587 unsigned char *page;
588 int retval;
589 int len;
590 u8 value;
591
592 dbg(" count = %d, offset = %lld\n", count, *offset);
593
594 if (*offset < 0)
595 return -EINVAL;
596 if (count == 0 || count > 16384)
597 return 0;
598 if (*offset != 0)
599 return 0;
600
601 if (slot == NULL) {
602 dbg("slot == NULL???\n");
603 return -ENODEV;
604 }
605
606 page = (unsigned char *)__get_free_page(GFP_KERNEL);
607 if (!page)
608 return -ENOMEM;
609
610 retval = get_power_status (slot, &value);
611 if (retval)
612 goto exit;
613 len = sprintf (page, "%d\n", value);
614
615 if (copy_to_user (buf, page, len)) {
616 retval = -EFAULT;
617 goto exit;
618 }
619 *offset = len;
620 retval = len;
621
622 exit:
623 free_page((unsigned long)page);
624 return retval;
625 }
626
power_write_file(struct file * file,const char * ubuff,size_t count,loff_t * offset)627 static ssize_t power_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
628 {
629 struct hotplug_slot *slot = file->private_data;
630 char *buff;
631 unsigned long lpower;
632 u8 power;
633 int retval = 0;
634
635 if (*offset < 0)
636 return -EINVAL;
637 if (count == 0 || count > 16384)
638 return 0;
639 if (*offset != 0)
640 return 0;
641
642 if (slot == NULL) {
643 dbg("slot == NULL???\n");
644 return -ENODEV;
645 }
646
647 buff = kmalloc (count + 1, GFP_KERNEL);
648 if (!buff)
649 return -ENOMEM;
650 memset (buff, 0x00, count + 1);
651
652 if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
653 retval = -EFAULT;
654 goto exit;
655 }
656
657 lpower = simple_strtoul (buff, NULL, 10);
658 power = (u8)(lpower & 0xff);
659 dbg ("power = %d\n", power);
660
661 switch (power) {
662 case 0:
663 if (!slot->ops->disable_slot)
664 break;
665 if (slot->ops->owner)
666 __MOD_INC_USE_COUNT(slot->ops->owner);
667 retval = slot->ops->disable_slot(slot);
668 if (slot->ops->owner)
669 __MOD_DEC_USE_COUNT(slot->ops->owner);
670 break;
671
672 case 1:
673 if (!slot->ops->enable_slot)
674 break;
675 if (slot->ops->owner)
676 __MOD_INC_USE_COUNT(slot->ops->owner);
677 retval = slot->ops->enable_slot(slot);
678 if (slot->ops->owner)
679 __MOD_DEC_USE_COUNT(slot->ops->owner);
680 break;
681
682 default:
683 err ("Illegal value specified for power\n");
684 retval = -EINVAL;
685 }
686
687 exit:
688 kfree (buff);
689
690 if (retval)
691 return retval;
692 return count;
693 }
694
attention_read_file(struct file * file,char * buf,size_t count,loff_t * offset)695 static ssize_t attention_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
696 {
697 struct hotplug_slot *slot = file->private_data;
698 unsigned char *page;
699 int retval;
700 int len;
701 u8 value;
702
703 dbg("count = %d, offset = %lld\n", count, *offset);
704
705 if (*offset < 0)
706 return -EINVAL;
707 if (count == 0 || count > 16384)
708 return 0;
709 if (*offset != 0)
710 return 0;
711
712 if (slot == NULL) {
713 dbg("slot == NULL???\n");
714 return -ENODEV;
715 }
716
717 page = (unsigned char *)__get_free_page(GFP_KERNEL);
718 if (!page)
719 return -ENOMEM;
720
721 retval = get_attention_status (slot, &value);
722 if (retval)
723 goto exit;
724 len = sprintf (page, "%d\n", value);
725
726 if (copy_to_user (buf, page, len)) {
727 retval = -EFAULT;
728 goto exit;
729 }
730 *offset = len;
731 retval = len;
732
733 exit:
734 free_page((unsigned long)page);
735 return retval;
736 }
737
attention_write_file(struct file * file,const char * ubuff,size_t count,loff_t * offset)738 static ssize_t attention_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
739 {
740 struct hotplug_slot *slot = file->private_data;
741 char *buff;
742 unsigned long lattention;
743 u8 attention;
744 int retval = 0;
745
746 if (*offset < 0)
747 return -EINVAL;
748 if (count == 0 || count > 16384)
749 return 0;
750 if (*offset != 0)
751 return 0;
752
753 if (slot == NULL) {
754 dbg("slot == NULL???\n");
755 return -ENODEV;
756 }
757
758 buff = kmalloc (count + 1, GFP_KERNEL);
759 if (!buff)
760 return -ENOMEM;
761 memset (buff, 0x00, count + 1);
762
763 if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
764 retval = -EFAULT;
765 goto exit;
766 }
767
768 lattention = simple_strtoul (buff, NULL, 10);
769 attention = (u8)(lattention & 0xff);
770 dbg (" - attention = %d\n", attention);
771
772 if (slot->ops->set_attention_status) {
773 if (slot->ops->owner)
774 __MOD_INC_USE_COUNT(slot->ops->owner);
775 retval = slot->ops->set_attention_status(slot, attention);
776 if (slot->ops->owner)
777 __MOD_DEC_USE_COUNT(slot->ops->owner);
778 }
779
780 exit:
781 kfree (buff);
782
783 if (retval)
784 return retval;
785 return count;
786 }
787
latch_read_file(struct file * file,char * buf,size_t count,loff_t * offset)788 static ssize_t latch_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
789 {
790 struct hotplug_slot *slot = file->private_data;
791 unsigned char *page;
792 int retval;
793 int len;
794 u8 value;
795 loff_t off = *offset;
796
797 dbg("count = %d, offset = %lld\n", count, off);
798
799 if (off < 0)
800 return -EINVAL;
801 if (count <= 0)
802 return 0;
803 if (off != 0)
804 return 0;
805
806 if (slot == NULL) {
807 dbg("slot == NULL???\n");
808 return -ENODEV;
809 }
810
811 page = (unsigned char *)__get_free_page(GFP_KERNEL);
812 if (!page)
813 return -ENOMEM;
814
815 retval = get_latch_status (slot, &value);
816 if (retval)
817 goto exit;
818 len = sprintf (page, "%d\n", value);
819
820 if (copy_to_user (buf, page, len)) {
821 retval = -EFAULT;
822 goto exit;
823 }
824 *offset = off + len;
825 retval = len;
826
827 exit:
828 free_page((unsigned long)page);
829 return retval;
830 }
831
presence_read_file(struct file * file,char * buf,size_t count,loff_t * offset)832 static ssize_t presence_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
833 {
834 struct hotplug_slot *slot = file->private_data;
835 unsigned char *page;
836 int retval;
837 int len;
838 u8 value;
839 loff_t off = *offset;
840
841 dbg("count = %d, offset = %lld\n", count, *offset);
842
843 if (off < 0)
844 return -EINVAL;
845 if (count <= 0)
846 return 0;
847 if (off != 0)
848 return 0;
849
850 if (slot == NULL) {
851 dbg("slot == NULL???\n");
852 return -ENODEV;
853 }
854
855 page = (unsigned char *)__get_free_page(GFP_KERNEL);
856 if (!page)
857 return -ENOMEM;
858
859 retval = get_adapter_status (slot, &value);
860 if (retval)
861 goto exit;
862 len = sprintf (page, "%d\n", value);
863
864 if (copy_to_user (buf, page, len)) {
865 retval = -EFAULT;
866 goto exit;
867 }
868 *offset = off + len;
869 retval = len;
870
871 exit:
872 free_page((unsigned long)page);
873 return retval;
874 }
875
address_read_file(struct file * file,char * buf,size_t count,loff_t * offset)876 static ssize_t address_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
877 {
878 struct hotplug_slot *slot = file->private_data;
879 unsigned char *page;
880 int retval;
881 int len;
882 u32 address;
883 loff_t off = *offset;
884
885 dbg("count = %d, offset = %lld\n", count, off);
886
887 if (off < 0)
888 return -EINVAL;
889 if (count <= 0)
890 return 0;
891 if (off != 0)
892 return 0;
893
894 if (slot == NULL) {
895 dbg("slot == NULL???\n");
896 return -ENODEV;
897 }
898
899 page = (unsigned char *)__get_free_page(GFP_KERNEL);
900 if (!page)
901 return -ENOMEM;
902
903 retval = get_address (slot, &address);
904 if (retval)
905 goto exit;
906 len = sprintf (page, "%04x:%02x:%02x\n",
907 (address >> 16) & 0xffff,
908 (address >> 8) & 0xff,
909 address & 0xff);
910
911 if (copy_to_user (buf, page, len)) {
912 retval = -EFAULT;
913 goto exit;
914 }
915 *offset = off + len;
916 retval = len;
917
918 exit:
919 free_page((unsigned long)page);
920 return retval;
921 }
922
923 static char *unknown_speed = "Unknown bus speed";
924
max_bus_speed_read_file(struct file * file,char * buf,size_t count,loff_t * offset)925 static ssize_t max_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
926 {
927 struct hotplug_slot *slot = file->private_data;
928 unsigned char *page;
929 char *speed_string;
930 int retval;
931 int len = 0;
932 enum pci_bus_speed value;
933 loff_t off = *offset;
934
935 dbg ("count = %d, offset = %lld\n", count, off);
936
937 if (off < 0)
938 return -EINVAL;
939 if (count <= 0)
940 return 0;
941 if (off != 0)
942 return 0;
943
944 if (slot == NULL) {
945 dbg("slot == NULL???\n");
946 return -ENODEV;
947 }
948
949 page = (unsigned char *)__get_free_page(GFP_KERNEL);
950 if (!page)
951 return -ENOMEM;
952
953 retval = get_max_bus_speed (slot, &value);
954 if (retval)
955 goto exit;
956
957 if (value == PCI_SPEED_UNKNOWN)
958 speed_string = unknown_speed;
959 else
960 speed_string = pci_bus_speed_strings[value];
961
962 len = sprintf (page, "%s\n", speed_string);
963
964 if (copy_to_user (buf, page, len)) {
965 retval = -EFAULT;
966 goto exit;
967 }
968 *offset = off + len;
969 retval = len;
970
971 exit:
972 free_page((unsigned long)page);
973 return retval;
974 }
975
cur_bus_speed_read_file(struct file * file,char * buf,size_t count,loff_t * offset)976 static ssize_t cur_bus_speed_read_file (struct file *file, char *buf, size_t count, loff_t *offset)
977 {
978 struct hotplug_slot *slot = file->private_data;
979 unsigned char *page;
980 char *speed_string;
981 int retval;
982 int len = 0;
983 enum pci_bus_speed value;
984 loff_t off = *offset;
985
986 dbg ("count = %d, offset = %lld\n", count, off);
987
988 if (off < 0)
989 return -EINVAL;
990 if (count <= 0)
991 return 0;
992 if (off != 0)
993 return 0;
994
995 if (slot == NULL) {
996 dbg("slot == NULL???\n");
997 return -ENODEV;
998 }
999
1000 page = (unsigned char *)__get_free_page(GFP_KERNEL);
1001 if (!page)
1002 return -ENOMEM;
1003
1004 retval = get_cur_bus_speed (slot, &value);
1005 if (retval)
1006 goto exit;
1007
1008 if (value == PCI_SPEED_UNKNOWN)
1009 speed_string = unknown_speed;
1010 else
1011 speed_string = pci_bus_speed_strings[value];
1012
1013 len = sprintf (page, "%s\n", speed_string);
1014
1015 if (copy_to_user (buf, page, len)) {
1016 retval = -EFAULT;
1017 goto exit;
1018 }
1019 *offset = off + len;
1020 retval = len;
1021
1022 exit:
1023 free_page((unsigned long)page);
1024 return retval;
1025 }
1026
test_write_file(struct file * file,const char * ubuff,size_t count,loff_t * offset)1027 static ssize_t test_write_file (struct file *file, const char *ubuff, size_t count, loff_t *offset)
1028 {
1029 struct hotplug_slot *slot = file->private_data;
1030 char *buff;
1031 unsigned long ltest;
1032 u32 test;
1033 int retval = 0;
1034
1035 if (*offset < 0)
1036 return -EINVAL;
1037 if (count == 0 || count > 16384)
1038 return 0;
1039 if (*offset != 0)
1040 return 0;
1041
1042 if (slot == NULL) {
1043 dbg("slot == NULL???\n");
1044 return -ENODEV;
1045 }
1046
1047 buff = kmalloc (count + 1, GFP_KERNEL);
1048 if (!buff)
1049 return -ENOMEM;
1050 memset (buff, 0x00, count + 1);
1051
1052 if (copy_from_user ((void *)buff, (void *)ubuff, count)) {
1053 retval = -EFAULT;
1054 goto exit;
1055 }
1056
1057 ltest = simple_strtoul (buff, NULL, 10);
1058 test = (u32)(ltest & 0xffffffff);
1059 dbg ("test = %d\n", test);
1060
1061 if (slot->ops->hardware_test) {
1062 if (slot->ops->owner)
1063 __MOD_INC_USE_COUNT(slot->ops->owner);
1064 retval = slot->ops->hardware_test(slot, test);
1065 if (slot->ops->owner)
1066 __MOD_DEC_USE_COUNT(slot->ops->owner);
1067 }
1068
1069 exit:
1070 kfree (buff);
1071
1072 if (retval)
1073 return retval;
1074 return count;
1075 }
1076
fs_add_slot(struct hotplug_slot * slot)1077 static int fs_add_slot (struct hotplug_slot *slot)
1078 {
1079 struct hotplug_slot_core *core = slot->core_priv;
1080 int result;
1081
1082 result = get_mount();
1083 if (result)
1084 return result;
1085
1086 core->dir_dentry = fs_create_file (slot->name,
1087 S_IFDIR | S_IXUGO | S_IRUGO,
1088 NULL, NULL, NULL);
1089 if (core->dir_dentry != NULL) {
1090 if ((slot->ops->enable_slot) ||
1091 (slot->ops->disable_slot) ||
1092 (slot->ops->get_power_status))
1093 core->power_dentry =
1094 fs_create_file ("power",
1095 S_IFREG | S_IRUGO | S_IWUSR,
1096 core->dir_dentry, slot,
1097 &power_file_operations);
1098
1099 if ((slot->ops->set_attention_status) ||
1100 (slot->ops->get_attention_status))
1101 core->attention_dentry =
1102 fs_create_file ("attention",
1103 S_IFREG | S_IRUGO | S_IWUSR,
1104 core->dir_dentry, slot,
1105 &attention_file_operations);
1106
1107 if (slot->ops->get_latch_status)
1108 core->latch_dentry =
1109 fs_create_file ("latch",
1110 S_IFREG | S_IRUGO,
1111 core->dir_dentry, slot,
1112 &latch_file_operations);
1113
1114 if (slot->ops->get_adapter_status)
1115 core->adapter_dentry =
1116 fs_create_file ("adapter",
1117 S_IFREG | S_IRUGO,
1118 core->dir_dentry, slot,
1119 &presence_file_operations);
1120
1121 if (slot->ops->get_address)
1122 core->address_dentry =
1123 fs_create_file ("address",
1124 S_IFREG | S_IRUGO,
1125 core->dir_dentry, slot,
1126 &address_file_operations);
1127
1128 if (slot->ops->get_max_bus_speed)
1129 core->max_bus_speed_dentry =
1130 fs_create_file ("max_bus_speed",
1131 S_IFREG | S_IRUGO,
1132 core->dir_dentry, slot,
1133 &max_bus_speed_file_operations);
1134
1135 if (slot->ops->get_cur_bus_speed)
1136 core->cur_bus_speed_dentry =
1137 fs_create_file ("cur_bus_speed",
1138 S_IFREG | S_IRUGO,
1139 core->dir_dentry, slot,
1140 &cur_bus_speed_file_operations);
1141
1142 if (slot->ops->hardware_test)
1143 core->test_dentry =
1144 fs_create_file ("test",
1145 S_IFREG | S_IRUGO | S_IWUSR,
1146 core->dir_dentry, slot,
1147 &test_file_operations);
1148 }
1149 return 0;
1150 }
1151
fs_remove_slot(struct hotplug_slot * slot)1152 static void fs_remove_slot (struct hotplug_slot *slot)
1153 {
1154 struct hotplug_slot_core *core = slot->core_priv;
1155
1156 if (core->dir_dentry) {
1157 if (core->power_dentry)
1158 fs_remove_file (core->power_dentry);
1159 if (core->attention_dentry)
1160 fs_remove_file (core->attention_dentry);
1161 if (core->latch_dentry)
1162 fs_remove_file (core->latch_dentry);
1163 if (core->adapter_dentry)
1164 fs_remove_file (core->adapter_dentry);
1165 if (core->address_dentry)
1166 fs_remove_file (core->address_dentry);
1167 if (core->max_bus_speed_dentry)
1168 fs_remove_file (core->max_bus_speed_dentry);
1169 if (core->cur_bus_speed_dentry)
1170 fs_remove_file (core->cur_bus_speed_dentry);
1171 if (core->test_dentry)
1172 fs_remove_file (core->test_dentry);
1173 fs_remove_file (core->dir_dentry);
1174 }
1175
1176 remove_mount();
1177 }
1178
get_slot_from_name(const char * name)1179 static struct hotplug_slot *get_slot_from_name (const char *name)
1180 {
1181 struct hotplug_slot *slot;
1182 struct list_head *tmp;
1183
1184 list_for_each (tmp, &pci_hotplug_slot_list) {
1185 slot = list_entry (tmp, struct hotplug_slot, slot_list);
1186 if (strcmp(slot->name, name) == 0)
1187 return slot;
1188 }
1189 return NULL;
1190 }
1191
1192 /**
1193 * pci_hp_register - register a hotplug_slot with the PCI hotplug subsystem
1194 * @slot: pointer to the &struct hotplug_slot to register
1195 *
1196 * Registers a hotplug slot with the pci hotplug subsystem, which will allow
1197 * userspace interaction to the slot.
1198 *
1199 * Returns 0 if successful, anything else for an error.
1200 */
pci_hp_register(struct hotplug_slot * slot)1201 int pci_hp_register (struct hotplug_slot *slot)
1202 {
1203 struct hotplug_slot_core *core;
1204 int result;
1205
1206 if (slot == NULL)
1207 return -ENODEV;
1208 if ((slot->info == NULL) || (slot->ops == NULL))
1209 return -EINVAL;
1210
1211 core = kmalloc (sizeof (struct hotplug_slot_core), GFP_KERNEL);
1212 if (!core)
1213 return -ENOMEM;
1214
1215 /* make sure we have not already registered this slot */
1216 spin_lock (&list_lock);
1217 if (get_slot_from_name (slot->name) != NULL) {
1218 spin_unlock (&list_lock);
1219 kfree (core);
1220 return -EEXIST;
1221 }
1222
1223 memset (core, 0, sizeof (struct hotplug_slot_core));
1224 slot->core_priv = core;
1225
1226 list_add (&slot->slot_list, &pci_hotplug_slot_list);
1227 spin_unlock (&list_lock);
1228
1229 result = fs_add_slot (slot);
1230 dbg ("Added slot %s to the list\n", slot->name);
1231 return result;
1232 }
1233
1234 /**
1235 * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem
1236 * @slot: pointer to the &struct hotplug_slot to deregister
1237 *
1238 * The @slot must have been registered with the pci hotplug subsystem
1239 * previously with a call to pci_hp_register().
1240 *
1241 * Returns 0 if successful, anything else for an error.
1242 */
pci_hp_deregister(struct hotplug_slot * slot)1243 int pci_hp_deregister (struct hotplug_slot *slot)
1244 {
1245 struct hotplug_slot *temp;
1246
1247 if (slot == NULL)
1248 return -ENODEV;
1249
1250 /* make sure we have this slot in our list before trying to delete it */
1251 spin_lock (&list_lock);
1252 temp = get_slot_from_name (slot->name);
1253 if (temp != slot) {
1254 spin_unlock (&list_lock);
1255 return -ENODEV;
1256 }
1257
1258 list_del (&slot->slot_list);
1259 spin_unlock (&list_lock);
1260
1261 fs_remove_slot (slot);
1262 kfree(slot->core_priv);
1263 dbg ("Removed slot %s from the list\n", slot->name);
1264 return 0;
1265 }
1266
update_dentry_inode_time(struct dentry * dentry)1267 static inline void update_dentry_inode_time (struct dentry *dentry)
1268 {
1269 struct inode *inode = dentry->d_inode;
1270 if (inode) {
1271 inode->i_mtime = CURRENT_TIME;
1272 dnotify_parent(dentry, DN_MODIFY);
1273 }
1274 }
1275
1276 /**
1277 * pci_hp_change_slot_info - changes the slot's information structure in the core
1278 * @name: the name of the slot whose info has changed
1279 * @info: pointer to the info copy into the slot's info structure
1280 *
1281 * A slot with @name must have been registered with the pci
1282 * hotplug subsystem previously with a call to pci_hp_register().
1283 *
1284 * Returns 0 if successful, anything else for an error.
1285 */
pci_hp_change_slot_info(const char * name,struct hotplug_slot_info * info)1286 int pci_hp_change_slot_info (const char *name, struct hotplug_slot_info *info)
1287 {
1288 struct hotplug_slot *temp;
1289 struct hotplug_slot_core *core;
1290
1291 if (info == NULL)
1292 return -ENODEV;
1293
1294 spin_lock (&list_lock);
1295 temp = get_slot_from_name (name);
1296 if (temp == NULL) {
1297 spin_unlock (&list_lock);
1298 return -ENODEV;
1299 }
1300
1301 /*
1302 * check all fields in the info structure, and update timestamps
1303 * for the files referring to the fields that have now changed.
1304 */
1305 core = temp->core_priv;
1306 if ((core->power_dentry) &&
1307 (temp->info->power_status != info->power_status))
1308 update_dentry_inode_time (core->power_dentry);
1309 if ((core->attention_dentry) &&
1310 (temp->info->attention_status != info->attention_status))
1311 update_dentry_inode_time (core->attention_dentry);
1312 if ((core->latch_dentry) &&
1313 (temp->info->latch_status != info->latch_status))
1314 update_dentry_inode_time (core->latch_dentry);
1315 if ((core->adapter_dentry) &&
1316 (temp->info->adapter_status != info->adapter_status))
1317 update_dentry_inode_time (core->adapter_dentry);
1318 if ((core->address_dentry) &&
1319 (temp->info->address != info->address))
1320 update_dentry_inode_time (core->address_dentry);
1321 if ((core->cur_bus_speed_dentry) &&
1322 (temp->info->cur_bus_speed != info->cur_bus_speed))
1323 update_dentry_inode_time (core->cur_bus_speed_dentry);
1324
1325 memcpy (temp->info, info, sizeof (struct hotplug_slot_info));
1326 spin_unlock (&list_lock);
1327 return 0;
1328 }
1329
pci_hotplug_init(void)1330 static int __init pci_hotplug_init (void)
1331 {
1332 int result;
1333
1334 spin_lock_init(&mount_lock);
1335 spin_lock_init(&list_lock);
1336
1337 dbg("registering filesystem.\n");
1338 result = register_filesystem(&pcihpfs_fs_type);
1339 if (result) {
1340 err("register_filesystem failed with %d\n", result);
1341 goto exit;
1342 }
1343
1344 #ifdef CONFIG_PROC_FS
1345 /* create mount point for pcihpfs */
1346 slotdir = proc_mkdir(slotdir_name, proc_bus_pci_dir);
1347 #endif
1348
1349 info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
1350
1351 exit:
1352 return result;
1353 }
1354
pci_hotplug_exit(void)1355 static void __exit pci_hotplug_exit (void)
1356 {
1357 unregister_filesystem(&pcihpfs_fs_type);
1358
1359 #ifdef CONFIG_PROC_FS
1360 if (slotdir)
1361 remove_proc_entry(slotdir_name, proc_bus_pci_dir);
1362 #endif
1363 }
1364
1365 module_init(pci_hotplug_init);
1366 module_exit(pci_hotplug_exit);
1367
1368 MODULE_AUTHOR(DRIVER_AUTHOR);
1369 MODULE_DESCRIPTION(DRIVER_DESC);
1370 MODULE_LICENSE("GPL");
1371 MODULE_PARM(debug, "i");
1372 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
1373
1374 EXPORT_SYMBOL_GPL(pci_hp_register);
1375 EXPORT_SYMBOL_GPL(pci_hp_deregister);
1376 EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
1377
1378