8eb957db5dc7deb0c794820b968947ef739c16b6
[openwrt/openwrt.git] / target / linux / layerscape / patches-4.4 / 1095-mtd-spi-nor-simplify-write-loop.patch
1 From 93b40e12f7e580a41c4aee5597579cc539fd8544 Mon Sep 17 00:00:00 2001
2 From: Michal Suchanek <hramrach@gmail.com>
3 Date: Wed, 2 Dec 2015 10:38:20 +0000
4 Subject: [PATCH 095/113] mtd: spi-nor: simplify write loop
5
6 The spi-nor write loop assumes that what is passed to the hardware
7 driver write() is what gets written.
8
9 When write() writes less than page size at once data is dropped on the
10 floor. Check the amount of data writen and exit if it does not match
11 requested amount.
12
13 Signed-off-by: Michal Suchanek <hramrach@gmail.com>
14 Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou@freescale.com>
15 ---
16 drivers/mtd/spi-nor/spi-nor.c | 58 ++++++++++++++++++-----------------------
17 1 file changed, 25 insertions(+), 33 deletions(-)
18
19 --- a/drivers/mtd/spi-nor/spi-nor.c
20 +++ b/drivers/mtd/spi-nor/spi-nor.c
21 @@ -1017,8 +1017,8 @@ static int spi_nor_write(struct mtd_info
22 size_t *retlen, const u_char *buf)
23 {
24 struct spi_nor *nor = mtd_to_spi_nor(mtd);
25 - u32 page_offset, page_size, i;
26 - int ret;
27 + size_t page_offset, page_remain, i;
28 + ssize_t ret;
29
30 dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
31
32 @@ -1026,45 +1026,37 @@ static int spi_nor_write(struct mtd_info
33 if (ret)
34 return ret;
35
36 - write_enable(nor);
37 + for (i = 0; i < len; ) {
38 + ssize_t written;
39
40 - page_offset = to & (nor->page_size - 1);
41 -
42 - /* do all the bytes fit onto one page? */
43 - if (page_offset + len <= nor->page_size) {
44 - ret = nor->write(nor, to, len, buf);
45 - if (ret < 0)
46 - goto write_err;
47 - *retlen += ret;
48 - } else {
49 + page_offset = to & (nor->page_size - 1);
50 + WARN_ONCE(page_offset,
51 + "Writing at offset %zu into a NOR page. Writing partial pages may decrease reliability and increase wear of NOR flash.",
52 + page_offset);
53 /* the size of data remaining on the first page */
54 - page_size = nor->page_size - page_offset;
55 - ret = nor->write(nor, to, page_size, buf);
56 + page_remain = min_t(size_t,
57 + nor->page_size - page_offset, len - i);
58 +
59 + write_enable(nor);
60 + ret = nor->write(nor, to + i, page_remain, buf + i);
61 if (ret < 0)
62 goto write_err;
63 - *retlen += ret;
64 + written = ret;
65
66 - /* write everything in nor->page_size chunks */
67 - for (i = ret; i < len; ) {
68 - page_size = len - i;
69 - if (page_size > nor->page_size)
70 - page_size = nor->page_size;
71 -
72 - ret = spi_nor_wait_till_ready(nor);
73 - if (ret)
74 - goto write_err;
75 -
76 - write_enable(nor);
77 -
78 - ret = nor->write(nor, to + i, page_size, buf + i);
79 - if (ret < 0)
80 - goto write_err;
81 - *retlen += ret;
82 - i += ret;
83 + ret = spi_nor_wait_till_ready(nor);
84 + if (ret)
85 + goto write_err;
86 + *retlen += written;
87 + i += written;
88 + if (written != page_remain) {
89 + dev_err(nor->dev,
90 + "While writing %zu bytes written %zd bytes\n",
91 + page_remain, written);
92 + ret = -EIO;
93 + goto write_err;
94 }
95 }
96
97 - ret = spi_nor_wait_till_ready(nor);
98 write_err:
99 spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
100 return ret;