aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uio/uio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/uio/uio.c')
-rw-r--r--drivers/uio/uio.c163
1 files changed, 69 insertions, 94 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 4d3a6fd1a152..a858d2b87b94 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -23,9 +23,10 @@
23#include <linux/sched.h> 23#include <linux/sched.h>
24#include <linux/string.h> 24#include <linux/string.h>
25#include <linux/kobject.h> 25#include <linux/kobject.h>
26#include <linux/cdev.h>
26#include <linux/uio_driver.h> 27#include <linux/uio_driver.h>
27 28
28#define UIO_MAX_DEVICES 255 29#define UIO_MAX_DEVICES (1U << MINORBITS)
29 30
30struct uio_device { 31struct uio_device {
31 struct module *owner; 32 struct module *owner;
@@ -41,15 +42,10 @@ struct uio_device {
41}; 42};
42 43
43static int uio_major; 44static int uio_major;
45static struct cdev *uio_cdev;
44static DEFINE_IDR(uio_idr); 46static DEFINE_IDR(uio_idr);
45static const struct file_operations uio_fops; 47static const struct file_operations uio_fops;
46 48
47/* UIO class infrastructure */
48static struct uio_class {
49 struct kref kref;
50 struct class *class;
51} *uio_class;
52
53/* Protect idr accesses */ 49/* Protect idr accesses */
54static DEFINE_MUTEX(minor_lock); 50static DEFINE_MUTEX(minor_lock);
55 51
@@ -232,45 +228,34 @@ static ssize_t show_name(struct device *dev,
232 struct device_attribute *attr, char *buf) 228 struct device_attribute *attr, char *buf)
233{ 229{
234 struct uio_device *idev = dev_get_drvdata(dev); 230 struct uio_device *idev = dev_get_drvdata(dev);
235 if (idev) 231 return sprintf(buf, "%s\n", idev->info->name);
236 return sprintf(buf, "%s\n", idev->info->name);
237 else
238 return -ENODEV;
239} 232}
240static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
241 233
242static ssize_t show_version(struct device *dev, 234static ssize_t show_version(struct device *dev,
243 struct device_attribute *attr, char *buf) 235 struct device_attribute *attr, char *buf)
244{ 236{
245 struct uio_device *idev = dev_get_drvdata(dev); 237 struct uio_device *idev = dev_get_drvdata(dev);
246 if (idev) 238 return sprintf(buf, "%s\n", idev->info->version);
247 return sprintf(buf, "%s\n", idev->info->version);
248 else
249 return -ENODEV;
250} 239}
251static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
252 240
253static ssize_t show_event(struct device *dev, 241static ssize_t show_event(struct device *dev,
254 struct device_attribute *attr, char *buf) 242 struct device_attribute *attr, char *buf)
255{ 243{
256 struct uio_device *idev = dev_get_drvdata(dev); 244 struct uio_device *idev = dev_get_drvdata(dev);
257 if (idev) 245 return sprintf(buf, "%u\n", (unsigned int)atomic_read(&idev->event));
258 return sprintf(buf, "%u\n",
259 (unsigned int)atomic_read(&idev->event));
260 else
261 return -ENODEV;
262} 246}
263static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
264 247
265static struct attribute *uio_attrs[] = { 248static struct device_attribute uio_class_attributes[] = {
266 &dev_attr_name.attr, 249 __ATTR(name, S_IRUGO, show_name, NULL),
267 &dev_attr_version.attr, 250 __ATTR(version, S_IRUGO, show_version, NULL),
268 &dev_attr_event.attr, 251 __ATTR(event, S_IRUGO, show_event, NULL),
269 NULL, 252 {}
270}; 253};
271 254
272static struct attribute_group uio_attr_grp = { 255/* UIO class infrastructure */
273 .attrs = uio_attrs, 256static struct class uio_class = {
257 .name = "uio",
258 .dev_attrs = uio_class_attributes,
274}; 259};
275 260
276/* 261/*
@@ -287,10 +272,6 @@ static int uio_dev_add_attributes(struct uio_device *idev)
287 struct uio_port *port; 272 struct uio_port *port;
288 struct uio_portio *portio; 273 struct uio_portio *portio;
289 274
290 ret = sysfs_create_group(&idev->dev->kobj, &uio_attr_grp);
291 if (ret)
292 goto err_group;
293
294 for (mi = 0; mi < MAX_UIO_MAPS; mi++) { 275 for (mi = 0; mi < MAX_UIO_MAPS; mi++) {
295 mem = &idev->info->mem[mi]; 276 mem = &idev->info->mem[mi];
296 if (mem->size == 0) 277 if (mem->size == 0)
@@ -358,8 +339,6 @@ err_map:
358 kobject_put(&map->kobj); 339 kobject_put(&map->kobj);
359 } 340 }
360 kobject_put(idev->map_dir); 341 kobject_put(idev->map_dir);
361 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
362err_group:
363 dev_err(idev->dev, "error creating sysfs files (%d)\n", ret); 342 dev_err(idev->dev, "error creating sysfs files (%d)\n", ret);
364 return ret; 343 return ret;
365} 344}
@@ -385,8 +364,6 @@ static void uio_dev_del_attributes(struct uio_device *idev)
385 kobject_put(&port->portio->kobj); 364 kobject_put(&port->portio->kobj);
386 } 365 }
387 kobject_put(idev->portio_dir); 366 kobject_put(idev->portio_dir);
388
389 sysfs_remove_group(&idev->dev->kobj, &uio_attr_grp);
390} 367}
391 368
392static int uio_get_minor(struct uio_device *idev) 369static int uio_get_minor(struct uio_device *idev)
@@ -525,7 +502,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
525 struct uio_listener *listener = filep->private_data; 502 struct uio_listener *listener = filep->private_data;
526 struct uio_device *idev = listener->dev; 503 struct uio_device *idev = listener->dev;
527 504
528 if (idev->info->irq == UIO_IRQ_NONE) 505 if (!idev->info->irq)
529 return -EIO; 506 return -EIO;
530 507
531 poll_wait(filep, &idev->wait, wait); 508 poll_wait(filep, &idev->wait, wait);
@@ -543,7 +520,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
543 ssize_t retval; 520 ssize_t retval;
544 s32 event_count; 521 s32 event_count;
545 522
546 if (idev->info->irq == UIO_IRQ_NONE) 523 if (!idev->info->irq)
547 return -EIO; 524 return -EIO;
548 525
549 if (count != sizeof(s32)) 526 if (count != sizeof(s32))
@@ -591,7 +568,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
591 ssize_t retval; 568 ssize_t retval;
592 s32 irq_on; 569 s32 irq_on;
593 570
594 if (idev->info->irq == UIO_IRQ_NONE) 571 if (!idev->info->irq)
595 return -EIO; 572 return -EIO;
596 573
597 if (count != sizeof(s32)) 574 if (count != sizeof(s32))
@@ -745,68 +722,72 @@ static const struct file_operations uio_fops = {
745 722
746static int uio_major_init(void) 723static int uio_major_init(void)
747{ 724{
748 uio_major = register_chrdev(0, "uio", &uio_fops); 725 static const char name[] = "uio";
749 if (uio_major < 0) 726 struct cdev *cdev = NULL;
750 return uio_major; 727 dev_t uio_dev = 0;
751 return 0; 728 int result;
729
730 result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
731 if (result)
732 goto out;
733
734 result = -ENOMEM;
735 cdev = cdev_alloc();
736 if (!cdev)
737 goto out_unregister;
738
739 cdev->owner = THIS_MODULE;
740 cdev->ops = &uio_fops;
741 kobject_set_name(&cdev->kobj, "%s", name);
742
743 result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
744 if (result)
745 goto out_put;
746
747 uio_major = MAJOR(uio_dev);
748 uio_cdev = cdev;
749 result = 0;
750out:
751 return result;
752out_put:
753 kobject_put(&cdev->kobj);
754out_unregister:
755 unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
756 goto out;
752} 757}
753 758
754static void uio_major_cleanup(void) 759static void uio_major_cleanup(void)
755{ 760{
756 unregister_chrdev(uio_major, "uio"); 761 unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
762 cdev_del(uio_cdev);
757} 763}
758 764
759static int init_uio_class(void) 765static int init_uio_class(void)
760{ 766{
761 int ret = 0; 767 int ret;
762
763 if (uio_class != NULL) {
764 kref_get(&uio_class->kref);
765 goto exit;
766 }
767 768
768 /* This is the first time in here, set everything up properly */ 769 /* This is the first time in here, set everything up properly */
769 ret = uio_major_init(); 770 ret = uio_major_init();
770 if (ret) 771 if (ret)
771 goto exit; 772 goto exit;
772 773
773 uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); 774 ret = class_register(&uio_class);
774 if (!uio_class) { 775 if (ret) {
775 ret = -ENOMEM; 776 printk(KERN_ERR "class_register failed for uio\n");
776 goto err_kzalloc; 777 goto err_class_register;
777 }
778
779 kref_init(&uio_class->kref);
780 uio_class->class = class_create(THIS_MODULE, "uio");
781 if (IS_ERR(uio_class->class)) {
782 ret = IS_ERR(uio_class->class);
783 printk(KERN_ERR "class_create failed for uio\n");
784 goto err_class_create;
785 } 778 }
786 return 0; 779 return 0;
787 780
788err_class_create: 781err_class_register:
789 kfree(uio_class);
790 uio_class = NULL;
791err_kzalloc:
792 uio_major_cleanup(); 782 uio_major_cleanup();
793exit: 783exit:
794 return ret; 784 return ret;
795} 785}
796 786
797static void release_uio_class(struct kref *kref) 787static void release_uio_class(void)
798{ 788{
799 /* Ok, we cheat as we know we only have one uio_class */ 789 class_unregister(&uio_class);
800 class_destroy(uio_class->class);
801 kfree(uio_class);
802 uio_major_cleanup(); 790 uio_major_cleanup();
803 uio_class = NULL;
804}
805
806static void uio_class_destroy(void)
807{
808 if (uio_class)
809 kref_put(&uio_class->kref, release_uio_class);
810} 791}
811 792
812/** 793/**
@@ -829,10 +810,6 @@ int __uio_register_device(struct module *owner,
829 810
830 info->uio_dev = NULL; 811 info->uio_dev = NULL;
831 812
832 ret = init_uio_class();
833 if (ret)
834 return ret;
835
836 idev = kzalloc(sizeof(*idev), GFP_KERNEL); 813 idev = kzalloc(sizeof(*idev), GFP_KERNEL);
837 if (!idev) { 814 if (!idev) {
838 ret = -ENOMEM; 815 ret = -ENOMEM;
@@ -848,7 +825,7 @@ int __uio_register_device(struct module *owner,
848 if (ret) 825 if (ret)
849 goto err_get_minor; 826 goto err_get_minor;
850 827
851 idev->dev = device_create(uio_class->class, parent, 828 idev->dev = device_create(&uio_class, parent,
852 MKDEV(uio_major, idev->minor), idev, 829 MKDEV(uio_major, idev->minor), idev,
853 "uio%d", idev->minor); 830 "uio%d", idev->minor);
854 if (IS_ERR(idev->dev)) { 831 if (IS_ERR(idev->dev)) {
@@ -863,9 +840,9 @@ int __uio_register_device(struct module *owner,
863 840
864 info->uio_dev = idev; 841 info->uio_dev = idev;
865 842
866 if (idev->info->irq >= 0) { 843 if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
867 ret = request_irq(idev->info->irq, uio_interrupt, 844 ret = request_irq(info->irq, uio_interrupt,
868 idev->info->irq_flags, idev->info->name, idev); 845 info->irq_flags, info->name, idev);
869 if (ret) 846 if (ret)
870 goto err_request_irq; 847 goto err_request_irq;
871 } 848 }
@@ -875,13 +852,12 @@ int __uio_register_device(struct module *owner,
875err_request_irq: 852err_request_irq:
876 uio_dev_del_attributes(idev); 853 uio_dev_del_attributes(idev);
877err_uio_dev_add_attributes: 854err_uio_dev_add_attributes:
878 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); 855 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
879err_device_create: 856err_device_create:
880 uio_free_minor(idev); 857 uio_free_minor(idev);
881err_get_minor: 858err_get_minor:
882 kfree(idev); 859 kfree(idev);
883err_kzalloc: 860err_kzalloc:
884 uio_class_destroy();
885 return ret; 861 return ret;
886} 862}
887EXPORT_SYMBOL_GPL(__uio_register_device); 863EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -902,15 +878,13 @@ void uio_unregister_device(struct uio_info *info)
902 878
903 uio_free_minor(idev); 879 uio_free_minor(idev);
904 880
905 if (info->irq >= 0) 881 if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
906 free_irq(info->irq, idev); 882 free_irq(info->irq, idev);
907 883
908 uio_dev_del_attributes(idev); 884 uio_dev_del_attributes(idev);
909 885
910 dev_set_drvdata(idev->dev, NULL); 886 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
911 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
912 kfree(idev); 887 kfree(idev);
913 uio_class_destroy();
914 888
915 return; 889 return;
916} 890}
@@ -918,11 +892,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
918 892
919static int __init uio_init(void) 893static int __init uio_init(void)
920{ 894{
921 return 0; 895 return init_uio_class();
922} 896}
923 897
924static void __exit uio_exit(void) 898static void __exit uio_exit(void)
925{ 899{
900 release_uio_class();
926} 901}
927 902
928module_init(uio_init) 903module_init(uio_init)