From 3dc850fd9250ee6afcca6ddaa6928670b3db3a58 Mon Sep 17 00:00:00 2001 From: Michal Koziel Date: Tue, 28 Jun 2016 16:25:42 +0200 Subject: [PATCH 1/2] Fixed bug in chunk writing in spi_nor_write spi_nor_write returned bytes written (retlen) from the last call to nor->write If nor->write was called several times the returned retlen would be smaller than expected by jffs2, even if writing was successful. The following message would appear: jffs2: Write of 183 bytes at 0x003e02ac failed. returned 0, retlen 167 --- drivers/mtd/spi-nor/spi-nor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f235d46fd4869..c645d92de95a9 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1113,6 +1113,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, { struct spi_nor *nor = mtd_to_spi_nor(mtd); u32 page_offset, page_size, i; + size_t retlen_l = 0; int ret; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); @@ -1128,10 +1129,12 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, /* do all the bytes fit onto one page? */ if (page_offset + len <= nor->page_size) { nor->write(nor, to, len, retlen, buf); + retlen_l += *retlen; } else { /* the size of data remaining on the first page */ page_size = nor->page_size - page_offset; nor->write(nor, to, page_size, retlen, buf); + retlen_l += *retlen; /* write everything in nor->page_size chunks */ for (i = page_size; i < len; i += page_size) { @@ -1146,11 +1149,13 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, write_enable(nor); nor->write(nor, to + i, page_size, retlen, buf + i); + retlen_l += *retlen; } } ret = spi_nor_wait_till_ready(nor); write_err: + *retlen = retlen_l; spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return ret; } From f2aa0f25ea994ad273f72c4ea2abd2dc1a223765 Mon Sep 17 00:00:00 2001 From: Michal Koziel Date: Wed, 29 Jun 2016 14:44:43 +0200 Subject: [PATCH 2/2] Fixed bug in chunk writing in spi_nor_write PART #2 /* some drivers implementing nor->write might not reset *retlen every time nor-write is called, thus accumulating bytes written. We can zero *retlen here since we are counting bytes written in retlen_l*/ --- drivers/mtd/spi-nor/spi-nor.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c645d92de95a9..7e92fc4a00c23 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -1130,11 +1130,15 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, if (page_offset + len <= nor->page_size) { nor->write(nor, to, len, retlen, buf); retlen_l += *retlen; + /* some drivers implementing nor->write might not reset *retlen every time nor-write is called, + thus accumulating bytes written. We can zero *retlen here since we are counting bytes written in retlen_l*/ + *retlen = 0; } else { /* the size of data remaining on the first page */ page_size = nor->page_size - page_offset; nor->write(nor, to, page_size, retlen, buf); retlen_l += *retlen; + *retlen = 0; /* write everything in nor->page_size chunks */ for (i = page_size; i < len; i += page_size) { @@ -1150,6 +1154,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, nor->write(nor, to + i, page_size, retlen, buf + i); retlen_l += *retlen; + *retlen = 0; } }