All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Norris <computersforpeace@gmail.com>
To: Michal Suchanek <hramrach@gmail.com>
Cc: "Hou Zhiqiang" <B48286@freescale.com>,
	shijie.huang@intel.com, "David Woodhouse" <dwmw2@infradead.org>,
	"Han Xu" <han.xu@freescale.com>,
	"Rafał Miłecki" <zajec5@gmail.com>,
	"Huang Shijie" <b32955@freescale.com>,
	"Ben Hutchings" <ben@decadent.org.uk>,
	"Marek Vasut" <marex@denx.de>, "Gabor Juhos" <juhosg@openwrt.org>,
	"Bean Huo 霍斌斌," <beanhuo@micron.com>,
	linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v4 6/7] mtd: spi-nor: simplify write loop
Date: Thu, 19 Nov 2015 15:18:57 -0800	[thread overview]
Message-ID: <20151119231857.GM64635@google.com> (raw)
In-Reply-To: <e1251eea4ec9cc8c72d54300f3396919a3afe4b1.1439543572.git.hramrach@gmail.com>

Hi Michal,

Sorry this has sat so long...

On Fri, Aug 14, 2015 at 09:23:08AM -0000, Michal Suchanek wrote:
> The spi-nor write loop assumes that what is passed to the hardware
> driver write() is what gets written.
> 
> When write() writes less than page size at once data is dropped on the
> floor. Check the amount of data writen.

Have you seen write() return less than the page size? I know you've
struggled with a SPI driver that can't do "very" (for some definition of
very) long transfers, due to unknown bugs, but I thought that "very" was
much larger than the page size.

> This also means that write can start mid-page any time so there is
> no special case for first page.

I think we'd have some problems if we start seeing hardware that can't
write ~256 bytes at a time. If nothing else, this can be a problem
because some SPI NOR flash are known to have inferior reliability if you
regularly write in small chunks. I believe this is because they actually
use some kind of internal ECC.

So, if you're just guarding against a theoretical behavior, perhaps it's
best if this is done with some kind of assertion, as I'd rather not
encourage non-aligned writes if possible. I notice you used BUG_ON() in
another patch, but I'd suggest maybe something less harsh, like WARN()
or WARN_ONCE().

Brian

> 
> Signed-off-by: Michal Suchanek <hramrach@gmail.com>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 48 ++++++++++++++-----------------------------
>  1 file changed, 15 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 837e3df..e0ae9cf 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -836,7 +836,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
>  	size_t *retlen, const u_char *buf)
>  {
>  	struct spi_nor *nor = mtd_to_spi_nor(mtd);
> -	u32 page_offset, page_size, i;
> +	size_t page_offset, page_remain, i;
>  	int ret;
>  
>  	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
> @@ -845,45 +845,27 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
>  	if (ret)
>  		return ret;
>  
> -	write_enable(nor);
> -
> -	page_offset = to & (nor->page_size - 1);
> +	for (i = 0; i < len; ) {
> +		int written;
>  
> -	/* do all the bytes fit onto one page? */
> -	if (page_offset + len <= nor->page_size) {
> -		ret = nor->write(nor, to, len, buf);
> -		if (ret < 0)
> -			goto write_err;
> -		*retlen += ret;
> -	} else {
> +		page_offset = to & (nor->page_size - 1);
>  		/* the size of data remaining on the first page */
> -		page_size = nor->page_size - page_offset;
> -		ret = nor->write(nor, to, page_size, buf);
> +		page_remain = min_t(size_t,
> +				    nor->page_size - page_offset, len - i);
> +
> +		write_enable(nor);
> +		ret = nor->write(nor, to + i, page_remain, buf + i);
>  		if (ret < 0)
>  			goto write_err;
> -		*retlen += ret;
> -
> -		/* write everything in nor->page_size chunks */
> -		for (i = ret; i < len; ) {
> -			page_size = len - i;
> -			if (page_size > nor->page_size)
> -				page_size = nor->page_size;
> -
> -			ret = spi_nor_wait_till_ready(nor);
> -			if (ret)
> -				goto write_err;
> +		written = ret;
>  
> -			write_enable(nor);
> -
> -			ret = nor->write(nor, to + i, page_size, buf + i);
> -			if (ret < 0)
> -				goto write_err;
> -			*retlen += ret;
> -			i += ret;
> -		}
> +		ret = spi_nor_wait_till_ready(nor);
> +		if (ret)
> +			goto write_err;
> +		*retlen += written;
> +		i += written;
>  	}
>  
> -	ret = spi_nor_wait_till_ready(nor);
>  write_err:
>  	spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
>  	return ret;
> -- 
> 2.1.4
> 

  reply	other threads:[~2015-11-19 23:19 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-14  9:23 [PATCH v4 0/7] Add spi-nor SPI transfer error handling Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 3/7] mtd: fsl-quadspi: return amount of data read/written or error Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 1/7] mtd: spi-nor: change return value of read/write Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 2/7] mtd: m25p80: return amount of data transferred or error in read/write Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 4/7] mtd: spi-nor: check return value from read/write Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 6/7] mtd: spi-nor: simplify write loop Michal Suchanek
2015-11-19 23:18   ` Brian Norris [this message]
2015-11-20 18:59     ` Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 5/7] mtd: spi-nor: stop passing around retlen Michal Suchanek
2015-08-14  9:23 ` [PATCH v4 7/7] mtd: spi-nor: add read loop Michal Suchanek
2015-08-14 10:02   ` Andrew Murray
2015-08-14 10:08     ` Michal Suchanek
2015-11-05  3:39       ` Hou Zhiqiang
2015-11-05  3:39         ` Hou Zhiqiang
2015-11-20 19:18         ` Michal Suchanek
2016-01-12  6:35           ` Zhiqiang Hou
2015-11-19 23:39   ` Brian Norris
2015-11-20  6:26     ` Heiner Kallweit
2015-08-15  1:51 ` [PATCH v4 0/7] Add spi-nor SPI transfer error handling Bean Huo 霍斌斌 (beanhuo)
2015-08-15  1:51   ` Bean Huo 霍斌斌 (beanhuo)
2015-08-16 10:20   ` Michal Suchanek
2015-11-19 23:43 ` Brian Norris

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=20151119231857.GM64635@google.com \
    --to=computersforpeace@gmail.com \
    --cc=B48286@freescale.com \
    --cc=b32955@freescale.com \
    --cc=beanhuo@micron.com \
    --cc=ben@decadent.org.uk \
    --cc=dwmw2@infradead.org \
    --cc=han.xu@freescale.com \
    --cc=hramrach@gmail.com \
    --cc=juhosg@openwrt.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=marex@denx.de \
    --cc=shijie.huang@intel.com \
    --cc=zajec5@gmail.com \
    /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.