import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / drivers / hotplug / pci_hotplug_core.c
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
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
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
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
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
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
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
189 static inline int pcihpfs_positive (struct dentry *dentry)
190 {
191         return dentry->d_inode && !d_unhashed(dentry);
192 }
193
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
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 */
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
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
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
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
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
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
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  */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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  */
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  */
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
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  */
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
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
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