diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/chips/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mtd/devices/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mtd/devices/slram.c | 2 | ||||
-rw-r--r-- | drivers/mtd/lpddr/Kconfig | 3 | ||||
-rw-r--r-- | drivers/mtd/maps/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/maps/omap_nor.c | 2 | ||||
-rw-r--r-- | drivers/mtd/maps/pcmciamtd.c | 197 | ||||
-rw-r--r-- | drivers/mtd/mtd_blkdevs.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/ams-delta.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/omap2.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/pxa3xx_nand.c | 82 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 2 | ||||
-rw-r--r-- | drivers/mtd/onenand/Kconfig | 4 | ||||
-rw-r--r-- | drivers/mtd/onenand/omap2.c | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 40 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 20 |
20 files changed, 236 insertions, 158 deletions
diff --git a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig index 9408099eec48..35c6a23b183b 100644 --- a/drivers/mtd/chips/Kconfig +++ b/drivers/mtd/chips/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/chips/Kconfig | ||
2 | |||
3 | menu "RAM/ROM/Flash chip drivers" | 1 | menu "RAM/ROM/Flash chip drivers" |
4 | depends on MTD!=n | 2 | depends on MTD!=n |
5 | 3 | ||
@@ -242,4 +240,3 @@ config MTD_XIP | |||
242 | then say N. | 240 | then say N. |
243 | 241 | ||
244 | endmenu | 242 | endmenu |
245 | |||
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index c222514bb70d..35081ce77fbd 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/maps/Kconfig | ||
2 | |||
3 | menu "Self-contained MTD device drivers" | 1 | menu "Self-contained MTD device drivers" |
4 | depends on MTD!=n | 2 | depends on MTD!=n |
5 | 3 | ||
@@ -308,4 +306,3 @@ config MTD_DOCPROBE_55AA | |||
308 | you have managed to wipe the first block. | 306 | you have managed to wipe the first block. |
309 | 307 | ||
310 | endmenu | 308 | endmenu |
311 | |||
diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 3aa05cd18ea1..592016a0668f 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c | |||
@@ -18,7 +18,7 @@ | |||
18 | to specify the offset instead of the absolute address | 18 | to specify the offset instead of the absolute address |
19 | 19 | ||
20 | NOTE: | 20 | NOTE: |
21 | With slram it's only possible to map a contigous memory region. Therfore | 21 | With slram it's only possible to map a contiguous memory region. Therefore |
22 | if there's a device mapped somewhere in the region specified slram will | 22 | if there's a device mapped somewhere in the region specified slram will |
23 | fail to load (see kernel log if modprobe fails). | 23 | fail to load (see kernel log if modprobe fails). |
24 | 24 | ||
diff --git a/drivers/mtd/lpddr/Kconfig b/drivers/mtd/lpddr/Kconfig index 5a401d8047ab..265f969817e3 100644 --- a/drivers/mtd/lpddr/Kconfig +++ b/drivers/mtd/lpddr/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/chips/Kconfig | ||
2 | |||
3 | menu "LPDDR flash memory drivers" | 1 | menu "LPDDR flash memory drivers" |
4 | depends on MTD!=n | 2 | depends on MTD!=n |
5 | 3 | ||
@@ -20,4 +18,3 @@ config MTD_QINFO_PROBE | |||
20 | families of devices. This serves similar purpose of CFI on legacy | 18 | families of devices. This serves similar purpose of CFI on legacy |
21 | Flash products | 19 | Flash products |
22 | endmenu | 20 | endmenu |
23 | |||
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 14be0755d7cd..847e214ade59 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/maps/Kconfig | ||
2 | |||
3 | menu "Mapping drivers for chip access" | 1 | menu "Mapping drivers for chip access" |
4 | depends on MTD!=n | 2 | depends on MTD!=n |
5 | 3 | ||
@@ -389,9 +387,9 @@ config MTD_IXP2000 | |||
389 | depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 | 387 | depends on MTD_CFI && MTD_COMPLEX_MAPPINGS && ARCH_IXP2000 |
390 | help | 388 | help |
391 | This enables MTD access to flash devices on platforms based | 389 | This enables MTD access to flash devices on platforms based |
392 | on Intel's IXP2000 family of network processors such as the | 390 | on Intel's IXP2000 family of network processors. If you have an |
393 | IXDP425 and Coyote. If you have an IXP2000 based board and | 391 | IXP2000 based board and would like to use the flash chips on it, |
394 | would like to use the flash chips on it, say 'Y'. | 392 | say 'Y'. |
395 | 393 | ||
396 | config MTD_FORTUNET | 394 | config MTD_FORTUNET |
397 | tristate "CFI Flash device mapped on the FortuNet board" | 395 | tristate "CFI Flash device mapped on the FortuNet board" |
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index a24478102b11..ead0b2fab670 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <asm/io.h> | 45 | #include <asm/io.h> |
46 | #include <mach/hardware.h> | 46 | #include <mach/hardware.h> |
47 | #include <asm/mach/flash.h> | 47 | #include <asm/mach/flash.h> |
48 | #include <mach/tc.h> | 48 | #include <plat/tc.h> |
49 | 49 | ||
50 | #ifdef CONFIG_MTD_PARTITIONS | 50 | #ifdef CONFIG_MTD_PARTITIONS |
51 | static const char *part_probes[] = { /* "RedBoot", */ "cmdlinepart", NULL }; | 51 | static const char *part_probes[] = { /* "RedBoot", */ "cmdlinepart", NULL }; |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index d600c2deff73..689d6a79ffc0 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
@@ -118,11 +118,9 @@ static caddr_t remap_window(struct map_info *map, unsigned long to) | |||
118 | DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", | 118 | DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", |
119 | dev->offset, mrq.CardOffset); | 119 | dev->offset, mrq.CardOffset); |
120 | mrq.Page = 0; | 120 | mrq.Page = 0; |
121 | ret = pcmcia_map_mem_page(win, &mrq); | 121 | ret = pcmcia_map_mem_page(dev->p_dev, win, &mrq); |
122 | if (ret != 0) { | 122 | if (ret != 0) |
123 | cs_error(dev->p_dev, MapMemPage, ret); | ||
124 | return NULL; | 123 | return NULL; |
125 | } | ||
126 | dev->offset = mrq.CardOffset; | 124 | dev->offset = mrq.CardOffset; |
127 | } | 125 | } |
128 | return dev->win_base + (to & (dev->win_size-1)); | 126 | return dev->win_base + (to & (dev->win_size-1)); |
@@ -327,8 +325,6 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on) | |||
327 | 325 | ||
328 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); | 326 | DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp); |
329 | ret = pcmcia_modify_configuration(link, &mod); | 327 | ret = pcmcia_modify_configuration(link, &mod); |
330 | if (ret != 0) | ||
331 | cs_error(link, ModifyConfiguration, ret); | ||
332 | } | 328 | } |
333 | 329 | ||
334 | 330 | ||
@@ -348,107 +344,116 @@ static void pcmciamtd_release(struct pcmcia_device *link) | |||
348 | iounmap(dev->win_base); | 344 | iounmap(dev->win_base); |
349 | dev->win_base = NULL; | 345 | dev->win_base = NULL; |
350 | } | 346 | } |
351 | pcmcia_release_window(link->win); | 347 | pcmcia_release_window(link, link->win); |
352 | } | 348 | } |
353 | pcmcia_disable_device(link); | 349 | pcmcia_disable_device(link); |
354 | } | 350 | } |
355 | 351 | ||
356 | 352 | ||
357 | static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) | 353 | #ifdef CONFIG_MTD_DEBUG |
354 | static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, | ||
355 | tuple_t *tuple, | ||
356 | void *priv_data) | ||
358 | { | 357 | { |
359 | int rc; | ||
360 | tuple_t tuple; | ||
361 | cisparse_t parse; | 358 | cisparse_t parse; |
362 | u_char buf[64]; | ||
363 | |||
364 | tuple.Attributes = 0; | ||
365 | tuple.TupleData = (cisdata_t *)buf; | ||
366 | tuple.TupleDataMax = sizeof(buf); | ||
367 | tuple.TupleOffset = 0; | ||
368 | tuple.DesiredTuple = RETURN_FIRST_TUPLE; | ||
369 | |||
370 | rc = pcmcia_get_first_tuple(link, &tuple); | ||
371 | while (rc == 0) { | ||
372 | rc = pcmcia_get_tuple_data(link, &tuple); | ||
373 | if (rc != 0) { | ||
374 | cs_error(link, GetTupleData, rc); | ||
375 | break; | ||
376 | } | ||
377 | rc = pcmcia_parse_tuple(&tuple, &parse); | ||
378 | if (rc != 0) { | ||
379 | cs_error(link, ParseTuple, rc); | ||
380 | break; | ||
381 | } | ||
382 | 359 | ||
383 | switch(tuple.TupleCode) { | 360 | if (!pcmcia_parse_tuple(tuple, &parse)) { |
384 | case CISTPL_FORMAT: { | 361 | cistpl_format_t *t = &parse.format; |
385 | cistpl_format_t *t = &parse.format; | 362 | (void)t; /* Shut up, gcc */ |
386 | (void)t; /* Shut up, gcc */ | 363 | DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", |
387 | DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", | 364 | t->type, t->edc, t->offset, t->length); |
388 | t->type, t->edc, t->offset, t->length); | 365 | } |
389 | break; | 366 | return -ENOSPC; |
367 | } | ||
390 | 368 | ||
391 | } | 369 | static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, |
370 | tuple_t *tuple, | ||
371 | void *priv_data) | ||
372 | { | ||
373 | cisparse_t parse; | ||
374 | int i; | ||
392 | 375 | ||
393 | case CISTPL_DEVICE: { | 376 | if (!pcmcia_parse_tuple(tuple, &parse)) { |
394 | cistpl_device_t *t = &parse.device; | 377 | cistpl_jedec_t *t = &parse.jedec; |
395 | int i; | 378 | for (i = 0; i < t->nid; i++) |
396 | DEBUG(2, "Common memory:"); | 379 | DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); |
397 | dev->pcmcia_map.size = t->dev[0].size; | 380 | } |
398 | for(i = 0; i < t->ndev; i++) { | 381 | return -ENOSPC; |
399 | DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); | 382 | } |
400 | DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); | 383 | #endif |
401 | DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); | ||
402 | DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); | ||
403 | } | ||
404 | break; | ||
405 | } | ||
406 | 384 | ||
407 | case CISTPL_VERS_1: { | 385 | static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, |
408 | cistpl_vers_1_t *t = &parse.version_1; | 386 | tuple_t *tuple, |
409 | int i; | 387 | void *priv_data) |
410 | if(t->ns) { | 388 | { |
411 | dev->mtd_name[0] = '\0'; | 389 | struct pcmciamtd_dev *dev = priv_data; |
412 | for(i = 0; i < t->ns; i++) { | 390 | cisparse_t parse; |
413 | if(i) | 391 | cistpl_device_t *t = &parse.device; |
414 | strcat(dev->mtd_name, " "); | 392 | int i; |
415 | strcat(dev->mtd_name, t->str+t->ofs[i]); | ||
416 | } | ||
417 | } | ||
418 | DEBUG(2, "Found name: %s", dev->mtd_name); | ||
419 | break; | ||
420 | } | ||
421 | 393 | ||
422 | case CISTPL_JEDEC_C: { | 394 | if (pcmcia_parse_tuple(tuple, &parse)) |
423 | cistpl_jedec_t *t = &parse.jedec; | 395 | return -EINVAL; |
424 | int i; | 396 | |
425 | for(i = 0; i < t->nid; i++) { | 397 | DEBUG(2, "Common memory:"); |
426 | DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); | 398 | dev->pcmcia_map.size = t->dev[0].size; |
427 | } | 399 | /* from here on: DEBUG only */ |
428 | break; | 400 | for (i = 0; i < t->ndev; i++) { |
429 | } | 401 | DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); |
402 | DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); | ||
403 | DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); | ||
404 | DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); | ||
405 | } | ||
406 | return 0; | ||
407 | } | ||
430 | 408 | ||
431 | case CISTPL_DEVICE_GEO: { | 409 | static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, |
432 | cistpl_device_geo_t *t = &parse.device_geo; | 410 | tuple_t *tuple, |
433 | int i; | 411 | void *priv_data) |
434 | dev->pcmcia_map.bankwidth = t->geo[0].buswidth; | 412 | { |
435 | for(i = 0; i < t->ngeo; i++) { | 413 | struct pcmciamtd_dev *dev = priv_data; |
436 | DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); | 414 | cisparse_t parse; |
437 | DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); | 415 | cistpl_device_geo_t *t = &parse.device_geo; |
438 | DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); | 416 | int i; |
439 | DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); | ||
440 | DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); | ||
441 | DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); | ||
442 | } | ||
443 | break; | ||
444 | } | ||
445 | 417 | ||
446 | default: | 418 | if (pcmcia_parse_tuple(tuple, &parse)) |
447 | DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); | 419 | return -EINVAL; |
448 | } | 420 | |
421 | dev->pcmcia_map.bankwidth = t->geo[0].buswidth; | ||
422 | /* from here on: DEBUG only */ | ||
423 | for (i = 0; i < t->ngeo; i++) { | ||
424 | DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); | ||
425 | DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); | ||
426 | DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); | ||
427 | DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); | ||
428 | DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); | ||
429 | DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); | ||
430 | } | ||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | |||
435 | static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) | ||
436 | { | ||
437 | int i; | ||
449 | 438 | ||
450 | rc = pcmcia_get_next_tuple(link, &tuple); | 439 | if (p_dev->prod_id[0]) { |
440 | dev->mtd_name[0] = '\0'; | ||
441 | for (i = 0; i < 4; i++) { | ||
442 | if (i) | ||
443 | strcat(dev->mtd_name, " "); | ||
444 | if (p_dev->prod_id[i]) | ||
445 | strcat(dev->mtd_name, p_dev->prod_id[i]); | ||
446 | } | ||
447 | DEBUG(2, "Found name: %s", dev->mtd_name); | ||
451 | } | 448 | } |
449 | |||
450 | #ifdef CONFIG_MTD_DEBUG | ||
451 | pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL); | ||
452 | pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL); | ||
453 | #endif | ||
454 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev); | ||
455 | pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev); | ||
456 | |||
452 | if(!dev->pcmcia_map.size) | 457 | if(!dev->pcmcia_map.size) |
453 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; | 458 | dev->pcmcia_map.size = MAX_PCMCIA_ADDR; |
454 | 459 | ||
@@ -481,16 +486,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, | |||
481 | * MTD device available to the system. | 486 | * MTD device available to the system. |
482 | */ | 487 | */ |
483 | 488 | ||
484 | #define CS_CHECK(fn, ret) \ | ||
485 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
486 | |||
487 | static int pcmciamtd_config(struct pcmcia_device *link) | 489 | static int pcmciamtd_config(struct pcmcia_device *link) |
488 | { | 490 | { |
489 | struct pcmciamtd_dev *dev = link->priv; | 491 | struct pcmciamtd_dev *dev = link->priv; |
490 | struct mtd_info *mtd = NULL; | 492 | struct mtd_info *mtd = NULL; |
491 | cs_status_t status; | 493 | cs_status_t status; |
492 | win_req_t req; | 494 | win_req_t req; |
493 | int last_ret = 0, last_fn = 0; | ||
494 | int ret; | 495 | int ret; |
495 | int i; | 496 | int i; |
496 | static char *probes[] = { "jedec_probe", "cfi_probe" }; | 497 | static char *probes[] = { "jedec_probe", "cfi_probe" }; |
@@ -529,7 +530,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
529 | int ret; | 530 | int ret; |
530 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", | 531 | DEBUG(2, "requesting window with size = %dKiB memspeed = %d", |
531 | req.Size >> 10, req.AccessSpeed); | 532 | req.Size >> 10, req.AccessSpeed); |
532 | ret = pcmcia_request_window(&link, &req, &link->win); | 533 | ret = pcmcia_request_window(link, &req, &link->win); |
533 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); | 534 | DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size); |
534 | if(ret) { | 535 | if(ret) { |
535 | req.Size >>= 1; | 536 | req.Size >>= 1; |
@@ -577,7 +578,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
577 | DEBUG(2, "Setting Configuration"); | 578 | DEBUG(2, "Setting Configuration"); |
578 | ret = pcmcia_request_configuration(link, &link->conf); | 579 | ret = pcmcia_request_configuration(link, &link->conf); |
579 | if (ret != 0) { | 580 | if (ret != 0) { |
580 | cs_error(link, RequestConfiguration, ret); | ||
581 | if (dev->win_base) { | 581 | if (dev->win_base) { |
582 | iounmap(dev->win_base); | 582 | iounmap(dev->win_base); |
583 | dev->win_base = NULL; | 583 | dev->win_base = NULL; |
@@ -652,8 +652,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) | |||
652 | link->dev_node = &dev->node; | 652 | link->dev_node = &dev->node; |
653 | return 0; | 653 | return 0; |
654 | 654 | ||
655 | cs_failed: | 655 | failed: |
656 | cs_error(link, last_fn, last_ret); | ||
657 | err("CS Error, exiting"); | 656 | err("CS Error, exiting"); |
658 | pcmciamtd_release(link); | 657 | pcmciamtd_release(link); |
659 | return -ENODEV; | 658 | return -ENODEV; |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 8ca17a3e96ea..64e2b379a350 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -59,12 +59,14 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
59 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 59 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
60 | if (tr->readsect(dev, block, buf)) | 60 | if (tr->readsect(dev, block, buf)) |
61 | return -EIO; | 61 | return -EIO; |
62 | rq_flush_dcache_pages(req); | ||
62 | return 0; | 63 | return 0; |
63 | 64 | ||
64 | case WRITE: | 65 | case WRITE: |
65 | if (!tr->writesect) | 66 | if (!tr->writesect) |
66 | return -EIO; | 67 | return -EIO; |
67 | 68 | ||
69 | rq_flush_dcache_pages(req); | ||
68 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 70 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
69 | if (tr->writesect(dev, block, buf)) | 71 | if (tr->writesect(dev, block, buf)) |
70 | return -EIO; | 72 | return -EIO; |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 2fda0b615246..0e35e1aefd22 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/nand/Kconfig | ||
2 | |||
3 | menuconfig MTD_NAND | 1 | menuconfig MTD_NAND |
4 | tristate "NAND Device Support" | 2 | tristate "NAND Device Support" |
5 | depends on MTD | 3 | depends on MTD |
@@ -358,7 +356,7 @@ endchoice | |||
358 | 356 | ||
359 | config MTD_NAND_PXA3xx | 357 | config MTD_NAND_PXA3xx |
360 | tristate "Support for NAND flash devices on PXA3xx" | 358 | tristate "Support for NAND flash devices on PXA3xx" |
361 | depends on MTD_NAND && PXA3xx | 359 | depends on MTD_NAND && (PXA3xx || ARCH_MMP) |
362 | help | 360 | help |
363 | This enables the driver for the NAND flash device found on | 361 | This enables the driver for the NAND flash device found on |
364 | PXA3xx processors | 362 | PXA3xx processors |
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 005b91f096f2..2548e1065bf8 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
26 | #include <asm/sizes.h> | 26 | #include <asm/sizes.h> |
27 | #include <mach/gpio.h> | 27 | #include <mach/gpio.h> |
28 | #include <mach/board-ams-delta.h> | 28 | #include <plat/board-ams-delta.h> |
29 | 29 | ||
30 | /* | 30 | /* |
31 | * MTD structure for E3 (Delta) | 31 | * MTD structure for E3 (Delta) |
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index e51c1ed7ac18..b126cf887476 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c | |||
@@ -1056,7 +1056,7 @@ static struct nand_ecclayout doc200x_oobinfo = { | |||
1056 | }; | 1056 | }; |
1057 | 1057 | ||
1058 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. | 1058 | /* Find the (I)NFTL Media Header, and optionally also the mirror media header. |
1059 | On sucessful return, buf will contain a copy of the media header for | 1059 | On successful return, buf will contain a copy of the media header for |
1060 | further processing. id is the string to scan for, and will presumably be | 1060 | further processing. id is the string to scan for, and will presumably be |
1061 | either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media | 1061 | either "ANAND" or "BNAND". If findmirror=1, also look for the mirror media |
1062 | header. The page #s of the found media headers are placed in mh0_page and | 1062 | header. The page #s of the found media headers are placed in mh0_page and |
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index db7ae9d6a296..92320a643275 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c | |||
@@ -475,7 +475,7 @@ int __nand_correct_data(unsigned char *buf, | |||
475 | * | 475 | * |
476 | * The b2 shift is there to get rid of the lowest two bits. | 476 | * The b2 shift is there to get rid of the lowest two bits. |
477 | * We could also do addressbits[b2] >> 1 but for the | 477 | * We could also do addressbits[b2] >> 1 but for the |
478 | * performace it does not make any difference | 478 | * performance it does not make any difference |
479 | */ | 479 | */ |
480 | if (eccsize_mult == 1) | 480 | if (eccsize_mult == 1) |
481 | byte_addr = (addressbits[b1] << 4) + addressbits[b0]; | 481 | byte_addr = (addressbits[b1] << 4) + addressbits[b0]; |
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 090ab87086b5..1bb799f0125c 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/mtd/partitions.h> | 18 | #include <linux/mtd/partitions.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | ||
21 | #include <mach/dma.h> | 21 | #include <plat/dma.h> |
22 | #include <mach/gpmc.h> | 22 | #include <plat/gpmc.h> |
23 | #include <mach/nand.h> | 23 | #include <plat/nand.h> |
24 | 24 | ||
25 | #define GPMC_IRQ_STATUS 0x18 | 25 | #define GPMC_IRQ_STATUS 0x18 |
26 | #define GPMC_ECC_CONFIG 0x1F4 | 26 | #define GPMC_ECC_CONFIG 0x1F4 |
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 6ea520ae2410..1a5a0365c983 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
@@ -9,6 +9,7 @@ | |||
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | ||
12 | #include <linux/module.h> | 13 | #include <linux/module.h> |
13 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
14 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
@@ -22,7 +23,7 @@ | |||
22 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
23 | 24 | ||
24 | #include <mach/dma.h> | 25 | #include <mach/dma.h> |
25 | #include <mach/pxa3xx_nand.h> | 26 | #include <plat/pxa3xx_nand.h> |
26 | 27 | ||
27 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | 28 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) |
28 | 29 | ||
@@ -84,10 +85,6 @@ | |||
84 | #define NDCB0_CMD1_MASK (0xff) | 85 | #define NDCB0_CMD1_MASK (0xff) |
85 | #define NDCB0_ADDR_CYC_SHIFT (16) | 86 | #define NDCB0_ADDR_CYC_SHIFT (16) |
86 | 87 | ||
87 | /* dma-able I/O address for the NAND data and commands */ | ||
88 | #define NDCB0_DMA_ADDR (0x43100048) | ||
89 | #define NDDB_DMA_ADDR (0x43100040) | ||
90 | |||
91 | /* macros for registers read/write */ | 88 | /* macros for registers read/write */ |
92 | #define nand_writel(info, off, val) \ | 89 | #define nand_writel(info, off, val) \ |
93 | __raw_writel((val), (info)->mmio_base + (off)) | 90 | __raw_writel((val), (info)->mmio_base + (off)) |
@@ -123,6 +120,7 @@ struct pxa3xx_nand_info { | |||
123 | 120 | ||
124 | struct clk *clk; | 121 | struct clk *clk; |
125 | void __iomem *mmio_base; | 122 | void __iomem *mmio_base; |
123 | unsigned long mmio_phys; | ||
126 | 124 | ||
127 | unsigned int buf_start; | 125 | unsigned int buf_start; |
128 | unsigned int buf_count; | 126 | unsigned int buf_count; |
@@ -228,13 +226,35 @@ static struct pxa3xx_nand_flash samsung512MbX16 = { | |||
228 | .chip_id = 0x46ec, | 226 | .chip_id = 0x46ec, |
229 | }; | 227 | }; |
230 | 228 | ||
229 | static struct pxa3xx_nand_flash samsung2GbX8 = { | ||
230 | .timing = &samsung512MbX16_timing, | ||
231 | .cmdset = &smallpage_cmdset, | ||
232 | .page_per_block = 64, | ||
233 | .page_size = 2048, | ||
234 | .flash_width = 8, | ||
235 | .dfc_width = 8, | ||
236 | .num_blocks = 2048, | ||
237 | .chip_id = 0xdaec, | ||
238 | }; | ||
239 | |||
240 | static struct pxa3xx_nand_flash samsung32GbX8 = { | ||
241 | .timing = &samsung512MbX16_timing, | ||
242 | .cmdset = &smallpage_cmdset, | ||
243 | .page_per_block = 128, | ||
244 | .page_size = 4096, | ||
245 | .flash_width = 8, | ||
246 | .dfc_width = 8, | ||
247 | .num_blocks = 8192, | ||
248 | .chip_id = 0xd7ec, | ||
249 | }; | ||
250 | |||
231 | static struct pxa3xx_nand_timing micron_timing = { | 251 | static struct pxa3xx_nand_timing micron_timing = { |
232 | .tCH = 10, | 252 | .tCH = 10, |
233 | .tCS = 25, | 253 | .tCS = 25, |
234 | .tWH = 15, | 254 | .tWH = 15, |
235 | .tWP = 25, | 255 | .tWP = 25, |
236 | .tRH = 15, | 256 | .tRH = 15, |
237 | .tRP = 25, | 257 | .tRP = 30, |
238 | .tR = 25000, | 258 | .tR = 25000, |
239 | .tWHR = 60, | 259 | .tWHR = 60, |
240 | .tAR = 10, | 260 | .tAR = 10, |
@@ -262,6 +282,28 @@ static struct pxa3xx_nand_flash micron1GbX16 = { | |||
262 | .chip_id = 0xb12c, | 282 | .chip_id = 0xb12c, |
263 | }; | 283 | }; |
264 | 284 | ||
285 | static struct pxa3xx_nand_flash micron4GbX8 = { | ||
286 | .timing = µn_timing, | ||
287 | .cmdset = &largepage_cmdset, | ||
288 | .page_per_block = 64, | ||
289 | .page_size = 2048, | ||
290 | .flash_width = 8, | ||
291 | .dfc_width = 8, | ||
292 | .num_blocks = 4096, | ||
293 | .chip_id = 0xdc2c, | ||
294 | }; | ||
295 | |||
296 | static struct pxa3xx_nand_flash micron4GbX16 = { | ||
297 | .timing = µn_timing, | ||
298 | .cmdset = &largepage_cmdset, | ||
299 | .page_per_block = 64, | ||
300 | .page_size = 2048, | ||
301 | .flash_width = 16, | ||
302 | .dfc_width = 16, | ||
303 | .num_blocks = 4096, | ||
304 | .chip_id = 0xcc2c, | ||
305 | }; | ||
306 | |||
265 | static struct pxa3xx_nand_timing stm2GbX16_timing = { | 307 | static struct pxa3xx_nand_timing stm2GbX16_timing = { |
266 | .tCH = 10, | 308 | .tCH = 10, |
267 | .tCS = 35, | 309 | .tCS = 35, |
@@ -287,8 +329,12 @@ static struct pxa3xx_nand_flash stm2GbX16 = { | |||
287 | 329 | ||
288 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | 330 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { |
289 | &samsung512MbX16, | 331 | &samsung512MbX16, |
332 | &samsung2GbX8, | ||
333 | &samsung32GbX8, | ||
290 | µn1GbX8, | 334 | µn1GbX8, |
291 | µn1GbX16, | 335 | µn1GbX16, |
336 | µn4GbX8, | ||
337 | µn4GbX16, | ||
292 | &stm2GbX16, | 338 | &stm2GbX16, |
293 | }; | 339 | }; |
294 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ | 340 | #endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ |
@@ -489,7 +535,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
489 | switch (info->state) { | 535 | switch (info->state) { |
490 | case STATE_PIO_WRITING: | 536 | case STATE_PIO_WRITING: |
491 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | 537 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, |
492 | info->data_size << 2); | 538 | DIV_ROUND_UP(info->data_size, 4)); |
493 | 539 | ||
494 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | 540 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); |
495 | 541 | ||
@@ -501,7 +547,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) | |||
501 | break; | 547 | break; |
502 | case STATE_PIO_READING: | 548 | case STATE_PIO_READING: |
503 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | 549 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, |
504 | info->data_size << 2); | 550 | DIV_ROUND_UP(info->data_size, 4)); |
505 | break; | 551 | break; |
506 | default: | 552 | default: |
507 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | 553 | printk(KERN_ERR "%s: invalid state %d\n", __func__, |
@@ -523,11 +569,11 @@ static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | |||
523 | 569 | ||
524 | if (dir_out) { | 570 | if (dir_out) { |
525 | desc->dsadr = info->data_buff_phys; | 571 | desc->dsadr = info->data_buff_phys; |
526 | desc->dtadr = NDDB_DMA_ADDR; | 572 | desc->dtadr = info->mmio_phys + NDDB; |
527 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; | 573 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; |
528 | } else { | 574 | } else { |
529 | desc->dtadr = info->data_buff_phys; | 575 | desc->dtadr = info->data_buff_phys; |
530 | desc->dsadr = NDDB_DMA_ADDR; | 576 | desc->dsadr = info->mmio_phys + NDDB; |
531 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; | 577 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; |
532 | } | 578 | } |
533 | 579 | ||
@@ -669,6 +715,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
669 | /* disable HW ECC to get all the OOB data */ | 715 | /* disable HW ECC to get all the OOB data */ |
670 | info->buf_count = mtd->writesize + mtd->oobsize; | 716 | info->buf_count = mtd->writesize + mtd->oobsize; |
671 | info->buf_start = mtd->writesize + column; | 717 | info->buf_start = mtd->writesize + column; |
718 | memset(info->data_buff, 0xFF, info->buf_count); | ||
672 | 719 | ||
673 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | 720 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) |
674 | break; | 721 | break; |
@@ -1239,13 +1286,17 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1239 | ret = -ENODEV; | 1286 | ret = -ENODEV; |
1240 | goto fail_free_res; | 1287 | goto fail_free_res; |
1241 | } | 1288 | } |
1289 | info->mmio_phys = r->start; | ||
1242 | 1290 | ||
1243 | ret = pxa3xx_nand_init_buff(info); | 1291 | ret = pxa3xx_nand_init_buff(info); |
1244 | if (ret) | 1292 | if (ret) |
1245 | goto fail_free_io; | 1293 | goto fail_free_io; |
1246 | 1294 | ||
1247 | ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED, | 1295 | /* initialize all interrupts to be disabled */ |
1248 | pdev->name, info); | 1296 | disable_int(info, NDSR_MASK); |
1297 | |||
1298 | ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, | ||
1299 | pdev->name, info); | ||
1249 | if (ret < 0) { | 1300 | if (ret < 0) { |
1250 | dev_err(&pdev->dev, "failed to request IRQ\n"); | 1301 | dev_err(&pdev->dev, "failed to request IRQ\n"); |
1251 | goto fail_free_buf; | 1302 | goto fail_free_buf; |
@@ -1271,7 +1322,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) | |||
1271 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | 1322 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); |
1272 | 1323 | ||
1273 | fail_free_irq: | 1324 | fail_free_irq: |
1274 | free_irq(IRQ_NAND, info); | 1325 | free_irq(irq, info); |
1275 | fail_free_buf: | 1326 | fail_free_buf: |
1276 | if (use_dma) { | 1327 | if (use_dma) { |
1277 | pxa_free_dma(info->data_dma_ch); | 1328 | pxa_free_dma(info->data_dma_ch); |
@@ -1296,12 +1347,15 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) | |||
1296 | struct mtd_info *mtd = platform_get_drvdata(pdev); | 1347 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
1297 | struct pxa3xx_nand_info *info = mtd->priv; | 1348 | struct pxa3xx_nand_info *info = mtd->priv; |
1298 | struct resource *r; | 1349 | struct resource *r; |
1350 | int irq; | ||
1299 | 1351 | ||
1300 | platform_set_drvdata(pdev, NULL); | 1352 | platform_set_drvdata(pdev, NULL); |
1301 | 1353 | ||
1302 | del_mtd_device(mtd); | 1354 | del_mtd_device(mtd); |
1303 | del_mtd_partitions(mtd); | 1355 | del_mtd_partitions(mtd); |
1304 | free_irq(IRQ_NAND, info); | 1356 | irq = platform_get_irq(pdev, 0); |
1357 | if (irq >= 0) | ||
1358 | free_irq(irq, info); | ||
1305 | if (use_dma) { | 1359 | if (use_dma) { |
1306 | pxa_free_dma(info->data_dma_ch); | 1360 | pxa_free_dma(info->data_dma_ch); |
1307 | dma_free_writecombine(&pdev->dev, info->data_buff_size, | 1361 | dma_free_writecombine(&pdev->dev, info->data_buff_size, |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 11dc7e69c4fb..68b5b3a486a9 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
@@ -875,7 +875,7 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
875 | * @info: The controller instance. | 875 | * @info: The controller instance. |
876 | * @nmtd: The driver version of the MTD instance. | 876 | * @nmtd: The driver version of the MTD instance. |
877 | * | 877 | * |
878 | * This routine is called after the chip probe has succesfully completed | 878 | * This routine is called after the chip probe has successfully completed |
879 | * and the relevant per-chip information updated. This call ensure that | 879 | * and the relevant per-chip information updated. This call ensure that |
880 | * we update the internal state accordingly. | 880 | * we update the internal state accordingly. |
881 | * | 881 | * |
diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index a38f580c2bb3..3a9f15784600 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig | |||
@@ -1,7 +1,3 @@ | |||
1 | # | ||
2 | # linux/drivers/mtd/onenand/Kconfig | ||
3 | # | ||
4 | |||
5 | menuconfig MTD_ONENAND | 1 | menuconfig MTD_ONENAND |
6 | tristate "OneNAND Device Support" | 2 | tristate "OneNAND Device Support" |
7 | depends on MTD | 3 | depends on MTD |
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index 0108ed42e877..86c4f6dcdc65 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c | |||
@@ -36,13 +36,13 @@ | |||
36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
37 | 37 | ||
38 | #include <asm/mach/flash.h> | 38 | #include <asm/mach/flash.h> |
39 | #include <mach/gpmc.h> | 39 | #include <plat/gpmc.h> |
40 | #include <mach/onenand.h> | 40 | #include <plat/onenand.h> |
41 | #include <mach/gpio.h> | 41 | #include <mach/gpio.h> |
42 | 42 | ||
43 | #include <mach/dma.h> | 43 | #include <plat/dma.h> |
44 | 44 | ||
45 | #include <mach/board.h> | 45 | #include <plat/board.h> |
46 | 46 | ||
47 | #define DRIVER_NAME "omap2-onenand" | 47 | #define DRIVER_NAME "omap2-onenand" |
48 | 48 | ||
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index b1cd7a1a2191..0a8c7ea764ae 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig | |||
@@ -1,5 +1,3 @@ | |||
1 | # drivers/mtd/ubi/Kconfig | ||
2 | |||
3 | menu "UBI - Unsorted block images" | 1 | menu "UBI - Unsorted block images" |
4 | depends on MTD | 2 | depends on MTD |
5 | 3 | ||
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 88a72e9c8beb..277786ebaa2c 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c | |||
@@ -22,6 +22,8 @@ | |||
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/namei.h> | ||
26 | #include <linux/fs.h> | ||
25 | #include <asm/div64.h> | 27 | #include <asm/div64.h> |
26 | #include "ubi.h" | 28 | #include "ubi.h" |
27 | 29 | ||
@@ -280,6 +282,44 @@ struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, | |||
280 | EXPORT_SYMBOL_GPL(ubi_open_volume_nm); | 282 | EXPORT_SYMBOL_GPL(ubi_open_volume_nm); |
281 | 283 | ||
282 | /** | 284 | /** |
285 | * ubi_open_volume_path - open UBI volume by its character device node path. | ||
286 | * @pathname: volume character device node path | ||
287 | * @mode: open mode | ||
288 | * | ||
289 | * This function is similar to 'ubi_open_volume()', but opens a volume the path | ||
290 | * to its character device node. | ||
291 | */ | ||
292 | struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) | ||
293 | { | ||
294 | int error, ubi_num, vol_id; | ||
295 | struct ubi_volume_desc *ret; | ||
296 | struct inode *inode; | ||
297 | struct path path; | ||
298 | |||
299 | dbg_gen("open volume %s, mode %d", pathname, mode); | ||
300 | |||
301 | if (!pathname || !*pathname) | ||
302 | return ERR_PTR(-EINVAL); | ||
303 | |||
304 | error = kern_path(pathname, LOOKUP_FOLLOW, &path); | ||
305 | if (error) | ||
306 | return ERR_PTR(error); | ||
307 | |||
308 | inode = path.dentry->d_inode; | ||
309 | ubi_num = ubi_major2num(imajor(inode)); | ||
310 | vol_id = iminor(inode) - 1; | ||
311 | |||
312 | if (vol_id >= 0 && ubi_num >= 0) | ||
313 | ret = ubi_open_volume(ubi_num, vol_id, mode); | ||
314 | else | ||
315 | ret = ERR_PTR(-ENODEV); | ||
316 | |||
317 | path_put(&path); | ||
318 | return ret; | ||
319 | } | ||
320 | EXPORT_SYMBOL_GPL(ubi_open_volume_path); | ||
321 | |||
322 | /** | ||
283 | * ubi_close_volume - close UBI volume. | 323 | * ubi_close_volume - close UBI volume. |
284 | * @desc: volume descriptor | 324 | * @desc: volume descriptor |
285 | */ | 325 | */ |
diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 74fdc40c8627..c1d7b880c795 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c | |||
@@ -147,12 +147,14 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, | |||
147 | } | 147 | } |
148 | 148 | ||
149 | if (bytes == 0) { | 149 | if (bytes == 0) { |
150 | err = ubi_wl_flush(ubi); | ||
151 | if (err) | ||
152 | return err; | ||
153 | |||
150 | err = clear_update_marker(ubi, vol, 0); | 154 | err = clear_update_marker(ubi, vol, 0); |
151 | if (err) | 155 | if (err) |
152 | return err; | 156 | return err; |
153 | err = ubi_wl_flush(ubi); | 157 | vol->updating = 0; |
154 | if (!err) | ||
155 | vol->updating = 0; | ||
156 | } | 158 | } |
157 | 159 | ||
158 | vol->upd_buf = vmalloc(ubi->leb_size); | 160 | vol->upd_buf = vmalloc(ubi->leb_size); |
@@ -362,16 +364,16 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, | |||
362 | 364 | ||
363 | ubi_assert(vol->upd_received <= vol->upd_bytes); | 365 | ubi_assert(vol->upd_received <= vol->upd_bytes); |
364 | if (vol->upd_received == vol->upd_bytes) { | 366 | if (vol->upd_received == vol->upd_bytes) { |
367 | err = ubi_wl_flush(ubi); | ||
368 | if (err) | ||
369 | return err; | ||
365 | /* The update is finished, clear the update marker */ | 370 | /* The update is finished, clear the update marker */ |
366 | err = clear_update_marker(ubi, vol, vol->upd_bytes); | 371 | err = clear_update_marker(ubi, vol, vol->upd_bytes); |
367 | if (err) | 372 | if (err) |
368 | return err; | 373 | return err; |
369 | err = ubi_wl_flush(ubi); | 374 | vol->updating = 0; |
370 | if (err == 0) { | 375 | err = to_write; |
371 | vol->updating = 0; | 376 | vfree(vol->upd_buf); |
372 | err = to_write; | ||
373 | vfree(vol->upd_buf); | ||
374 | } | ||
375 | } | 377 | } |
376 | 378 | ||
377 | return err; | 379 | return err; |