public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
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;
}

  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