From 6ff77ad30cda0719947c96190dcdf1f8e67c63f2 Mon Sep 17 00:00:00 2001 From: Michal Koziel Date: Tue, 28 Jun 2016 16:22:05 +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 c8c77f668e5d9..078e8b10e3a59 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -810,6 +810,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; int ret; + size_t retlen_l = 0; dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); @@ -824,10 +825,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) { @@ -842,11 +845,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 1ce57c389cf407226dcf33a8ec2f6af6c7809dee Mon Sep 17 00:00:00 2001 From: Michal Koziel Date: Wed, 29 Jun 2016 14:46:29 +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 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 078e8b10e3a59..3a714e6fd9708 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -826,11 +826,16 @@ 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) { @@ -846,6 +851,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; } }