[PATCH v6 03/15] mtd: nand: add a nand.h file to expose basic NAND stuff

Boris Brezillon boris.brezillon at free-electrons.com
Mon May 29 13:14:17 PDT 2017


On Wed, 24 May 2017 15:06:59 +0800
Peter Pan <peterpandong at micron.com> wrote:

> +
> +/**
> + * nand_check_oob_ops - check mtd_oob_ops is valid or not
> + * @nand: NAND device
> + * @start: start address to check
> + * @ops: oob operation description struct
> + *
> + * Returns 0 for valid ops and -EINVAL for invalid ops.
> + */
> +static inline int nand_check_oob_ops(struct nand_device *nand, loff_t start,
> +				     struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
> +				mtd->oobavail : mtd->oobsize;
> +	int pages = nand_len_to_pages(nand, nand_size(nand));
> +	int max_pages = pages - nand_offs_to_page(nand, start);
> +	int max_ooblen = max_pages * oobbytes_per_page;
> +
> +	if ((!!ops->datbuf != !!ops->len) ||
> +	    (!!ops->oobbuf != !!ops->ooblen))
> +		return -EINVAL;

Can we make the test more obvious:

	if ((ops->len && !ops->datbuf) ||
	    (ops->ooblen && !ops->oobbuf))

> +	if (ops->ooboffs >= oobbytes_per_page)
> +		return -EINVAL;

Please add blank lines after each if () block.

> +	if (ops->ooboffs + ops->ooblen > max_ooblen)
> +		return -EINVAL;

I thought we agreed that these tests should go in mtdcore.c. That's
clearly generic and could benefit to everyone, not only NAND users.

> +
> +	return 0;
> +}
> +
> +/**
> + * nand_oob_ops_across_page - check oob operation across page or not

You mean cross, not across, right?

> + * @nand: NAND device
> + * @ops: oob operation description struct
> + *
> + * Returns true if oob operation across page and false when not.
> + */
> +static inline bool nand_oob_ops_across_page(struct nand_device *nand,
> +					    struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	int oobbytes_per_page = ops->mode == MTD_OPS_AUTO_OOB ?
> +				mtd->oobavail : mtd->oobsize;
> +
> +	return (ops->ooboffs + ops->ooblen) > oobbytes_per_page;

Since mtd_oob_ops is actually not only about oob data, I guess we
should check in-band data as well. This implies passing the start
offset in argument of course.

	if (ops->ooboffs + ops->ooblen > oobbytes_per_page ||
	    ops->len > mtd->writesize ||
	    mtd_mod_by_ws(start_offs, mtd) + ops->len > mtd->writesize)
		return true;

	return false;

> +}

Again, this is completely generic, so probably something we should put
in mtd.h/mtdcore.c.

> +
> +/**
> + * nand_check_erase_ops - check erase operation is valid or not
> + * @nand: NAND device
> + * @einfo: erase instruction
> + *
> + * Returns 0 for valid erase operation and -EINVAL for invalid.
> + */
> +static inline int nand_check_erase_ops(struct nand_device *nand,
> +				       struct erase_info *einfo)
> +{
> +	/* check address align on block boundary */
> +	if (einfo->addr & (nand_eraseblock_size(nand) - 1))
> +		return -EINVAL;
> +	/* check lendth align on block boundary */
> +	if (einfo->len & (nand_eraseblock_size(nand) - 1))
> +		return -EINVAL;
> +	/* Do not allow erase past end of device */
> +	if ((einfo->addr + einfo->len) > nand_size(nand))
> +		return -EINVAL;
> +
> +	return 0;
> +}

And here again, this should be moved to mtdcore.c/mtd.h. Actually, the
last check you're doing here is already done in mtd_erase() [1].

[1]http://elixir.free-electrons.com/linux/latest/source/drivers/mtd/mtdcore.c#L958




More information about the linux-mtd mailing list