aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-29 21:12:58 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-29 21:12:58 -0500
commit0d280884961de51afd87465f72ade9e8876d1e26 (patch)
treefa03d8593ddda2026545b369c4a87397deb7bdca /drivers/mtd
parent9b4d142d521963ee1c53cefcd1f9790ca32b5db7 (diff)
parent766fb95ba06e1bbf531d30dc05e21b2d4a0e8dd2 (diff)
Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
* 'linux-next' of git://git.infradead.org/ubi-2.6: UBI: allow direct user-space I/O UBI: fix resource de-allocation UBI: remove unused variable UBI: use nicer 64-bit math UBI: add ioctl compatibility UBI: constify file operations UBI: allow all ioctls UBI: remove unnecessry header inclusion UBI: improve ioctl commentaries UBI: add ioctl for is_mapped operation UBI: add ioctl for unmap operation UBI: add ioctl for map operation
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/Kconfig.debug10
-rw-r--r--drivers/mtd/ubi/build.c21
-rw-r--r--drivers/mtd/ubi/cdev.c184
-rw-r--r--drivers/mtd/ubi/gluebi.c11
-rw-r--r--drivers/mtd/ubi/scan.c8
-rw-r--r--drivers/mtd/ubi/ubi.h11
-rw-r--r--drivers/mtd/ubi/upd.c21
-rw-r--r--drivers/mtd/ubi/vmt.c17
8 files changed, 174 insertions, 109 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
36config 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
46config MTD_UBI_DEBUG_EMULATE_BITFLIPS 36config 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 */ 266static void dev_release(struct device *dev)
267static 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 */
381static int uif_init(struct ubi_device *ubi) 385static 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
428out_volumes: 432out_volumes:
429 kill_volumes(ubi); 433 kill_volumes(ubi);
430 do_free = 0;
431out_sysfs: 434out_sysfs:
432 ubi_sysfs_close(ubi); 435 ubi_sysfs_close(ubi);
433 cdev_del(&ubi->cdev); 436 cdev_del(&ubi->cdev);
434out_unreg: 437out_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 */
273static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, 266static 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
354static ssize_t vol_cdev_write(struct file *file, const char __user *buf, 342static 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
405static int vol_cdev_ioctl(struct inode *inode, struct file *file, 393static 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
765static int ubi_cdev_ioctl(struct inode *inode, struct file *file, 816static 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
912static int ctrl_cdev_ioctl(struct inode *inode, struct file *file, 961static 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
990struct file_operations ubi_ctrl_cdev_operations = { 1039static 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
1047static 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
1055static 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 */
1069const 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 */
996struct file_operations ubi_cdev_operations = { 1081const 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 */
1003struct file_operations ubi_vol_cdev_operations = { 1089const 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
451extern struct kmem_cache *ubi_wl_entry_slab; 454extern struct kmem_cache *ubi_wl_entry_slab;
452extern struct file_operations ubi_ctrl_cdev_operations; 455extern const struct file_operations ubi_ctrl_cdev_operations;
453extern struct file_operations ubi_cdev_operations; 456extern const struct file_operations ubi_cdev_operations;
454extern struct file_operations ubi_vol_cdev_operations; 457extern const struct file_operations ubi_vol_cdev_operations;
455extern struct class *ubi_class; 458extern struct class *ubi_class;
456extern struct mutex ubi_devices_mutex; 459extern 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,
282int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, 279int 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;