diff options
Diffstat (limited to 'drivers/uio')
-rw-r--r-- | drivers/uio/uio.c | 58 |
1 files changed, 15 insertions, 43 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index bff1afbde5a4..bc774cce0a4d 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c | |||
@@ -45,10 +45,7 @@ static DEFINE_IDR(uio_idr); | |||
45 | static const struct file_operations uio_fops; | 45 | static const struct file_operations uio_fops; |
46 | 46 | ||
47 | /* UIO class infrastructure */ | 47 | /* UIO class infrastructure */ |
48 | static struct uio_class { | 48 | static struct class *uio_class; |
49 | struct kref kref; | ||
50 | struct class *class; | ||
51 | } *uio_class; | ||
52 | 49 | ||
53 | /* Protect idr accesses */ | 50 | /* Protect idr accesses */ |
54 | static DEFINE_MUTEX(minor_lock); | 51 | static DEFINE_MUTEX(minor_lock); |
@@ -757,55 +754,35 @@ static void uio_major_cleanup(void) | |||
757 | 754 | ||
758 | static int init_uio_class(void) | 755 | static int init_uio_class(void) |
759 | { | 756 | { |
760 | int ret = 0; | 757 | struct class *class; |
761 | 758 | int ret; | |
762 | if (uio_class != NULL) { | ||
763 | kref_get(&uio_class->kref); | ||
764 | goto exit; | ||
765 | } | ||
766 | 759 | ||
767 | /* This is the first time in here, set everything up properly */ | 760 | /* This is the first time in here, set everything up properly */ |
768 | ret = uio_major_init(); | 761 | ret = uio_major_init(); |
769 | if (ret) | 762 | if (ret) |
770 | goto exit; | 763 | goto exit; |
771 | 764 | ||
772 | uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); | 765 | class = class_create(THIS_MODULE, "uio"); |
773 | if (!uio_class) { | 766 | if (IS_ERR(class)) { |
774 | ret = -ENOMEM; | 767 | ret = IS_ERR(class); |
775 | goto err_kzalloc; | ||
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"); | 768 | printk(KERN_ERR "class_create failed for uio\n"); |
783 | goto err_class_create; | 769 | goto err_class_create; |
784 | } | 770 | } |
771 | uio_class = class; | ||
785 | return 0; | 772 | return 0; |
786 | 773 | ||
787 | err_class_create: | 774 | err_class_create: |
788 | kfree(uio_class); | ||
789 | uio_class = NULL; | ||
790 | err_kzalloc: | ||
791 | uio_major_cleanup(); | 775 | uio_major_cleanup(); |
792 | exit: | 776 | exit: |
793 | return ret; | 777 | return ret; |
794 | } | 778 | } |
795 | 779 | ||
796 | static void release_uio_class(struct kref *kref) | 780 | static void release_uio_class(void) |
797 | { | 781 | { |
798 | /* Ok, we cheat as we know we only have one uio_class */ | 782 | /* Ok, we cheat as we know we only have one uio_class */ |
799 | class_destroy(uio_class->class); | 783 | class_destroy(uio_class); |
800 | kfree(uio_class); | ||
801 | uio_major_cleanup(); | ||
802 | uio_class = NULL; | 784 | uio_class = NULL; |
803 | } | 785 | uio_major_cleanup(); |
804 | |||
805 | static void uio_class_destroy(void) | ||
806 | { | ||
807 | if (uio_class) | ||
808 | kref_put(&uio_class->kref, release_uio_class); | ||
809 | } | 786 | } |
810 | 787 | ||
811 | /** | 788 | /** |
@@ -828,10 +805,6 @@ int __uio_register_device(struct module *owner, | |||
828 | 805 | ||
829 | info->uio_dev = NULL; | 806 | info->uio_dev = NULL; |
830 | 807 | ||
831 | ret = init_uio_class(); | ||
832 | if (ret) | ||
833 | return ret; | ||
834 | |||
835 | idev = kzalloc(sizeof(*idev), GFP_KERNEL); | 808 | idev = kzalloc(sizeof(*idev), GFP_KERNEL); |
836 | if (!idev) { | 809 | if (!idev) { |
837 | ret = -ENOMEM; | 810 | ret = -ENOMEM; |
@@ -847,7 +820,7 @@ int __uio_register_device(struct module *owner, | |||
847 | if (ret) | 820 | if (ret) |
848 | goto err_get_minor; | 821 | goto err_get_minor; |
849 | 822 | ||
850 | idev->dev = device_create(uio_class->class, parent, | 823 | idev->dev = device_create(uio_class, parent, |
851 | MKDEV(uio_major, idev->minor), idev, | 824 | MKDEV(uio_major, idev->minor), idev, |
852 | "uio%d", idev->minor); | 825 | "uio%d", idev->minor); |
853 | if (IS_ERR(idev->dev)) { | 826 | if (IS_ERR(idev->dev)) { |
@@ -874,13 +847,12 @@ int __uio_register_device(struct module *owner, | |||
874 | err_request_irq: | 847 | err_request_irq: |
875 | uio_dev_del_attributes(idev); | 848 | uio_dev_del_attributes(idev); |
876 | err_uio_dev_add_attributes: | 849 | err_uio_dev_add_attributes: |
877 | device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); | 850 | device_destroy(uio_class, MKDEV(uio_major, idev->minor)); |
878 | err_device_create: | 851 | err_device_create: |
879 | uio_free_minor(idev); | 852 | uio_free_minor(idev); |
880 | err_get_minor: | 853 | err_get_minor: |
881 | kfree(idev); | 854 | kfree(idev); |
882 | err_kzalloc: | 855 | err_kzalloc: |
883 | uio_class_destroy(); | ||
884 | return ret; | 856 | return ret; |
885 | } | 857 | } |
886 | EXPORT_SYMBOL_GPL(__uio_register_device); | 858 | EXPORT_SYMBOL_GPL(__uio_register_device); |
@@ -907,9 +879,8 @@ void uio_unregister_device(struct uio_info *info) | |||
907 | uio_dev_del_attributes(idev); | 879 | uio_dev_del_attributes(idev); |
908 | 880 | ||
909 | dev_set_drvdata(idev->dev, NULL); | 881 | dev_set_drvdata(idev->dev, NULL); |
910 | device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); | 882 | device_destroy(uio_class, MKDEV(uio_major, idev->minor)); |
911 | kfree(idev); | 883 | kfree(idev); |
912 | uio_class_destroy(); | ||
913 | 884 | ||
914 | return; | 885 | return; |
915 | } | 886 | } |
@@ -917,11 +888,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device); | |||
917 | 888 | ||
918 | static int __init uio_init(void) | 889 | static int __init uio_init(void) |
919 | { | 890 | { |
920 | return 0; | 891 | return init_uio_class(); |
921 | } | 892 | } |
922 | 893 | ||
923 | static void __exit uio_exit(void) | 894 | static void __exit uio_exit(void) |
924 | { | 895 | { |
896 | release_uio_class(); | ||
925 | } | 897 | } |
926 | 898 | ||
927 | module_init(uio_init) | 899 | module_init(uio_init) |