*/
/*
- * This file includes UBI initialization and building of UBI devices. At the
- * moment UBI devices may only be added while UBI is initialized, but dynamic
- * device add/remove functionality is planned. Also, at the moment we only
- * attach UBI devices by scanning, which will become a bottleneck when flashes
- * reach certain large size. Then one may improve UBI and add other methods.
+ * This file includes UBI initialization and building of UBI devices.
+ *
+ * When UBI is initialized, it attaches all the MTD devices specified as the
+ * module load parameters or the kernel boot parameters. If MTD devices were
+ * specified, UBI does not attach any MTD device, but it is possible to do
+ * later using the "UBI control device".
+ *
+ * At the moment we only attach UBI devices by scanning, which will become a
+ * bottleneck when flashes reach certain large size. Then one may improve UBI
+ * and add other methods, although it does not seem to be easy to do.
*/
#include <linux/err.h>
#include <linux/moduleparam.h>
#include <linux/stringify.h>
#include <linux/stat.h>
+#include <linux/miscdevice.h>
#include <linux/log2.h>
#include "ubi.h"
/* Slab cache for wear-leveling entries */
struct kmem_cache *ubi_wl_entry_slab;
+/* UBI control character device */
+static struct miscdevice ubi_ctrl_cdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "ubi_ctrl",
+ .fops = &ubi_ctrl_cdev_operations,
+};
/* "Show" method for files in '/<sysfs>/class/ubi/' */
static ssize_t ubi_version_show(struct class *class, char *buf)
return -EINVAL;
}
+ /* Create base sysfs directory and sysfs files */
ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
- if (IS_ERR(ubi_class))
- return PTR_ERR(ubi_class);
+ if (IS_ERR(ubi_class)) {
+ err = PTR_ERR(ubi_class);
+ printk(KERN_ERR "UBI error: cannot create UBI class\n");
+ goto out;
+ }
err = class_create_file(ubi_class, &ubi_version);
- if (err)
+ if (err) {
+ printk(KERN_ERR "UBI error: cannot create sysfs file\n");
goto out_class;
+ }
+
+ err = misc_register(&ubi_ctrl_cdev);
+ if (err) {
+ printk(KERN_ERR "UBI error: cannot register device\n");
+ goto out_version;
+ }
ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab",
sizeof(struct ubi_ltree_entry), 0,
0, <ree_entry_ctor);
if (!ubi_ltree_slab)
- goto out_version;
+ goto out_dev_unreg;
ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
sizeof(struct ubi_wl_entry),
cond_resched();
err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs);
- if (err)
+ if (err) {
+ printk(KERN_ERR "UBI error: cannot attach %s\n",
+ p->name);
goto out_detach;
+ }
}
return 0;
kmem_cache_destroy(ubi_wl_entry_slab);
out_ltree:
kmem_cache_destroy(ubi_ltree_slab);
+out_dev_unreg:
+ misc_deregister(&ubi_ctrl_cdev);
out_version:
class_remove_file(ubi_class, &ubi_version);
out_class:
class_destroy(ubi_class);
+out:
+ printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
return err;
}
module_init(ubi_init);
detach_mtd_dev(ubi_devices[i]);
kmem_cache_destroy(ubi_wl_entry_slab);
kmem_cache_destroy(ubi_ltree_slab);
+ misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version);
class_destroy(ubi_class);
}
/**
* struct ubi_device - UBI device description structure
- * @dev: class device object to use the the Linux device model
+ * @dev: UBI device object to use the the Linux device model
* @cdev: character device object to create character device
* @ubi_num: UBI device number
* @ubi_name: UBI device name
extern struct kmem_cache *ubi_ltree_slab;
extern struct kmem_cache *ubi_wl_entry_slab;
+extern struct file_operations ubi_ctrl_cdev_operations;
extern struct file_operations ubi_cdev_operations;
extern struct file_operations ubi_vol_cdev_operations;
extern struct ubi_device *ubi_devices[];