diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2005-06-14 11:39:57 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-06-29 08:24:41 -0400 |
commit | c9e0536523f5191395d62f6c84d007e6ffd38d33 (patch) | |
tree | a20381bcaac4f7b02afd7bdc36f76a631906f5ce /drivers/mtd/nand/nand_bbt.c | |
parent | bfabb98688e7089381baa0974f7ff6786ce2a2d0 (diff) |
[MTD] NAND: Fix broken bad block table scan
Make the bad block table search functional again
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/nand/nand_bbt.c')
-rw-r--r-- | drivers/mtd/nand/nand_bbt.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index c85c69dec540..5ac2d2962220 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.31 2005/02/16 17:09:36 dedekind Exp $ | 9 | * $Id: nand_bbt.c,v 1.33 2005/06/14 15:47:56 gleixner 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 |
@@ -80,14 +80,14 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
80 | int i, end = 0; | 80 | int i, end = 0; |
81 | uint8_t *p = buf; | 81 | uint8_t *p = buf; |
82 | 82 | ||
83 | end = paglen + td->offs; | ||
83 | if (td->options & NAND_BBT_SCANEMPTY) { | 84 | if (td->options & NAND_BBT_SCANEMPTY) { |
84 | end = paglen + td->offs; | ||
85 | for (i = 0; i < end; i++) { | 85 | for (i = 0; i < end; i++) { |
86 | if (p[i] != 0xff) | 86 | if (p[i] != 0xff) |
87 | return -1; | 87 | return -1; |
88 | } | 88 | } |
89 | p += end; | ||
90 | } | 89 | } |
90 | p += end; | ||
91 | 91 | ||
92 | /* Compare the pattern */ | 92 | /* Compare the pattern */ |
93 | for (i = 0; i < td->len; i++) { | 93 | for (i = 0; i < td->len; i++) { |
@@ -106,6 +106,32 @@ static int check_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_des | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | /** | ||
110 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | ||
111 | * @buf: the buffer to search | ||
112 | * @len: the length of buffer to search | ||
113 | * @paglen: the pagelength | ||
114 | * @td: search pattern descriptor | ||
115 | * | ||
116 | * Check for a pattern at the given place. Used to search bad block | ||
117 | * tables and good / bad block identifiers. Same as check_pattern, but | ||
118 | * no optional empty check and the pattern is expected to start | ||
119 | * at offset 0. | ||
120 | * | ||
121 | */ | ||
122 | static int check_short_pattern (uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) | ||
123 | { | ||
124 | int i; | ||
125 | uint8_t *p = buf; | ||
126 | |||
127 | /* Compare the pattern */ | ||
128 | for (i = 0; i < td->len; i++) { | ||
129 | if (p[i] != td->pattern[i]) | ||
130 | return -1; | ||
131 | } | ||
132 | return 0; | ||
133 | } | ||
134 | |||
109 | /** | 135 | /** |
110 | * read_bbt - [GENERIC] Read the bad block table starting from page | 136 | * read_bbt - [GENERIC] Read the bad block table starting from page |
111 | * @mtd: MTD device structure | 137 | * @mtd: MTD device structure |
@@ -316,18 +342,25 @@ static int create_bbt (struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr | |||
316 | readlen, &retlen, &buf[0]); | 342 | readlen, &retlen, &buf[0]); |
317 | if (ret) | 343 | if (ret) |
318 | return ret; | 344 | return ret; |
319 | } | 345 | |
320 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { | 346 | if (check_short_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { |
321 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | 347 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); |
322 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | 348 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", |
323 | i >> 1, (unsigned int) from); | 349 | i >> 1, (unsigned int) from); |
324 | break; | 350 | break; |
351 | } | ||
352 | } else { | ||
353 | if (check_pattern (&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { | ||
354 | this->bbt[i >> 3] |= 0x03 << (i & 0x6); | ||
355 | printk (KERN_WARNING "Bad eraseblock %d at 0x%08x\n", | ||
356 | i >> 1, (unsigned int) from); | ||
357 | break; | ||
358 | } | ||
325 | } | 359 | } |
326 | } | 360 | } |
327 | i += 2; | 361 | i += 2; |
328 | from += (1 << this->bbt_erase_shift); | 362 | from += (1 << this->bbt_erase_shift); |
329 | } | 363 | } |
330 | |||
331 | return 0; | 364 | return 0; |
332 | } | 365 | } |
333 | 366 | ||