All of lore.kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.