Add hook for UBI bakvol in ubi_io_write.

Modify ubi_io_write, if program lower page of MLC NAND,
Duplicated it and backup one copy into internal log volume by
Dual plane program method.

Signed-off-by: Bean Huo <[email protected]>
---
 drivers/mtd/ubi/io.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 55 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 5bbd1f0..912c458 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -236,8 +236,9 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, 
int pnum, int offset,
                 int len)
 {
        int err;
-       size_t written;
+       size_t retlen;
        loff_t addr;
+       int skip = 0;
 
        dbg_io("write %d bytes to PEB %d:%d", len, pnum, offset);
 
@@ -281,14 +282,60 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, 
int pnum, int offset,
        }
 
        addr = (loff_t)pnum * ubi->peb_size + offset;
-       err = mtd_write(ubi->mtd, addr, len, &written, buf);
-       if (err) {
-               ubi_err(ubi, "error %d while writing %d bytes to PEB %d:%d, 
written %zd bytes",
-                       err, len, pnum, offset, written);
-               dump_stack();
-               ubi_dump_flash(ubi, pnum, offset, len);
+
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+       if ((offset == 0) && (len == ubi->peb_size))
+               skip = 1;
+
+       if (ubi_check_backup_volume(ubi) && (!skip)) {
+               loff_t addr_temp;
+               unsigned char *buf_temp = (unsigned char *)buf;
+               int len_temp;
+               int writelen = 0;
+
+               addr_temp = addr;
+
+               for (len_temp = len; len_temp > 0; len_temp -= ubi->min_io_size,
+                       addr_temp += ubi->min_io_size,
+                       buf_temp += ubi->min_io_size) {
+                       /* Split data according to min_io_size */
+
+                       if (len_temp/ubi->min_io_size)
+                               writelen = ubi->min_io_size;
+                       else
+                               writelen %= ubi->min_io_size;
+
+                       if (is_backup_need(ubi, addr_temp)) {
+                               err = ubi_backup_data_to_backup_volume(ubi,
+                                       addr_temp, writelen, &retlen, buf_temp);
+                               } else
+                               err = mtd_write(ubi->mtd, addr_temp, writelen,
+                                               &retlen, buf_temp);
+
+                       if (err) {
+                               ubi_err(ubi, "Writing %d byptes to PEB %d:%d",
+                                       writelen, pnum, offset);
+                               ubi_err(ubi, "Error %d", err);
+                               ubi_err(ubi, "Written %zd bytes", retlen);
+                               dump_stack();
+                               ubi_dump_flash(ubi, pnum, offset, writelen);
+                               } else
+                               ubi_assert(retlen == writelen);
+               }
        } else
-               ubi_assert(written == len);
+#endif
+       {
+               err = mtd_write(ubi->mtd, addr, len, &retlen, buf);
+               if (err) {
+                       ubi_err(ubi, "Writing %d byptes to PEB %d:%d",
+                               len, pnum, offset);
+                       ubi_err(ubi, "Error %d", err);
+                       ubi_err(ubi, "Written %zd bytes", retlen);
+                       dump_stack();
+                       ubi_dump_flash(ubi, pnum, offset, len);
+               } else
+                       ubi_assert(retlen == len);
+       }
 
        if (!err) {
                err = self_check_write(ubi, buf, pnum, offset, len);
-- 
1.9.1

Reply via email to