summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-06-28 13:33:28 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2010-07-05 15:07:14 +0200
commite0677920d6e61e246d6906cd931263d35292dc7e (patch)
treea90eb89efef852773cd6ff041d7e48759890147f /drivers
parent8dbed40da9c07f106246584e91980dba856dad1e (diff)
downloadbarebox-e0677920d6e61e246d6906cd931263d35292dc7e.tar.gz
barebox-e0677920d6e61e246d6906cd931263d35292dc7e.tar.xz
barebox ubi changes
This adds the layer between barebox and UBI. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/ubi/Makefile2
-rw-r--r--drivers/mtd/ubi/build.c160
-rw-r--r--drivers/mtd/ubi/cdev.c238
-rw-r--r--drivers/mtd/ubi/kapi.c4
-rw-r--r--drivers/mtd/ubi/ubi.h9
-rw-r--r--drivers/mtd/ubi/upd.c36
-rw-r--r--drivers/mtd/ubi/vmt.c14
7 files changed, 291 insertions, 172 deletions
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index 425c185417..cef11416a1 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -1,3 +1,3 @@
-obj-y += build.o vtbl.o vmt.o upd.o kapi.o eba.o io.o wl.o scan.o misc.o debug.o
+obj-y += build.o vtbl.o vmt.o upd.o kapi.o eba.o io.o wl.o scan.o misc.o debug.o cdev.o
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 03ce392917..a59972faa6 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -399,7 +399,7 @@ static int uif_init(struct ubi_device *ubi)
#ifdef UBI_LINUX
ubi->cdev.owner = THIS_MODULE;
#endif
- err = cdev_add(&ubi->cdev, dev, 1);
+ err = ubi_cdev_add(ubi);
if (err) {
ubi_err("cannot add character device");
goto out_unreg;
@@ -424,7 +424,7 @@ out_volumes:
kill_volumes(ubi);
out_sysfs:
ubi_sysfs_close(ubi);
- cdev_del(&ubi->cdev);
+ ubi_cdev_remove(ubi);
out_unreg:
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err);
@@ -439,7 +439,7 @@ static void uif_close(struct ubi_device *ubi)
{
kill_volumes(ubi);
ubi_sysfs_close(ubi);
- cdev_del(&ubi->cdev);
+ ubi_cdev_remove(ubi);
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
}
@@ -724,7 +724,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
*/
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
- if (ubi && mtd->index == ubi->mtd->index) {
+ if (ubi && mtd == ubi->mtd) {
dbg_err("mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
@@ -879,15 +879,21 @@ out_free:
* Note, the invocations of this function has to be serialized by the
* @ubi_devices_mutex.
*/
-int ubi_detach_mtd_dev(int ubi_num, int anyway)
+int ubi_detach_mtd_dev(struct mtd_info *mtd, int anyway)
{
struct ubi_device *ubi;
-
- if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
- return -EINVAL;
+ int ubi_num = 0, i;
spin_lock(&ubi_devices_lock);
- ubi = ubi_devices[ubi_num];
+
+ for (i = 0; i < UBI_MAX_DEVICES; i++) {
+ ubi = ubi_devices[i];
+ if (ubi && mtd == ubi->mtd) {
+ ubi_num = i;
+ break;
+ }
+ }
+
if (!ubi) {
spin_unlock(&ubi_devices_lock);
return -EINVAL;
@@ -919,7 +925,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
ubi_eba_close(ubi);
ubi_wl_close(ubi);
vfree(ubi->vtbl);
- put_mtd_device(ubi->mtd);
vfree(ubi->peb_buf1);
vfree(ubi->peb_buf2);
#ifdef CONFIG_MTD_UBI_DEBUG
@@ -931,141 +936,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
}
/**
- * find_mtd_device - open an MTD device by its name or number.
- * @mtd_dev: name or number of the device
- *
- * This function tries to open and MTD device described by @mtd_dev string,
- * which is first treated as an ASCII number, and if it is not true, it is
- * treated as MTD device name. Returns MTD device description object in case of
- * success and a negative error code in case of failure.
- */
-static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
-{
- struct mtd_info *mtd;
- int mtd_num;
- char *endp;
-
- mtd_num = simple_strtoul(mtd_dev, &endp, 0);
- if (*endp != '\0' || mtd_dev == endp) {
- /*
- * This does not look like an ASCII integer, probably this is
- * MTD device name.
- */
- mtd = get_mtd_device_nm(mtd_dev);
- } else
- mtd = get_mtd_device(NULL, mtd_num);
-
- return mtd;
-}
-
-int __init ubi_init(void)
-{
- int err, i, k;
-
- /* Ensure that EC and VID headers have correct size */
- BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
- BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
-
- if (mtd_devs > UBI_MAX_DEVICES) {
- ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES);
- return -EINVAL;
- }
-
- /* Create base sysfs directory and sysfs files */
- ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
- if (IS_ERR(ubi_class)) {
- err = PTR_ERR(ubi_class);
- ubi_err("cannot create UBI class");
- goto out;
- }
-
- err = class_create_file(ubi_class, &ubi_version);
- if (err) {
- ubi_err("cannot create sysfs file");
- goto out_class;
- }
-
- err = misc_register(&ubi_ctrl_cdev);
- if (err) {
- ubi_err("cannot register device");
- goto out_version;
- }
-
-#ifdef UBI_LINUX
- ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
- sizeof(struct ubi_wl_entry),
- 0, 0, NULL);
- if (!ubi_wl_entry_slab)
- goto out_dev_unreg;
-#endif
-
- /* Attach MTD devices */
- for (i = 0; i < mtd_devs; i++) {
- struct mtd_dev_param *p = &mtd_dev_param[i];
- struct mtd_info *mtd;
-
- cond_resched();
-
- mtd = open_mtd_device(p->name);
- if (IS_ERR(mtd)) {
- err = PTR_ERR(mtd);
- goto out_detach;
- }
-
- mutex_lock(&ubi_devices_mutex);
- err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO,
- p->vid_hdr_offs);
- mutex_unlock(&ubi_devices_mutex);
- if (err < 0) {
- put_mtd_device(mtd);
- ubi_err("cannot attach mtd%d", mtd->index);
- goto out_detach;
- }
- }
-
- return 0;
-
-out_detach:
- for (k = 0; k < i; k++)
- if (ubi_devices[k]) {
- mutex_lock(&ubi_devices_mutex);
- ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
- mutex_unlock(&ubi_devices_mutex);
- }
-#ifdef UBI_LINUX
- kmem_cache_destroy(ubi_wl_entry_slab);
-out_dev_unreg:
-#endif
- misc_deregister(&ubi_ctrl_cdev);
-out_version:
- class_remove_file(ubi_class, &ubi_version);
-out_class:
- class_destroy(ubi_class);
-out:
- ubi_err("UBI error: cannot initialize UBI, error %d", err);
- return err;
-}
-module_init(ubi_init);
-
-void __exit ubi_exit(void)
-{
- int i;
-
- for (i = 0; i < UBI_MAX_DEVICES; i++)
- if (ubi_devices[i]) {
- mutex_lock(&ubi_devices_mutex);
- ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
- mutex_unlock(&ubi_devices_mutex);
- }
- kmem_cache_destroy(ubi_wl_entry_slab);
- misc_deregister(&ubi_ctrl_cdev);
- class_remove_file(ubi_class, &ubi_version);
- class_destroy(ubi_class);
- mtd_devs = 0;
-}
-module_exit(ubi_exit);
-
-/**
* bytes_str_to_int - convert a string representing number of bytes to an
* integer.
* @str: the string to convert
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
new file mode 100644
index 0000000000..30b8308dcc
--- /dev/null
+++ b/drivers/mtd/ubi/cdev.c
@@ -0,0 +1,238 @@
+#include <common.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <ioctl.h>
+#include "ubi-barebox.h"
+#include "ubi.h"
+
+struct ubi_volume_cdev_priv {
+ struct ubi_device *ubi;
+ struct ubi_volume *vol;
+ int updating;
+ unsigned long mode;
+};
+
+static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size,
+ unsigned long offset, unsigned long flags)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+ struct ubi_volume *vol = priv->vol;
+ struct ubi_device *ubi = priv->ubi;
+ int err, lnum, off, len;
+ size_t count_save = size;
+ unsigned long long tmp;
+ loff_t offp = offset;
+ int usable_leb_size = vol->usable_leb_size;
+
+ printf("%s: %d @ 0x%08x\n", __func__, size, offset);
+
+ len = size > usable_leb_size ? usable_leb_size : size;
+
+ tmp = offp;
+ off = do_div(tmp, usable_leb_size);
+ lnum = tmp;
+ do {
+ if (off + len >= usable_leb_size)
+ len = usable_leb_size - off;
+
+ err = ubi_eba_read_leb(ubi, vol, lnum, buf, off, len, 0);
+ if (err) {
+ printf("read err %x\n", err);
+ break;
+ }
+ off += len;
+ if (off == usable_leb_size) {
+ lnum += 1;
+ off -= usable_leb_size;
+ }
+
+ size -= len;
+ offp += len;
+
+ buf += len;
+ len = size > usable_leb_size ? usable_leb_size : size;
+ } while (size);
+
+ return count_save;
+}
+
+static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf,
+ size_t size, unsigned long offset, unsigned long flags)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+ struct ubi_volume *vol = priv->vol;
+ struct ubi_device *ubi = priv->ubi;
+ int err;
+
+ if (!priv->updating) {
+ err = ubi_start_update(ubi, vol, 16*1024*1024);
+ if (err < 0) {
+ printf("Cannot start volume update\n");
+ return err;
+ }
+ priv->updating = 1;
+ }
+
+ err = ubi_more_update_data(ubi, vol, buf, size);
+ if (err < 0) {
+ printf("Couldnt or partially wrote data \n");
+ return err;
+ }
+
+ return err;
+}
+
+static int ubi_volume_cdev_open(struct cdev *cdev, struct filep *f)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+
+ /* only allow read or write, but not both */
+ if ((f->flags & O_ACCMODE) == O_RDWR)
+ return -EINVAL;
+
+ priv->updating = 0;
+ priv->mode = f->flags & O_ACCMODE;
+
+ return 0;
+}
+
+static int ubi_volume_cdev_close(struct cdev *cdev, struct filep *f)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+ struct ubi_volume *vol = priv->vol;
+ struct ubi_device *ubi = priv->ubi;
+ int err;
+
+ if (priv->updating) {
+ err = ubi_finish_update(ubi, vol);
+ if (err)
+ return err;
+
+ err = ubi_check_volume(ubi, vol->vol_id);
+ if (err < 0) {
+ printf("check failed: %s\n", strerror(err));
+ return err;
+ }
+
+ if (err) {
+ ubi_warn("volume %d on UBI device %d is corrupted",
+ vol->vol_id, ubi->ubi_num);
+ vol->corrupted = 1;
+ }
+
+ vol->checked = 1;
+ ubi_gluebi_updated(vol);
+ }
+
+ return 0;
+}
+
+static off_t ubi_volume_cdev_lseek(struct cdev *cdev, off_t ofs)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+
+ /* We can only update ubi volumes sequentially */
+ if (priv->mode == O_WRONLY)
+ return -EINVAL;
+
+ return ofs;
+}
+
+static struct file_operations ubi_volume_fops = {
+ .open = ubi_volume_cdev_open,
+ .close = ubi_volume_cdev_close,
+ .read = ubi_volume_cdev_read,
+ .write = ubi_volume_cdev_write,
+ .lseek = ubi_volume_cdev_lseek,
+};
+
+int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
+{
+ struct cdev *cdev = &vol->cdev;
+ struct ubi_volume_cdev_priv *priv;
+ int ret;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->vol = vol;
+ priv->ubi = ubi;
+
+ cdev->ops = &ubi_volume_fops;
+ cdev->name = asprintf("ubi%d.%s", ubi->ubi_num, vol->name);
+ cdev->priv = priv;
+ cdev->size = vol->used_bytes;
+ printf("registering %s as /dev/%s\n", vol->name, cdev->name);
+ ret = devfs_create(cdev);
+ if (ret) {
+ free(priv);
+ free(cdev->name);
+ }
+
+ return 0;
+}
+
+void ubi_volume_cdev_remove(struct ubi_volume *vol)
+{
+ struct cdev *cdev = &vol->cdev;
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+
+ devfs_remove(cdev);
+ free(cdev->name);
+ free(priv);
+}
+
+static int ubi_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
+{
+ struct ubi_volume_desc *desc;
+ struct ubi_device *ubi = cdev->priv;
+ struct ubi_mkvol_req *req = buf;
+
+ switch (cmd) {
+ case UBI_IOCRMVOL:
+ desc = ubi_open_volume_nm(ubi->ubi_num, req->name,
+ UBI_EXCLUSIVE);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+ ubi_remove_volume(desc);
+ break;
+ case UBI_IOCMKVOL:
+ if (!req->bytes)
+ req->bytes = ubi->avail_pebs * ubi->leb_size;
+ return ubi_create_volume(ubi, req);
+ };
+
+ return 0;
+}
+
+
+static struct file_operations ubi_fops = {
+ .ioctl = ubi_cdev_ioctl,
+};
+
+int ubi_cdev_add(struct ubi_device *ubi)
+{
+ struct cdev *cdev = &ubi->cdev;
+ int ret;
+
+ cdev->ops = &ubi_fops;
+ cdev->name = asprintf("ubi%d", ubi->ubi_num);
+ cdev->priv = ubi;
+ cdev->size = 0;
+
+ printf("registering /dev/%s\n", cdev->name);
+ ret = devfs_create(cdev);
+ if (ret)
+ free(cdev->name);
+
+ return ret;
+}
+
+void ubi_cdev_remove(struct ubi_device *ubi)
+{
+ struct cdev *cdev = &ubi->cdev;
+
+ printf("removing %s\n", cdev->name);
+
+ devfs_remove(cdev);
+ free(cdev->name);
+}
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index fac76f2d09..d423f87908 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -52,7 +52,7 @@ int ubi_get_device_info(int ubi_num, struct ubi_device_info *di)
di->leb_size = ubi->leb_size;
di->min_io_size = ubi->min_io_size;
di->ro_mode = ubi->ro_mode;
- di->cdev = ubi->cdev.dev;
+ di->cdev = &ubi->cdev;
ubi_put_device(ubi);
return 0;
@@ -81,7 +81,7 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc,
vi->usable_leb_size = vol->usable_leb_size;
vi->name_len = vol->name_len;
vi->name = vol->name;
- vi->cdev = vol->cdev.dev;
+ vi->cdev = &vol->cdev;
}
EXPORT_SYMBOL_GPL(ubi_get_volume_info);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 358c8dcbc9..5552237910 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -448,6 +448,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol);
/* upd.c */
int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
long long bytes);
+int ubi_finish_update(struct ubi_device *ubi, struct ubi_volume *vol);
int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
const void __user *buf, int count);
int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
@@ -516,12 +517,18 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
/* build.c */
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset);
-int ubi_detach_mtd_dev(int ubi_num, int anyway);
+int ubi_detach_mtd_dev(struct mtd_info *mtd, int anyway);
struct ubi_device *ubi_get_device(int ubi_num);
void ubi_put_device(struct ubi_device *ubi);
struct ubi_device *ubi_get_by_major(int major);
int ubi_major2num(int major);
+/* cdev.c */
+int ubi_cdev_add(struct ubi_device *ubi);
+void ubi_cdev_remove(struct ubi_device *ubi);
+int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol);
+void ubi_volume_cdev_remove(struct ubi_volume *vol);
+
/*
* ubi_rb_for_each_entry - walk an RB-tree.
* @rb: a pointer to type 'struct rb_node' to to use as a loop counter
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
index 8267b1adc5..fda2043183 100644
--- a/drivers/mtd/ubi/upd.c
+++ b/drivers/mtd/ubi/upd.c
@@ -173,6 +173,23 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
return 0;
}
+int ubi_finish_update(struct ubi_device *ubi, struct ubi_volume *vol)
+{
+ int err;
+
+ /* The update is finished, clear the update marker */
+ err = clear_update_marker(ubi, vol, vol->upd_bytes);
+ if (err)
+ return err;
+ err = ubi_wl_flush(ubi);
+ if (err == 0) {
+ vol->updating = 0;
+ vfree(vol->upd_buf);
+ }
+
+ return err;
+}
+
/**
* ubi_start_leb_change - start atomic LEB change.
* @ubi: UBI device description object
@@ -320,13 +337,12 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
if (err)
return -EFAULT;
- if (offs + len == vol->usable_leb_size ||
- vol->upd_received + len == vol->upd_bytes) {
+ if (offs + len == vol->usable_leb_size) {
int flush_len = offs + len;
/*
- * OK, we gathered either the whole eraseblock or this
- * is the last chunk, it's time to flush the buffer.
+ * OK, we gathered the whole eraseblock, it's time to flush
+ * the buffer.
*/
ubi_assert(flush_len <= vol->usable_leb_size);
err = write_leb(ubi, vol, lnum, vol->upd_buf, flush_len,
@@ -370,18 +386,6 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol,
}
ubi_assert(vol->upd_received <= vol->upd_bytes);
- if (vol->upd_received == vol->upd_bytes) {
- /* The update is finished, clear the update marker */
- err = clear_update_marker(ubi, vol, vol->upd_bytes);
- if (err)
- return err;
- err = ubi_wl_flush(ubi);
- if (err == 0) {
- vol->updating = 0;
- err = to_write;
- vfree(vol->upd_buf);
- }
- }
return err;
}
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 935dcdc9ac..4f1d0f4209 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -323,7 +323,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->cdev.owner = THIS_MODULE;
#endif
dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);
- err = cdev_add(&vol->cdev, dev, 1);
+ err = ubi_volume_cdev_add(ubi, vol);
if (err) {
ubi_err("cannot add character device");
goto out_mapping;
@@ -390,7 +390,7 @@ out_gluebi:
dbg_err("cannot destroy gluebi for volume %d:%d",
ubi->ubi_num, vol_id);
out_cdev:
- cdev_del(&vol->cdev);
+ ubi_volume_cdev_remove(vol);
out_mapping:
kfree(vol->eba_tbl);
out_acc:
@@ -457,7 +457,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc)
kfree(vol->eba_tbl);
vol->eba_tbl = NULL;
- cdev_del(&vol->cdev);
+ ubi_volume_cdev_remove(vol);
volume_sysfs_close(vol);
spin_lock(&ubi->volumes_lock);
@@ -634,7 +634,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
vol->cdev.owner = THIS_MODULE;
#endif
dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1);
- err = cdev_add(&vol->cdev, dev, 1);
+ err = ubi_volume_cdev_add(ubi, vol);
if (err) {
ubi_err("cannot add character device for volume %d, error %d",
vol_id, err);
@@ -656,7 +656,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
err = volume_sysfs_init(ubi, vol);
if (err) {
- cdev_del(&vol->cdev);
+ ubi_volume_cdev_remove(vol);
err = ubi_destroy_gluebi(vol);
volume_sysfs_close(vol);
return err;
@@ -668,7 +668,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
out_gluebi:
err = ubi_destroy_gluebi(vol);
out_cdev:
- cdev_del(&vol->cdev);
+ ubi_volume_cdev_remove(vol);
return err;
}
@@ -688,7 +688,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
ubi->volumes[vol->vol_id] = NULL;
err = ubi_destroy_gluebi(vol);
- cdev_del(&vol->cdev);
+ ubi_volume_cdev_remove(vol);
volume_sysfs_close(vol);
}