diff options
| author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-16 09:59:31 -0500 |
|---|---|---|
| committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-12-26 12:15:17 -0500 |
| commit | 9f961b57568960a150cc9781c52824c9093a0514 (patch) | |
| tree | 345d60347d63bdc9973a2447d84024776b73dd2f | |
| parent | 16f557ecbf96dd13d13788a6f62d4d97ae73b1f9 (diff) | |
UBI: add UBI control device
This patch is a preparation to make UBI devices dynamic. It
adds an UBI control device which has dynamically allocated
major number and registers itself as "ubi_ctrl". It does not
do anything so far. The idea is that this device will allow
to attach/detach MTD devices from userspace.
This is symilar to what the Linux device mapper has.
The next things to do are:
* Fix UBI, because it now assumes UBI devices cannot go away
* Implement control device ioctls which will attach/detach MTD
devices
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
| -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[]; |
