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.c182
1 files changed, 81 insertions, 101 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bff1afbde5a4..d2efe823c20d 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de> 4 * Copyright(C) 2005, Benedikt Spranger <b.spranger@linutronix.de>
5 * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> 5 * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de>
6 * Copyright(C) 2006, Hans J. Koch <hjk@linutronix.de> 6 * Copyright(C) 2006, Hans J. Koch <hjk@hansjkoch.de>
7 * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com> 7 * Copyright(C) 2006, Greg Kroah-Hartman <greg@kroah.com>
8 * 8 *
9 * Userspace IO 9 * Userspace IO
@@ -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)
@@ -404,7 +381,13 @@ static int uio_get_minor(struct uio_device *idev)
404 retval = -ENOMEM; 381 retval = -ENOMEM;
405 goto exit; 382 goto exit;
406 } 383 }
407 idev->minor = id & MAX_ID_MASK; 384 if (id < UIO_MAX_DEVICES) {
385 idev->minor = id;
386 } else {
387 dev_err(idev->dev, "too many uio devices\n");
388 retval = -EINVAL;
389 idr_remove(&uio_idr, id);
390 }
408exit: 391exit:
409 mutex_unlock(&minor_lock); 392 mutex_unlock(&minor_lock);
410 return retval; 393 return retval;
@@ -525,7 +508,7 @@ static unsigned int uio_poll(struct file *filep, poll_table *wait)
525 struct uio_listener *listener = filep->private_data; 508 struct uio_listener *listener = filep->private_data;
526 struct uio_device *idev = listener->dev; 509 struct uio_device *idev = listener->dev;
527 510
528 if (idev->info->irq == UIO_IRQ_NONE) 511 if (!idev->info->irq)
529 return -EIO; 512 return -EIO;
530 513
531 poll_wait(filep, &idev->wait, wait); 514 poll_wait(filep, &idev->wait, wait);
@@ -543,7 +526,7 @@ static ssize_t uio_read(struct file *filep, char __user *buf,
543 ssize_t retval; 526 ssize_t retval;
544 s32 event_count; 527 s32 event_count;
545 528
546 if (idev->info->irq == UIO_IRQ_NONE) 529 if (!idev->info->irq)
547 return -EIO; 530 return -EIO;
548 531
549 if (count != sizeof(s32)) 532 if (count != sizeof(s32))
@@ -591,7 +574,7 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
591 ssize_t retval; 574 ssize_t retval;
592 s32 irq_on; 575 s32 irq_on;
593 576
594 if (idev->info->irq == UIO_IRQ_NONE) 577 if (!idev->info->irq)
595 return -EIO; 578 return -EIO;
596 579
597 if (count != sizeof(s32)) 580 if (count != sizeof(s32))
@@ -610,14 +593,12 @@ static ssize_t uio_write(struct file *filep, const char __user *buf,
610 593
611static int uio_find_mem_index(struct vm_area_struct *vma) 594static int uio_find_mem_index(struct vm_area_struct *vma)
612{ 595{
613 int mi;
614 struct uio_device *idev = vma->vm_private_data; 596 struct uio_device *idev = vma->vm_private_data;
615 597
616 for (mi = 0; mi < MAX_UIO_MAPS; mi++) { 598 if (vma->vm_pgoff < MAX_UIO_MAPS) {
617 if (idev->info->mem[mi].size == 0) 599 if (idev->info->mem[vma->vm_pgoff].size == 0)
618 return -1; 600 return -1;
619 if (vma->vm_pgoff == mi) 601 return (int)vma->vm_pgoff;
620 return mi;
621 } 602 }
622 return -1; 603 return -1;
623} 604}
@@ -740,72 +721,77 @@ static const struct file_operations uio_fops = {
740 .mmap = uio_mmap, 721 .mmap = uio_mmap,
741 .poll = uio_poll, 722 .poll = uio_poll,
742 .fasync = uio_fasync, 723 .fasync = uio_fasync,
724 .llseek = noop_llseek,
743}; 725};
744 726
745static int uio_major_init(void) 727static int uio_major_init(void)
746{ 728{
747 uio_major = register_chrdev(0, "uio", &uio_fops); 729 static const char name[] = "uio";
748 if (uio_major < 0) 730 struct cdev *cdev = NULL;
749 return uio_major; 731 dev_t uio_dev = 0;
750 return 0; 732 int result;
733
734 result = alloc_chrdev_region(&uio_dev, 0, UIO_MAX_DEVICES, name);
735 if (result)
736 goto out;
737
738 result = -ENOMEM;
739 cdev = cdev_alloc();
740 if (!cdev)
741 goto out_unregister;
742
743 cdev->owner = THIS_MODULE;
744 cdev->ops = &uio_fops;
745 kobject_set_name(&cdev->kobj, "%s", name);
746
747 result = cdev_add(cdev, uio_dev, UIO_MAX_DEVICES);
748 if (result)
749 goto out_put;
750
751 uio_major = MAJOR(uio_dev);
752 uio_cdev = cdev;
753 result = 0;
754out:
755 return result;
756out_put:
757 kobject_put(&cdev->kobj);
758out_unregister:
759 unregister_chrdev_region(uio_dev, UIO_MAX_DEVICES);
760 goto out;
751} 761}
752 762
753static void uio_major_cleanup(void) 763static void uio_major_cleanup(void)
754{ 764{
755 unregister_chrdev(uio_major, "uio"); 765 unregister_chrdev_region(MKDEV(uio_major, 0), UIO_MAX_DEVICES);
766 cdev_del(uio_cdev);
756} 767}
757 768
758static int init_uio_class(void) 769static int init_uio_class(void)
759{ 770{
760 int ret = 0; 771 int ret;
761
762 if (uio_class != NULL) {
763 kref_get(&uio_class->kref);
764 goto exit;
765 }
766 772
767 /* This is the first time in here, set everything up properly */ 773 /* This is the first time in here, set everything up properly */
768 ret = uio_major_init(); 774 ret = uio_major_init();
769 if (ret) 775 if (ret)
770 goto exit; 776 goto exit;
771 777
772 uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); 778 ret = class_register(&uio_class);
773 if (!uio_class) { 779 if (ret) {
774 ret = -ENOMEM; 780 printk(KERN_ERR "class_register failed for uio\n");
775 goto err_kzalloc; 781 goto err_class_register;
776 }
777
778 kref_init(&uio_class->kref);
779 uio_class->class = class_create(THIS_MODULE, "uio");
780 if (IS_ERR(uio_class->class)) {
781 ret = IS_ERR(uio_class->class);
782 printk(KERN_ERR "class_create failed for uio\n");
783 goto err_class_create;
784 } 782 }
785 return 0; 783 return 0;
786 784
787err_class_create: 785err_class_register:
788 kfree(uio_class);
789 uio_class = NULL;
790err_kzalloc:
791 uio_major_cleanup(); 786 uio_major_cleanup();
792exit: 787exit:
793 return ret; 788 return ret;
794} 789}
795 790
796static void release_uio_class(struct kref *kref) 791static void release_uio_class(void)
797{ 792{
798 /* Ok, we cheat as we know we only have one uio_class */ 793 class_unregister(&uio_class);
799 class_destroy(uio_class->class);
800 kfree(uio_class);
801 uio_major_cleanup(); 794 uio_major_cleanup();
802 uio_class = NULL;
803}
804
805static void uio_class_destroy(void)
806{
807 if (uio_class)
808 kref_put(&uio_class->kref, release_uio_class);
809} 795}
810 796
811/** 797/**
@@ -828,10 +814,6 @@ int __uio_register_device(struct module *owner,
828 814
829 info->uio_dev = NULL; 815 info->uio_dev = NULL;
830 816
831 ret = init_uio_class();
832 if (ret)
833 return ret;
834
835 idev = kzalloc(sizeof(*idev), GFP_KERNEL); 817 idev = kzalloc(sizeof(*idev), GFP_KERNEL);
836 if (!idev) { 818 if (!idev) {
837 ret = -ENOMEM; 819 ret = -ENOMEM;
@@ -847,7 +829,7 @@ int __uio_register_device(struct module *owner,
847 if (ret) 829 if (ret)
848 goto err_get_minor; 830 goto err_get_minor;
849 831
850 idev->dev = device_create(uio_class->class, parent, 832 idev->dev = device_create(&uio_class, parent,
851 MKDEV(uio_major, idev->minor), idev, 833 MKDEV(uio_major, idev->minor), idev,
852 "uio%d", idev->minor); 834 "uio%d", idev->minor);
853 if (IS_ERR(idev->dev)) { 835 if (IS_ERR(idev->dev)) {
@@ -862,9 +844,9 @@ int __uio_register_device(struct module *owner,
862 844
863 info->uio_dev = idev; 845 info->uio_dev = idev;
864 846
865 if (idev->info->irq >= 0) { 847 if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
866 ret = request_irq(idev->info->irq, uio_interrupt, 848 ret = request_irq(info->irq, uio_interrupt,
867 idev->info->irq_flags, idev->info->name, idev); 849 info->irq_flags, info->name, idev);
868 if (ret) 850 if (ret)
869 goto err_request_irq; 851 goto err_request_irq;
870 } 852 }
@@ -874,13 +856,12 @@ int __uio_register_device(struct module *owner,
874err_request_irq: 856err_request_irq:
875 uio_dev_del_attributes(idev); 857 uio_dev_del_attributes(idev);
876err_uio_dev_add_attributes: 858err_uio_dev_add_attributes:
877 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); 859 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
878err_device_create: 860err_device_create:
879 uio_free_minor(idev); 861 uio_free_minor(idev);
880err_get_minor: 862err_get_minor:
881 kfree(idev); 863 kfree(idev);
882err_kzalloc: 864err_kzalloc:
883 uio_class_destroy();
884 return ret; 865 return ret;
885} 866}
886EXPORT_SYMBOL_GPL(__uio_register_device); 867EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -901,15 +882,13 @@ void uio_unregister_device(struct uio_info *info)
901 882
902 uio_free_minor(idev); 883 uio_free_minor(idev);
903 884
904 if (info->irq >= 0) 885 if (info->irq && (info->irq != UIO_IRQ_CUSTOM))
905 free_irq(info->irq, idev); 886 free_irq(info->irq, idev);
906 887
907 uio_dev_del_attributes(idev); 888 uio_dev_del_attributes(idev);
908 889
909 dev_set_drvdata(idev->dev, NULL); 890 device_destroy(&uio_class, MKDEV(uio_major, idev->minor));
910 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor));
911 kfree(idev); 891 kfree(idev);
912 uio_class_destroy();
913 892
914 return; 893 return;
915} 894}
@@ -917,11 +896,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
917 896
918static int __init uio_init(void) 897static int __init uio_init(void)
919{ 898{
920 return 0; 899 return init_uio_class();
921} 900}
922 901
923static void __exit uio_exit(void) 902static void __exit uio_exit(void)
924{ 903{
904 release_uio_class();
925} 905}
926 906
927module_init(uio_init) 907module_init(uio_init)