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