Commit bff4fae4fc29376e62ac6d420b189f23a57e4294
Exists in
master
and in
53 other branches
Merge branch 'master' of git://git.denx.de/u-boot-nand-flash
Showing 9 changed files Side-by-side Diff
common/cmd_mtdparts.c
... | ... | @@ -93,13 +93,13 @@ |
93 | 93 | DECLARE_GLOBAL_DATA_PTR; |
94 | 94 | |
95 | 95 | /* special size referring to all the remaining space in a partition */ |
96 | -#define SIZE_REMAINING 0xFFFFFFFF | |
96 | +#define SIZE_REMAINING (~0llu) | |
97 | 97 | |
98 | 98 | /* special offset value, it is used when not provided by user |
99 | 99 | * |
100 | 100 | * this value is used temporarily during parsing, later such offests |
101 | 101 | * are recalculated */ |
102 | -#define OFFSET_NOT_SPECIFIED 0xFFFFFFFF | |
102 | +#define OFFSET_NOT_SPECIFIED (~0llu) | |
103 | 103 | |
104 | 104 | /* minimum partition size */ |
105 | 105 | #define MIN_PART_SIZE 4096 |
106 | 106 | |
... | ... | @@ -160,9 +160,9 @@ |
160 | 160 | * @param retptr output pointer to next char after parse completes (output) |
161 | 161 | * @return resulting unsigned int |
162 | 162 | */ |
163 | -static unsigned long memsize_parse (const char *const ptr, const char **retptr) | |
163 | +static u64 memsize_parse (const char *const ptr, const char **retptr) | |
164 | 164 | { |
165 | - unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0); | |
165 | + u64 ret = simple_strtoull(ptr, (char **)retptr, 0); | |
166 | 166 | |
167 | 167 | switch (**retptr) { |
168 | 168 | case 'G': |
169 | 169 | |
170 | 170 | |
171 | 171 | |
172 | 172 | |
... | ... | @@ -193,20 +193,20 @@ |
193 | 193 | * @param buf output buffer |
194 | 194 | * @param size size to be converted to string |
195 | 195 | */ |
196 | -static void memsize_format(char *buf, u32 size) | |
196 | +static void memsize_format(char *buf, u64 size) | |
197 | 197 | { |
198 | 198 | #define SIZE_GB ((u32)1024*1024*1024) |
199 | 199 | #define SIZE_MB ((u32)1024*1024) |
200 | 200 | #define SIZE_KB ((u32)1024) |
201 | 201 | |
202 | 202 | if ((size % SIZE_GB) == 0) |
203 | - sprintf(buf, "%ug", size/SIZE_GB); | |
203 | + sprintf(buf, "%llug", size/SIZE_GB); | |
204 | 204 | else if ((size % SIZE_MB) == 0) |
205 | - sprintf(buf, "%um", size/SIZE_MB); | |
205 | + sprintf(buf, "%llum", size/SIZE_MB); | |
206 | 206 | else if (size % SIZE_KB == 0) |
207 | - sprintf(buf, "%uk", size/SIZE_KB); | |
207 | + sprintf(buf, "%lluk", size/SIZE_KB); | |
208 | 208 | else |
209 | - sprintf(buf, "%u", size); | |
209 | + sprintf(buf, "%llu", size); | |
210 | 210 | } |
211 | 211 | |
212 | 212 | /** |
... | ... | @@ -310,6 +310,7 @@ |
310 | 310 | struct mtd_info *mtd = NULL; |
311 | 311 | int i, j; |
312 | 312 | ulong start; |
313 | + u64 offset, size; | |
313 | 314 | |
314 | 315 | if (get_mtd_info(id->type, id->num, &mtd)) |
315 | 316 | return 1; |
316 | 317 | |
... | ... | @@ -321,14 +322,16 @@ |
321 | 322 | * Only one eraseregion (NAND, OneNAND or uniform NOR), |
322 | 323 | * checking for alignment is easy here |
323 | 324 | */ |
324 | - if ((unsigned long)part->offset % mtd->erasesize) { | |
325 | + offset = part->offset; | |
326 | + if (do_div(offset, mtd->erasesize)) { | |
325 | 327 | printf("%s%d: partition (%s) start offset" |
326 | 328 | "alignment incorrect\n", |
327 | 329 | MTD_DEV_TYPE(id->type), id->num, part->name); |
328 | 330 | return 1; |
329 | 331 | } |
330 | 332 | |
331 | - if (part->size % mtd->erasesize) { | |
333 | + size = part->size; | |
334 | + if (do_div(size, mtd->erasesize)) { | |
332 | 335 | printf("%s%d: partition (%s) size alignment incorrect\n", |
333 | 336 | MTD_DEV_TYPE(id->type), id->num, part->name); |
334 | 337 | return 1; |
... | ... | @@ -395,7 +398,7 @@ |
395 | 398 | part->size = id->size - part->offset; |
396 | 399 | |
397 | 400 | if (part->offset > id->size) { |
398 | - printf("%s: offset %08x beyond flash size %08x\n", | |
401 | + printf("%s: offset %08llx beyond flash size %08llx\n", | |
399 | 402 | id->mtd_id, part->offset, id->size); |
400 | 403 | return 1; |
401 | 404 | } |
... | ... | @@ -578,8 +581,8 @@ |
578 | 581 | static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart) |
579 | 582 | { |
580 | 583 | struct part_info *part; |
581 | - unsigned long size; | |
582 | - unsigned long offset; | |
584 | + u64 size; | |
585 | + u64 offset; | |
583 | 586 | const char *name; |
584 | 587 | int name_len; |
585 | 588 | unsigned int mask_flags; |
... | ... | @@ -598,7 +601,7 @@ |
598 | 601 | } else { |
599 | 602 | size = memsize_parse(p, &p); |
600 | 603 | if (size < MIN_PART_SIZE) { |
601 | - printf("partition size too small (%lx)\n", size); | |
604 | + printf("partition size too small (%llx)\n", size); | |
602 | 605 | return 1; |
603 | 606 | } |
604 | 607 | } |
605 | 608 | |
... | ... | @@ -670,14 +673,14 @@ |
670 | 673 | part->auto_name = 0; |
671 | 674 | } else { |
672 | 675 | /* auto generated name in form of size@offset */ |
673 | - sprintf(part->name, "0x%08lx@0x%08lx", size, offset); | |
676 | + sprintf(part->name, "0x%08llx@0x%08llx", size, offset); | |
674 | 677 | part->auto_name = 1; |
675 | 678 | } |
676 | 679 | |
677 | 680 | part->name[name_len - 1] = '\0'; |
678 | 681 | INIT_LIST_HEAD(&part->link); |
679 | 682 | |
680 | - debug("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n", | |
683 | + debug("+ partition: name %-22s size 0x%08llx offset 0x%08llx mask flags %d\n", | |
681 | 684 | part->name, part->size, |
682 | 685 | part->offset, part->mask_flags); |
683 | 686 | |
... | ... | @@ -693,7 +696,7 @@ |
693 | 696 | * @param size a pointer to the size of the mtd device (output) |
694 | 697 | * @return 0 if device is valid, 1 otherwise |
695 | 698 | */ |
696 | -static int mtd_device_validate(u8 type, u8 num, u32 *size) | |
699 | +static int mtd_device_validate(u8 type, u8 num, u64 *size) | |
697 | 700 | { |
698 | 701 | struct mtd_info *mtd = NULL; |
699 | 702 | |
... | ... | @@ -826,7 +829,7 @@ |
826 | 829 | LIST_HEAD(tmp_list); |
827 | 830 | struct list_head *entry, *n; |
828 | 831 | u16 num_parts; |
829 | - u32 offset; | |
832 | + u64 offset; | |
830 | 833 | int err = 1; |
831 | 834 | |
832 | 835 | debug("===device_parse===\n"); |
... | ... | @@ -1071,7 +1074,8 @@ |
1071 | 1074 | struct part_info *part, *prev_part; |
1072 | 1075 | char *p = buf; |
1073 | 1076 | char tmpbuf[32]; |
1074 | - u32 size, offset, len, part_cnt; | |
1077 | + u64 size, offset; | |
1078 | + u32 len, part_cnt; | |
1075 | 1079 | u32 maxlen = buflen - 1; |
1076 | 1080 | |
1077 | 1081 | debug("--- generate_mtdparts ---\n"); |
... | ... | @@ -1270,7 +1274,7 @@ |
1270 | 1274 | |
1271 | 1275 | list_for_each(pentry, &dev->parts) { |
1272 | 1276 | part = list_entry(pentry, struct part_info, link); |
1273 | - printf("%2d: %-20s0x%08x\t0x%08x\t%d\n", | |
1277 | + printf("%2d: %-20s0x%08llx\t0x%08llx\t%d\n", | |
1274 | 1278 | part_num, part->name, part->size, |
1275 | 1279 | part->offset, part->mask_flags); |
1276 | 1280 | #endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */ |
... | ... | @@ -1297,7 +1301,7 @@ |
1297 | 1301 | if (current_mtd_dev) { |
1298 | 1302 | part = mtd_part_info(current_mtd_dev, current_mtd_partnum); |
1299 | 1303 | if (part) { |
1300 | - printf("\nactive partition: %s%d,%d - (%s) 0x%08x @ 0x%08x\n", | |
1304 | + printf("\nactive partition: %s%d,%d - (%s) 0x%08llx @ 0x%08llx\n", | |
1301 | 1305 | MTD_DEV_TYPE(current_mtd_dev->id->type), |
1302 | 1306 | current_mtd_dev->id->num, current_mtd_partnum, |
1303 | 1307 | part->name, part->size, part->offset); |
... | ... | @@ -1397,7 +1401,7 @@ |
1397 | 1401 | |
1398 | 1402 | if (find_dev_and_part(id, &dev, &pnum, &part) == 0) { |
1399 | 1403 | |
1400 | - debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n", | |
1404 | + debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08llx@0x%08llx\n", | |
1401 | 1405 | MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum, |
1402 | 1406 | part->name, part->size, part->offset); |
1403 | 1407 | |
... | ... | @@ -1589,7 +1593,7 @@ |
1589 | 1593 | struct list_head *entry, *n; |
1590 | 1594 | struct mtdids *id_tmp; |
1591 | 1595 | u8 type, num; |
1592 | - u32 size; | |
1596 | + u64 size; | |
1593 | 1597 | int ret = 1; |
1594 | 1598 | |
1595 | 1599 | debug("\n---parse_mtdids---\nmtdids = %s\n\n", ids); |
... | ... | @@ -1663,7 +1667,7 @@ |
1663 | 1667 | id->mtd_id[mtd_id_len - 1] = '\0'; |
1664 | 1668 | INIT_LIST_HEAD(&id->link); |
1665 | 1669 | |
1666 | - debug("+ id %s%d\t%16d bytes\t%s\n", | |
1670 | + debug("+ id %s%d\t%16lld bytes\t%s\n", | |
1667 | 1671 | MTD_DEV_TYPE(id->type), id->num, |
1668 | 1672 | id->size, id->mtd_id); |
1669 | 1673 |
common/cmd_ubi.c
... | ... | @@ -167,7 +167,7 @@ |
167 | 167 | return err; |
168 | 168 | } |
169 | 169 | |
170 | -static int ubi_create_vol(char *volume, int size, int dynamic) | |
170 | +static int ubi_create_vol(char *volume, int64_t size, int dynamic) | |
171 | 171 | { |
172 | 172 | struct ubi_mkvol_req req; |
173 | 173 | int err; |
... | ... | @@ -191,7 +191,7 @@ |
191 | 191 | printf("verify_mkvol_req failed %d\n", err); |
192 | 192 | return err; |
193 | 193 | } |
194 | - printf("Creating %s volume %s of size %d\n", | |
194 | + printf("Creating %s volume %s of size %lld\n", | |
195 | 195 | dynamic ? "dynamic" : "static", volume, size); |
196 | 196 | /* Call real ubi create volume */ |
197 | 197 | return ubi_create_volume(ubi, &req); |
198 | 198 | |
199 | 199 | |
... | ... | @@ -266,28 +266,15 @@ |
266 | 266 | return err; |
267 | 267 | } |
268 | 268 | |
269 | -int ubi_volume_write(char *volume, void *buf, size_t size) | |
269 | +int ubi_volume_continue_write(char *volume, void *buf, size_t size) | |
270 | 270 | { |
271 | 271 | int err = 1; |
272 | - int rsvd_bytes = 0; | |
273 | 272 | struct ubi_volume *vol; |
274 | 273 | |
275 | 274 | vol = ubi_find_volume(volume); |
276 | 275 | if (vol == NULL) |
277 | 276 | return ENODEV; |
278 | 277 | |
279 | - rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); | |
280 | - if (size < 0 || size > rsvd_bytes) { | |
281 | - printf("size > volume size! Aborting!\n"); | |
282 | - return EINVAL; | |
283 | - } | |
284 | - | |
285 | - err = ubi_start_update(ubi, vol, size); | |
286 | - if (err < 0) { | |
287 | - printf("Cannot start volume update\n"); | |
288 | - return -err; | |
289 | - } | |
290 | - | |
291 | 278 | err = ubi_more_update_data(ubi, vol, buf, size); |
292 | 279 | if (err < 0) { |
293 | 280 | printf("Couldnt or partially wrote data\n"); |
... | ... | @@ -314,6 +301,37 @@ |
314 | 301 | return 0; |
315 | 302 | } |
316 | 303 | |
304 | +int ubi_volume_begin_write(char *volume, void *buf, size_t size, | |
305 | + size_t full_size) | |
306 | +{ | |
307 | + int err = 1; | |
308 | + int rsvd_bytes = 0; | |
309 | + struct ubi_volume *vol; | |
310 | + | |
311 | + vol = ubi_find_volume(volume); | |
312 | + if (vol == NULL) | |
313 | + return ENODEV; | |
314 | + | |
315 | + rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); | |
316 | + if (size < 0 || size > rsvd_bytes) { | |
317 | + printf("size > volume size! Aborting!\n"); | |
318 | + return EINVAL; | |
319 | + } | |
320 | + | |
321 | + err = ubi_start_update(ubi, vol, full_size); | |
322 | + if (err < 0) { | |
323 | + printf("Cannot start volume update\n"); | |
324 | + return -err; | |
325 | + } | |
326 | + | |
327 | + return ubi_volume_continue_write(volume, buf, size); | |
328 | +} | |
329 | + | |
330 | +int ubi_volume_write(char *volume, void *buf, size_t size) | |
331 | +{ | |
332 | + return ubi_volume_begin_write(volume, buf, size, size); | |
333 | +} | |
334 | + | |
317 | 335 | int ubi_volume_read(char *volume, char *buf, size_t size) |
318 | 336 | { |
319 | 337 | int err, lnum, off, len, tbuf_size; |
... | ... | @@ -498,7 +516,7 @@ |
498 | 516 | |
499 | 517 | static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
500 | 518 | { |
501 | - size_t size = 0; | |
519 | + int64_t size = 0; | |
502 | 520 | ulong addr = 0; |
503 | 521 | |
504 | 522 | if (argc < 2) |
505 | 523 | |
... | ... | @@ -558,13 +576,13 @@ |
558 | 576 | } |
559 | 577 | /* E.g., create volume size */ |
560 | 578 | if (argc == 4) { |
561 | - size = simple_strtoul(argv[3], NULL, 16); | |
579 | + size = simple_strtoull(argv[3], NULL, 16); | |
562 | 580 | argc--; |
563 | 581 | } |
564 | 582 | /* Use maximum available size */ |
565 | 583 | if (!size) { |
566 | - size = ubi->avail_pebs * ubi->leb_size; | |
567 | - printf("No size specified -> Using max size (%u)\n", size); | |
584 | + size = (int64_t)ubi->avail_pebs * ubi->leb_size; | |
585 | + printf("No size specified -> Using max size (%lld)\n", size); | |
568 | 586 | } |
569 | 587 | /* E.g., create volume */ |
570 | 588 | if (argc == 3) |
571 | 589 | |
... | ... | @@ -588,9 +606,22 @@ |
588 | 606 | addr = simple_strtoul(argv[2], NULL, 16); |
589 | 607 | size = simple_strtoul(argv[4], NULL, 16); |
590 | 608 | |
591 | - ret = ubi_volume_write(argv[3], (void *)addr, size); | |
609 | + if (strlen(argv[1]) == 10 && | |
610 | + strncmp(argv[1] + 5, ".part", 5) == 0) { | |
611 | + if (argc < 6) { | |
612 | + ret = ubi_volume_continue_write(argv[3], | |
613 | + (void *)addr, size); | |
614 | + } else { | |
615 | + size_t full_size; | |
616 | + full_size = simple_strtoul(argv[5], NULL, 16); | |
617 | + ret = ubi_volume_begin_write(argv[3], | |
618 | + (void *)addr, size, full_size); | |
619 | + } | |
620 | + } else { | |
621 | + ret = ubi_volume_write(argv[3], (void *)addr, size); | |
622 | + } | |
592 | 623 | if (!ret) { |
593 | - printf("%d bytes written to volume %s\n", size, | |
624 | + printf("%lld bytes written to volume %s\n", size, | |
594 | 625 | argv[3]); |
595 | 626 | } |
596 | 627 | |
... | ... | @@ -613,7 +644,7 @@ |
613 | 644 | } |
614 | 645 | |
615 | 646 | if (argc == 3) { |
616 | - printf("Read %d bytes from volume %s to %lx\n", size, | |
647 | + printf("Read %lld bytes from volume %s to %lx\n", size, | |
617 | 648 | argv[3], addr); |
618 | 649 | |
619 | 650 | return ubi_volume_read(argv[3], (char *)addr, size); |
... | ... | @@ -636,6 +667,8 @@ |
636 | 667 | " - create volume name with size\n" |
637 | 668 | "ubi write[vol] address volume size" |
638 | 669 | " - Write volume from address with size\n" |
670 | + "ubi write.part address volume size [fullsize]\n" | |
671 | + " - Write part of a volume from address\n" | |
639 | 672 | "ubi read[vol] address volume [size]" |
640 | 673 | " - Read volume to address with size\n" |
641 | 674 | "ubi remove[vol] volume" |
doc/README.ubi
... | ... | @@ -14,6 +14,8 @@ |
14 | 14 | ubi info [l[ayout]] - Display volume and ubi layout information |
15 | 15 | ubi create[vol] volume [size] [type] - create volume name with size |
16 | 16 | ubi write[vol] address volume size - Write volume from address with size |
17 | +ubi write.part address volume size [fullsize] | |
18 | + - Write part of a volume from address | |
17 | 19 | ubi read[vol] address volume [size] - Read volume to address with size |
18 | 20 | ubi remove[vol] volume - Remove volume |
19 | 21 | [Legends] |
... | ... | @@ -77,6 +79,7 @@ |
77 | 79 | ubi removevol Remove UBI volume from UBI device |
78 | 80 | ubi read Read data from UBI volume to memory |
79 | 81 | ubi write Write data from memory to UBI volume |
82 | +ubi write.part Write data from memory to UBI volume, in parts | |
80 | 83 | |
81 | 84 | |
82 | 85 | Here a few examples on the usage: |
drivers/mtd/mtdcore.c
... | ... | @@ -217,11 +217,23 @@ |
217 | 217 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, |
218 | 218 | u_char *buf) |
219 | 219 | { |
220 | + int ret_code; | |
220 | 221 | if (from < 0 || from > mtd->size || len > mtd->size - from) |
221 | 222 | return -EINVAL; |
222 | 223 | if (!len) |
223 | 224 | return 0; |
224 | - return mtd->_read(mtd, from, len, retlen, buf); | |
225 | + | |
226 | + /* | |
227 | + * In the absence of an error, drivers return a non-negative integer | |
228 | + * representing the maximum number of bitflips that were corrected on | |
229 | + * any one ecc region (if applicable; zero otherwise). | |
230 | + */ | |
231 | + ret_code = mtd->_read(mtd, from, len, retlen, buf); | |
232 | + if (unlikely(ret_code < 0)) | |
233 | + return ret_code; | |
234 | + if (mtd->ecc_strength == 0) | |
235 | + return 0; /* device lacks ecc */ | |
236 | + return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; | |
225 | 237 | } |
226 | 238 | |
227 | 239 | int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, |
drivers/mtd/mtdpart.c
... | ... | @@ -53,12 +53,12 @@ |
53 | 53 | |
54 | 54 | stats = part->master->ecc_stats; |
55 | 55 | res = mtd_read(part->master, from + part->offset, len, retlen, buf); |
56 | - if (unlikely(res)) { | |
57 | - if (mtd_is_bitflip(res)) | |
58 | - mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected; | |
59 | - if (mtd_is_eccerr(res)) | |
60 | - mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed; | |
61 | - } | |
56 | + if (unlikely(mtd_is_eccerr(res))) | |
57 | + mtd->ecc_stats.failed += | |
58 | + part->master->ecc_stats.failed - stats.failed; | |
59 | + else | |
60 | + mtd->ecc_stats.corrected += | |
61 | + part->master->ecc_stats.corrected - stats.corrected; | |
62 | 62 | return res; |
63 | 63 | } |
64 | 64 |
drivers/mtd/nand/nand_base.c
... | ... | @@ -1238,6 +1238,7 @@ |
1238 | 1238 | mtd->oobavail : mtd->oobsize; |
1239 | 1239 | |
1240 | 1240 | uint8_t *bufpoi, *oob, *buf; |
1241 | + unsigned int max_bitflips = 0; | |
1241 | 1242 | |
1242 | 1243 | stats = mtd->ecc_stats; |
1243 | 1244 | |
... | ... | @@ -1265,7 +1266,10 @@ |
1265 | 1266 | |
1266 | 1267 | chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); |
1267 | 1268 | |
1268 | - /* Now read the page into the buffer */ | |
1269 | + /* | |
1270 | + * Now read the page into the buffer. Absent an error, | |
1271 | + * the read methods return max bitflips per ecc step. | |
1272 | + */ | |
1269 | 1273 | if (unlikely(ops->mode == MTD_OPS_RAW)) |
1270 | 1274 | ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, |
1271 | 1275 | oob_required, |
1272 | 1276 | |
1273 | 1277 | |
1274 | 1278 | |
... | ... | @@ -1284,15 +1288,19 @@ |
1284 | 1288 | break; |
1285 | 1289 | } |
1286 | 1290 | |
1291 | + max_bitflips = max_t(unsigned int, max_bitflips, ret); | |
1292 | + | |
1287 | 1293 | /* Transfer not aligned data */ |
1288 | 1294 | if (!aligned) { |
1289 | 1295 | if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && |
1290 | 1296 | !(mtd->ecc_stats.failed - stats.failed) && |
1291 | - (ops->mode != MTD_OPS_RAW)) | |
1297 | + (ops->mode != MTD_OPS_RAW)) { | |
1292 | 1298 | chip->pagebuf = realpage; |
1293 | - else | |
1299 | + chip->pagebuf_bitflips = ret; | |
1300 | + } else { | |
1294 | 1301 | /* Invalidate page cache */ |
1295 | 1302 | chip->pagebuf = -1; |
1303 | + } | |
1296 | 1304 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1297 | 1305 | } |
1298 | 1306 | |
... | ... | @@ -1310,6 +1318,8 @@ |
1310 | 1318 | } else { |
1311 | 1319 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1312 | 1320 | buf += bytes; |
1321 | + max_bitflips = max_t(unsigned int, max_bitflips, | |
1322 | + chip->pagebuf_bitflips); | |
1313 | 1323 | } |
1314 | 1324 | |
1315 | 1325 | readlen -= bytes; |
... | ... | @@ -1341,7 +1351,7 @@ |
1341 | 1351 | if (mtd->ecc_stats.failed - stats.failed) |
1342 | 1352 | return -EBADMSG; |
1343 | 1353 | |
1344 | - return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | |
1354 | + return max_bitflips; | |
1345 | 1355 | } |
1346 | 1356 | |
1347 | 1357 | /** |
drivers/mtd/onenand/onenand_base.c
... | ... | @@ -969,7 +969,8 @@ |
969 | 969 | if (mtd->ecc_stats.failed - stats.failed) |
970 | 970 | return -EBADMSG; |
971 | 971 | |
972 | - return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0; | |
972 | + /* return max bitflips per ecc step; ONENANDs correct 1 bit only */ | |
973 | + return mtd->ecc_stats.corrected != stats.corrected ? 1 : 0; | |
973 | 974 | } |
974 | 975 | |
975 | 976 | /** |
include/jffs2/load_kernel.h
... | ... | @@ -32,8 +32,8 @@ |
32 | 32 | struct list_head link; |
33 | 33 | char *name; /* partition name */ |
34 | 34 | u8 auto_name; /* set to 1 for generated name */ |
35 | - u32 size; /* total size of the partition */ | |
36 | - u32 offset; /* offset within device */ | |
35 | + u64 size; /* total size of the partition */ | |
36 | + u64 offset; /* offset within device */ | |
37 | 37 | void *jffs2_priv; /* used internaly by jffs2 */ |
38 | 38 | u32 mask_flags; /* kernel MTD mask flags */ |
39 | 39 | u32 sector_size; /* size of sector */ |
... | ... | @@ -44,7 +44,7 @@ |
44 | 44 | struct list_head link; |
45 | 45 | u8 type; /* device type */ |
46 | 46 | u8 num; /* device number */ |
47 | - u32 size; /* device size */ | |
47 | + u64 size; /* device size */ | |
48 | 48 | char *mtd_id; /* linux kernel device id */ |
49 | 49 | }; |
50 | 50 |
include/linux/mtd/nand.h
... | ... | @@ -464,6 +464,8 @@ |
464 | 464 | * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1 |
465 | 465 | * @pagebuf: [INTERN] holds the pagenumber which is currently in |
466 | 466 | * data_buf. |
467 | + * @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is | |
468 | + * currently in data_buf. | |
467 | 469 | * @subpagesize: [INTERN] holds the subpagesize |
468 | 470 | * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded), |
469 | 471 | * non 0 if ONFI supported. |
... | ... | @@ -531,6 +533,7 @@ |
531 | 533 | uint64_t chipsize; |
532 | 534 | int pagemask; |
533 | 535 | int pagebuf; |
536 | + unsigned int pagebuf_bitflips; | |
534 | 537 | int subpagesize; |
535 | 538 | uint8_t cellinfo; |
536 | 539 | int badblockpos; |