diff options
| -rw-r--r-- | drivers/mtd/ubi/Kconfig.debug | 10 | ||||
| -rw-r--r-- | drivers/mtd/ubi/build.c | 21 | ||||
| -rw-r--r-- | drivers/mtd/ubi/cdev.c | 184 | ||||
| -rw-r--r-- | drivers/mtd/ubi/gluebi.c | 11 | ||||
| -rw-r--r-- | drivers/mtd/ubi/scan.c | 8 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 11 | ||||
| -rw-r--r-- | drivers/mtd/ubi/upd.c | 21 | ||||
| -rw-r--r-- | drivers/mtd/ubi/vmt.c | 17 | ||||
| -rw-r--r-- | include/mtd/ubi-user.h | 132 | 
9 files changed, 284 insertions, 131 deletions
| diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index 1e2ee22edeff..2246f154e2f7 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug | |||
| @@ -33,16 +33,6 @@ config MTD_UBI_DEBUG_DISABLE_BGT | |||
| 33 | This option switches the background thread off by default. The thread | 33 | This option switches the background thread off by default. The thread | 
| 34 | may be also be enabled/disabled via UBI sysfs. | 34 | may be also be enabled/disabled via UBI sysfs. | 
| 35 | 35 | ||
| 36 | config MTD_UBI_DEBUG_USERSPACE_IO | ||
| 37 | bool "Direct user-space write/erase support" | ||
| 38 | default n | ||
| 39 | depends on MTD_UBI_DEBUG | ||
| 40 | help | ||
| 41 | By default, users cannot directly write and erase individual | ||
| 42 | eraseblocks of dynamic volumes, and have to use update operation | ||
| 43 | instead. This option enables this capability - it is very useful for | ||
| 44 | debugging and testing. | ||
| 45 | |||
| 46 | config MTD_UBI_DEBUG_EMULATE_BITFLIPS | 36 | config MTD_UBI_DEBUG_EMULATE_BITFLIPS | 
| 47 | bool "Emulate flash bit-flips" | 37 | bool "Emulate flash bit-flips" | 
| 48 | depends on MTD_UBI_DEBUG | 38 | depends on MTD_UBI_DEBUG | 
| diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 9082768cc6c3..4048db83aef6 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -263,8 +263,12 @@ static ssize_t dev_attribute_show(struct device *dev, | |||
| 263 | return ret; | 263 | return ret; | 
| 264 | } | 264 | } | 
| 265 | 265 | ||
| 266 | /* Fake "release" method for UBI devices */ | 266 | static void dev_release(struct device *dev) | 
| 267 | static void dev_release(struct device *dev) { } | 267 | { | 
| 268 | struct ubi_device *ubi = container_of(dev, struct ubi_device, dev); | ||
| 269 | |||
| 270 | kfree(ubi); | ||
| 271 | } | ||
| 268 | 272 | ||
| 269 | /** | 273 | /** | 
| 270 | * ubi_sysfs_init - initialize sysfs for an UBI device. | 274 | * ubi_sysfs_init - initialize sysfs for an UBI device. | 
| @@ -380,7 +384,7 @@ static void free_user_volumes(struct ubi_device *ubi) | |||
| 380 | */ | 384 | */ | 
| 381 | static int uif_init(struct ubi_device *ubi) | 385 | static int uif_init(struct ubi_device *ubi) | 
| 382 | { | 386 | { | 
| 383 | int i, err, do_free = 0; | 387 | int i, err; | 
| 384 | dev_t dev; | 388 | dev_t dev; | 
| 385 | 389 | ||
| 386 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 390 | sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); | 
| @@ -427,13 +431,10 @@ static int uif_init(struct ubi_device *ubi) | |||
| 427 | 431 | ||
| 428 | out_volumes: | 432 | out_volumes: | 
| 429 | kill_volumes(ubi); | 433 | kill_volumes(ubi); | 
| 430 | do_free = 0; | ||
| 431 | out_sysfs: | 434 | out_sysfs: | 
| 432 | ubi_sysfs_close(ubi); | 435 | ubi_sysfs_close(ubi); | 
| 433 | cdev_del(&ubi->cdev); | 436 | cdev_del(&ubi->cdev); | 
| 434 | out_unreg: | 437 | out_unreg: | 
| 435 | if (do_free) | ||
| 436 | free_user_volumes(ubi); | ||
| 437 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); | 438 | unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); | 
| 438 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); | 439 | ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); | 
| 439 | return err; | 440 | return err; | 
| @@ -947,6 +948,12 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 947 | if (ubi->bgt_thread) | 948 | if (ubi->bgt_thread) | 
| 948 | kthread_stop(ubi->bgt_thread); | 949 | kthread_stop(ubi->bgt_thread); | 
| 949 | 950 | ||
| 951 | /* | ||
| 952 | * Get a reference to the device in order to prevent 'dev_release()' | ||
| 953 | * from freeing @ubi object. | ||
| 954 | */ | ||
| 955 | get_device(&ubi->dev); | ||
| 956 | |||
| 950 | uif_close(ubi); | 957 | uif_close(ubi); | 
| 951 | ubi_wl_close(ubi); | 958 | ubi_wl_close(ubi); | 
| 952 | free_internal_volumes(ubi); | 959 | free_internal_volumes(ubi); | 
| @@ -958,7 +965,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) | |||
| 958 | vfree(ubi->dbg_peb_buf); | 965 | vfree(ubi->dbg_peb_buf); | 
| 959 | #endif | 966 | #endif | 
| 960 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); | 967 | ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); | 
| 961 | kfree(ubi); | 968 | put_device(&ubi->dev); | 
| 962 | return 0; | 969 | return 0; | 
| 963 | } | 970 | } | 
| 964 | 971 | ||
| diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 98cf31ed0814..e63c8fc3df3a 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
| @@ -40,9 +40,9 @@ | |||
| 40 | #include <linux/ioctl.h> | 40 | #include <linux/ioctl.h> | 
| 41 | #include <linux/capability.h> | 41 | #include <linux/capability.h> | 
| 42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> | 
| 43 | #include <linux/smp_lock.h> | 43 | #include <linux/compat.h> | 
| 44 | #include <linux/math64.h> | ||
| 44 | #include <mtd/ubi-user.h> | 45 | #include <mtd/ubi-user.h> | 
| 45 | #include <asm/div64.h> | ||
| 46 | #include "ubi.h" | 46 | #include "ubi.h" | 
| 47 | 47 | ||
| 48 | /** | 48 | /** | 
| @@ -195,7 +195,6 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
| 195 | int err, lnum, off, len, tbuf_size; | 195 | int err, lnum, off, len, tbuf_size; | 
| 196 | size_t count_save = count; | 196 | size_t count_save = count; | 
| 197 | void *tbuf; | 197 | void *tbuf; | 
| 198 | uint64_t tmp; | ||
| 199 | 198 | ||
| 200 | dbg_gen("read %zd bytes from offset %lld of volume %d", | 199 | dbg_gen("read %zd bytes from offset %lld of volume %d", | 
| 201 | count, *offp, vol->vol_id); | 200 | count, *offp, vol->vol_id); | 
| @@ -225,10 +224,7 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
| 225 | return -ENOMEM; | 224 | return -ENOMEM; | 
| 226 | 225 | ||
| 227 | len = count > tbuf_size ? tbuf_size : count; | 226 | len = count > tbuf_size ? tbuf_size : count; | 
| 228 | 227 | lnum = div_u64_rem(*offp, vol->usable_leb_size, &off); | |
| 229 | tmp = *offp; | ||
| 230 | off = do_div(tmp, vol->usable_leb_size); | ||
| 231 | lnum = tmp; | ||
| 232 | 228 | ||
| 233 | do { | 229 | do { | 
| 234 | cond_resched(); | 230 | cond_resched(); | 
| @@ -263,12 +259,9 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, | |||
| 263 | return err ? err : count_save - count; | 259 | return err ? err : count_save - count; | 
| 264 | } | 260 | } | 
| 265 | 261 | ||
| 266 | #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO | ||
| 267 | |||
| 268 | /* | 262 | /* | 
| 269 | * This function allows to directly write to dynamic UBI volumes, without | 263 | * This function allows to directly write to dynamic UBI volumes, without | 
| 270 | * issuing the volume update operation. Available only as a debugging feature. | 264 | * issuing the volume update operation. | 
| 271 | * Very useful for testing UBI. | ||
| 272 | */ | 265 | */ | 
| 273 | static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | 266 | static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | 
| 274 | size_t count, loff_t *offp) | 267 | size_t count, loff_t *offp) | 
| @@ -279,7 +272,9 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 279 | int lnum, off, len, tbuf_size, err = 0; | 272 | int lnum, off, len, tbuf_size, err = 0; | 
| 280 | size_t count_save = count; | 273 | size_t count_save = count; | 
| 281 | char *tbuf; | 274 | char *tbuf; | 
| 282 | uint64_t tmp; | 275 | |
| 276 | if (!vol->direct_writes) | ||
| 277 | return -EPERM; | ||
| 283 | 278 | ||
| 284 | dbg_gen("requested: write %zd bytes to offset %lld of volume %u", | 279 | dbg_gen("requested: write %zd bytes to offset %lld of volume %u", | 
| 285 | count, *offp, vol->vol_id); | 280 | count, *offp, vol->vol_id); | 
| @@ -287,10 +282,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 287 | if (vol->vol_type == UBI_STATIC_VOLUME) | 282 | if (vol->vol_type == UBI_STATIC_VOLUME) | 
| 288 | return -EROFS; | 283 | return -EROFS; | 
| 289 | 284 | ||
| 290 | tmp = *offp; | 285 | lnum = div_u64_rem(*offp, vol->usable_leb_size, &off); | 
| 291 | off = do_div(tmp, vol->usable_leb_size); | ||
| 292 | lnum = tmp; | ||
| 293 | |||
| 294 | if (off & (ubi->min_io_size - 1)) { | 286 | if (off & (ubi->min_io_size - 1)) { | 
| 295 | dbg_err("unaligned position"); | 287 | dbg_err("unaligned position"); | 
| 296 | return -EINVAL; | 288 | return -EINVAL; | 
| @@ -347,10 +339,6 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, | |||
| 347 | return err ? err : count_save - count; | 339 | return err ? err : count_save - count; | 
| 348 | } | 340 | } | 
| 349 | 341 | ||
| 350 | #else | ||
| 351 | #define vol_cdev_direct_write(file, buf, count, offp) (-EPERM) | ||
| 352 | #endif /* CONFIG_MTD_UBI_DEBUG_USERSPACE_IO */ | ||
| 353 | |||
| 354 | static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | 342 | static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | 
| 355 | size_t count, loff_t *offp) | 343 | size_t count, loff_t *offp) | 
| 356 | { | 344 | { | 
| @@ -402,8 +390,8 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf, | |||
| 402 | return count; | 390 | return count; | 
| 403 | } | 391 | } | 
| 404 | 392 | ||
| 405 | static int vol_cdev_ioctl(struct inode *inode, struct file *file, | 393 | static long vol_cdev_ioctl(struct file *file, unsigned int cmd, | 
| 406 | unsigned int cmd, unsigned long arg) | 394 | unsigned long arg) | 
| 407 | { | 395 | { | 
| 408 | int err = 0; | 396 | int err = 0; | 
| 409 | struct ubi_volume_desc *desc = file->private_data; | 397 | struct ubi_volume_desc *desc = file->private_data; | 
| @@ -487,7 +475,6 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 487 | break; | 475 | break; | 
| 488 | } | 476 | } | 
| 489 | 477 | ||
| 490 | #ifdef CONFIG_MTD_UBI_DEBUG_USERSPACE_IO | ||
| 491 | /* Logical eraseblock erasure command */ | 478 | /* Logical eraseblock erasure command */ | 
| 492 | case UBI_IOCEBER: | 479 | case UBI_IOCEBER: | 
| 493 | { | 480 | { | 
| @@ -518,13 +505,77 @@ static int vol_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 518 | err = ubi_wl_flush(ubi); | 505 | err = ubi_wl_flush(ubi); | 
| 519 | break; | 506 | break; | 
| 520 | } | 507 | } | 
| 521 | #endif | 508 | |
| 509 | /* Logical eraseblock map command */ | ||
| 510 | case UBI_IOCEBMAP: | ||
| 511 | { | ||
| 512 | struct ubi_map_req req; | ||
| 513 | |||
| 514 | err = copy_from_user(&req, argp, sizeof(struct ubi_map_req)); | ||
| 515 | if (err) { | ||
| 516 | err = -EFAULT; | ||
| 517 | break; | ||
| 518 | } | ||
| 519 | err = ubi_leb_map(desc, req.lnum, req.dtype); | ||
| 520 | break; | ||
| 521 | } | ||
| 522 | |||
| 523 | /* Logical eraseblock un-map command */ | ||
| 524 | case UBI_IOCEBUNMAP: | ||
| 525 | { | ||
| 526 | int32_t lnum; | ||
| 527 | |||
| 528 | err = get_user(lnum, (__user int32_t *)argp); | ||
| 529 | if (err) { | ||
| 530 | err = -EFAULT; | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | err = ubi_leb_unmap(desc, lnum); | ||
| 534 | break; | ||
| 535 | } | ||
| 536 | |||
| 537 | /* Check if logical eraseblock is mapped command */ | ||
| 538 | case UBI_IOCEBISMAP: | ||
| 539 | { | ||
| 540 | int32_t lnum; | ||
| 541 | |||
| 542 | err = get_user(lnum, (__user int32_t *)argp); | ||
| 543 | if (err) { | ||
| 544 | err = -EFAULT; | ||
| 545 | break; | ||
| 546 | } | ||
| 547 | err = ubi_is_mapped(desc, lnum); | ||
| 548 | break; | ||
| 549 | } | ||
| 550 | |||
| 551 | /* Set volume property command*/ | ||
| 552 | case UBI_IOCSETPROP: | ||
| 553 | { | ||
| 554 | struct ubi_set_prop_req req; | ||
| 555 | |||
| 556 | err = copy_from_user(&req, argp, | ||
| 557 | sizeof(struct ubi_set_prop_req)); | ||
| 558 | if (err) { | ||
| 559 | err = -EFAULT; | ||
| 560 | break; | ||
| 561 | } | ||
| 562 | switch (req.property) { | ||
| 563 | case UBI_PROP_DIRECT_WRITE: | ||
| 564 | mutex_lock(&ubi->volumes_mutex); | ||
| 565 | desc->vol->direct_writes = !!req.value; | ||
| 566 | mutex_unlock(&ubi->volumes_mutex); | ||
| 567 | break; | ||
| 568 | default: | ||
| 569 | err = -EINVAL; | ||
| 570 | break; | ||
| 571 | } | ||
| 572 | break; | ||
| 573 | } | ||
| 522 | 574 | ||
| 523 | default: | 575 | default: | 
| 524 | err = -ENOTTY; | 576 | err = -ENOTTY; | 
| 525 | break; | 577 | break; | 
| 526 | } | 578 | } | 
| 527 | |||
| 528 | return err; | 579 | return err; | 
| 529 | } | 580 | } | 
| 530 | 581 | ||
| @@ -762,8 +813,8 @@ out_free: | |||
| 762 | return err; | 813 | return err; | 
| 763 | } | 814 | } | 
| 764 | 815 | ||
| 765 | static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | 816 | static long ubi_cdev_ioctl(struct file *file, unsigned int cmd, | 
| 766 | unsigned int cmd, unsigned long arg) | 817 | unsigned long arg) | 
| 767 | { | 818 | { | 
| 768 | int err = 0; | 819 | int err = 0; | 
| 769 | struct ubi_device *ubi; | 820 | struct ubi_device *ubi; | 
| @@ -773,7 +824,7 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 773 | if (!capable(CAP_SYS_RESOURCE)) | 824 | if (!capable(CAP_SYS_RESOURCE)) | 
| 774 | return -EPERM; | 825 | return -EPERM; | 
| 775 | 826 | ||
| 776 | ubi = ubi_get_by_major(imajor(inode)); | 827 | ubi = ubi_get_by_major(imajor(file->f_mapping->host)); | 
| 777 | if (!ubi) | 828 | if (!ubi) | 
| 778 | return -ENODEV; | 829 | return -ENODEV; | 
| 779 | 830 | ||
| @@ -843,7 +894,6 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 843 | case UBI_IOCRSVOL: | 894 | case UBI_IOCRSVOL: | 
| 844 | { | 895 | { | 
| 845 | int pebs; | 896 | int pebs; | 
| 846 | uint64_t tmp; | ||
| 847 | struct ubi_rsvol_req req; | 897 | struct ubi_rsvol_req req; | 
| 848 | 898 | ||
| 849 | dbg_gen("re-size volume"); | 899 | dbg_gen("re-size volume"); | 
| @@ -863,9 +913,8 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 863 | break; | 913 | break; | 
| 864 | } | 914 | } | 
| 865 | 915 | ||
| 866 | tmp = req.bytes; | 916 | pebs = div_u64(req.bytes + desc->vol->usable_leb_size - 1, | 
| 867 | pebs = !!do_div(tmp, desc->vol->usable_leb_size); | 917 | desc->vol->usable_leb_size); | 
| 868 | pebs += tmp; | ||
| 869 | 918 | ||
| 870 | mutex_lock(&ubi->volumes_mutex); | 919 | mutex_lock(&ubi->volumes_mutex); | 
| 871 | err = ubi_resize_volume(desc, pebs); | 920 | err = ubi_resize_volume(desc, pebs); | 
| @@ -909,8 +958,8 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 909 | return err; | 958 | return err; | 
| 910 | } | 959 | } | 
| 911 | 960 | ||
| 912 | static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, | 961 | static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd, | 
| 913 | unsigned int cmd, unsigned long arg) | 962 | unsigned long arg) | 
| 914 | { | 963 | { | 
| 915 | int err = 0; | 964 | int err = 0; | 
| 916 | void __user *argp = (void __user *)arg; | 965 | void __user *argp = (void __user *)arg; | 
| @@ -986,26 +1035,59 @@ static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, | |||
| 986 | return err; | 1035 | return err; | 
| 987 | } | 1036 | } | 
| 988 | 1037 | ||
| 989 | /* UBI control character device operations */ | 1038 | #ifdef CONFIG_COMPAT | 
| 990 | struct file_operations ubi_ctrl_cdev_operations = { | 1039 | static long vol_cdev_compat_ioctl(struct file *file, unsigned int cmd, | 
| 991 | .ioctl = ctrl_cdev_ioctl, | 1040 | unsigned long arg) | 
| 992 | .owner = THIS_MODULE, | 1041 | { | 
| 1042 | unsigned long translated_arg = (unsigned long)compat_ptr(arg); | ||
| 1043 | |||
| 1044 | return vol_cdev_ioctl(file, cmd, translated_arg); | ||
| 1045 | } | ||
| 1046 | |||
| 1047 | static long ubi_cdev_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 1048 | unsigned long arg) | ||
| 1049 | { | ||
| 1050 | unsigned long translated_arg = (unsigned long)compat_ptr(arg); | ||
| 1051 | |||
| 1052 | return ubi_cdev_ioctl(file, cmd, translated_arg); | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static long ctrl_cdev_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 1056 | unsigned long arg) | ||
| 1057 | { | ||
| 1058 | unsigned long translated_arg = (unsigned long)compat_ptr(arg); | ||
| 1059 | |||
| 1060 | return ctrl_cdev_ioctl(file, cmd, translated_arg); | ||
| 1061 | } | ||
| 1062 | #else | ||
| 1063 | #define vol_cdev_compat_ioctl NULL | ||
| 1064 | #define ubi_cdev_compat_ioctl NULL | ||
| 1065 | #define ctrl_cdev_compat_ioctl NULL | ||
| 1066 | #endif | ||
| 1067 | |||
| 1068 | /* UBI volume character device operations */ | ||
| 1069 | const struct file_operations ubi_vol_cdev_operations = { | ||
| 1070 | .owner = THIS_MODULE, | ||
| 1071 | .open = vol_cdev_open, | ||
| 1072 | .release = vol_cdev_release, | ||
| 1073 | .llseek = vol_cdev_llseek, | ||
| 1074 | .read = vol_cdev_read, | ||
| 1075 | .write = vol_cdev_write, | ||
| 1076 | .unlocked_ioctl = vol_cdev_ioctl, | ||
| 1077 | .compat_ioctl = vol_cdev_compat_ioctl, | ||
| 993 | }; | 1078 | }; | 
| 994 | 1079 | ||
| 995 | /* UBI character device operations */ | 1080 | /* UBI character device operations */ | 
| 996 | struct file_operations ubi_cdev_operations = { | 1081 | const struct file_operations ubi_cdev_operations = { | 
| 997 | .owner = THIS_MODULE, | 1082 | .owner = THIS_MODULE, | 
| 998 | .ioctl = ubi_cdev_ioctl, | 1083 | .llseek = no_llseek, | 
| 999 | .llseek = no_llseek, | 1084 | .unlocked_ioctl = ubi_cdev_ioctl, | 
| 1085 | .compat_ioctl = ubi_cdev_compat_ioctl, | ||
| 1000 | }; | 1086 | }; | 
| 1001 | 1087 | ||
| 1002 | /* UBI volume character device operations */ | 1088 | /* UBI control character device operations */ | 
| 1003 | struct file_operations ubi_vol_cdev_operations = { | 1089 | const struct file_operations ubi_ctrl_cdev_operations = { | 
| 1004 | .owner = THIS_MODULE, | 1090 | .owner = THIS_MODULE, | 
| 1005 | .open = vol_cdev_open, | 1091 | .unlocked_ioctl = ctrl_cdev_ioctl, | 
| 1006 | .release = vol_cdev_release, | 1092 | .compat_ioctl = ctrl_cdev_compat_ioctl, | 
| 1007 | .llseek = vol_cdev_llseek, | ||
| 1008 | .read = vol_cdev_read, | ||
| 1009 | .write = vol_cdev_write, | ||
| 1010 | .ioctl = vol_cdev_ioctl, | ||
| 1011 | }; | 1093 | }; | 
| diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 6dd4f5e77f82..49cd55ade9c8 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | * eraseblock size is equivalent to the logical eraseblock size of the volume. | 28 | * eraseblock size is equivalent to the logical eraseblock size of the volume. | 
| 29 | */ | 29 | */ | 
| 30 | 30 | ||
| 31 | #include <asm/div64.h> | 31 | #include <linux/math64.h> | 
| 32 | #include "ubi.h" | 32 | #include "ubi.h" | 
| 33 | 33 | ||
| 34 | /** | 34 | /** | 
| @@ -109,7 +109,6 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 109 | int err = 0, lnum, offs, total_read; | 109 | int err = 0, lnum, offs, total_read; | 
| 110 | struct ubi_volume *vol; | 110 | struct ubi_volume *vol; | 
| 111 | struct ubi_device *ubi; | 111 | struct ubi_device *ubi; | 
| 112 | uint64_t tmp = from; | ||
| 113 | 112 | ||
| 114 | dbg_gen("read %zd bytes from offset %lld", len, from); | 113 | dbg_gen("read %zd bytes from offset %lld", len, from); | 
| 115 | 114 | ||
| @@ -119,9 +118,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 119 | vol = container_of(mtd, struct ubi_volume, gluebi_mtd); | 118 | vol = container_of(mtd, struct ubi_volume, gluebi_mtd); | 
| 120 | ubi = vol->ubi; | 119 | ubi = vol->ubi; | 
| 121 | 120 | ||
| 122 | offs = do_div(tmp, mtd->erasesize); | 121 | lnum = div_u64_rem(from, mtd->erasesize, &offs); | 
| 123 | lnum = tmp; | ||
| 124 | |||
| 125 | total_read = len; | 122 | total_read = len; | 
| 126 | while (total_read) { | 123 | while (total_read) { | 
| 127 | size_t to_read = mtd->erasesize - offs; | 124 | size_t to_read = mtd->erasesize - offs; | 
| @@ -160,7 +157,6 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 160 | int err = 0, lnum, offs, total_written; | 157 | int err = 0, lnum, offs, total_written; | 
| 161 | struct ubi_volume *vol; | 158 | struct ubi_volume *vol; | 
| 162 | struct ubi_device *ubi; | 159 | struct ubi_device *ubi; | 
| 163 | uint64_t tmp = to; | ||
| 164 | 160 | ||
| 165 | dbg_gen("write %zd bytes to offset %lld", len, to); | 161 | dbg_gen("write %zd bytes to offset %lld", len, to); | 
| 166 | 162 | ||
| @@ -173,8 +169,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 173 | if (ubi->ro_mode) | 169 | if (ubi->ro_mode) | 
| 174 | return -EROFS; | 170 | return -EROFS; | 
| 175 | 171 | ||
| 176 | offs = do_div(tmp, mtd->erasesize); | 172 | lnum = div_u64_rem(to, mtd->erasesize, &offs); | 
| 177 | lnum = tmp; | ||
| 178 | 173 | ||
| 179 | if (len % mtd->writesize || offs % mtd->writesize) | 174 | if (len % mtd->writesize || offs % mtd->writesize) | 
| 180 | return -EINVAL; | 175 | return -EINVAL; | 
| diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index ecde202a5a12..c3d653ba5ca0 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | #include <linux/err.h> | 43 | #include <linux/err.h> | 
| 44 | #include <linux/crc32.h> | 44 | #include <linux/crc32.h> | 
| 45 | #include <asm/div64.h> | 45 | #include <linux/math64.h> | 
| 46 | #include "ubi.h" | 46 | #include "ubi.h" | 
| 47 | 47 | ||
| 48 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 48 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 
| @@ -904,10 +904,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
| 904 | dbg_msg("scanning is finished"); | 904 | dbg_msg("scanning is finished"); | 
| 905 | 905 | ||
| 906 | /* Calculate mean erase counter */ | 906 | /* Calculate mean erase counter */ | 
| 907 | if (si->ec_count) { | 907 | if (si->ec_count) | 
| 908 | do_div(si->ec_sum, si->ec_count); | 908 | si->mean_ec = div_u64(si->ec_sum, si->ec_count); | 
| 909 | si->mean_ec = si->ec_sum; | ||
| 910 | } | ||
| 911 | 909 | ||
| 912 | if (si->is_empty) | 910 | if (si->is_empty) | 
| 913 | ubi_msg("empty MTD device detected"); | 911 | ubi_msg("empty MTD device detected"); | 
| diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 4a8ec485c91d..c055511bb1b2 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -206,6 +206,7 @@ struct ubi_volume_desc; | |||
| 206 | * @upd_marker: %1 if the update marker is set for this volume | 206 | * @upd_marker: %1 if the update marker is set for this volume | 
| 207 | * @updating: %1 if the volume is being updated | 207 | * @updating: %1 if the volume is being updated | 
| 208 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress | 208 | * @changing_leb: %1 if the atomic LEB change ioctl command is in progress | 
| 209 | * @direct_writes: %1 if direct writes are enabled for this volume | ||
| 209 | * | 210 | * | 
| 210 | * @gluebi_desc: gluebi UBI volume descriptor | 211 | * @gluebi_desc: gluebi UBI volume descriptor | 
| 211 | * @gluebi_refcount: reference count of the gluebi MTD device | 212 | * @gluebi_refcount: reference count of the gluebi MTD device | 
| @@ -253,6 +254,7 @@ struct ubi_volume { | |||
| 253 | unsigned int upd_marker:1; | 254 | unsigned int upd_marker:1; | 
| 254 | unsigned int updating:1; | 255 | unsigned int updating:1; | 
| 255 | unsigned int changing_leb:1; | 256 | unsigned int changing_leb:1; | 
| 257 | unsigned int direct_writes:1; | ||
| 256 | 258 | ||
| 257 | #ifdef CONFIG_MTD_UBI_GLUEBI | 259 | #ifdef CONFIG_MTD_UBI_GLUEBI | 
| 258 | /* | 260 | /* | 
| @@ -304,7 +306,8 @@ struct ubi_wl_entry; | |||
| 304 | * @vtbl_size: size of the volume table in bytes | 306 | * @vtbl_size: size of the volume table in bytes | 
| 305 | * @vtbl: in-RAM volume table copy | 307 | * @vtbl: in-RAM volume table copy | 
| 306 | * @volumes_mutex: protects on-flash volume table and serializes volume | 308 | * @volumes_mutex: protects on-flash volume table and serializes volume | 
| 307 | * changes, like creation, deletion, update, re-size and re-name | 309 | * changes, like creation, deletion, update, re-size, | 
| 310 | * re-name and set property | ||
| 308 | * | 311 | * | 
| 309 | * @max_ec: current highest erase counter value | 312 | * @max_ec: current highest erase counter value | 
| 310 | * @mean_ec: current mean erase counter value | 313 | * @mean_ec: current mean erase counter value | 
| @@ -449,9 +452,9 @@ struct ubi_device { | |||
| 449 | }; | 452 | }; | 
| 450 | 453 | ||
| 451 | extern struct kmem_cache *ubi_wl_entry_slab; | 454 | extern struct kmem_cache *ubi_wl_entry_slab; | 
| 452 | extern struct file_operations ubi_ctrl_cdev_operations; | 455 | extern const struct file_operations ubi_ctrl_cdev_operations; | 
| 453 | extern struct file_operations ubi_cdev_operations; | 456 | extern const struct file_operations ubi_cdev_operations; | 
| 454 | extern struct file_operations ubi_vol_cdev_operations; | 457 | extern const struct file_operations ubi_vol_cdev_operations; | 
| 455 | extern struct class *ubi_class; | 458 | extern struct class *ubi_class; | 
| 456 | extern struct mutex ubi_devices_mutex; | 459 | extern struct mutex ubi_devices_mutex; | 
| 457 | 460 | ||
| diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 8b89cc18ff0b..6b4d1ae891ae 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | 40 | ||
| 41 | #include <linux/err.h> | 41 | #include <linux/err.h> | 
| 42 | #include <linux/uaccess.h> | 42 | #include <linux/uaccess.h> | 
| 43 | #include <asm/div64.h> | 43 | #include <linux/math64.h> | 
| 44 | #include "ubi.h" | 44 | #include "ubi.h" | 
| 45 | 45 | ||
| 46 | /** | 46 | /** | 
| @@ -89,7 +89,6 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 89 | long long bytes) | 89 | long long bytes) | 
| 90 | { | 90 | { | 
| 91 | int err; | 91 | int err; | 
| 92 | uint64_t tmp; | ||
| 93 | struct ubi_vtbl_record vtbl_rec; | 92 | struct ubi_vtbl_record vtbl_rec; | 
| 94 | 93 | ||
| 95 | dbg_gen("clear update marker for volume %d", vol->vol_id); | 94 | dbg_gen("clear update marker for volume %d", vol->vol_id); | 
| @@ -101,9 +100,9 @@ static int clear_update_marker(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 101 | 100 | ||
| 102 | if (vol->vol_type == UBI_STATIC_VOLUME) { | 101 | if (vol->vol_type == UBI_STATIC_VOLUME) { | 
| 103 | vol->corrupted = 0; | 102 | vol->corrupted = 0; | 
| 104 | vol->used_bytes = tmp = bytes; | 103 | vol->used_bytes = bytes; | 
| 105 | vol->last_eb_bytes = do_div(tmp, vol->usable_leb_size); | 104 | vol->used_ebs = div_u64_rem(bytes, vol->usable_leb_size, | 
| 106 | vol->used_ebs = tmp; | 105 | &vol->last_eb_bytes); | 
| 107 | if (vol->last_eb_bytes) | 106 | if (vol->last_eb_bytes) | 
| 108 | vol->used_ebs += 1; | 107 | vol->used_ebs += 1; | 
| 109 | else | 108 | else | 
| @@ -131,7 +130,6 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 131 | long long bytes) | 130 | long long bytes) | 
| 132 | { | 131 | { | 
| 133 | int i, err; | 132 | int i, err; | 
| 134 | uint64_t tmp; | ||
| 135 | 133 | ||
| 136 | dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes); | 134 | dbg_gen("start update of volume %d, %llu bytes", vol->vol_id, bytes); | 
| 137 | ubi_assert(!vol->updating && !vol->changing_leb); | 135 | ubi_assert(!vol->updating && !vol->changing_leb); | 
| @@ -161,9 +159,8 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 161 | if (!vol->upd_buf) | 159 | if (!vol->upd_buf) | 
| 162 | return -ENOMEM; | 160 | return -ENOMEM; | 
| 163 | 161 | ||
| 164 | tmp = bytes; | 162 | vol->upd_ebs = div_u64(bytes + vol->usable_leb_size - 1, | 
| 165 | vol->upd_ebs = !!do_div(tmp, vol->usable_leb_size); | 163 | vol->usable_leb_size); | 
| 166 | vol->upd_ebs += tmp; | ||
| 167 | vol->upd_bytes = bytes; | 164 | vol->upd_bytes = bytes; | 
| 168 | vol->upd_received = 0; | 165 | vol->upd_received = 0; | 
| 169 | return 0; | 166 | return 0; | 
| @@ -282,7 +279,6 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, | |||
| 282 | int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | 279 | int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | 
| 283 | const void __user *buf, int count) | 280 | const void __user *buf, int count) | 
| 284 | { | 281 | { | 
| 285 | uint64_t tmp; | ||
| 286 | int lnum, offs, err = 0, len, to_write = count; | 282 | int lnum, offs, err = 0, len, to_write = count; | 
| 287 | 283 | ||
| 288 | dbg_gen("write %d of %lld bytes, %lld already passed", | 284 | dbg_gen("write %d of %lld bytes, %lld already passed", | 
| @@ -291,10 +287,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
| 291 | if (ubi->ro_mode) | 287 | if (ubi->ro_mode) | 
| 292 | return -EROFS; | 288 | return -EROFS; | 
| 293 | 289 | ||
| 294 | tmp = vol->upd_received; | 290 | lnum = div_u64_rem(vol->upd_received, vol->usable_leb_size, &offs); | 
| 295 | offs = do_div(tmp, vol->usable_leb_size); | ||
| 296 | lnum = tmp; | ||
| 297 | |||
| 298 | if (vol->upd_received + count > vol->upd_bytes) | 291 | if (vol->upd_received + count > vol->upd_bytes) | 
| 299 | to_write = count = vol->upd_bytes - vol->upd_received; | 292 | to_write = count = vol->upd_bytes - vol->upd_received; | 
| 300 | 293 | ||
| diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 22e1d7398fce..df5483562b7a 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | */ | 24 | */ | 
| 25 | 25 | ||
| 26 | #include <linux/err.h> | 26 | #include <linux/err.h> | 
| 27 | #include <asm/div64.h> | 27 | #include <linux/math64.h> | 
| 28 | #include "ubi.h" | 28 | #include "ubi.h" | 
| 29 | 29 | ||
| 30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 30 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 
| @@ -205,7 +205,6 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 205 | int i, err, vol_id = req->vol_id, do_free = 1; | 205 | int i, err, vol_id = req->vol_id, do_free = 1; | 
| 206 | struct ubi_volume *vol; | 206 | struct ubi_volume *vol; | 
| 207 | struct ubi_vtbl_record vtbl_rec; | 207 | struct ubi_vtbl_record vtbl_rec; | 
| 208 | uint64_t bytes; | ||
| 209 | dev_t dev; | 208 | dev_t dev; | 
| 210 | 209 | ||
| 211 | if (ubi->ro_mode) | 210 | if (ubi->ro_mode) | 
| @@ -255,10 +254,8 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 255 | 254 | ||
| 256 | /* Calculate how many eraseblocks are requested */ | 255 | /* Calculate how many eraseblocks are requested */ | 
| 257 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; | 256 | vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; | 
| 258 | bytes = req->bytes; | 257 | vol->reserved_pebs += div_u64(req->bytes + vol->usable_leb_size - 1, | 
| 259 | if (do_div(bytes, vol->usable_leb_size)) | 258 | vol->usable_leb_size); | 
| 260 | vol->reserved_pebs = 1; | ||
| 261 | vol->reserved_pebs += bytes; | ||
| 262 | 259 | ||
| 263 | /* Reserve physical eraseblocks */ | 260 | /* Reserve physical eraseblocks */ | 
| 264 | if (vol->reserved_pebs > ubi->avail_pebs) { | 261 | if (vol->reserved_pebs > ubi->avail_pebs) { | 
| @@ -301,10 +298,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) | |||
| 301 | vol->used_bytes = | 298 | vol->used_bytes = | 
| 302 | (long long)vol->used_ebs * vol->usable_leb_size; | 299 | (long long)vol->used_ebs * vol->usable_leb_size; | 
| 303 | } else { | 300 | } else { | 
| 304 | bytes = vol->used_bytes; | 301 | vol->used_ebs = div_u64_rem(vol->used_bytes, | 
| 305 | vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size); | 302 | vol->usable_leb_size, | 
| 306 | vol->used_ebs = bytes; | 303 | &vol->last_eb_bytes); | 
| 307 | if (vol->last_eb_bytes) | 304 | if (vol->last_eb_bytes != 0) | 
| 308 | vol->used_ebs += 1; | 305 | vol->used_ebs += 1; | 
| 309 | else | 306 | else | 
| 310 | vol->last_eb_bytes = vol->usable_leb_size; | 307 | vol->last_eb_bytes = vol->usable_leb_size; | 
| diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h index 2dc2eb2b8e22..296efae3525e 100644 --- a/include/mtd/ubi-user.h +++ b/include/mtd/ubi-user.h | |||
| @@ -40,37 +40,37 @@ | |||
| 40 | * UBI volume creation | 40 | * UBI volume creation | 
| 41 | * ~~~~~~~~~~~~~~~~~~~ | 41 | * ~~~~~~~~~~~~~~~~~~~ | 
| 42 | * | 42 | * | 
| 43 | * UBI volumes are created via the %UBI_IOCMKVOL IOCTL command of UBI character | 43 | * UBI volumes are created via the %UBI_IOCMKVOL ioctl command of UBI character | 
| 44 | * device. A &struct ubi_mkvol_req object has to be properly filled and a | 44 | * device. A &struct ubi_mkvol_req object has to be properly filled and a | 
| 45 | * pointer to it has to be passed to the IOCTL. | 45 | * pointer to it has to be passed to the ioctl. | 
| 46 | * | 46 | * | 
| 47 | * UBI volume deletion | 47 | * UBI volume deletion | 
| 48 | * ~~~~~~~~~~~~~~~~~~~ | 48 | * ~~~~~~~~~~~~~~~~~~~ | 
| 49 | * | 49 | * | 
| 50 | * To delete a volume, the %UBI_IOCRMVOL IOCTL command of the UBI character | 50 | * To delete a volume, the %UBI_IOCRMVOL ioctl command of the UBI character | 
| 51 | * device should be used. A pointer to the 32-bit volume ID hast to be passed | 51 | * device should be used. A pointer to the 32-bit volume ID hast to be passed | 
| 52 | * to the IOCTL. | 52 | * to the ioctl. | 
| 53 | * | 53 | * | 
| 54 | * UBI volume re-size | 54 | * UBI volume re-size | 
| 55 | * ~~~~~~~~~~~~~~~~~~ | 55 | * ~~~~~~~~~~~~~~~~~~ | 
| 56 | * | 56 | * | 
| 57 | * To re-size a volume, the %UBI_IOCRSVOL IOCTL command of the UBI character | 57 | * To re-size a volume, the %UBI_IOCRSVOL ioctl command of the UBI character | 
| 58 | * device should be used. A &struct ubi_rsvol_req object has to be properly | 58 | * device should be used. A &struct ubi_rsvol_req object has to be properly | 
| 59 | * filled and a pointer to it has to be passed to the IOCTL. | 59 | * filled and a pointer to it has to be passed to the ioctl. | 
| 60 | * | 60 | * | 
| 61 | * UBI volumes re-name | 61 | * UBI volumes re-name | 
| 62 | * ~~~~~~~~~~~~~~~~~~~ | 62 | * ~~~~~~~~~~~~~~~~~~~ | 
| 63 | * | 63 | * | 
| 64 | * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command | 64 | * To re-name several volumes atomically at one go, the %UBI_IOCRNVOL command | 
| 65 | * of the UBI character device should be used. A &struct ubi_rnvol_req object | 65 | * of the UBI character device should be used. A &struct ubi_rnvol_req object | 
| 66 | * has to be properly filled and a pointer to it has to be passed to the IOCTL. | 66 | * has to be properly filled and a pointer to it has to be passed to the ioctl. | 
| 67 | * | 67 | * | 
| 68 | * UBI volume update | 68 | * UBI volume update | 
| 69 | * ~~~~~~~~~~~~~~~~~ | 69 | * ~~~~~~~~~~~~~~~~~ | 
| 70 | * | 70 | * | 
| 71 | * Volume update should be done via the %UBI_IOCVOLUP IOCTL command of the | 71 | * Volume update should be done via the %UBI_IOCVOLUP ioctl command of the | 
| 72 | * corresponding UBI volume character device. A pointer to a 64-bit update | 72 | * corresponding UBI volume character device. A pointer to a 64-bit update | 
| 73 | * size should be passed to the IOCTL. After this, UBI expects user to write | 73 | * size should be passed to the ioctl. After this, UBI expects user to write | 
| 74 | * this number of bytes to the volume character device. The update is finished | 74 | * this number of bytes to the volume character device. The update is finished | 
| 75 | * when the claimed number of bytes is passed. So, the volume update sequence | 75 | * when the claimed number of bytes is passed. So, the volume update sequence | 
| 76 | * is something like: | 76 | * is something like: | 
| @@ -80,14 +80,58 @@ | |||
| 80 | * write(fd, buf, image_size); | 80 | * write(fd, buf, image_size); | 
| 81 | * close(fd); | 81 | * close(fd); | 
| 82 | * | 82 | * | 
| 83 | * Atomic eraseblock change | 83 | * Logical eraseblock erase | 
| 84 | * ~~~~~~~~~~~~~~~~~~~~~~~~ | 84 | * ~~~~~~~~~~~~~~~~~~~~~~~~ | 
| 85 | * | 85 | * | 
| 86 | * Atomic eraseblock change operation is done via the %UBI_IOCEBCH IOCTL | 86 | * To erase a logical eraseblock, the %UBI_IOCEBER ioctl command of the | 
| 87 | * command of the corresponding UBI volume character device. A pointer to | 87 | * corresponding UBI volume character device should be used. This command | 
| 88 | * &struct ubi_leb_change_req has to be passed to the IOCTL. Then the user is | 88 | * unmaps the requested logical eraseblock, makes sure the corresponding | 
| 89 | * expected to write the requested amount of bytes. This is similar to the | 89 | * physical eraseblock is successfully erased, and returns. | 
| 90 | * "volume update" IOCTL. | 90 | * | 
| 91 | * Atomic logical eraseblock change | ||
| 92 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 93 | * | ||
| 94 | * Atomic logical eraseblock change operation is called using the %UBI_IOCEBCH | ||
| 95 | * ioctl command of the corresponding UBI volume character device. A pointer to | ||
| 96 | * a &struct ubi_leb_change_req object has to be passed to the ioctl. Then the | ||
| 97 | * user is expected to write the requested amount of bytes (similarly to what | ||
| 98 | * should be done in case of the "volume update" ioctl). | ||
| 99 | * | ||
| 100 | * Logical eraseblock map | ||
| 101 | * ~~~~~~~~~~~~~~~~~~~~~ | ||
| 102 | * | ||
| 103 | * To map a logical eraseblock to a physical eraseblock, the %UBI_IOCEBMAP | ||
| 104 | * ioctl command should be used. A pointer to a &struct ubi_map_req object is | ||
| 105 | * expected to be passed. The ioctl maps the requested logical eraseblock to | ||
| 106 | * a physical eraseblock and returns. Only non-mapped logical eraseblocks can | ||
| 107 | * be mapped. If the logical eraseblock specified in the request is already | ||
| 108 | * mapped to a physical eraseblock, the ioctl fails and returns error. | ||
| 109 | * | ||
| 110 | * Logical eraseblock unmap | ||
| 111 | * ~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 112 | * | ||
| 113 | * To unmap a logical eraseblock to a physical eraseblock, the %UBI_IOCEBUNMAP | ||
| 114 | * ioctl command should be used. The ioctl unmaps the logical eraseblocks, | ||
| 115 | * schedules corresponding physical eraseblock for erasure, and returns. Unlike | ||
| 116 | * the "LEB erase" command, it does not wait for the physical eraseblock being | ||
| 117 | * erased. Note, the side effect of this is that if an unclean reboot happens | ||
| 118 | * after the unmap ioctl returns, you may find the LEB mapped again to the same | ||
| 119 | * physical eraseblock after the UBI is run again. | ||
| 120 | * | ||
| 121 | * Check if logical eraseblock is mapped | ||
| 122 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 123 | * | ||
| 124 | * To check if a logical eraseblock is mapped to a physical eraseblock, the | ||
| 125 | * %UBI_IOCEBISMAP ioctl command should be used. It returns %0 if the LEB is | ||
| 126 | * not mapped, and %1 if it is mapped. | ||
| 127 | * | ||
| 128 | * Set an UBI volume property | ||
| 129 | * ~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 130 | * | ||
| 131 | * To set an UBI volume property the %UBI_IOCSETPROP ioctl command should be | ||
| 132 | * used. A pointer to a &struct ubi_set_prop_req object is expected to be | ||
| 133 | * passed. The object describes which property should be set, and to which value | ||
| 134 | * it should be set. | ||
| 91 | */ | 135 | */ | 
| 92 | 136 | ||
| 93 | /* | 137 | /* | 
| @@ -101,7 +145,7 @@ | |||
| 101 | /* Maximum volume name length */ | 145 | /* Maximum volume name length */ | 
| 102 | #define UBI_MAX_VOLUME_NAME 127 | 146 | #define UBI_MAX_VOLUME_NAME 127 | 
| 103 | 147 | ||
| 104 | /* IOCTL commands of UBI character devices */ | 148 | /* ioctl commands of UBI character devices */ | 
| 105 | 149 | ||
| 106 | #define UBI_IOC_MAGIC 'o' | 150 | #define UBI_IOC_MAGIC 'o' | 
| 107 | 151 | ||
| @@ -114,7 +158,7 @@ | |||
| 114 | /* Re-name volumes */ | 158 | /* Re-name volumes */ | 
| 115 | #define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req) | 159 | #define UBI_IOCRNVOL _IOW(UBI_IOC_MAGIC, 3, struct ubi_rnvol_req) | 
| 116 | 160 | ||
| 117 | /* IOCTL commands of the UBI control character device */ | 161 | /* ioctl commands of the UBI control character device */ | 
| 118 | 162 | ||
| 119 | #define UBI_CTRL_IOC_MAGIC 'o' | 163 | #define UBI_CTRL_IOC_MAGIC 'o' | 
| 120 | 164 | ||
| @@ -123,16 +167,24 @@ | |||
| 123 | /* Detach an MTD device */ | 167 | /* Detach an MTD device */ | 
| 124 | #define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) | 168 | #define UBI_IOCDET _IOW(UBI_CTRL_IOC_MAGIC, 65, int32_t) | 
| 125 | 169 | ||
| 126 | /* IOCTL commands of UBI volume character devices */ | 170 | /* ioctl commands of UBI volume character devices */ | 
| 127 | 171 | ||
| 128 | #define UBI_VOL_IOC_MAGIC 'O' | 172 | #define UBI_VOL_IOC_MAGIC 'O' | 
| 129 | 173 | ||
| 130 | /* Start UBI volume update */ | 174 | /* Start UBI volume update */ | 
| 131 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) | 175 | #define UBI_IOCVOLUP _IOW(UBI_VOL_IOC_MAGIC, 0, int64_t) | 
| 132 | /* An eraseblock erasure command, used for debugging, disabled by default */ | 176 | /* LEB erasure command, used for debugging, disabled by default */ | 
| 133 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) | 177 | #define UBI_IOCEBER _IOW(UBI_VOL_IOC_MAGIC, 1, int32_t) | 
| 134 | /* An atomic eraseblock change command */ | 178 | /* Atomic LEB change command */ | 
| 135 | #define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) | 179 | #define UBI_IOCEBCH _IOW(UBI_VOL_IOC_MAGIC, 2, int32_t) | 
| 180 | /* Map LEB command */ | ||
| 181 | #define UBI_IOCEBMAP _IOW(UBI_VOL_IOC_MAGIC, 3, struct ubi_map_req) | ||
| 182 | /* Unmap LEB command */ | ||
| 183 | #define UBI_IOCEBUNMAP _IOW(UBI_VOL_IOC_MAGIC, 4, int32_t) | ||
| 184 | /* Check if LEB is mapped command */ | ||
| 185 | #define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) | ||
| 186 | /* Set an UBI volume property */ | ||
| 187 | #define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req) | ||
| 136 | 188 | ||
| 137 | /* Maximum MTD device name length supported by UBI */ | 189 | /* Maximum MTD device name length supported by UBI */ | 
| 138 | #define MAX_UBI_MTD_NAME_LEN 127 | 190 | #define MAX_UBI_MTD_NAME_LEN 127 | 
| @@ -168,6 +220,16 @@ enum { | |||
| 168 | UBI_STATIC_VOLUME = 4, | 220 | UBI_STATIC_VOLUME = 4, | 
| 169 | }; | 221 | }; | 
| 170 | 222 | ||
| 223 | /* | ||
| 224 | * UBI set property ioctl constants | ||
| 225 | * | ||
| 226 | * @UBI_PROP_DIRECT_WRITE: allow / disallow user to directly write and | ||
| 227 | * erase individual eraseblocks on dynamic volumes | ||
| 228 | */ | ||
| 229 | enum { | ||
| 230 | UBI_PROP_DIRECT_WRITE = 1, | ||
| 231 | }; | ||
| 232 | |||
| 171 | /** | 233 | /** | 
| 172 | * struct ubi_attach_req - attach MTD device request. | 234 | * struct ubi_attach_req - attach MTD device request. | 
| 173 | * @ubi_num: UBI device number to create | 235 | * @ubi_num: UBI device number to create | 
| @@ -305,8 +367,8 @@ struct ubi_rnvol_req { | |||
| 305 | } __attribute__ ((packed)); | 367 | } __attribute__ ((packed)); | 
| 306 | 368 | ||
| 307 | /** | 369 | /** | 
| 308 | * struct ubi_leb_change_req - a data structure used in atomic logical | 370 | * struct ubi_leb_change_req - a data structure used in atomic LEB change | 
| 309 | * eraseblock change requests. | 371 | * requests. | 
| 310 | * @lnum: logical eraseblock number to change | 372 | * @lnum: logical eraseblock number to change | 
| 311 | * @bytes: how many bytes will be written to the logical eraseblock | 373 | * @bytes: how many bytes will be written to the logical eraseblock | 
| 312 | * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) | 374 | * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) | 
| @@ -319,4 +381,30 @@ struct ubi_leb_change_req { | |||
| 319 | int8_t padding[7]; | 381 | int8_t padding[7]; | 
| 320 | } __attribute__ ((packed)); | 382 | } __attribute__ ((packed)); | 
| 321 | 383 | ||
| 384 | /** | ||
| 385 | * struct ubi_map_req - a data structure used in map LEB requests. | ||
| 386 | * @lnum: logical eraseblock number to unmap | ||
| 387 | * @dtype: data type (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN) | ||
| 388 | * @padding: reserved for future, not used, has to be zeroed | ||
| 389 | */ | ||
| 390 | struct ubi_map_req { | ||
| 391 | int32_t lnum; | ||
| 392 | int8_t dtype; | ||
| 393 | int8_t padding[3]; | ||
| 394 | } __attribute__ ((packed)); | ||
| 395 | |||
| 396 | |||
| 397 | /** | ||
| 398 | * struct ubi_set_prop_req - a data structure used to set an ubi volume | ||
| 399 | * property. | ||
| 400 | * @property: property to set (%UBI_PROP_DIRECT_WRITE) | ||
| 401 | * @padding: reserved for future, not used, has to be zeroed | ||
| 402 | * @value: value to set | ||
| 403 | */ | ||
| 404 | struct ubi_set_prop_req { | ||
| 405 | uint8_t property; | ||
| 406 | uint8_t padding[7]; | ||
| 407 | uint64_t value; | ||
| 408 | } __attribute__ ((packed)); | ||
| 409 | |||
| 322 | #endif /* __UBI_USER_H__ */ | 410 | #endif /* __UBI_USER_H__ */ | 
