diff options
-rw-r--r-- | drivers/mtd/ubi/build.c | 52 | ||||
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 10 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 3 |
3 files changed, 54 insertions, 11 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index b3efb2fa3c10..3f37b16f8774 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
@@ -21,11 +21,16 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * This file includes UBI initialization and building of UBI devices. At the | 24 | * This file includes UBI initialization and building of UBI devices. |
25 | * moment UBI devices may only be added while UBI is initialized, but dynamic | 25 | * |
26 | * device add/remove functionality is planned. Also, at the moment we only | 26 | * When UBI is initialized, it attaches all the MTD devices specified as the |
27 | * attach UBI devices by scanning, which will become a bottleneck when flashes | 27 | * module load parameters or the kernel boot parameters. If MTD devices were |
28 | * reach certain large size. Then one may improve UBI and add other methods. | 28 | * specified, UBI does not attach any MTD device, but it is possible to do |
29 | * later using the "UBI control device". | ||
30 | * | ||
31 | * At the moment we only attach UBI devices by scanning, which will become a | ||
32 | * bottleneck when flashes reach certain large size. Then one may improve UBI | ||
33 | * and add other methods, although it does not seem to be easy to do. | ||
29 | */ | 34 | */ |
30 | 35 | ||
31 | #include <linux/err.h> | 36 | #include <linux/err.h> |
@@ -33,6 +38,7 @@ | |||
33 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
34 | #include <linux/stringify.h> | 39 | #include <linux/stringify.h> |
35 | #include <linux/stat.h> | 40 | #include <linux/stat.h> |
41 | #include <linux/miscdevice.h> | ||
36 | #include <linux/log2.h> | 42 | #include <linux/log2.h> |
37 | #include "ubi.h" | 43 | #include "ubi.h" |
38 | 44 | ||
@@ -70,6 +76,12 @@ struct kmem_cache *ubi_ltree_slab; | |||
70 | /* Slab cache for wear-leveling entries */ | 76 | /* Slab cache for wear-leveling entries */ |
71 | struct kmem_cache *ubi_wl_entry_slab; | 77 | struct kmem_cache *ubi_wl_entry_slab; |
72 | 78 | ||
79 | /* UBI control character device */ | ||
80 | static struct miscdevice ubi_ctrl_cdev = { | ||
81 | .minor = MISC_DYNAMIC_MINOR, | ||
82 | .name = "ubi_ctrl", | ||
83 | .fops = &ubi_ctrl_cdev_operations, | ||
84 | }; | ||
73 | 85 | ||
74 | /* "Show" method for files in '/<sysfs>/class/ubi/' */ | 86 | /* "Show" method for files in '/<sysfs>/class/ubi/' */ |
75 | static ssize_t ubi_version_show(struct class *class, char *buf) | 87 | static ssize_t ubi_version_show(struct class *class, char *buf) |
@@ -701,19 +713,31 @@ static int __init ubi_init(void) | |||
701 | return -EINVAL; | 713 | return -EINVAL; |
702 | } | 714 | } |
703 | 715 | ||
716 | /* Create base sysfs directory and sysfs files */ | ||
704 | ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); | 717 | ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); |
705 | if (IS_ERR(ubi_class)) | 718 | if (IS_ERR(ubi_class)) { |
706 | return PTR_ERR(ubi_class); | 719 | err = PTR_ERR(ubi_class); |
720 | printk(KERN_ERR "UBI error: cannot create UBI class\n"); | ||
721 | goto out; | ||
722 | } | ||
707 | 723 | ||
708 | err = class_create_file(ubi_class, &ubi_version); | 724 | err = class_create_file(ubi_class, &ubi_version); |
709 | if (err) | 725 | if (err) { |
726 | printk(KERN_ERR "UBI error: cannot create sysfs file\n"); | ||
710 | goto out_class; | 727 | goto out_class; |
728 | } | ||
729 | |||
730 | err = misc_register(&ubi_ctrl_cdev); | ||
731 | if (err) { | ||
732 | printk(KERN_ERR "UBI error: cannot register device\n"); | ||
733 | goto out_version; | ||
734 | } | ||
711 | 735 | ||
712 | ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab", | 736 | ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab", |
713 | sizeof(struct ubi_ltree_entry), 0, | 737 | sizeof(struct ubi_ltree_entry), 0, |
714 | 0, <ree_entry_ctor); | 738 | 0, <ree_entry_ctor); |
715 | if (!ubi_ltree_slab) | 739 | if (!ubi_ltree_slab) |
716 | goto out_version; | 740 | goto out_dev_unreg; |
717 | 741 | ||
718 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", | 742 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", |
719 | sizeof(struct ubi_wl_entry), | 743 | sizeof(struct ubi_wl_entry), |
@@ -727,8 +751,11 @@ static int __init ubi_init(void) | |||
727 | 751 | ||
728 | cond_resched(); | 752 | cond_resched(); |
729 | err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs); | 753 | err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs); |
730 | if (err) | 754 | if (err) { |
755 | printk(KERN_ERR "UBI error: cannot attach %s\n", | ||
756 | p->name); | ||
731 | goto out_detach; | 757 | goto out_detach; |
758 | } | ||
732 | } | 759 | } |
733 | 760 | ||
734 | return 0; | 761 | return 0; |
@@ -739,10 +766,14 @@ out_detach: | |||
739 | kmem_cache_destroy(ubi_wl_entry_slab); | 766 | kmem_cache_destroy(ubi_wl_entry_slab); |
740 | out_ltree: | 767 | out_ltree: |
741 | kmem_cache_destroy(ubi_ltree_slab); | 768 | kmem_cache_destroy(ubi_ltree_slab); |
769 | out_dev_unreg: | ||
770 | misc_deregister(&ubi_ctrl_cdev); | ||
742 | out_version: | 771 | out_version: |
743 | class_remove_file(ubi_class, &ubi_version); | 772 | class_remove_file(ubi_class, &ubi_version); |
744 | out_class: | 773 | out_class: |
745 | class_destroy(ubi_class); | 774 | class_destroy(ubi_class); |
775 | out: | ||
776 | printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err); | ||
746 | return err; | 777 | return err; |
747 | } | 778 | } |
748 | module_init(ubi_init); | 779 | module_init(ubi_init); |
@@ -756,6 +787,7 @@ static void __exit ubi_exit(void) | |||
756 | detach_mtd_dev(ubi_devices[i]); | 787 | detach_mtd_dev(ubi_devices[i]); |
757 | kmem_cache_destroy(ubi_wl_entry_slab); | 788 | kmem_cache_destroy(ubi_wl_entry_slab); |
758 | kmem_cache_destroy(ubi_ltree_slab); | 789 | kmem_cache_destroy(ubi_ltree_slab); |
790 | misc_deregister(&ubi_ctrl_cdev); | ||
759 | class_remove_file(ubi_class, &ubi_version); | 791 | class_remove_file(ubi_class, &ubi_version); |
760 | class_destroy(ubi_class); | 792 | class_destroy(ubi_class); |
761 | } | 793 | } |
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 22c15a388f28..bc900d24cdba 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
@@ -28,6 +28,11 @@ | |||
28 | * | 28 | * |
29 | * Major and minor numbers are assigned dynamically to both UBI and volume | 29 | * Major and minor numbers are assigned dynamically to both UBI and volume |
30 | * character devices. | 30 | * character devices. |
31 | * | ||
32 | * Well, there is the third kind of character devices - the UBI control | ||
33 | * character device, which allows to manipulate by UBI devices - create and | ||
34 | * delete them. In other words, it is used for attaching and detaching MTD | ||
35 | * devices. | ||
31 | */ | 36 | */ |
32 | 37 | ||
33 | #include <linux/module.h> | 38 | #include <linux/module.h> |
@@ -693,6 +698,11 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
693 | return err; | 698 | return err; |
694 | } | 699 | } |
695 | 700 | ||
701 | /* UBI control character device operations */ | ||
702 | struct file_operations ubi_ctrl_cdev_operations = { | ||
703 | .owner = THIS_MODULE, | ||
704 | }; | ||
705 | |||
696 | /* UBI character device operations */ | 706 | /* UBI character device operations */ |
697 | struct file_operations ubi_cdev_operations = { | 707 | struct file_operations ubi_cdev_operations = { |
698 | .owner = THIS_MODULE, | 708 | .owner = THIS_MODULE, |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 994233d6e1e3..21c028366fd2 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
@@ -235,7 +235,7 @@ struct ubi_wl_entry; | |||
235 | 235 | ||
236 | /** | 236 | /** |
237 | * struct ubi_device - UBI device description structure | 237 | * struct ubi_device - UBI device description structure |
238 | * @dev: class device object to use the the Linux device model | 238 | * @dev: UBI device object to use the the Linux device model |
239 | * @cdev: character device object to create character device | 239 | * @cdev: character device object to create character device |
240 | * @ubi_num: UBI device number | 240 | * @ubi_num: UBI device number |
241 | * @ubi_name: UBI device name | 241 | * @ubi_name: UBI device name |
@@ -398,6 +398,7 @@ struct ubi_device { | |||
398 | 398 | ||
399 | extern struct kmem_cache *ubi_ltree_slab; | 399 | extern struct kmem_cache *ubi_ltree_slab; |
400 | extern struct kmem_cache *ubi_wl_entry_slab; | 400 | extern struct kmem_cache *ubi_wl_entry_slab; |
401 | extern struct file_operations ubi_ctrl_cdev_operations; | ||
401 | extern struct file_operations ubi_cdev_operations; | 402 | extern struct file_operations ubi_cdev_operations; |
402 | extern struct file_operations ubi_vol_cdev_operations; | 403 | extern struct file_operations ubi_vol_cdev_operations; |
403 | extern struct ubi_device *ubi_devices[]; | 404 | extern struct ubi_device *ubi_devices[]; |