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