mtd: UBI: Add support for updating static volumes
Added support to update UBI static volumes in barebox. This is mainly realized with adding the ioctl UBI_IOCVOLUP. Signed-off-by: Teresa Remmet <t.remmet@phytec.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
2c80865bc1
commit
c087e0804f
|
@ -65,7 +65,10 @@ static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf,
|
|||
struct ubi_device *ubi = priv->ubi;
|
||||
int err;
|
||||
|
||||
if (!priv->written) {
|
||||
if (!priv->written && !vol->updating) {
|
||||
if (vol->vol_type == UBI_STATIC_VOLUME)
|
||||
return -EROFS;
|
||||
|
||||
err = ubi_start_update(ubi, vol, vol->used_bytes);
|
||||
if (err < 0) {
|
||||
ubi_err(ubi, "Cannot start volume update");
|
||||
|
@ -104,7 +107,7 @@ static int ubi_volume_cdev_close(struct cdev *cdev)
|
|||
int remaining = vol->usable_leb_size -
|
||||
(priv->written % vol->usable_leb_size);
|
||||
|
||||
if (remaining) {
|
||||
if (remaining && vol->vol_type == UBI_DYNAMIC_VOLUME) {
|
||||
void *buf = kmalloc(remaining, GFP_KERNEL);
|
||||
|
||||
if (!buf)
|
||||
|
@ -122,6 +125,9 @@ static int ubi_volume_cdev_close(struct cdev *cdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (vol->vol_type == UBI_STATIC_VOLUME)
|
||||
cdev->size = priv->written;
|
||||
|
||||
err = ubi_finish_update(ubi, vol);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -156,12 +162,54 @@ static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs)
|
|||
return ofs;
|
||||
}
|
||||
|
||||
static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
|
||||
{
|
||||
struct ubi_volume_cdev_priv *priv = cdev->priv;
|
||||
struct ubi_device *ubi = priv->ubi;
|
||||
struct ubi_volume *vol = priv->vol;
|
||||
int err = 0;
|
||||
|
||||
switch (cmd) {
|
||||
/* Volume update command */
|
||||
case UBI_IOCVOLUP:
|
||||
{
|
||||
int64_t bytes, rsvd_bytes;
|
||||
|
||||
err = copy_from_user(&bytes, buf, sizeof(int64_t));
|
||||
if (err) {
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
rsvd_bytes = (long long)vol->reserved_pebs *
|
||||
ubi->leb_size - vol->data_pad;
|
||||
|
||||
if (bytes < 0 || bytes > rsvd_bytes) {
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
err = ubi_start_update(ubi, vol, bytes);
|
||||
if (bytes == 0)
|
||||
ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
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,
|
||||
.ioctl = ubi_volume_cdev_ioctl,
|
||||
};
|
||||
|
||||
int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
|
||||
|
@ -179,6 +227,10 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
|
|||
cdev->name = basprintf("%s.%s", ubi->cdev.name, vol->name);
|
||||
cdev->priv = priv;
|
||||
cdev->size = vol->used_bytes;
|
||||
|
||||
if (vol->vol_type == UBI_STATIC_VOLUME)
|
||||
cdev->flags = DEVFS_IS_CHARACTER_DEV;
|
||||
|
||||
cdev->dev = &vol->dev;
|
||||
ubi_msg(ubi, "registering %s as /dev/%s", vol->name, cdev->name);
|
||||
ret = devfs_create(cdev);
|
||||
|
|
|
@ -368,18 +368,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) {
|
||||
err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
|
||||
if (err)
|
||||
return err;
|
||||
/* The update is finished, clear the update marker */
|
||||
err = clear_update_marker(ubi, vol, vol->upd_bytes);
|
||||
if (err)
|
||||
return err;
|
||||
vol->updating = 0;
|
||||
err = to_write;
|
||||
vfree(vol->upd_buf);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue