Commit bff4fae4fc29376e62ac6d420b189f23a57e4294

Authored by Tom Rini

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  
... ... @@ -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"
... ... @@ -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;