|
@@ -420,41 +420,6 @@ static void dev_release(struct device *dev)
|
|
|
kfree(ubi);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * ubi_sysfs_init - initialize sysfs for an UBI device.
|
|
|
- * @ubi: UBI device description object
|
|
|
- * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
|
|
|
- * taken
|
|
|
- *
|
|
|
- * This function returns zero in case of success and a negative error code in
|
|
|
- * case of failure.
|
|
|
- */
|
|
|
-static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
|
|
|
-{
|
|
|
- int err;
|
|
|
-
|
|
|
- ubi->dev.release = dev_release;
|
|
|
- ubi->dev.devt = ubi->cdev.dev;
|
|
|
- ubi->dev.class = &ubi_class;
|
|
|
- ubi->dev.groups = ubi_dev_groups;
|
|
|
- dev_set_name(&ubi->dev, UBI_NAME_STR"%d", ubi->ubi_num);
|
|
|
- err = device_register(&ubi->dev);
|
|
|
- if (err)
|
|
|
- return err;
|
|
|
-
|
|
|
- *ref = 1;
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * ubi_sysfs_close - close sysfs for an UBI device.
|
|
|
- * @ubi: UBI device description object
|
|
|
- */
|
|
|
-static void ubi_sysfs_close(struct ubi_device *ubi)
|
|
|
-{
|
|
|
- device_unregister(&ubi->dev);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* kill_volumes - destroy all user volumes.
|
|
|
* @ubi: UBI device description object
|
|
@@ -471,27 +436,19 @@ static void kill_volumes(struct ubi_device *ubi)
|
|
|
/**
|
|
|
* uif_init - initialize user interfaces for an UBI device.
|
|
|
* @ubi: UBI device description object
|
|
|
- * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
|
|
|
- * taken, otherwise set to %0
|
|
|
*
|
|
|
* This function initializes various user interfaces for an UBI device. If the
|
|
|
* initialization fails at an early stage, this function frees all the
|
|
|
- * resources it allocated, returns an error, and @ref is set to %0. However,
|
|
|
- * if the initialization fails after the UBI device was registered in the
|
|
|
- * driver core subsystem, this function takes a reference to @ubi->dev, because
|
|
|
- * otherwise the release function ('dev_release()') would free whole @ubi
|
|
|
- * object. The @ref argument is set to %1 in this case. The caller has to put
|
|
|
- * this reference.
|
|
|
+ * resources it allocated, returns an error.
|
|
|
*
|
|
|
* This function returns zero in case of success and a negative error code in
|
|
|
* case of failure.
|
|
|
*/
|
|
|
-static int uif_init(struct ubi_device *ubi, int *ref)
|
|
|
+static int uif_init(struct ubi_device *ubi)
|
|
|
{
|
|
|
int i, err;
|
|
|
dev_t dev;
|
|
|
|
|
|
- *ref = 0;
|
|
|
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
|
|
|
|
|
|
/*
|
|
@@ -508,20 +465,17 @@ static int uif_init(struct ubi_device *ubi, int *ref)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+ ubi->dev.devt = dev;
|
|
|
+
|
|
|
ubi_assert(MINOR(dev) == 0);
|
|
|
cdev_init(&ubi->cdev, &ubi_cdev_operations);
|
|
|
dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
|
|
|
ubi->cdev.owner = THIS_MODULE;
|
|
|
|
|
|
- err = cdev_add(&ubi->cdev, dev, 1);
|
|
|
- if (err) {
|
|
|
- ubi_err(ubi, "cannot add character device");
|
|
|
- goto out_unreg;
|
|
|
- }
|
|
|
-
|
|
|
- err = ubi_sysfs_init(ubi, ref);
|
|
|
+ dev_set_name(&ubi->dev, UBI_NAME_STR "%d", ubi->ubi_num);
|
|
|
+ err = cdev_device_add(&ubi->cdev, &ubi->dev);
|
|
|
if (err)
|
|
|
- goto out_sysfs;
|
|
|
+ goto out_unreg;
|
|
|
|
|
|
for (i = 0; i < ubi->vtbl_slots; i++)
|
|
|
if (ubi->volumes[i]) {
|
|
@@ -536,11 +490,7 @@ static int uif_init(struct ubi_device *ubi, int *ref)
|
|
|
|
|
|
out_volumes:
|
|
|
kill_volumes(ubi);
|
|
|
-out_sysfs:
|
|
|
- if (*ref)
|
|
|
- get_device(&ubi->dev);
|
|
|
- ubi_sysfs_close(ubi);
|
|
|
- cdev_del(&ubi->cdev);
|
|
|
+ cdev_device_del(&ubi->cdev, &ubi->dev);
|
|
|
out_unreg:
|
|
|
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
|
|
|
ubi_err(ubi, "cannot initialize UBI %s, error %d",
|
|
@@ -559,8 +509,7 @@ out_unreg:
|
|
|
static void uif_close(struct ubi_device *ubi)
|
|
|
{
|
|
|
kill_volumes(ubi);
|
|
|
- ubi_sysfs_close(ubi);
|
|
|
- cdev_del(&ubi->cdev);
|
|
|
+ cdev_device_del(&ubi->cdev, &ubi->dev);
|
|
|
unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
|
|
|
}
|
|
|
|
|
@@ -857,7 +806,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
|
int vid_hdr_offset, int max_beb_per1024)
|
|
|
{
|
|
|
struct ubi_device *ubi;
|
|
|
- int i, err, ref = 0;
|
|
|
+ int i, err;
|
|
|
|
|
|
if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT)
|
|
|
return -EINVAL;
|
|
@@ -919,6 +868,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
|
if (!ubi)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ device_initialize(&ubi->dev);
|
|
|
+ ubi->dev.release = dev_release;
|
|
|
+ ubi->dev.class = &ubi_class;
|
|
|
+ ubi->dev.groups = ubi_dev_groups;
|
|
|
+
|
|
|
ubi->mtd = mtd;
|
|
|
ubi->ubi_num = ubi_num;
|
|
|
ubi->vid_hdr_offset = vid_hdr_offset;
|
|
@@ -995,7 +949,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
|
/* Make device "available" before it becomes accessible via sysfs */
|
|
|
ubi_devices[ubi_num] = ubi;
|
|
|
|
|
|
- err = uif_init(ubi, &ref);
|
|
|
+ err = uif_init(ubi);
|
|
|
if (err)
|
|
|
goto out_detach;
|
|
|
|
|
@@ -1045,8 +999,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
|
|
|
out_debugfs:
|
|
|
ubi_debugfs_exit_dev(ubi);
|
|
|
out_uif:
|
|
|
- get_device(&ubi->dev);
|
|
|
- ubi_assert(ref);
|
|
|
uif_close(ubi);
|
|
|
out_detach:
|
|
|
ubi_devices[ubi_num] = NULL;
|
|
@@ -1056,10 +1008,7 @@ out_detach:
|
|
|
out_free:
|
|
|
vfree(ubi->peb_buf);
|
|
|
vfree(ubi->fm_buf);
|
|
|
- if (ref)
|
|
|
- put_device(&ubi->dev);
|
|
|
- else
|
|
|
- kfree(ubi);
|
|
|
+ put_device(&ubi->dev);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
@@ -1120,12 +1069,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
|
|
|
if (ubi->bgt_thread)
|
|
|
kthread_stop(ubi->bgt_thread);
|
|
|
|
|
|
- /*
|
|
|
- * Get a reference to the device in order to prevent 'dev_release()'
|
|
|
- * from freeing the @ubi object.
|
|
|
- */
|
|
|
- get_device(&ubi->dev);
|
|
|
-
|
|
|
ubi_debugfs_exit_dev(ubi);
|
|
|
uif_close(ubi);
|
|
|
|