From: Troy Kisky <troy.kisky@boundarydevices.com>
To: frans <fransmeulenbroeks@gmail.com>
Cc: David Woodhouse <dwmw2@infradead.org>, linux-mtd@lists.infradead.org
Subject: Re: [RESUBMIT] [PATCH] [MTD] NAND nand_ecc.c: rewrite for improved performance
Date: Thu, 14 Aug 2008 12:10:40 -0700 [thread overview]
Message-ID: <48A48330.70105@boundarydevices.com> (raw)
In-Reply-To: <alpine.DEB.0.99.0808142007340.6572@frans-desktop>
frans wrote:
> Fixed the last remaining issues, made sure to diff with the very latest mtd
> git version.
>
> Attached is a complete rewrite of nand_ecc.c including documentation.
> This rewrite improves performance about 18 times on intel (D920),
> 7 times on MIPS and 5 times on ARM (NSLU2)
>
> Signed-off-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
This look very complex to me. How about something like this.
Note, I could make it much smaller if allowed to result in a different
ecc value than current implementation.
#ifdef CONFIG_MTD_NAND_ECC_SMC
#define LOW_ORDER_INDEX 0
#define HIGH_ORDER_INDEX 1
#else
#define LOW_ORDER_INDEX 1
#define HIGH_ORDER_INDEX 0
#endif
/**
* nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512 byte block
* @mtd: MTD block structure
* @dat: raw data
* @ecc_code: buffer for ECC
*/
int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
u_char *ecc_code)
{
uint32_t j = ((struct nand_chip *)mtd->priv)->ecc.size; /* 256 or 512 bytes/ecc */
uint32_t k=0;
uint32_t xor = 0;
uint32_t tecc = 0;
uint32_t ecc = 0;
uint32_t * p = (uint32_t *)dat;
uint32_t v;
//#define FORCE_ECC_ERROR
#ifdef FORCE_ECC_ERROR
uint32_t forceBitNum;
{
/* force single bit ecc error to test ecc correction code */
u_char* p = (u_char*)dat;
forceBitNum = p[0] | (p[1]<<8); /* 1st word of block determines which bit is made in error */
forceBitNum &= 0xfff;
if ((forceBitNum&0x800)==0) {
/* limit error to 1st 256 bytes */
p[forceBitNum>>3] ^= 1<<(forceBitNum&7);
printk(KERN_INFO "Forcing ecc error, byte:0x%x, bit:%i\n",forceBitNum>>3,forceBitNum&7);
}
}
#endif
do {
v = *p++;
xor ^= v;
v ^= (v>>16);
v ^= (v>>8);
v ^= (v>>4);
v ^= (v>>2);
v ^= (v>>1);
if (v&1) tecc ^= k;
k++;
j-=4;
} while (j);
__cpu_to_le64s(xor);
v = (xor>>16)^xor;
v ^= ((v>>8)&(0x00ff00ff&0x00ffffff));
v ^= ((v>>4)&(0x0f0f0f0f&0x000f0fff));
v ^= ((v>>2)&(0x33333333&0x0003033f));
v ^= ((v>>1)&(0x55555555&0x00010117));
/* now duplicate all bits */
if (tecc&(1<<6)) ecc ^= 3<<22;
if (tecc&(1<<5)) ecc ^= 3<<20;
if (tecc&(1<<4)) ecc ^= 3<<18;
if (tecc&(1<<3)) ecc ^= 3<<16;
if (tecc&(1<<2)) ecc ^= 3<<14;
if (tecc&(1<<1)) ecc ^= 3<<12;
if (tecc&(1<<0)) ecc ^= 3<<10;
if (v&(1<<16)) ecc ^= 3<<8;
if (v&(1<<8)) ecc ^= 3<<6;
if (v&(1<<4)) ecc ^= 3<<4;
if (v&(1<<2)) ecc ^= 3<<2;
if (v&(1<<1)) ecc ^= 3<<0;
if (v&(1<<0)) ecc ^= 0x555555; /* if parity is odd, low bits are opposite of high bits */
#ifdef FORCE_ECC_ERROR
if (forceBitNum&0x800) {
ecc ^= 1<<(forceBitNum&0xf);
printk(KERN_INFO "Forcing single bit error in ecc itself bit %i\n",forceBitNum&0xf);
}
#endif
if (((struct nand_chip *)mtd->priv)->ecc.size==256) ecc <<= 2;
ecc = ~ecc;
#ifdef VERIFY_NEW_ECC_ALG
{
uint32_t s;
nand_calculate_ecc_old(mtd,dat,ecc_code);
ecc &= 0xffffff;
s = (ecc_code[HIGH_ORDER_INDEX]<<16) | (ecc_code[LOW_ORDER_INDEX]<<8) | ecc_code[2];
if (s != ecc) {
printk(KERN_ERR "New algorithm is buggy!!!! s=%x, ecc=%x\n",s,ecc);
return 0;
}
}
#endif
/* Calculate final ECC code */
ecc_code[HIGH_ORDER_INDEX] = (u_char)(ecc>>16);
ecc_code[LOW_ORDER_INDEX] = (u_char)(ecc>>8);
ecc_code[2] = (u_char)ecc;
return 0;
}
next prev parent reply other threads:[~2008-08-14 19:10 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-07-31 8:35 [RESUBMIT] [PATCH] [MTD] NAND nand_ecc.c: rewrite for improved performance frans
2008-08-11 11:35 ` Frans Meulenbroeks
2008-08-11 16:30 ` David Woodhouse
[not found] ` <ac9c93b10808120153m7435424ci3e49a70d3599cc06@mail.gmail.com>
[not found] ` <1218535872.2977.133.camel@pmac.infradead.org>
2008-08-14 18:07 ` frans
2008-08-14 19:10 ` Troy Kisky [this message]
2008-08-15 8:41 ` Frans Meulenbroeks
2008-08-15 8:46 ` David Woodhouse
2008-08-15 9:23 ` Frans Meulenbroeks
2008-08-15 9:41 ` David Woodhouse
2008-08-15 10:04 ` Frans Meulenbroeks
2008-08-15 10:12 ` David Woodhouse
2008-08-15 18:56 ` Troy Kisky
2008-08-15 21:14 ` frans
2008-08-16 10:04 ` David Woodhouse
2008-08-17 21:09 ` Troy Kisky
2008-08-18 6:33 ` Frans Meulenbroeks
2008-08-18 17:20 ` Troy Kisky
2008-08-18 21:09 ` Frans Meulenbroeks
2008-08-18 21:29 ` Troy Kisky
2008-08-18 21:31 ` David Woodhouse
2008-08-18 22:14 ` Troy Kisky
2008-08-18 22:10 ` Troy Kisky
2008-08-19 6:00 ` Frans Meulenbroeks
2008-08-17 23:30 ` Troy Kisky
2008-08-18 6:40 ` Frans Meulenbroeks
2008-08-18 17:08 ` Troy Kisky
-- strict thread matches above, loose matches on Subject: below --
2008-07-29 17:58 Frans Meulenbroeks
2008-07-29 20:04 ` Ricard Wanderlof
2008-07-30 6:17 ` Artem Bityutskiy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48A48330.70105@boundarydevices.com \
--to=troy.kisky@boundarydevices.com \
--cc=dwmw2@infradead.org \
--cc=fransmeulenbroeks@gmail.com \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox