aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorArtem B. Bityuckiy <dedekind@infradead.org>2005-02-11 05:14:15 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 06:32:18 -0400
commiteeada24da8bd23fcf6acd2729be054ea99b301bb (patch)
treec5d3cdffbfc11ec2ee82d64aef4177e92dfdffc7 /drivers/mtd/nand
parent41ce921440bd14d9b69b19fbf47d9278582739fe (diff)
[MTD] NAND: Read only OOB bytes during bad block scan
When scanning NAND for bad blocks, don't read the whole page, read only needed OOB bytes instead. Also check the return code of the nand_read_raw() function. Correctly free the this->bbt array in case of failure. Tested with Large page NAND. Fix debugging message. Signed-off-by: Artem B. Bityuckiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/nand_bbt.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 9a1949751c1f..5ff6eba8bec6 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -6,7 +6,7 @@
6 * 6 *
7 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) 7 * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de)
8 * 8 *
9 * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $ 9 * $Id: nand_bbt.c,v 1.30 2005/02/11 10:14:12 dedekind Exp $
10 * 10 *
11 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as 12 * it under the terms of the GNU General Public License version 2 as
@@ -252,10 +252,10 @@ static int read_abs_bbts (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_de
252 * Create a bad block table by scanning the device 252 * Create a bad block table by scanning the device
253 * for the given good/bad block identify pattern 253 * for the given good/bad block identify pattern
254 */ 254 */
255static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) 255static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip)
256{ 256{
257 struct nand_chip *this = mtd->priv; 257 struct nand_chip *this = mtd->priv;
258 int i, j, numblocks, len, scanlen; 258 int i, j, numblocks, len, scanlen, pagelen;
259 int startblock; 259 int startblock;
260 loff_t from; 260 loff_t from;
261 size_t readlen, ooblen; 261 size_t readlen, ooblen;
@@ -270,9 +270,18 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
270 else 270 else
271 len = 1; 271 len = 1;
272 } 272 }
273 scanlen = mtd->oobblock + mtd->oobsize; 273
274 readlen = len * mtd->oobblock; 274 if (bd->options == 0) {
275 ooblen = len * mtd->oobsize; 275 /* Memory-based BBT. We may read only needed bytes from the OOB area to
276 * test if block is bad, no need to read the whole page content. */
277 scanlen = ooblen = pagelen = 0;
278 readlen = bd->len;
279 } else {
280 scanlen = mtd->oobblock + mtd->oobsize;
281 readlen = len * mtd->oobblock;
282 ooblen = len * mtd->oobsize;
283 pagelen = mtd->oobblock;
284 }
276 285
277 if (chip == -1) { 286 if (chip == -1) {
278 /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it 287 /* Note that numblocks is 2 * (real numblocks) here, see i+=2 below as it
@@ -284,7 +293,7 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
284 if (chip >= this->numchips) { 293 if (chip >= this->numchips) {
285 printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n", 294 printk (KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
286 chip + 1, this->numchips); 295 chip + 1, this->numchips);
287 return; 296 return -EINVAL;
288 } 297 }
289 numblocks = this->chipsize >> (this->bbt_erase_shift - 1); 298 numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
290 startblock = chip * numblocks; 299 startblock = chip * numblocks;
@@ -293,9 +302,18 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
293 } 302 }
294 303
295 for (i = startblock; i < numblocks;) { 304 for (i = startblock; i < numblocks;) {
296 nand_read_raw (mtd, buf, from, readlen, ooblen); 305 int ret;
306
307 if (bd->options == 0) {
308 size_t retlen;
309 if ((ret = mtd->read_oob(mtd, from + bd->offs, bd->len, &retlen, &buf[bd->offs])))
310 return ret;
311 } else {
312 if ((ret = nand_read_raw (mtd, buf, from, readlen, ooblen)))
313 return ret;
314 }
297 for (j = 0; j < len; j++) { 315 for (j = 0; j < len; j++) {
298 if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { 316 if (check_pattern (&buf[j * scanlen], scanlen, pagelen, bd)) {
299 this->bbt[i >> 3] |= 0x03 << (i & 0x6); 317 this->bbt[i >> 3] |= 0x03 << (i & 0x6);
300 printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", 318 printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
301 i >> 1, (unsigned int) from); 319 i >> 1, (unsigned int) from);
@@ -305,6 +323,7 @@ static void create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_desc
305 i += 2; 323 i += 2;
306 from += (1 << this->bbt_erase_shift); 324 from += (1 << this->bbt_erase_shift);
307 } 325 }
326 return 0;
308} 327}
309 328
310/** 329/**
@@ -595,8 +614,7 @@ static int nand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
595 614
596 /* Ensure that we only scan for the pattern and nothing else */ 615 /* Ensure that we only scan for the pattern and nothing else */
597 bd->options = 0; 616 bd->options = 0;
598 create_bbt (mtd, this->data_buf, bd, -1); 617 return create_bbt (mtd, this->data_buf, bd, -1);
599 return 0;
600} 618}
601 619
602/** 620/**
@@ -808,8 +826,14 @@ int nand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
808 /* If no primary table decriptor is given, scan the device 826 /* If no primary table decriptor is given, scan the device
809 * to build a memory based bad block table 827 * to build a memory based bad block table
810 */ 828 */
811 if (!td) 829 if (!td) {
812 return nand_memory_bbt(mtd, bd); 830 if ((res = nand_memory_bbt(mtd, bd))) {
831 printk (KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
832 kfree (this->bbt);
833 this->bbt = NULL;
834 }
835 return res;
836 }
813 837
814 /* Allocate a temporary buffer for one eraseblock incl. oob */ 838 /* Allocate a temporary buffer for one eraseblock incl. oob */
815 len = (1 << this->bbt_erase_shift); 839 len = (1 << this->bbt_erase_shift);
@@ -1042,7 +1066,7 @@ int nand_isbad_bbt (struct mtd_info *mtd, loff_t offs, int allowbbt)
1042 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03; 1066 res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
1043 1067
1044 DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", 1068 DEBUG (MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
1045 (unsigned int)offs, res, block >> 1); 1069 (unsigned int)offs, block >> 1, res);
1046 1070
1047 switch ((int)res) { 1071 switch ((int)res) {
1048 case 0x00: return 0; 1072 case 0x00: return 0;