Home | History | Annotate | Download | only in tbase
      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 (at) 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 
     86 static int tbase_open(struct inode *ino, struct file *f)
     87 {
     88 	return 0;
     89 }
     90 
     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 
    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 */
    122 int test_dev_probe(struct device *dev)
    123 {
    124 	printk("tbase: Entered test_dev_probe\n");
    125 	return 0;
    126 }
    127 
    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 */
    149 static void test_class_release(struct class_device *class_dev)
    150 {
    151 	printk("tbase: Entered test_class_release\n");
    152 }
    153 
    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 */
    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 
    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 */
    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
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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