[PATCH] NAND: fix reading/writing OOB for syndrome

Thomas Gleixner tglx at linutronix.de
Tue Jun 13 11:34:55 EDT 2006


On Tue, 2006-06-13 at 19:01 +0400, Vitaly Wool wrote:
> +/**
> + * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
> + * 					 with syndromes
> + * @mtd:	mtd info structure
> + * @chip:	nand chip info structure
> + * @buf:	buffer to store read data
> + * @offs:	offset to start reading from
> + * @length:	length of the OOB data to read
> + * @page:	page number to read
> + */
> +static void nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
> +				   uint8_t *buf, int offs, int length,
> +				   int page)
> +{
> +	int portion = mtd->oobsize / chip->ecc.steps;
> +	uint8_t *bufpoi = buf;
> +	int i;
> +
> +	/*
> +	 * We presume here that the chip driver is capable of
> +	 * emulating NAND_CMD_READOOB properly
> +	 */

???? You want to read in the data area of the FLASH !

> +	for (i = 0; i < chip->ecc.steps; i++) {
> +		if (offs) {
> +			while (portion < offs) {
> +				offs -= portion;
> +				i++;

		if (offs >= portion) {
			offs -= portion;
			continue;
		}

> +		}
> +		chip->read_buf(mtd, bufpoi, portion - offs);
> +		bufpoi += portion - offs;
> +		offs = 0;
> +		chip->cmdfunc(mtd, NAND_CMD_READOOB, (i + 1) * portion, page);

		CMD_READOOB is simply wrong 

Also it ignores the prepad and postpad parts.



> +	}
> +}
> +
> +/**
> + * nand_write_oob_raw - [REPLACABLE] the most common OOB data write function
> + * @mtd:	mtd info structure
> + * @chip:	nand chip info structure
> + * @buf:	buffer where to write data from
> + * @offs:	offset to start writing from
> + * @length:	length of the OOB data to write
> + * @page:	page number to write
> + */
> +static void nand_write_oob_raw(struct mtd_info *mtd, struct nand_chip *chip,
> +			       const uint8_t *buf, int offs, int length,
> +			       int page)
> +{
> +	chip->write_buf(mtd, buf, length);
> +}
> +static void (*nand_write_oob_swecc) (struct mtd_info *mtd,
> +				     struct nand_chip *chip,
> +				     const uint8_t *buf, int offs, int length,
> +				     int page) = nand_write_oob_raw;
> +static void (*nand_write_oob_hwecc) (struct mtd_info *mtd,
> +				     struct nand_chip *chip,
> +				     const uint8_t *buf, int offs, int length,
> +				     int page) = nand_write_oob_raw;
> +
> +/**
> + * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
> + * 					  with syndrome
> + * @mtd:	mtd info structure
> + * @chip:	nand chip info structure
> + * @buf:	buffer where to write data from
> + * @offs:	offset to start writing from
> + * @length:	length of the OOB data to write
> + * @page:	page number to write
> + */
> +static void nand_write_oob_syndrome(struct mtd_info *mtd,
> +				    struct nand_chip *chip, const uint8_t *buf,
> +				    int offs, int length, int page)
> +{
> +	int portion = mtd->oobsize / chip->ecc.steps;
> +	int eccsize = chip->ecc.size;
> +	const uint8_t *bufpoi = buf;
> +	int i, len;
> +
> +	for (i = 0; i < chip->ecc.steps; i++) {
> +		if (offs < portion) {
> +			int status;
> +			chip->cmdfunc(mtd, NAND_CMD_SEQIN,
> +				      eccsize + i * (eccsize + portion) + offs,
> +				      page);
> +			len = min_t(int, length, portion - offs);
> +			chip->write_buf(mtd, bufpoi, len);
> +			bufpoi += len;
> +			length -= len;
> +			offs = 0;
> +
> +			if (i < chip->ecc.steps - 1) {
> +				chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
> +				status = chip->waitfunc(mtd, chip, FL_WRITING);
> +
> +				/* See if device thinks it succeeded */
> +				if (status & NAND_STATUS_FAIL)
> +					DEBUG(MTD_DEBUG_LEVEL0, "%s: "
> +					      "Failed write, page 0x%08x\n",
> +					      __FUNCTION__, page);
> +			}
> +		} else
> +			offs -= portion;
> +	}
> +}
> +

What about the prepad and postpad parts ?

> +/**
>   * nand_do_read_oob - [Intern] NAND read out-of-band
>   * @mtd:	MTD device structure
>   * @from:	offset to read from
> @@ -1127,7 +1254,7 @@ static int nand_do_read_oob(struct mtd_i
>  			sndcmd = 0;
>  		}
>  
> -		chip->read_buf(mtd, bufpoi, bytes);
> +		chip->ecc.read_oob(mtd, chip, bufpoi, col, bytes, page);
>  
>  		if (unlikely(!direct))
>  			buf = nand_transfer_oob(chip, buf, ops);

The direct part should go away and done inside the read functions.

> @@ -1598,13 +1726,15 @@ static int nand_do_write_oob(struct mtd_
>  		nand_fill_oob(chip, ops->oobbuf, ops);
>  		chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize,
>  			      page & chip->pagemask);

You put it unconditionally into oob area !!!

> -		chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
> +		chip->ecc.write_oob(mtd, chip, chip->oob_poi, 0, mtd->oobsize,
> +				    page & chip->pagemask);
>  		memset(chip->oob_poi, 0xff, mtd->oobsize);
>  	} else {
>  		chip->cmdfunc(mtd, NAND_CMD_SEQIN,
>  			      mtd->writesize + ops->ooboffs,
>  			      page & chip->pagemask);

Same here !

> -		chip->write_buf(mtd, ops->oobbuf, ops->len);
> +		chip->ecc.write_oob(mtd, chip, ops->oobbuf, ops->ooboffs,
> +				    ops->len, page & chip->pagemask);
>  	}
>  

	tglx
	






More information about the linux-mtd mailing list