diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index f235d46fd4869..7e92fc4a00c23 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,16 @@ 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) { @@ -1146,11 +1153,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; }