[RFC/PATCH 3/3] NAND multiple plane feature

Jörn Engel joern at logfs.org
Tue Jun 3 14:03:12 EDT 2008


On Wed, 28 May 2008 14:42:48 +0100, Alexey Korolev wrote:
>
> +static int nand_read_operations(struct mtd_info *mtd, struct nand_chip *chip,
> +				      const uint8_t *buf, loff_t offt, int len, int sndcmd, int raw)
> +{
> +	int i = 0;
> +	int ret, phys_page;
> +	int page = (int)(offt >> chip->page_shift) & chip->pagemask;
> +	int block_mask = (1 << (chip->erase_shift - chip->page_shift)) - 1;
> +	int col, bytes, start_block, page_num;
> +	uint8_t *datbuf, *oobbuf;
> +
> +	/* starting erase block at first plane */
> +	start_block = (page & ~block_mask) * chip->numplanes;
> +	page_num = page & block_mask;
> +	while (i < chip->numplanes) {
> +		datbuf = (uint8_t *)(buf + chip->page_phys_size * i);
> +		oobbuf = chip->oob_poi + chip->oob_phys_size * i;
> +		col = (int)(offt & (mtd->writesize - 1));

Does the explicit cast make any difference?

> +		/* calculate column for current plane */
> +		col = (int)(col & (chip->page_phys_size - 1));
> +		bytes = min(chip->page_phys_size - col, len);
> +
> +		phys_page = start_block + page_num + (block_mask + 1) * i;
> +		if (likely(sndcmd)) {
> +			chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, phys_page);
> +			if (chip->numplanes == 1)
> +				sndcmd = 0;
> +		}
> +		/* Now read the page into the buffer */
> +		if (unlikely(raw))
> +			ret = chip->ecc.read_page_raw(mtd, chip, datbuf, oobbuf);
> +		else
> +			ret = chip->ecc.read_page(mtd, chip, datbuf, oobbuf);
> +
> +		offt += bytes;
> +		len -= bytes;
> +		i++;

Looks like this could be a standard for loop as well.

And I am a bit surprised that you don't break out of the loop if bytes
ever becomes zero.  Is there a reason or did you just forget?

> +
> +		if (ret)
> +			break;
> +
> +		if (!(chip->options & NAND_NO_READRDY)) {
> +			if (!chip->dev_ready)
> +				udelay(chip->chip_delay);
> +			else
> +				nand_wait_ready(mtd);
> +			}

Wrong indentation.

> -			if (likely(sndcmd)) {
> -				chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
> -				sndcmd = 0;
> -			}
> -
> -			/* Now read the page into the buffer */
> -			if (unlikely(ops->mode == MTD_OOB_RAW))
> -				ret = chip->ecc.read_page_raw(mtd, chip, bufpoi);
> -			else
> -				ret = chip->ecc.read_page(mtd, chip, bufpoi);
> -			if (ret < 0)
> -				break;
> +			nand_read_operations(mtd, chip, bufpoi, from, bytes, sndcmd, (ops->mode == MTD_OOB_RAW));

I like this part.  Actually making our monster-functions shorter is
always a good thing.

> -					int toread = min(oobreadlen,
> -						chip->ecc.layout->oobavail);
> +					int toread = min(oobreadlen, chip->ecc.layout->oobavail);

Please don't reformat the code.  Or if you do, send that as a seperate
patch, either the first or the last in the series.  Makes the review a
lot easier if I don't have to double-check every time. :)

>  					if (toread) {
> -						oob = nand_transfer_oob(chip,
> -							oob, ops, toread);
> +						oob = nand_transfer_oob(chip, oob, ops, toread);
>  						oobreadlen -= toread;
>  					}
>  				} else
> -					buf = nand_transfer_oob(chip,
> -						buf, ops, mtd->oobsize);
> +					buf = nand_transfer_oob(chip, buf, ops, mtd->oobsize);

Same here.  And dito for the newline-removals somewhere above.

> -static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
> +static int nand_write_operations(struct mtd_info *mtd, struct nand_chip *chip,
>  			   const uint8_t *buf, int page, int cached, int raw)
>  {
> +	int i = 0;
>  	int status;
> +	int block_mask = (1 << (chip->erase_shift - chip->page_shift)) - 1;
> +	int start_block = (page & ~block_mask) * chip->numplanes;
> +	int page_num = page & block_mask;
> +
> +	/* calculate physycal page at first plane */
> +	while (i < chip->numplanes) {
> +		page = start_block + page_num + (block_mask + 1) * i;
> +		chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
> +
> +		if (unlikely(raw))
> +			chip->ecc.write_page_raw(mtd, chip, buf + chip->page_phys_size * i,
> +									chip->oob_poi + chip->oob_phys_size * i);
> +		else
> +			chip->ecc.write_page(mtd, chip, buf + chip->page_phys_size * i,
> +									chip->oob_poi + chip->oob_phys_size * i);
> +		i++;

Even here I'd prefer a for loop and use "i - 1" in the condition below.

> +		if (i < chip->numplanes) {
> +			chip->cmdfunc(mtd, NAND_CMD_PAGEPROG_MP, -1, -1);
> +			if (!chip->dev_ready)
> +				udelay(chip->chip_delay);
> +			else
> +				nand_wait_ready(mtd);

This occurs for the second time.  And each time it was new code added by
you.  Looks like you should move it into some helper function, along
with a few lines of explanations why it is needed.

Jörn

-- 
There are three principal ways to lose money: wine, women, and engineers.
While the first two are more pleasant, the third is by far the more certain.
-- Baron Rothschild



More information about the linux-mtd mailing list