Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 116001
b: refs/heads/master
c: 1077be5
h: refs/heads/master
i:
  115999: 2bd8a85
v: v3
  • Loading branch information
frans authored and David Woodhouse committed Aug 20, 2008
1 parent 5fdd062 commit ece0e4b
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 75caf6b5acc6b895df9bdd36db631220e1096e9f
refs/heads/master: 1077be58ad7baadd86e47e8b4f6209fa5b6364a5
44 changes: 33 additions & 11 deletions trunk/drivers/mtd/nand/nand_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mtd/nand_ecc.h>
#include <asm/byteorder.h>
#else
#include <stdint.h>
struct mtd_info;
Expand All @@ -51,6 +52,9 @@ struct mtd_info;
#define MODULE_LICENSE(x) /* x */
#define MODULE_AUTHOR(x) /* x */
#define MODULE_DESCRIPTION(x) /* x */

#define printk printf
#define KERN_ERR ""
#endif

/*
Expand Down Expand Up @@ -273,24 +277,38 @@ int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
/*
* we also need to calculate the row parity for rp0..rp3
* This is present in par, because par is now
* rp3 rp3 rp2 rp2
* rp3 rp3 rp2 rp2 in little endian and
* rp2 rp2 rp3 rp3 in big endian
* as well as
* rp1 rp0 rp1 rp0
* rp1 rp0 rp1 rp0 in little endian and
* rp0 rp1 rp0 rp1 in big endian
* First calculate rp2 and rp3
* (and yes: rp2 = (par ^ rp3) & 0xff; but doing that did not
* give a performance improvement)
*/
#ifdef __BIG_ENDIAN
rp2 = (par >> 16);
rp2 ^= (rp2 >> 8);
rp2 &= 0xff;
rp3 = par & 0xffff;
rp3 ^= (rp3 >> 8);
rp3 &= 0xff;
#else
rp3 = (par >> 16);
rp3 ^= (rp3 >> 8);
rp3 &= 0xff;
rp2 = par & 0xffff;
rp2 ^= (rp2 >> 8);
rp2 &= 0xff;
#endif

/* reduce par to 16 bits then calculate rp1 and rp0 */
par ^= (par >> 16);
#ifdef __BIG_ENDIAN
rp0 = (par >> 8) & 0xff;
rp1 = (par & 0xff);
#else
rp1 = (par >> 8) & 0xff;
rp0 = (par & 0xff);
#endif

/* finally reduce par to 8 bits */
par ^= (par >> 8);
Expand Down Expand Up @@ -381,7 +399,6 @@ EXPORT_SYMBOL(nand_calculate_ecc);
int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
int nr_bits;
unsigned char b0, b1, b2;
unsigned char byte_addr, bit_addr;

Expand All @@ -401,14 +418,15 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,

/* check if there are any bitfaults */

/* count nr of bits; use table lookup, faster than calculating it */
nr_bits = bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2];

/* repeated if statements are slightly more efficient than switch ... */
/* ordered in order of likelihood */
if (nr_bits == 0)

if ((b0 | b1 | b2) == 0)
return 0; /* no error */
if (nr_bits == 11) { /* correctable error */

if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
(((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
(((b2 ^ (b2 >> 1)) & 0x54) == 0x54)) { /* single bit error */
/*
* rp15/13/11/9/7/5/3/1 indicate which byte is the faulty byte
* cp 5/3/1 indicate the faulty bit.
Expand All @@ -430,9 +448,13 @@ int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
/* flip the bit */
buf[byte_addr] ^= (1 << bit_addr);
return 1;

}
if (nr_bits == 1)
/* count nr of bits; use table lookup, faster than calculating it */
if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
return 1; /* error in ecc data; no action needed */

printk(KERN_ERR "uncorrectable error : ");
return -1;
}
EXPORT_SYMBOL(nand_correct_data);
Expand Down

0 comments on commit ece0e4b

Please sign in to comment.