summaryrefslogtreecommitdiff
path: root/drivers/mtd/ubi/vmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/ubi/vmt.c')
-rw-r--r--drivers/mtd/ubi/vmt.c173
1 files changed, 62 insertions, 111 deletions
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index f4392f5969..f8ab08f9df 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -114,6 +114,19 @@ static ssize_t vol_attribute_show(struct device *dev,
ubi_put_device(ubi);
return ret;
}
+
+static struct attribute *volume_dev_attrs[] = {
+ &attr_vol_reserved_ebs.attr,
+ &attr_vol_type.attr,
+ &attr_vol_name.attr,
+ &attr_vol_corrupted.attr,
+ &attr_vol_alignment.attr,
+ &attr_vol_usable_eb_size.attr,
+ &attr_vol_data_bytes.attr,
+ &attr_vol_upd_marker.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(volume_dev);
#endif
/* Release method for volume devices */
@@ -125,66 +138,6 @@ static void vol_release(struct device *dev)
kfree(vol);
}
-#ifndef __UBOOT__
-/**
- * volume_sysfs_init - initialize sysfs for new volume.
- * @ubi: UBI device description object
- * @vol: volume description object
- *
- * This function returns zero in case of success and a negative error code in
- * case of failure.
- *
- * Note, this function does not free allocated resources in case of failure -
- * the caller does it. This is because this would cause release() here and the
- * caller would oops.
- */
-static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol)
-{
- int err;
-
- err = device_create_file(&vol->dev, &attr_vol_reserved_ebs);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_type);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_name);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_corrupted);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_alignment);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_usable_eb_size);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_data_bytes);
- if (err)
- return err;
- err = device_create_file(&vol->dev, &attr_vol_upd_marker);
- return err;
-}
-
-/**
- * volume_sysfs_close - close sysfs for a volume.
- * @vol: volume description object
- */
-static void volume_sysfs_close(struct ubi_volume *vol)
-{
- device_remove_file(&vol->dev, &attr_vol_upd_marker);
- device_remove_file(&vol->dev, &attr_vol_data_bytes);
- device_remove_file(&vol->dev, &attr_vol_usable_eb_size);
- device_remove_file(&vol->dev, &attr_vol_alignment);
- device_remove_file(&vol->dev, &attr_vol_corrupted);
- device_remove_file(&vol->dev, &attr_vol_name);
- device_remove_file(&vol->dev, &attr_vol_type);
- device_remove_file(&vol->dev, &attr_vol_reserved_ebs);
- device_unregister(&vol->dev);
-}
-#endif
-
/**
* ubi_create_volume - create volume.
* @ubi: UBI device description object
@@ -221,7 +174,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
}
if (vol_id == UBI_VOL_NUM_AUTO) {
- ubi_err("out of volume IDs");
+ ubi_err(ubi, "out of volume IDs");
err = -ENFILE;
goto out_unlock;
}
@@ -235,7 +188,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Ensure that this volume does not exist */
err = -EEXIST;
if (ubi->volumes[vol_id]) {
- ubi_err("volume %d already exists", vol_id);
+ ubi_err(ubi, "volume %d already exists", vol_id);
goto out_unlock;
}
@@ -244,20 +197,22 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
if (ubi->volumes[i] &&
ubi->volumes[i]->name_len == req->name_len &&
!strcmp(ubi->volumes[i]->name, req->name)) {
- ubi_err("volume \"%s\" exists (ID %d)", req->name, i);
+ ubi_err(ubi, "volume \"%s\" exists (ID %d)",
+ req->name, i);
goto out_unlock;
}
/* Calculate how many eraseblocks are requested */
vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;
- vol->reserved_pebs += div_u64(req->bytes + vol->usable_leb_size - 1,
- vol->usable_leb_size);
+ vol->reserved_pebs = div_u64(req->bytes + vol->usable_leb_size - 1,
+ vol->usable_leb_size);
/* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) {
- ubi_err("not enough PEBs, only %d available", ubi->avail_pebs);
+ ubi_err(ubi, "not enough PEBs, only %d available",
+ ubi->avail_pebs);
if (ubi->corr_peb_count)
- ubi_err("%d PEBs are corrupted and not used",
+ ubi_err(ubi, "%d PEBs are corrupted and not used",
ubi->corr_peb_count);
err = -ENOSPC;
goto out_unlock;
@@ -312,26 +267,25 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);
err = cdev_add(&vol->cdev, dev, 1);
if (err) {
- ubi_err("cannot add character device");
+ ubi_err(ubi, "cannot add character device");
goto out_mapping;
}
vol->dev.release = vol_release;
vol->dev.parent = &ubi->dev;
vol->dev.devt = dev;
- vol->dev.class = ubi_class;
+#ifndef __UBOOT__
+ vol->dev.class = &ubi_class;
+ vol->dev.groups = volume_dev_groups;
+#endif
dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
err = device_register(&vol->dev);
if (err) {
- ubi_err("cannot register device");
+ ubi_err(ubi, "cannot register device");
goto out_cdev;
}
- err = volume_sysfs_init(ubi, vol);
- if (err)
- goto out_sysfs;
-
/* Fill volume table record */
memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs);
@@ -368,7 +322,7 @@ out_sysfs:
*/
do_free = 0;
get_device(&vol->dev);
- volume_sysfs_close(vol);
+ device_unregister(&vol->dev);
out_cdev:
cdev_del(&vol->cdev);
out_mapping:
@@ -384,7 +338,7 @@ out_unlock:
kfree(vol);
else
put_device(&vol->dev);
- ubi_err("cannot create volume %d, error %d", vol_id, err);
+ ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err);
return err;
}
@@ -436,7 +390,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
}
cdev_del(&vol->cdev);
- volume_sysfs_close(vol);
+ device_unregister(&vol->dev);
spin_lock(&ubi->volumes_lock);
ubi->rsvd_pebs -= reserved_pebs;
@@ -452,7 +406,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
return err;
out_err:
- ubi_err("cannot remove volume %d, error %d", vol_id, err);
+ ubi_err(ubi, "cannot remove volume %d, error %d", vol_id, err);
spin_lock(&ubi->volumes_lock);
ubi->volumes[vol_id] = vol;
out_unlock:
@@ -485,7 +439,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (vol->vol_type == UBI_STATIC_VOLUME &&
reserved_pebs < vol->used_ebs) {
- ubi_err("too small size %d, %d LEBs contain data",
+ ubi_err(ubi, "too small size %d, %d LEBs contain data",
reserved_pebs, vol->used_ebs);
return -EINVAL;
}
@@ -514,10 +468,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (pebs > 0) {
spin_lock(&ubi->volumes_lock);
if (pebs > ubi->avail_pebs) {
- ubi_err("not enough PEBs: requested %d, available %d",
+ ubi_err(ubi, "not enough PEBs: requested %d, available %d",
pebs, ubi->avail_pebs);
if (ubi->corr_peb_count)
- ubi_err("%d PEBs are corrupted and not used",
+ ubi_err(ubi, "%d PEBs are corrupted and not used",
ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock);
err = -ENOSPC;
@@ -641,7 +595,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1);
err = cdev_add(&vol->cdev, dev, 1);
if (err) {
- ubi_err("cannot add character device for volume %d, error %d",
+ ubi_err(ubi, "cannot add character device for volume %d, error %d",
vol_id, err);
return err;
}
@@ -649,19 +603,15 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)
vol->dev.release = vol_release;
vol->dev.parent = &ubi->dev;
vol->dev.devt = dev;
- vol->dev.class = ubi_class;
+#ifndef __UBOOT__
+ vol->dev.class = &ubi_class;
+ vol->dev.groups = volume_dev_groups;
+#endif
dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);
err = device_register(&vol->dev);
if (err)
goto out_cdev;
- err = volume_sysfs_init(ubi, vol);
- if (err) {
- cdev_del(&vol->cdev);
- volume_sysfs_close(vol);
- return err;
- }
-
self_check_volumes(ubi);
return err;
@@ -684,7 +634,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)
ubi->volumes[vol->vol_id] = NULL;
cdev_del(&vol->cdev);
- volume_sysfs_close(vol);
+ device_unregister(&vol->dev);
}
/**
@@ -708,7 +658,7 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
if (!vol) {
if (reserved_pebs) {
- ubi_err("no volume info, but volume exists");
+ ubi_err(ubi, "no volume info, but volume exists");
goto fail;
}
spin_unlock(&ubi->volumes_lock);
@@ -717,90 +667,91 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||
vol->name_len < 0) {
- ubi_err("negative values");
+ ubi_err(ubi, "negative values");
goto fail;
}
if (vol->alignment > ubi->leb_size || vol->alignment == 0) {
- ubi_err("bad alignment");
+ ubi_err(ubi, "bad alignment");
goto fail;
}
n = vol->alignment & (ubi->min_io_size - 1);
if (vol->alignment != 1 && n) {
- ubi_err("alignment is not multiple of min I/O unit");
+ ubi_err(ubi, "alignment is not multiple of min I/O unit");
goto fail;
}
n = ubi->leb_size % vol->alignment;
if (vol->data_pad != n) {
- ubi_err("bad data_pad, has to be %lld", n);
+ ubi_err(ubi, "bad data_pad, has to be %lld", n);
goto fail;
}
if (vol->vol_type != UBI_DYNAMIC_VOLUME &&
vol->vol_type != UBI_STATIC_VOLUME) {
- ubi_err("bad vol_type");
+ ubi_err(ubi, "bad vol_type");
goto fail;
}
if (vol->upd_marker && vol->corrupted) {
- ubi_err("update marker and corrupted simultaneously");
+ ubi_err(ubi, "update marker and corrupted simultaneously");
goto fail;
}
if (vol->reserved_pebs > ubi->good_peb_count) {
- ubi_err("too large reserved_pebs");
+ ubi_err(ubi, "too large reserved_pebs");
goto fail;
}
n = ubi->leb_size - vol->data_pad;
if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) {
- ubi_err("bad usable_leb_size, has to be %lld", n);
+ ubi_err(ubi, "bad usable_leb_size, has to be %lld", n);
goto fail;
}
if (vol->name_len > UBI_VOL_NAME_MAX) {
- ubi_err("too long volume name, max is %d", UBI_VOL_NAME_MAX);
+ ubi_err(ubi, "too long volume name, max is %d",
+ UBI_VOL_NAME_MAX);
goto fail;
}
n = strnlen(vol->name, vol->name_len + 1);
if (n != vol->name_len) {
- ubi_err("bad name_len %lld", n);
+ ubi_err(ubi, "bad name_len %lld", n);
goto fail;
}
n = (long long)vol->used_ebs * vol->usable_leb_size;
if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
if (vol->corrupted) {
- ubi_err("corrupted dynamic volume");
+ ubi_err(ubi, "corrupted dynamic volume");
goto fail;
}
if (vol->used_ebs != vol->reserved_pebs) {
- ubi_err("bad used_ebs");
+ ubi_err(ubi, "bad used_ebs");
goto fail;
}
if (vol->last_eb_bytes != vol->usable_leb_size) {
- ubi_err("bad last_eb_bytes");
+ ubi_err(ubi, "bad last_eb_bytes");
goto fail;
}
if (vol->used_bytes != n) {
- ubi_err("bad used_bytes");
+ ubi_err(ubi, "bad used_bytes");
goto fail;
}
} else {
if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {
- ubi_err("bad used_ebs");
+ ubi_err(ubi, "bad used_ebs");
goto fail;
}
if (vol->last_eb_bytes < 0 ||
vol->last_eb_bytes > vol->usable_leb_size) {
- ubi_err("bad last_eb_bytes");
+ ubi_err(ubi, "bad last_eb_bytes");
goto fail;
}
if (vol->used_bytes < 0 || vol->used_bytes > n ||
vol->used_bytes < n - vol->usable_leb_size) {
- ubi_err("bad used_bytes");
+ ubi_err(ubi, "bad used_bytes");
goto fail;
}
}
@@ -818,7 +769,7 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
if (alignment != vol->alignment || data_pad != vol->data_pad ||
upd_marker != vol->upd_marker || vol_type != vol->vol_type ||
name_len != vol->name_len || strncmp(name, vol->name, name_len)) {
- ubi_err("volume info is different");
+ ubi_err(ubi, "volume info is different");
goto fail;
}
@@ -826,7 +777,7 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
return 0;
fail:
- ubi_err("self-check failed for volume %d", vol_id);
+ ubi_err(ubi, "self-check failed for volume %d", vol_id);
if (vol)
ubi_dump_vol_info(vol);
ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);