• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *   Copyright (c) International Business Machines  Corp., 2001
4  *
5  *   This program is free software;  you can redistribute it and/or modify
6  *   it under the terms of the GNU General Public License as published by
7  *   the Free Software Foundation; either version 2 of the License, or
8  *   (at your option) any later version.
9  *
10  *   This program is distributed in the hope that it will be useful,
11  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13  *   the GNU General Public License for more details.
14  *
15  *   You should have received a copy of the GNU General Public License
16  *   along with this program;  if not, write to the Free Software
17  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 /*
20  * This test module is for executing and testing
21  * the kernel code from drivers/base. This module
22  * is driven by a user space program through
23  * calls to the ioctl
24  *
25  * author: Sean Ruyle
26  * date:   07/14/2003
27  *
28  * module: tbase
29  */
30 
31 #include <linux/types.h>
32 #include <linux/kernel.h>
33 #include <linux/fs.h>
34 #include <linux/ioctl.h>
35 #include <linux/module.h>
36 #include <linux/init.h>
37 #include <linux/device.h>
38 #include <linux/pci.h>
39 #include <linux/sysdev.h>
40 #include <asm/uaccess.h>
41 
42 #include "tbase.h"
43 #include "str_mod.h"
44 
45 MODULE_AUTHOR("Sean Ruyle <srruyle@us.ibm.com>");
46 MODULE_DESCRIPTION(TMOD_DRIVER_NAME);
47 MODULE_LICENSE("GPL");
48 
49 static int tbase_ioctl(struct inode *, struct file *, unsigned int,
50 		       unsigned long);
51 static int tbase_open(struct inode *, struct file *);
52 static int tbase_close(struct inode *, struct file *);
53 
54 static int test_device_register(void);
55 static int test_device_unregister(void);
56 static int test_bus_add(void);
57 static int test_get_drv(void);
58 static int test_put_drv(void);
59 static int test_reg_firm(void);
60 static int test_create_file(void);
61 static int test_dev_suspend(void);
62 static int test_dev_file(void);
63 static int test_bus_rescan(void);
64 static int test_bus_file(void);
65 static int test_class_reg(void);
66 static int test_class_get(void);
67 static int test_class_file(void);
68 static int test_classdev_reg(void);
69 static int test_classint_reg(void);
70 static int test_sysdev_cls_reg(void);
71 static int test_sysdev_reg(void);
72 
73 static int Major = TBASEMAJOR;
74 static ltpmod_user_t ltp_mod;
75 
76 /*
77  * File operations struct, to use operations find the
78  * correct file descriptor
79  */
80 static struct file_operations tbase_fops = {
81 open:	tbase_open,
82 release:tbase_close,
83 ioctl:	tbase_ioctl,
84 };
85 
tbase_open(struct inode * ino,struct file * f)86 static int tbase_open(struct inode *ino, struct file *f)
87 {
88 	return 0;
89 }
90 
tbase_close(struct inode * ino,struct file * f)91 static int tbase_close(struct inode *ino, struct file *f)
92 {
93 	return 0;
94 }
95 
96 /* my bus stuff */
97 struct device_driver test_driver;
98 struct device test_device;
99 
test_device_match(struct device * dev,struct device_driver * drv)100 static int test_device_match(struct device *dev, struct device_driver *drv)
101 {
102 
103 	printk("tbase: driver is %s\n", drv->name);
104 //      printk("tbase: device is %s\n", dev->name);
105 
106 	if (drv == &test_driver && dev == &test_device) {
107 		printk("tbase: match\n");
108 		return 1;
109 	} else {
110 		printk("tbase: no match\n");
111 		return 0;
112 	}
113 
114 }
115 
116 struct bus_type test_bus_type = {
117 	.name = "test_bus",
118 	.match = test_device_match,
119 };
120 
121 /* my driver stuff */
test_dev_probe(struct device * dev)122 int test_dev_probe(struct device *dev)
123 {
124 	printk("tbase: Entered test_dev_probe\n");
125 	return 0;
126 }
127 
test_dev_remove(struct device * dev)128 int test_dev_remove(struct device *dev)
129 {
130 	printk("tbase: Entered test_dev_remove\n");
131 	return 0;
132 }
133 
134 struct device_driver test_driver = {
135 	.name = "TestDriver",
136 	.bus = &test_bus_type,
137 	.probe = test_dev_probe,
138 	.remove = test_dev_remove,
139 };
140 
141 /* my device stuff */
142 struct device test_device = {
143 //      .name = "TestDevice",
144 	.bus = &test_bus_type,
145 	.bus_id = "test_bus",
146 };
147 
148 /* my class stuff */
test_class_release(struct class_device * class_dev)149 static void test_class_release(struct class_device *class_dev)
150 {
151 	printk("tbase: Entered test_class_release\n");
152 }
153 
test_class_hotplug(struct class_device * dev,char ** envp,int num_envp,char * buffer,int buffer_size)154 int test_class_hotplug(struct class_device *dev, char **envp,
155 		       int num_envp, char *buffer, int buffer_size)
156 {
157 	printk("tbase: Entered test_class_hotplug\n");
158 	return 0;
159 }
160 
161 struct class test_class = {
162 	.name = "TestClass",
163 	.hotplug = test_class_hotplug,
164 	.release = test_class_release,
165 };
166 
167 /* my class device stuff */
168 struct class_device test_class_dev = {
169 	.class_id = "test_bus",
170 	.dev = &test_device,
171 	.class = &test_class,
172 };
173 
174 /* my class interface stuff */
test_intf_add(struct class_device * class_dev)175 int test_intf_add(struct class_device *class_dev)
176 {
177 	printk("tbase: Entered test_intf_add for the test class_interface\n");
178 	return 0;
179 }
180 
test_intf_rem(struct class_device * class_dev)181 void test_intf_rem(struct class_device *class_dev)
182 {
183 	printk("tbase: Entered test_intf_rem for the test class interface\n");
184 }
185 
186 struct class_interface test_interface = {
187 	.class = &test_class,
188 	.add = &test_intf_add,
189 	.remove = &test_intf_rem,
190 };
191 
192 /* my sys_device stuff */
test_resume(struct sys_device * dev)193 int test_resume(struct sys_device *dev)
194 {
195 	printk("tbase: Entered test resume for sys device\n");
196 	return 0;
197 }
198 
199 struct sysdev_class test_sysclass = {
200 	set_kset_name("TestSysclass"),
201 	.resume = test_resume,
202 };
203 
204 struct sys_device test_sys_device = {
205 	.id = 0,
206 	.cls = &test_sysclass,
207 };
208 
209 /* my attribute stuff */
210 static inline ssize_t
store_new_id(struct device_driver * driver,const char * buf,size_t count)211 store_new_id(struct device_driver *driver, const char *buf, size_t count)
212 {
213 	printk("tbase: Entered store new id\n");
214 	return count;
215 }
216 
217 /* create attribute driver_attr_new_id */
218 DRIVER_ATTR(new_id, 0200, NULL, store_new_id);
219 
220 /* create attribute dev_attr_test_id */
221 DEVICE_ATTR(test_id, S_IRUGO, NULL, NULL);
222 
223 /* create attribute bus_attr_test_id */
224 BUS_ATTR(test_id, S_IRUGO, NULL, NULL);
225 
226 /* create attribute class_attr_test_id */
227 CLASS_ATTR(test_id, 0644, NULL, NULL);
228 
229 /* create attribute class_device_attr_test_id */
230 CLASS_DEVICE_ATTR(test_id, 0644, NULL, NULL);
231 
232 /*
233  * tbase_ioctl:
234  *      a user space program can drive the test functions
235  *      through a call to ioctl once the correct file
236  *      descriptor has been attained
237  */
tbase_ioctl(struct inode * ino,struct file * f,unsigned int cmd,unsigned long l)238 static int tbase_ioctl(struct inode *ino, struct file *f,
239 		       unsigned int cmd, unsigned long l)
240 {
241 	int rc;
242 	tmod_interface_t tif;
243 	caddr_t *inparms;
244 	caddr_t *outparms;
245 
246 	printk("Enter tbase_ioctl\n");
247 
248 	inparms = NULL;
249 	outparms = NULL;
250 	rc = 0;
251 
252 	/*
253 	 * the following calls are used to setup the
254 	 * parameters that might need to be passed
255 	 * between user and kernel space, using the tif
256 	 * pointer that is passed in as the last
257 	 * parameter to the ioctl
258 	 *
259 	 */
260 	if (copy_from_user(&tif, (void *)l, sizeof(tif))) {
261 		/* Bad address */
262 		return (-EFAULT);
263 	}
264 
265 	/*
266 	 * Setup inparms and outparms as needed
267 	 */
268 	if (tif.in_len > 0) {
269 		inparms = (caddr_t *) kmalloc(tif.in_len, GFP_KERNEL);
270 		if (!inparms) {
271 			return (-ENOMEM);
272 		}
273 
274 		rc = copy_from_user(inparms, tif.in_data, tif.in_len);
275 		if (rc) {
276 			kfree(inparms);
277 			return (-EFAULT);
278 		}
279 	}
280 	if (tif.out_len > 0) {
281 		outparms = (caddr_t *) kmalloc(tif.out_len, GFP_KERNEL);
282 		if (!outparms) {
283 			kfree(inparms);
284 			return (-ENOMEM);
285 		}
286 	}
287 
288 	/*
289 	 * Use a switch statement to determine which function
290 	 * to call, based on the cmd flag that is specified
291 	 * in user space. Pass in inparms or outparms as
292 	 * needed
293 	 *
294 	 */
295 	switch (cmd) {
296 	case REG_DEVICE:
297 		rc = test_device_register();
298 		break;
299 	case UNREG_DEVICE:
300 		rc = test_device_unregister();
301 		break;
302 	case BUS_ADD:
303 		rc = test_bus_add();
304 		break;
305 	case GET_DRV:
306 		rc = test_get_drv();
307 		break;
308 	case PUT_DRV:
309 		rc = test_put_drv();
310 		break;
311 	case REG_FIRM:
312 		rc = test_reg_firm();
313 		break;
314 	case CREATE_FILE:
315 		rc = test_create_file();
316 		break;
317 	case DEV_SUSPEND:
318 		rc = test_dev_suspend();
319 		break;
320 	case DEV_FILE:
321 		rc = test_dev_file();
322 		break;
323 	case BUS_RESCAN:
324 		rc = test_bus_rescan();
325 		break;
326 	case BUS_FILE:
327 		rc = test_bus_file();
328 		break;
329 	case CLASS_REG:
330 		rc = test_class_reg();
331 		break;
332 	case CLASS_UNREG:
333 		class_unregister(&test_class);
334 		break;
335 	case CLASS_GET:
336 		rc = test_class_get();
337 		break;
338 	case CLASS_FILE:
339 		rc = test_class_file();
340 		break;
341 	case CLASSDEV_REG:
342 		rc = test_classdev_reg();
343 		break;
344 	case CLASSINT_REG:
345 		rc = test_classint_reg();
346 		break;
347 	case SYSDEV_CLS_REG:
348 		rc = test_sysdev_cls_reg();
349 		break;
350 	case SYSDEV_CLS_UNREG:
351 		sysdev_class_unregister(&test_sysclass);
352 		break;
353 	case SYSDEV_REG:
354 		rc = test_sysdev_reg();
355 		break;
356 	case SYSDEV_UNREG:
357 		sys_device_unregister(&test_sys_device);
358 		break;
359 	default:
360 		printk("tbase: Mismatching ioctl command\n");
361 		break;
362 	}
363 
364 	/*
365 	 * copy in the test return code, the reason we
366 	 * this is so that in user space we can tell the
367 	 * difference between an error in one of our test
368 	 * calls or an error in the ioctl function
369 	 */
370 	tif.out_rc = rc;
371 	rc = 0;
372 
373 	/*
374 	 * setup the rest of tif pointer for returning to
375 	 * to user space, using copy_to_user if needed
376 	 */
377 
378 	/* if outparms then copy outparms into tif.out_data */
379 	if (outparms) {
380 		if (copy_to_user(tif.out_data, outparms, tif.out_len)) {
381 			printk
382 			    ("tbase: Unsuccessful copy_to_user of outparms\n");
383 			rc = -EFAULT;
384 		}
385 	}
386 
387 	/* copy tif structure into l so that can be used by user program */
388 	if (copy_to_user((void *)l, &tif, sizeof(tif))) {
389 		printk("tbase: Unsuccessful copy_to_user of tif\n");
390 		rc = -EFAULT;
391 	}
392 
393 	/*
394 	 * free inparms and outparms
395 	 */
396 	if (inparms) {
397 		kfree(inparms);
398 	}
399 	if (outparms) {
400 		kfree(outparms);
401 	}
402 
403 	return rc;
404 }
405 
406 /*
407  * test_device_register
408  *	makes call to device register passing in
409  *	the device pointer that we found in a previos
410  *	function, returns an error code
411  */
test_device_register()412 static int test_device_register()
413 {
414 	struct device *dev = ltp_mod.dev;
415 	struct device_driver *drv = dev->driver;
416 
417 	/* check if device register returns an error */
418 	if (device_register(dev)) {
419 		printk("tbase: Device not registered\n");
420 		return 1;
421 	} else
422 		printk("tbase: Device registered\n");
423 
424 	driver_unregister(drv);
425 
426 	/* check if driver_register returns an error */
427 	if (driver_register(drv)) {
428 		printk("tbase: Driver not registered\n");
429 		return 1;
430 	} else
431 		printk("tbase: Driver registered\n");
432 
433 	return 0;
434 
435 }
436 
437 /*
438  * test_device_unregister
439  * 	make test call to device_unregister which
440  * 	will in turn make calls that will decrememnt
441  * 	the reference count and clean up as required
442  */
test_device_unregister()443 static int test_device_unregister()
444 {
445 	struct device *dev = ltp_mod.dev;
446 
447 	/* increment reference count */
448 	get_device(dev);
449 
450 	/* reset remove pointer */
451 	if (dev->driver->remove)
452 		dev->driver->remove = NULL;
453 
454 	device_unregister(dev);
455 	//check that reference count is smaller by one
456 
457 	return 0;
458 }
459 
460 /*
461  * test_bus_add
462  *	make call to bus_add_device, which will
463  *	in turn add the device that is passed in
464  *	to the bus
465  */
test_bus_add()466 static int test_bus_add()
467 {
468 	/* check if device register returns an error */
469 	if (bus_add_device(&test_device)) {
470 		printk("tbase: Device not added to bus\n");
471 		return 1;
472 	} else {
473 		printk("tbase: Device added to bus\n");
474 		return 0;
475 	}
476 }
477 
478 /*
479  * test_get_drv
480  *	make test call to get_driver which should
481  *	return a pointer to the driver passed in
482  *	and increase the reference count to that
483  *	kobject
484  */
test_get_drv()485 static int test_get_drv()
486 {
487 	int a, rc;
488 	struct device_driver *drv = &test_driver, *tmp = NULL;
489 
490 	/* get reference count before test call */
491 	a = atomic_read(&drv->kobj.refcount);
492 
493 	/* make test call */
494 	if ((tmp = get_driver(drv))) {
495 		rc = 0;
496 		printk("tbase: get driver returned driver\n");
497 	} else {
498 		rc = 1;
499 		printk("tbase: get driver failed to return driver\n");
500 	}
501 
502 	/* check reference count */
503 	if ((a == (atomic_read(&drv->kobj.refcount) - 1))) {
504 		rc = 0;
505 		printk("tbase: correctly set ref count get driver\n");
506 	} else {
507 		rc = 1;
508 		printk("tbase: incorrect ref count get driver\n");
509 	}
510 
511 	return rc;
512 }
513 
514 /*
515  * test_class_get
516  *	make test call to class_get which should return
517  *	a pointer to the class passed in and increase
518  *	the reference count to that kobject
519  */
test_class_get()520 static int test_class_get()
521 {
522 	int rc;
523 	struct class *tmp = NULL;
524 
525 	/* get reference count before test call */
526 	tmp = class_get(&test_class);
527 	if (tmp == &test_class) {
528 		printk("tbase: Success get class\n");
529 		rc = 0;
530 	} else {
531 		printk("tbase: Failure get class\n");
532 		rc = 1;
533 	}
534 
535 	class_put(&test_class);
536 	return rc;
537 }
538 
539 /*
540  * test_put_drv
541  *      make test call to put_driver which should
542  *      decrease the reference count to the kobject
543  *      pointer in the driver structure
544  */
test_put_drv()545 static int test_put_drv()
546 {
547 	int a, rc;
548 	struct device_driver *drv = &test_driver;
549 
550 	/* get reference count before test call */
551 	a = atomic_read(&drv->kobj.refcount);
552 
553 	/* make test call */
554 	put_driver(drv);
555 
556 	/* check reference count */
557 	if ((a == (atomic_read(&drv->kobj.refcount) + 1))) {
558 		rc = 0;
559 		printk("tbase: correctly set ref count put driver\n");
560 	} else {
561 		rc = 1;
562 		printk("tbase: incorrect ref count put driver\n");
563 	}
564 
565 	return rc;
566 }
567 
568 /*
569  * test_reg_firm
570  *	test call to register_firmware, which will
571  *	register the subsystem, takes in a struct
572  *	subsystem pointer, we can use our bus pointer
573  *	that should have been found in a previous test
574  *	to pass in a subsystem pointer, returns an
575  *	error code
576  */
test_reg_firm()577 static int test_reg_firm()
578 {
579 	struct subsystem *subsys = NULL;
580 
581 	/* check pointer exists */
582 	if (!(subsys = &test_bus_type.subsys)) {
583 		printk("tbase: subsys pointer not set in reg firmware\n");
584 		return 1;
585 	}
586 
587 	/* unregiser firmware */
588 	firmware_unregister(subsys);
589 
590 	/* make test call */
591 	if (firmware_register(subsys)) {
592 		printk("tbase: failed register firmware\n");
593 		return 1;
594 	} else {
595 		printk("tbase: regsitered firmware\n");
596 		return 0;
597 	}
598 
599 }
600 
601 /*
602  * test_create_file
603  *	make test call to create sysfs file for the
604  *	driver and if that call is successful then
605  *	make a call to remove the file
606  */
test_create_file()607 static int test_create_file()
608 {
609 	struct device_driver *drv = &test_driver;
610 
611 	if (driver_create_file(drv, &driver_attr_new_id)) {
612 		printk("tbase: failed create sysfs file\n");
613 		return 1;
614 	} else {
615 		printk("tbase: created sysfs file\n");
616 		driver_remove_file(drv, &driver_attr_new_id);
617 		return 0;
618 	}
619 
620 }
621 
622 /*
623  * test_dev_suspend
624  *	make test call to device_suspend and
625  *	if that call is successful then make
626  *	a call to device_resume
627  */
test_dev_suspend()628 static int test_dev_suspend()
629 {
630 	int error = 0;
631 
632 	error = device_suspend(SUSPEND_SAVE_STATE);
633 	if (error)
634 		printk("tbase: Failed on device suspend call\n");
635 	else {
636 		printk("tbase: Successful on device suspend call\n");
637 		device_resume();
638 	}
639 
640 	error = device_suspend(SUSPEND_DISABLE);
641 	if (error)
642 		printk("tbase: Failed on device suspend call\n");
643 	else {
644 		printk("tbase: Successful on device suspend call\n");
645 		device_resume();
646 	}
647 
648 	return error;
649 
650 }
651 
652 /*
653  * test_dev_file
654  *	make test call to device_create_file
655  *	and if that call is successful make
656  *	another call to device_remove_file
657  */
test_dev_file()658 static int test_dev_file()
659 {
660 	struct device *dev = &test_device;
661 
662 	if (device_create_file(dev, &dev_attr_test_id)) {
663 		printk("tbase: failed to create dev sysfs file\n");
664 		return 1;
665 	} else {
666 		printk("tbase: created dev sysfs file\n");
667 		device_remove_file(dev, &dev_attr_test_id);
668 		return 0;
669 	}
670 
671 }
672 
673 /*
674  * test_bus_rescan
675  *	make test call to bus_rescan_devices which
676  *	will rescan the bus and attempt to match devices
677  *	to drivers, will return 0 for no matches or
678  *	the number of matches made, check that the
679  *	value returned is not negative
680  */
test_bus_rescan()681 static int test_bus_rescan()
682 {
683 	int count = 0;
684 
685 	count = bus_rescan_devices(&test_bus_type);
686 	if (count == 0)
687 		printk("tbase: found no device/driver matches\n");
688 	else if (count > 0)
689 		printk("tbase; found match\n");
690 	else {
691 		printk("tbase: bus rescan failed\n");
692 		return count;
693 	}
694 
695 	return 0;
696 }
697 
698 /*
699  * test_bus_file
700  *      make test call to bus_create_file
701  *      and if that call is successful make
702  *      another call to bus_remove_file
703  */
test_bus_file()704 static int test_bus_file()
705 {
706 	struct bus_type *bus = &test_bus_type;
707 
708 	if (bus_create_file(bus, &bus_attr_test_id)) {
709 		printk("tbase: failed to create bus sysfs file\n");
710 		return 1;
711 	} else {
712 		printk("tbase: created bus sysfs file\n");
713 		bus_remove_file(bus, &bus_attr_test_id);
714 		return 0;
715 	}
716 
717 }
718 
719 /*
720  * test_class_file
721  *      make test call to class_create_file
722  *      and if that call is successful make
723  *      another call to class_remove_file
724  */
test_class_file()725 static int test_class_file()
726 {
727 	struct class *cls = &test_class;
728 
729 	if (class_create_file(cls, &class_attr_test_id)) {
730 		printk("tbase: failed to create class sysfs file\n");
731 		return 1;
732 	} else {
733 		printk("tbase: created class sysfs file\n");
734 		class_remove_file(cls, &class_attr_test_id);
735 		return 0;
736 	}
737 
738 }
739 
740 /*
741  * test_class_reg
742  *	make test call to class_register
743  *	with the test_class that is defined
744  *	in this module, if that call is
745  *	successful then call unregister
746  */
test_class_reg()747 static int test_class_reg()
748 {
749 	int error;
750 
751 	error = class_register(&test_class);
752 	if (error)
753 		printk("tbase: class register failed\n");
754 	else
755 		printk("tbase: class register succeeded\n");
756 
757 	return error;
758 }
759 
760 /*
761  * test_classdev_reg
762  *	make test call to class_device_register
763  *	and if that returns successful then
764  *	make call to class_device_unregister
765  */
test_classdev_reg()766 static int test_classdev_reg()
767 {
768 	int rc = 0;
769 
770 	if (class_device_register(&test_class_dev)) {
771 		printk("tbase: Failed to register class device\n");
772 		rc = 1;
773 	} else {
774 		printk("tbase: Registered class device\n");
775 
776 		/* make class device sysfs file */
777 		if (class_device_create_file
778 		    (&test_class_dev, &class_device_attr_test_id)) {
779 			rc = 1;
780 			printk
781 			    ("tbase: Failed to create class device sysfs file\n");
782 		} else {
783 			printk("tbase: Created class device sysfs file\n");
784 			class_device_remove_file(&test_class_dev,
785 						 &class_device_attr_test_id);
786 		}
787 
788 		class_device_unregister(&test_class_dev);
789 	}
790 
791 	return rc;
792 }
793 
794 /*
795  * test_classint_reg
796  *	make test call to class_interface_register
797  *	and if that returns successfule then
798  *	make call to class_interface_unregister
799  */
test_classint_reg()800 static int test_classint_reg()
801 {
802 
803 	if (class_interface_register(&test_interface)) {
804 		printk("tbase: Failed to register class interface\n");
805 		return 1;
806 	} else {
807 		printk("tbase: Registered class interface\n");
808 		class_interface_unregister(&test_interface);
809 		return 0;
810 	}
811 
812 }
813 
814 /*
815  * test_sysdev_cls_reg
816  *	make test call to sysdev_class_register
817  *	to register the test_sysclass pointer
818  *	as a sysdev_class with the system, check
819  *	the return code
820  */
test_sysdev_cls_reg()821 static int test_sysdev_cls_reg()
822 {
823 
824 	if (sysdev_class_register(&test_sysclass)) {
825 		printk("tbase: Failed to register sysdev class\n");
826 		return 1;
827 	} else {
828 		printk("tbase: Registered sysdev class\n");
829 		return 0;
830 	}
831 
832 }
833 
834 /*
835  * test_sysdev_reg
836  *      make test call to sys_device_register
837  *      to register the test_sysdev pointer
838  *      as a sys_device with the system, check
839  *      the return code
840  */
test_sysdev_reg()841 static int test_sysdev_reg()
842 {
843 
844 	if (sys_device_register(&test_sys_device)) {
845 		printk("tbase: Failed to register sysdev \n");
846 		return 1;
847 	} else {
848 		printk("tbase: Registered sysdev \n");
849 		return 0;
850 	}
851 
852 }
853 
854 /*
855  * tbase_init_module
856  *      set the owner of tbase_fops, register the module
857  *      as a char device, and perform any necessary
858  *      initialization
859  */
tbase_init_module(void)860 static int tbase_init_module(void)
861 {
862 	int rc;
863 
864 	bus_register(&test_bus_type);
865 	driver_register(&test_driver);
866 	device_register(&test_device);
867 
868 	tbase_fops.owner = THIS_MODULE;
869 
870 	printk("tbase: *** Register device %s **\n", DEVICE_NAME);
871 
872 	rc = register_chrdev(Major, DEVICE_NAME, &tbase_fops);
873 	if (rc < 0) {
874 		printk("tbase: Failed to register device.\n");
875 		return rc;
876 	}
877 
878 	if (Major == 0)
879 		Major = rc;
880 
881 	/* call any other init functions you might use here */
882 
883 	printk("tbase: Registration success.\n");
884 	return 0;
885 }
886 
887 /*
888  * tmod_exit_module
889  *      unregister the device and any necessary
890  *      operations to close devices
891  */
tbase_exit_module(void)892 static void tbase_exit_module(void)
893 {
894 	int rc;
895 
896 	device_unregister(&test_device);
897 	driver_unregister(&test_driver);
898 	bus_unregister(&test_bus_type);
899 
900 	/* free any pointers still allocated, using kfree */
901 
902 	rc = unregister_chrdev(Major, DEVICE_NAME);
903 	if (rc < 0)
904 		printk("tbase: unregister failed\n");
905 	else
906 		printk("tbase: unregister success\n");
907 
908 }
909 
910 /* specify what that init is run when the module is first
911 loaded and that exit is run when it is removed */
912 
913 module_init(tbase_init_module)
914     module_exit(tbase_exit_module)
915