aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-03-08 19:30:55 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2009-03-08 19:30:55 -0400
commitd15c22e78674f9a5bc0de0932a43abe1aafae303 (patch)
tree3e4198c44bd2d9184e91647346c66aa95e28f843 /drivers/mtd
parent0f4954819fb6f840d46076f0dbd313ef5da48f5d (diff)
parentfec6c6fec3e20637bee5d276fb61dd8b49a3f9cc (diff)
Merge commit 'v2.6.29-rc7' into next
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/chips/map_rom.c8
-rw-r--r--drivers/mtd/devices/slram.c14
-rw-r--r--drivers/mtd/lpddr/Kconfig1
-rw-r--r--drivers/mtd/maps/Kconfig2
-rw-r--r--drivers/mtd/maps/bfin-async-flash.c6
-rw-r--r--drivers/mtd/maps/ck804xrom.c2
-rw-r--r--drivers/mtd/maps/physmap.c38
-rw-r--r--drivers/mtd/maps/sa1100-flash.c4
-rw-r--r--drivers/mtd/nand/atmel_nand.c3
-rw-r--r--drivers/mtd/nand/fsl_elbc_nand.c8
-rw-r--r--drivers/mtd/nand/orion_nand.c2
-rw-r--r--drivers/mtd/nand/pasemi_nand.c4
-rw-r--r--drivers/mtd/onenand/omap2.c6
-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
21 files changed, 233 insertions, 148 deletions
diff --git a/drivers/mtd/chips/map_rom.c b/drivers/mtd/chips/map_rom.c
index 821d0ed6bae3..c76d6e5f47ee 100644
--- a/drivers/mtd/chips/map_rom.c
+++ b/drivers/mtd/chips/map_rom.c
@@ -19,6 +19,7 @@ static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
19static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 19static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
20static void maprom_nop (struct mtd_info *); 20static void maprom_nop (struct mtd_info *);
21static struct mtd_info *map_rom_probe(struct map_info *map); 21static struct mtd_info *map_rom_probe(struct map_info *map);
22static int maprom_erase (struct mtd_info *mtd, struct erase_info *info);
22 23
23static struct mtd_chip_driver maprom_chipdrv = { 24static struct mtd_chip_driver maprom_chipdrv = {
24 .probe = map_rom_probe, 25 .probe = map_rom_probe,
@@ -42,6 +43,7 @@ static struct mtd_info *map_rom_probe(struct map_info *map)
42 mtd->read = maprom_read; 43 mtd->read = maprom_read;
43 mtd->write = maprom_write; 44 mtd->write = maprom_write;
44 mtd->sync = maprom_nop; 45 mtd->sync = maprom_nop;
46 mtd->erase = maprom_erase;
45 mtd->flags = MTD_CAP_ROM; 47 mtd->flags = MTD_CAP_ROM;
46 mtd->erasesize = map->size; 48 mtd->erasesize = map->size;
47 mtd->writesize = 1; 49 mtd->writesize = 1;
@@ -71,6 +73,12 @@ static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *re
71 return -EIO; 73 return -EIO;
72} 74}
73 75
76static int maprom_erase (struct mtd_info *mtd, struct erase_info *info)
77{
78 /* We do our best 8) */
79 return -EROFS;
80}
81
74static int __init map_rom_init(void) 82static int __init map_rom_init(void)
75{ 83{
76 register_mtd_chip_driver(&maprom_chipdrv); 84 register_mtd_chip_driver(&maprom_chipdrv);
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c
index a425d09f35a0..00248e81ecd5 100644
--- a/drivers/mtd/devices/slram.c
+++ b/drivers/mtd/devices/slram.c
@@ -267,22 +267,28 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
267 if (*(szlength) != '+') { 267 if (*(szlength) != '+') {
268 devlength = simple_strtoul(szlength, &buffer, 0); 268 devlength = simple_strtoul(szlength, &buffer, 0);
269 devlength = handle_unit(devlength, buffer) - devstart; 269 devlength = handle_unit(devlength, buffer) - devstart;
270 if (devlength < devstart)
271 goto err_out;
272
273 devlength -= devstart;
270 } else { 274 } else {
271 devlength = simple_strtoul(szlength + 1, &buffer, 0); 275 devlength = simple_strtoul(szlength + 1, &buffer, 0);
272 devlength = handle_unit(devlength, buffer); 276 devlength = handle_unit(devlength, buffer);
273 } 277 }
274 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", 278 T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n",
275 devname, devstart, devlength); 279 devname, devstart, devlength);
276 if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) { 280 if (devlength % SLRAM_BLK_SZ != 0)
277 E("slram: Illegal start / length parameter.\n"); 281 goto err_out;
278 return(-EINVAL);
279 }
280 282
281 if ((devstart = register_device(devname, devstart, devlength))){ 283 if ((devstart = register_device(devname, devstart, devlength))){
282 unregister_devices(); 284 unregister_devices();
283 return((int)devstart); 285 return((int)devstart);
284 } 286 }
285 return(0); 287 return(0);
288
289err_out:
290 E("slram: Illegal length parameter.\n");
291 return(-EINVAL);
286} 292}
287 293
288#ifndef MODULE 294#ifndef MODULE
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig
index acd4ea9b2278..5a401d8047ab 100644
--- a/drivers/mtd/lpddr/Kconfig
+++ b/drivers/mtd/lpddr/Kconfig
@@ -12,6 +12,7 @@ config MTD_LPDDR
12 DDR memories, intended for battery-operated systems. 12 DDR memories, intended for battery-operated systems.
13 13
14config MTD_QINFO_PROBE 14config MTD_QINFO_PROBE
15 depends on MTD_LPDDR
15 tristate "Detect flash chips by QINFO probe" 16 tristate "Detect flash chips by QINFO probe"
16 help 17 help
17 Device Information for LPDDR chips is offered through the Overlay 18 Device Information for LPDDR chips is offered through the Overlay
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 0225cbbf22de..043d50fb6ef6 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -491,7 +491,7 @@ config MTD_PCMCIA_ANONYMOUS
491 491
492config MTD_BFIN_ASYNC 492config MTD_BFIN_ASYNC
493 tristate "Blackfin BF533-STAMP Flash Chip Support" 493 tristate "Blackfin BF533-STAMP Flash Chip Support"
494 depends on BFIN533_STAMP && MTD_CFI 494 depends on BFIN533_STAMP && MTD_CFI && MTD_COMPLEX_MAPPINGS
495 select MTD_PARTITIONS 495 select MTD_PARTITIONS
496 default y 496 default y
497 help 497 help
diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index 6fec86aaed7e..576611f605db 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -152,14 +152,18 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
152 152
153 if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) { 153 if (gpio_request(state->enet_flash_pin, DRIVER_NAME)) {
154 pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin); 154 pr_devinit(KERN_ERR DRIVER_NAME ": Failed to request gpio %d\n", state->enet_flash_pin);
155 kfree(state);
155 return -EBUSY; 156 return -EBUSY;
156 } 157 }
157 gpio_direction_output(state->enet_flash_pin, 1); 158 gpio_direction_output(state->enet_flash_pin, 1);
158 159
159 pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8); 160 pr_devinit(KERN_NOTICE DRIVER_NAME ": probing %d-bit flash bus\n", state->map.bankwidth * 8);
160 state->mtd = do_map_probe(memory->name, &state->map); 161 state->mtd = do_map_probe(memory->name, &state->map);
161 if (!state->mtd) 162 if (!state->mtd) {
163 gpio_free(state->enet_flash_pin);
164 kfree(state);
162 return -ENXIO; 165 return -ENXIO;
166 }
163 167
164#ifdef CONFIG_MTD_PARTITIONS 168#ifdef CONFIG_MTD_PARTITIONS
165 ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0); 169 ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c
index 5f7a245ed132..424f17d6ffd1 100644
--- a/drivers/mtd/maps/ck804xrom.c
+++ b/drivers/mtd/maps/ck804xrom.c
@@ -342,9 +342,9 @@ static struct pci_device_id ck804xrom_pci_tbl[] = {
342 { 0, } 342 { 0, }
343}; 343};
344 344
345#if 0
345MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl); 346MODULE_DEVICE_TABLE(pci, ck804xrom_pci_tbl);
346 347
347#if 0
348static struct pci_driver ck804xrom_driver = { 348static struct pci_driver ck804xrom_driver = {
349 .name = MOD_NAME, 349 .name = MOD_NAME,
350 .id_table = ck804xrom_pci_tbl, 350 .id_table = ck804xrom_pci_tbl,
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 87743661d48e..4b122e7ab4b3 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -29,6 +29,7 @@ struct physmap_flash_info {
29 struct map_info map[MAX_RESOURCES]; 29 struct map_info map[MAX_RESOURCES];
30#ifdef CONFIG_MTD_PARTITIONS 30#ifdef CONFIG_MTD_PARTITIONS
31 int nr_parts; 31 int nr_parts;
32 struct mtd_partition *parts;
32#endif 33#endif
33}; 34};
34 35
@@ -45,25 +46,26 @@ static int physmap_flash_remove(struct platform_device *dev)
45 46
46 physmap_data = dev->dev.platform_data; 47 physmap_data = dev->dev.platform_data;
47 48
48#ifdef CONFIG_MTD_CONCAT 49#ifdef CONFIG_MTD_PARTITIONS
49 if (info->cmtd != info->mtd[0]) { 50 if (info->nr_parts) {
51 del_mtd_partitions(info->cmtd);
52 kfree(info->parts);
53 } else if (physmap_data->nr_parts)
54 del_mtd_partitions(info->cmtd);
55 else
50 del_mtd_device(info->cmtd); 56 del_mtd_device(info->cmtd);
57#else
58 del_mtd_device(info->cmtd);
59#endif
60
61#ifdef CONFIG_MTD_CONCAT
62 if (info->cmtd != info->mtd[0])
51 mtd_concat_destroy(info->cmtd); 63 mtd_concat_destroy(info->cmtd);
52 }
53#endif 64#endif
54 65
55 for (i = 0; i < MAX_RESOURCES; i++) { 66 for (i = 0; i < MAX_RESOURCES; i++) {
56 if (info->mtd[i] != NULL) { 67 if (info->mtd[i] != NULL)
57#ifdef CONFIG_MTD_PARTITIONS
58 if (info->nr_parts || physmap_data->nr_parts)
59 del_mtd_partitions(info->mtd[i]);
60 else
61 del_mtd_device(info->mtd[i]);
62#else
63 del_mtd_device(info->mtd[i]);
64#endif
65 map_destroy(info->mtd[i]); 68 map_destroy(info->mtd[i]);
66 }
67 } 69 }
68 return 0; 70 return 0;
69} 71}
@@ -86,9 +88,6 @@ static int physmap_flash_probe(struct platform_device *dev)
86 int err = 0; 88 int err = 0;
87 int i; 89 int i;
88 int devices_found = 0; 90 int devices_found = 0;
89#ifdef CONFIG_MTD_PARTITIONS
90 struct mtd_partition *parts;
91#endif
92 91
93 physmap_data = dev->dev.platform_data; 92 physmap_data = dev->dev.platform_data;
94 if (physmap_data == NULL) 93 if (physmap_data == NULL)
@@ -167,10 +166,11 @@ static int physmap_flash_probe(struct platform_device *dev)
167 goto err_out; 166 goto err_out;
168 167
169#ifdef CONFIG_MTD_PARTITIONS 168#ifdef CONFIG_MTD_PARTITIONS
170 err = parse_mtd_partitions(info->cmtd, part_probe_types, &parts, 0); 169 err = parse_mtd_partitions(info->cmtd, part_probe_types,
170 &info->parts, 0);
171 if (err > 0) { 171 if (err > 0) {
172 add_mtd_partitions(info->cmtd, parts, err); 172 add_mtd_partitions(info->cmtd, info->parts, err);
173 kfree(parts); 173 info->nr_parts = err;
174 return 0; 174 return 0;
175 } 175 }
176 176
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index 7df6bbf0e4d9..6f6a0f6dafd6 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -453,7 +453,7 @@ static struct platform_driver sa1100_mtd_driver = {
453 .resume = sa1100_mtd_resume, 453 .resume = sa1100_mtd_resume,
454 .shutdown = sa1100_mtd_shutdown, 454 .shutdown = sa1100_mtd_shutdown,
455 .driver = { 455 .driver = {
456 .name = "flash", 456 .name = "sa1100-mtd",
457 .owner = THIS_MODULE, 457 .owner = THIS_MODULE,
458 }, 458 },
459}; 459};
@@ -474,4 +474,4 @@ module_exit(sa1100_mtd_exit);
474MODULE_AUTHOR("Nicolas Pitre"); 474MODULE_AUTHOR("Nicolas Pitre");
475MODULE_DESCRIPTION("SA1100 CFI map driver"); 475MODULE_DESCRIPTION("SA1100 CFI map driver");
476MODULE_LICENSE("GPL"); 476MODULE_LICENSE("GPL");
477MODULE_ALIAS("platform:flash"); 477MODULE_ALIAS("platform:sa1100-mtd");
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index c98c1570a40b..47a33cec3793 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -139,7 +139,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
139 struct nand_chip *nand_chip = mtd->priv; 139 struct nand_chip *nand_chip = mtd->priv;
140 struct atmel_nand_host *host = nand_chip->priv; 140 struct atmel_nand_host *host = nand_chip->priv;
141 141
142 return gpio_get_value(host->board->rdy_pin); 142 return gpio_get_value(host->board->rdy_pin) ^
143 !!host->board->rdy_pin_active_low;
143} 144}
144 145
145/* 146/*
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 65929db29446..1f6eb2578717 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -676,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
676 676
677 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n", 677 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->numchips = %d\n",
678 chip->numchips); 678 chip->numchips);
679 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %ld\n", 679 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->chipsize = %lld\n",
680 chip->chipsize); 680 chip->chipsize);
681 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n", 681 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->pagemask = %8x\n",
682 chip->pagemask); 682 chip->pagemask);
@@ -703,7 +703,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
703 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n", 703 dev_dbg(ctrl->dev, "fsl_elbc_init: nand->ecc.layout = %p\n",
704 chip->ecc.layout); 704 chip->ecc.layout);
705 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags); 705 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->flags = %08x\n", mtd->flags);
706 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %d\n", mtd->size); 706 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->size = %lld\n", mtd->size);
707 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n", 707 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->erasesize = %d\n",
708 mtd->erasesize); 708 mtd->erasesize);
709 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n", 709 dev_dbg(ctrl->dev, "fsl_elbc_init: mtd->writesize = %d\n",
@@ -932,8 +932,8 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
932#endif 932#endif
933 add_mtd_device(&priv->mtd); 933 add_mtd_device(&priv->mtd);
934 934
935 printk(KERN_INFO "eLBC NAND device at 0x%zx, bank %d\n", 935 printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
936 res.start, priv->bank); 936 (unsigned long long)res.start, priv->bank);
937 return 0; 937 return 0;
938 938
939err: 939err:
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 917cf8d3ae95..c2dfd3ea353d 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -149,7 +149,7 @@ static int __devexit orion_nand_remove(struct platform_device *pdev)
149 149
150static struct platform_driver orion_nand_driver = { 150static struct platform_driver orion_nand_driver = {
151 .probe = orion_nand_probe, 151 .probe = orion_nand_probe,
152 .remove = orion_nand_remove, 152 .remove = __devexit_p(orion_nand_remove),
153 .driver = { 153 .driver = {
154 .name = "orion_nand", 154 .name = "orion_nand",
155 .owner = THIS_MODULE, 155 .owner = THIS_MODULE,
diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c
index 9bd6c9ac8443..a8b9376cf324 100644
--- a/drivers/mtd/nand/pasemi_nand.c
+++ b/drivers/mtd/nand/pasemi_nand.c
@@ -107,7 +107,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev,
107 if (pasemi_nand_mtd) 107 if (pasemi_nand_mtd)
108 return -ENODEV; 108 return -ENODEV;
109 109
110 pr_debug("pasemi_nand at %lx-%lx\n", res.start, res.end); 110 pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);
111 111
112 /* Allocate memory for MTD device structure and private data */ 112 /* Allocate memory for MTD device structure and private data */
113 pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) + 113 pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
@@ -170,7 +170,7 @@ static int __devinit pasemi_nand_probe(struct of_device *ofdev,
170 goto out_lpc; 170 goto out_lpc;
171 } 171 }
172 172
173 printk(KERN_INFO "PA Semi NAND flash at %08lx, control at I/O %x\n", 173 printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n",
174 res.start, lpcctl); 174 res.start, lpcctl);
175 175
176 return 0; 176 return 0;
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 96ecc1766fa8..77a4f1446156 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -629,7 +629,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
629 } 629 }
630 630
631 if (c->gpio_irq) { 631 if (c->gpio_irq) {
632 if ((r = omap_request_gpio(c->gpio_irq)) < 0) { 632 if ((r = gpio_request(c->gpio_irq, "OneNAND irq")) < 0) {
633 dev_err(&pdev->dev, "Failed to request GPIO%d for " 633 dev_err(&pdev->dev, "Failed to request GPIO%d for "
634 "OneNAND\n", c->gpio_irq); 634 "OneNAND\n", c->gpio_irq);
635 goto err_iounmap; 635 goto err_iounmap;
@@ -726,7 +726,7 @@ err_release_dma:
726 free_irq(gpio_to_irq(c->gpio_irq), c); 726 free_irq(gpio_to_irq(c->gpio_irq), c);
727err_release_gpio: 727err_release_gpio:
728 if (c->gpio_irq) 728 if (c->gpio_irq)
729 omap_free_gpio(c->gpio_irq); 729 gpio_free(c->gpio_irq);
730err_iounmap: 730err_iounmap:
731 iounmap(c->onenand.base); 731 iounmap(c->onenand.base);
732err_release_mem_region: 732err_release_mem_region:
@@ -761,7 +761,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
761 platform_set_drvdata(pdev, NULL); 761 platform_set_drvdata(pdev, NULL);
762 if (c->gpio_irq) { 762 if (c->gpio_irq) {
763 free_irq(gpio_to_irq(c->gpio_irq), c); 763 free_irq(gpio_to_irq(c->gpio_irq), c);
764 omap_free_gpio(c->gpio_irq); 764 gpio_free(c->gpio_irq);
765 } 765 }
766 iounmap(c->onenand.base); 766 iounmap(c->onenand.base);
767 release_mem_region(c->phys_base, ONENAND_IO_SIZE); 767 release_mem_region(c->phys_base, ONENAND_IO_SIZE);
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;