diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c8c77f668e5d9..3a714e6fd9708 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,17 @@ 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; + /* 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) { @@ -842,11 +850,14 @@ 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; + *retlen = 0; } } ret = spi_nor_wait_till_ready(nor); write_err: + *retlen = retlen_l; spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); return ret; }