aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdpart.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-29 18:37:34 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-29 18:37:34 -0400
commitf1a28c02843efcfcc41982149880bac3ac180234 (patch)
treeb15ca1a140e463ef3cde6b9a8591e7be172ee1f1 /drivers/mtd/mtdpart.c
parent9a1fcdfd4bee27c418424cac47abf7c049541297 (diff)
[MTD] NAND Expose the new raw mode function and status info to userspace
The raw read/write access to NAND (without ECC) has been changed in the NAND rework. Expose the new way - setting the file mode via ioctl - to userspace. Also allow to read out the ecc statistics information so userspace tools can see that bitflips happened and whether errors where correctable or not. Also expose the number of bad blocks for the partition, so nandwrite can check if the data fits into the parition before writing to it. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/mtdpart.c')
-rw-r--r--drivers/mtd/mtdpart.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index f22aeccf01e7..77a7123a5c56 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -51,12 +51,21 @@ static int part_read (struct mtd_info *mtd, loff_t from, size_t len,
51 size_t *retlen, u_char *buf) 51 size_t *retlen, u_char *buf)
52{ 52{
53 struct mtd_part *part = PART(mtd); 53 struct mtd_part *part = PART(mtd);
54 int res;
55
54 if (from >= mtd->size) 56 if (from >= mtd->size)
55 len = 0; 57 len = 0;
56 else if (from + len > mtd->size) 58 else if (from + len > mtd->size)
57 len = mtd->size - from; 59 len = mtd->size - from;
58 return part->master->read (part->master, from + part->offset, 60 res = part->master->read (part->master, from + part->offset,
59 len, retlen, buf); 61 len, retlen, buf);
62 if (unlikely(res)) {
63 if (res == -EUCLEAN)
64 mtd->ecc_stats.corrected++;
65 if (res == -EBADMSG)
66 mtd->ecc_stats.failed++;
67 }
68 return res;
60} 69}
61 70
62static int part_point (struct mtd_info *mtd, loff_t from, size_t len, 71static int part_point (struct mtd_info *mtd, loff_t from, size_t len,
@@ -82,12 +91,21 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
82 struct mtd_oob_ops *ops) 91 struct mtd_oob_ops *ops)
83{ 92{
84 struct mtd_part *part = PART(mtd); 93 struct mtd_part *part = PART(mtd);
94 int res;
85 95
86 if (from >= mtd->size) 96 if (from >= mtd->size)
87 return -EINVAL; 97 return -EINVAL;
88 if (from + ops->len > mtd->size) 98 if (from + ops->len > mtd->size)
89 return -EINVAL; 99 return -EINVAL;
90 return part->master->read_oob(part->master, from + part->offset, ops); 100 res = part->master->read_oob(part->master, from + part->offset, ops);
101
102 if (unlikely(res)) {
103 if (res == -EUCLEAN)
104 mtd->ecc_stats.corrected++;
105 if (res == -EBADMSG)
106 mtd->ecc_stats.failed++;
107 }
108 return res;
91} 109}
92 110
93static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, 111static int part_read_user_prot_reg (struct mtd_info *mtd, loff_t from, size_t len,
@@ -246,12 +264,17 @@ static int part_block_isbad (struct mtd_info *mtd, loff_t ofs)
246static int part_block_markbad (struct mtd_info *mtd, loff_t ofs) 264static int part_block_markbad (struct mtd_info *mtd, loff_t ofs)
247{ 265{
248 struct mtd_part *part = PART(mtd); 266 struct mtd_part *part = PART(mtd);
267 int res;
268
249 if (!(mtd->flags & MTD_WRITEABLE)) 269 if (!(mtd->flags & MTD_WRITEABLE))
250 return -EROFS; 270 return -EROFS;
251 if (ofs >= mtd->size) 271 if (ofs >= mtd->size)
252 return -EINVAL; 272 return -EINVAL;
253 ofs += part->offset; 273 ofs += part->offset;
254 return part->master->block_markbad(part->master, ofs); 274 res = part->master->block_markbad(part->master, ofs);
275 if (!res)
276 mtd->ecc_stats.badblocks++;
277 return res;
255} 278}
256 279
257/* 280/*
@@ -436,6 +459,16 @@ int add_mtd_partitions(struct mtd_info *master,
436 } 459 }
437 460
438 slave->mtd.ecclayout = master->ecclayout; 461 slave->mtd.ecclayout = master->ecclayout;
462 if (master->block_isbad) {
463 uint32_t offs = 0;
464
465 while(offs < slave->mtd.size) {
466 if (master->block_isbad(master,
467 offs + slave->offset))
468 slave->mtd.ecc_stats.badblocks++;
469 offs += slave->mtd.erasesize;
470 }
471 }
439 472
440 if(parts[i].mtdp) 473 if(parts[i].mtdp)
441 { /* store the object pointer (caller may or may not register it */ 474 { /* store the object pointer (caller may or may not register it */