Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1323741 > unrolled thread

[PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue

Started byBean Huo <jackyard88@gmail.com>
First post2016-02-02 03:40 +0100
Last post2016-02-03 07:20 +0100
Articles 7 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue Bean Huo <jackyard88@gmail.com> - 2016-02-02 03:40 +0100
    [PATCH v2 15/17] fs:ubifs:enable bakvol module and  recover operation Bean Huo <jackyard88@gmail.com> - 2016-02-02 03:40 +0100
    [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function Bean Huo <jackyard88@gmail.com> - 2016-02-02 03:50 +0100
      Re: [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program  function kbuild test robot <lkp@intel.com> - 2016-02-02 04:10 +0100
    [PATCH v2 01/17] include:mtd:add multi-plane page program command Bean Huo <jackyard88@gmail.com> - 2016-02-02 03:50 +0100
    Re: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired  page power loss issue Richard Weinberger <richard@nod.at> - 2016-02-03 00:10 +0100
      RE: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC  paired page power loss issue Bean Huo 霍斌斌 (beanhuo)   <beanhuo@micron.com> - 2016-02-03 07:20 +0100

#1323741 — [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue

FromBean Huo <jackyard88@gmail.com>
Date2016-02-02 03:40 +0100
Subject[PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
Message-ID<qXz2N-3Wf-3@gated-at.bofh.it>
From: BeanHuo <beanhuo@micron.com>

These patches aim to solve MLC NAND paired page power loss
issue,by adding a bakvol(backup volume) module in UBI layer.

MLC NAND paired page power loss issue is a known issue so far,
MLC NAND pages are coupled in a sense that if you cut power
while writing to a page, you corrupt not only this page, but
also one of the previous pages which is paired with the current
one.
http://www.linux-mtd.infradead.org/doc/ubifs.html#L_ubifs_mlc

This paired page power loss solution is based on NAND multiple
plane program feature. Dual plane page program method can program
two different plane pages at the same time. as for this solution,
there are three main steps:

1. initialization
 While UBI attach process, if ubi first attach MTD to ubi device,
bakvol will be created, and reserve 20 PEBs for bakvol. if not,
scan every PEB to find out bakvol PEB, update a bakvol PEB table
in RAM.
2. recovery
 While UBIFS mount, and if there is a power loss, bakvol module will
 check if there are lower pages being dameged by last power loss, if
 yes, bakvol will apply for one new PEB, move uncorrupted data to this
 PEB, and recover dameged data by backup page data in bakvol PEB.
3. backup
if UBI proggrams one lower page, bakvol module will duplicate this lower
page data,and then program source page data and backup page data into two
different plane pages(one is user data volume and another is backup volume)
at the same time through dual plane program command.
If UBI porgrams upper page data, still uses mtd_write() to program. In
another word, backup only implements while program lower page.

These patches have already been tested on Micron 70s/80s MLC NAND.

Any suggestions and comments welcomed.

This version patches based on Linux kernel 4.2-rc7.
 
 v2:
   1.Add CRC32 protection for user OOB area data.
   2.Move recovery action from attach step to ubifs mount step.
   3.Add more comments for some key function.
   4.standard multi-plane program function.
   5.Standard send-mail patches

Bean Huo (17):
  include:mtd:add multi-plane page program command
  include:mtd:add multi-plane program in mtd_info
  drivers:mtd:add multi-plane page program support in partition layer
  drivers:mtd:nand:enable dual plane page program function
  drivers:mtd:ubi:add bakvol on-flash and RAM data structures
  drivers:mtd:ubi:add bakvol function define in ubi layer
  fs:ubifs:add bakvol function define in ubifs layer
  drivers:mtd:ubi:disable bakvol function while writing volume table
  drivers:mtd:ubi:get PEB according to specfied plane number
  drivers:mtd:ubi:enable bakvol function for fastmap operation
  drivers:mtd:ubi:add disable/enable bakvol while ubi write
  drivers:mtd:ubi:add disable bakvol while ubi detach
  drivers:mtd:ubi:add bakvol init while attach ubi
  drivers:mtd:ubi:add backup operation in ubi_io_write
  fs:ubifs:enable bakvol module and  recover operation
  driver:mtd:ubi:add new bakvol module in ubi layer
  drivers:mtd:ubi: Kconfig Makefile

 drivers/mtd/mtdpart.c        |   19 +
 drivers/mtd/nand/nand_base.c |  405 +++++++++++++
 drivers/mtd/ubi/Kconfig      |   15 +
 drivers/mtd/ubi/Makefile     |    2 +-
 drivers/mtd/ubi/attach.c     |   24 +-
 drivers/mtd/ubi/bakvol.c     | 1296 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/ubi/build.c      |    2 +
 drivers/mtd/ubi/eba.c        |   13 +-
 drivers/mtd/ubi/fastmap.c    |    2 +-
 drivers/mtd/ubi/io.c         |   73 ++-
 drivers/mtd/ubi/ubi-media.h  |   64 +++
 drivers/mtd/ubi/ubi.h        |   23 +-
 drivers/mtd/ubi/vtbl.c       |    2 +-
 drivers/mtd/ubi/wl.c         |  140 +++++
 fs/ubifs/super.c             |   11 +
 fs/ubifs/ubifs.h             |    2 +
 include/linux/mtd/mtd.h      |   19 +
 include/linux/mtd/nand.h     |    4 +
 18 files changed, 2091 insertions(+), 25 deletions(-)
 create mode 100644 drivers/mtd/ubi/bakvol.c

-- 
1.9.1

[toc] | [next] | [standalone]


#1323742 — [PATCH v2 15/17] fs:ubifs:enable bakvol module and recover operation

FromBean Huo <jackyard88@gmail.com>
Date2016-02-02 03:40 +0100
Subject[PATCH v2 15/17] fs:ubifs:enable bakvol module and recover operation
Message-ID<qXz2Q-3Wf-65@gated-at.bofh.it>
In reply to#1323741
From: Bean Huo <beanhuo@micron.com>

Before mounting, bakvol will do recovery operaion according to
master node flag(clearly unmount or not). If corrupted page damaged by
power loss exists, bakvol will reocover it through its backup page data.
bakvol module will be enable after ubifs mount successfully.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 fs/ubifs/super.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..0aaeafa 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1270,6 +1270,11 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->need_recovery = 1;
 	}
 
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	if (c->need_recovery)
+		ubi_corrupted_data_recovery(c->ubi);
+#endif
+
 	if (c->need_recovery && !c->ro_mount) {
 		err = ubifs_recover_inl_heads(c, c->sbuf);
 		if (err)
@@ -1463,6 +1468,8 @@ static int mount_ubifs(struct ubifs_info *c)
 	dbg_gen("max. seq. number:    %llu", c->max_sqnum);
 	dbg_gen("commit number:       %llu", c->cmt_no);
 
+	init_bakvol(c->ubi, 1);
+
 	return 0;
 
 out_infos:
@@ -1774,6 +1781,10 @@ static void ubifs_put_super(struct super_block *sb)
 	 * the mutex is locked.
 	 */
 	mutex_lock(&c->umount_mutex);
+
+	/* Disable ubi MLC power loss backup function */
+	init_bakvol(c->ubi, 0);
+
 	if (!c->ro_mount) {
 		/*
 		 * First of all kill the background thread to make sure it does
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1323744 — [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function

FromBean Huo <jackyard88@gmail.com>
Date2016-02-02 03:50 +0100
Subject[PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function
Message-ID<qXzcu-3ZH-3@gated-at.bofh.it>
In reply to#1323741
From: Bean Huo <beanhuo@micron.com>

The PROGRAM PAGE MULTI-PLANE (80h-11h) command enables
the host to input data to the addressed plane's cache register
and queue the cache register to ultimately be moved to the
NAND Flash array. This command can be issued one or more times.
Each time a new plane address is specified that plane is also
queued for data transfer. To input data for the final plane and
to begin the program operation for all previously queued planes,
issue either the PROGRAM PAGE (80h-10h) command or the PROGRAM
PAGE CACHE (80h-15h) command. All of the queued planes will move
the data to the NAND Flash array.

For this version patches, currently, only support dual plane page program.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 drivers/mtd/nand/nand_base.c | 405 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 405 insertions(+)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ceb68ca..b5cbd0a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2249,6 +2249,75 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
 
 	return 0;
 }
+/**
+ * nand_write_plane_page - [REPLACEABLE] write one page
+ * @mtd: MTD device structure
+ * @chip: NAND chip descriptor
+ * @offset: address offset within the page
+ * @data_len: length of actual data to be written
+ * @buf: the data to write
+ * @oob_required: must write chip->oob_poi to OOB
+ * @page: page number to write
+ * @plane: multiple plane programming
+ * @raw: use _raw version of write_page
+ */
+static int nand_write_plane_page(struct mtd_info *mtd, struct nand_chip *chip,
+			    uint32_t offset, int data_len, const uint8_t *buf,
+			    int oob_required, int page, int plane, int raw)
+{
+	int status, subpage;
+
+	if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
+	    chip->ecc.write_subpage)
+		subpage = offset || (data_len < mtd->writesize);
+	else
+		subpage = 0;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+
+	if (unlikely(raw))
+		status = chip->ecc.write_page_raw(mtd, chip, buf,
+							oob_required);
+	else if (subpage)
+		status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
+							buf, oob_required);
+	else
+		status = chip->ecc.write_page(mtd, chip, buf, oob_required);
+
+	if (status < 0)
+		return status;
+
+	/* Multipal plane progamming */
+	if (plane) {
+		chip->cmdfunc(mtd, NAND_CMD_MULTI_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available.
+		 */
+	    if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+	    if (status & NAND_STATUS_FAIL)
+		return -EIO;
+
+	} else if (!plane || !NAND_HAS_CACHEPROG(chip)) {
+
+		chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+		status = chip->waitfunc(mtd, chip);
+		/*
+		 * See if operation failed and additional status checks are
+		 * available.
+		 */
+	    if ((status & NAND_STATUS_FAIL) && (chip->errstat))
+		status = chip->errstat(mtd, chip, FL_WRITING, status, page);
+
+	    if (status & NAND_STATUS_FAIL)
+		return -EIO;
+	}
+
+	return 0;
+}
 
 /**
  * nand_write_page - [REPLACEABLE] write one page
@@ -2373,6 +2442,277 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 }
 
 #define NOTALIGNED(x)	((x & (chip->subpagesize - 1)) != 0)
+/**
+ * nand_do_dual_plane_write_ops - [INTERN] NAND write with ECC by dual plane
+ * @mtd: MTD device structure
+ * @to_plane0: offset of  write plane 0
+ * @ops_plane0: oob operations description structure for plane 0
+ * @to_plane1: offset of  write plane 1
+ * @ops_plane1: oob operations description structure for plane 1
+ *
+ * NAND write with ECC through dual plane program.
+ */
+static int nand_do_dual_plane_write_ops(struct mtd_info *mtd, loff_t to_plane0,
+			   struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			   struct mtd_oob_ops *ops_plane1)
+{
+	int chipnr0, chipnr1, chipnr = 0, blockmask;
+	uint32_t oobwritelen = 0;
+	uint32_t oobmaxlen = 0;
+	int ret;
+	int column = 0, realpage = 0, page = 0;
+	uint32_t writelen = 0;
+	char flag = 0, cycle = 0;
+	int oob_required = 0;
+	uint8_t *oob = NULL;
+	uint8_t *buf = NULL;
+	uint32_t bak0_oobwritelen = 0, bak1_oobwritelen = 0;
+	int bak0_column = 0, bak1_column = 0;
+	int bak0_realpage = 0, bak1_realpage = 0;
+	int bak0_page = 0, bak1_page = 0;
+	int bak0_writelen = 0, bak1_writelen = 0;
+	uint8_t *bak0_buf = NULL, *bak1_buf = NULL;
+	uint8_t *bak0_oob = NULL, *bak1_oob = NULL;
+	uint8_t bak0_pagebuf = 0, bak1_pagebuf = 0;
+	int bytes = 0;
+	int cached = 0;
+	uint8_t *wbuf = NULL;
+	int use_bufpoi = 0;
+	int part_pagewr = 0;
+	struct nand_chip *chip = mtd->priv;
+	struct mtd_oob_ops *ops = NULL;
+
+	ops_plane0->retlen = 0;
+	ops_plane1->retlen = 0;
+
+	if ((!ops_plane0->len) || (!ops_plane1->len))
+		return 0;
+
+	/* Reject writes, which are not page aligned */
+	if (NOTALIGNED(to_plane0) || NOTALIGNED(ops_plane0->len) ||
+	    NOTALIGNED(to_plane1) || NOTALIGNED(ops_plane1->len)) {
+		pr_notice("%s: attempt to write non page aligned data\n",
+								__func__);
+		return -EINVAL;
+	}
+
+	chipnr0 = (int)(to_plane0 >> chip->chip_shift);
+	chipnr1 = (int)(to_plane1 >> chip->chip_shift);
+
+	if (unlikely(chipnr0 != chipnr1)) {
+		pr_notice("%s: attempt to write different nand chip\n",
+								__func__);
+		return -EINVAL;
+	}
+
+	chip->select_chip(mtd, chipnr0);
+
+	/* Check, if it is write protected */
+	if (nand_check_wp(mtd)) {
+		ret = -EIO;
+		goto err_out;
+	}
+
+	blockmask = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
+
+	/* Don't allow multipage oob writes with offset */
+	if ((ops_plane0->oobbuf && ops_plane0->ooboffs &&
+	(ops_plane0->ooboffs + ops_plane0->ooblen > oobmaxlen)) ||
+	(ops_plane1->oobbuf && ops_plane1->ooboffs &&
+	(ops_plane1->ooboffs + ops_plane1->ooblen > oobmaxlen))) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	while (1) {
+retry:
+		if (flag == 0) {
+			/* operate plane 0 */
+			ops = ops_plane0;
+			oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
+					mtd->oobavail : mtd->oobsize;
+			chipnr = chipnr0;
+			oob_required = ops->oobbuf ? 1 : 0;
+
+		   if (cycle == 0) {
+			/* plane 0 first write,backup programming infor */
+			bak0_oobwritelen = oobwritelen = ops->ooblen;
+			bak0_column = column = to_plane0 & (mtd->writesize - 1);
+			realpage = (int)(to_plane0 >> chip->page_shift);
+			bak0_realpage = realpage;
+			bak0_page = page = realpage & chip->pagemask;
+			bak0_writelen = writelen = ops->len;
+			bak0_buf = buf = ops->datbuf;
+			bak0_oob = oob = ops->oobbuf;
+
+		if (to_plane0 <= ((loff_t)chip->pagebuf << chip->page_shift) &&
+	   ((loff_t)chip->pagebuf << chip->page_shift) < (to_plane0 + ops->len))
+				chip->pagebuf = -1;
+
+			bak0_pagebuf = chip->pagebuf;
+
+		   } else {
+			oobwritelen = bak0_oobwritelen;
+			column = bak0_column;
+			realpage = bak0_realpage;
+			page = bak0_page;
+			writelen = bak0_writelen;
+			buf = bak0_buf;
+			oob = bak0_oob;
+			chip->pagebuf  = bak0_pagebuf;
+		   }
+		} else if (flag == 1) {
+			/* operate plane 1 */
+			ops = ops_plane1;
+			oobmaxlen = ops->mode == MTD_OPS_AUTO_OOB ?
+					mtd->oobavail : mtd->oobsize;
+			chipnr = chipnr1;
+			oob_required = ops->oobbuf ? 1 : 0;
+
+		   if (cycle == 0) {
+			/* plane 1 first write,backup programming infor */
+			bak1_oobwritelen = oobwritelen = ops->ooblen;
+			bak1_column = column = to_plane1 & (mtd->writesize - 1);
+			realpage = (int)(to_plane1 >> chip->page_shift);
+			bak1_realpage = realpage;
+			bak1_page = page = realpage & chip->pagemask;
+			bak1_writelen = writelen = ops->len;
+			bak1_buf = buf = ops->datbuf;
+			bak1_oob = oob = ops->oobbuf;
+
+	      if (to_plane1 <= ((loff_t)chip->pagebuf << chip->page_shift) &&
+	   ((loff_t)chip->pagebuf << chip->page_shift) < (to_plane1 + ops->len))
+				chip->pagebuf = -1;
+
+			bak1_pagebuf = chip->pagebuf;
+			} else {
+			oobwritelen = bak1_oobwritelen;
+			column = bak1_column;
+			realpage = bak1_realpage;
+			page = bak1_page;
+			writelen = bak1_writelen;
+			buf = bak1_buf;
+			oob = bak1_oob;
+			chip->pagebuf  = bak1_pagebuf;
+			}
+		}
+
+		/* Don't allow multipage oob writes with offset */
+		if (ops->oobbuf && ops->ooboffs &&
+			(ops->ooboffs + ops->ooblen > oobmaxlen)) {
+			ret = -EINVAL;
+			goto err_out;
+		}
+
+		bytes = mtd->writesize;
+		cached = writelen > bytes && page != blockmask;
+		wbuf = buf;
+
+		part_pagewr = (column || writelen < (mtd->writesize - 1));
+
+		if (part_pagewr)
+			use_bufpoi = 1;
+		else if (chip->options & NAND_USE_BOUNCE_BUFFER)
+			use_bufpoi = !virt_addr_valid(buf);
+		else
+			use_bufpoi = 0;
+
+		/* Partial page write?, or need to use bounce buffer */
+		if (use_bufpoi) {
+			pr_debug("%s: using write bounce buffer for buf@%p\n",
+								__func__, buf);
+			cached = 0;
+			if (part_pagewr)
+				bytes = min_t(int, bytes - column, writelen);
+			chip->pagebuf = -1;
+			memset(chip->buffers->databuf, 0xff, mtd->writesize);
+			memcpy(&chip->buffers->databuf[column], buf, bytes);
+			wbuf = chip->buffers->databuf;
+		}
+
+		if (unlikely(oob)) {
+			size_t len = min(oobwritelen, oobmaxlen);
+
+			oob = nand_fill_oob(mtd, oob, len, ops);
+			oobwritelen -= len;
+		} else {
+			/* We still need to erase leftover OOB data */
+			memset(chip->oob_poi, 0xff, mtd->oobsize);
+		}
+
+		if (flag == 0) {
+			ret = chip->write_plane_page(mtd, chip, column, bytes,
+		      wbuf, oob_required, page, 1, (ops->mode == MTD_OPS_RAW));
+		} else if (flag == 1) {
+			ret = chip->write_page(mtd, chip, column, bytes, wbuf,
+			oob_required, page, cached, (ops->mode == MTD_OPS_RAW));
+		}
+
+		if (ret)
+			break;
+
+		writelen -= bytes;
+		column = 0;
+
+		if (flag == 0) {
+			bak0_writelen = writelen;
+			bak0_column = column;
+			bak0_oobwritelen = oobwritelen;
+		} else {
+			bak1_writelen = writelen;
+			bak1_column = column;
+			bak1_oobwritelen = oobwritelen;
+		}
+
+		if ((!writelen) && (flag == 1))
+			break;
+
+		buf += bytes;
+		realpage++;
+
+		if (flag == 0) {
+			bak0_buf = buf;
+			bak0_oob = oob;
+			bak0_realpage = realpage;
+		} else {
+			bak1_buf = buf;
+			bak1_oob = oob;
+			bak1_realpage = realpage;
+		}
+
+		if (flag == 0) {
+			flag = 1;
+		goto retry;
+		}
+
+		page = realpage & chip->pagemask;
+
+		/* Check, if we cross a chip boundary */
+		if (!page) {
+			chipnr++;
+			chip->select_chip(mtd, -1);
+			chip->select_chip(mtd, chipnr);
+		}
+
+		flag = 0;
+		cycle++;
+
+	}
+
+	ops_plane0->retlen = ops_plane0->len - bak0_writelen;
+	ops_plane1->retlen = ops_plane1->len - bak1_writelen;
+
+	if (unlikely(bak0_oob))
+		ops_plane0->oobretlen = ops_plane0->ooblen;
+	if (unlikely(bak1_oob))
+		ops_plane1->oobretlen = ops_plane1->ooblen;
+
+err_out:
+	flag = 0;
+	cycle = 0;
+	chip->select_chip(mtd, -1);
+	return ret;
+}
 
 /**
  * nand_do_write_ops - [INTERN] NAND write with ECC
@@ -2564,6 +2904,14 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
 	return ret;
 }
 
+static int nand_do_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
+			      struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			      struct mtd_oob_ops *ops_plane1)
+{
+	return 0;
+
+}
+
 /**
  * nand_do_write_oob - [MTD Interface] NAND write out-of-band
  * @mtd: MTD device structure
@@ -2692,6 +3040,52 @@ out:
 	return ret;
 }
 
+static int nand_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
+			   struct mtd_oob_ops *ops_plane0, loff_t to_plane1,
+			   struct mtd_oob_ops *ops_plane1)
+{
+	int ret = -ENOTSUPP;
+
+	/* Do not allow writes past end of device */
+	if ((ops_plane0->datbuf && (to_plane0 + ops_plane0->len) > mtd->size) ||
+	    (ops_plane1->datbuf && (to_plane1 + ops_plane1->len) > mtd->size)) {
+		pr_debug("%s: attempt to write beyond end of device\n",
+								__func__);
+		return -EINVAL;
+	}
+	nand_get_device(mtd, FL_WRITING);
+
+	switch (ops_plane0->mode) {
+	case MTD_OPS_PLACE_OOB:
+		if (ops_plane1->mode != MTD_OPS_PLACE_OOB)
+			goto out;
+		break;
+	case MTD_OPS_AUTO_OOB:
+		if (ops_plane1->mode != MTD_OPS_AUTO_OOB)
+			goto out;
+		break;
+	case MTD_OPS_RAW:
+		if (ops_plane1->mode != MTD_OPS_RAW)
+			goto out;
+		break;
+
+	default:
+		goto out;
+	}
+
+	if (!ops_plane0->datbuf && !ops_plane1->datbuf)
+		ret = nand_do_dual_plane_write_oob(mtd, to_plane0, ops_plane0,
+							to_plane1, ops_plane1);
+	else
+		ret = nand_do_dual_plane_write_ops(mtd, to_plane0, ops_plane0,
+							to_plane1, ops_plane1);
+
+out:
+	nand_release_device(mtd);
+	return ret;
+}
+EXPORT_SYMBOL(nand_dual_plane_write_oob);
+
 /**
  * single_erase - [GENERIC] NAND standard block erase command function
  * @mtd: MTD device structure
@@ -2764,6 +3158,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		goto erase_exit;
 	}
 
+
 	/* Loop through the pages */
 	len = instr->len;
 
@@ -2904,6 +3299,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip,
 	for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i)
 		chip->write_byte(mtd, subfeature_param[i]);
 
+	if ((addr == ONFI_FEATURE_ADDR_TIMING_MODE) && ((subfeature_param[0]&0xF0) != 0))
+		return 0;
+
 	status = chip->waitfunc(mtd, chip);
 	if (status & NAND_STATUS_FAIL)
 		return -EIO;
@@ -3991,6 +4389,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 	if (!chip->write_page)
 		chip->write_page = nand_write_page;
+	if (!chip->write_plane_page)
+		chip->write_plane_page = nand_write_plane_page;
 
 	/*
 	 * Check ECC mode, default to software if 3byte/512byte hardware ECC is
@@ -4206,6 +4606,11 @@ int nand_scan_tail(struct mtd_info *mtd)
 	mtd->_panic_write = panic_nand_write;
 	mtd->_read_oob = nand_read_oob;
 	mtd->_write_oob = nand_write_oob;
+#ifdef CONFIG_MTD_UBI_MLC_NAND_BAKVOL
+	mtd->_dual_plane_write_oob = nand_dual_plane_write_oob;
+#else
+	mtd->_dual_plane_write_oob = NULL;
+#endif
 	mtd->_sync = nand_sync;
 	mtd->_lock = NULL;
 	mtd->_unlock = NULL;
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1323748 — Re: [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function

Fromkbuild test robot <lkp@intel.com>
Date2016-02-02 04:10 +0100
SubjectRe: [PATCH v2 04/17] drivers:mtd:nand:enable dual plane page program function
Message-ID<qXzvQ-4pr-1@gated-at.bofh.it>
In reply to#1323744

[Multipart message — attachments visible in raw view] — view raw

Hi Bean,

[auto build test ERROR on v4.5-rc2]
[also build test ERROR on next-20160201]
[if your patch is applied to the wrong git tree, please drop us a note to help improving the system]

url:    https://github.com/0day-ci/linux/commits/Bean-Huo/Add-a-bakvol-module-in-UBI-layer-for-MLC-paired-page-power-loss-issue/20160202-104450
config: x86_64-randconfig-x012-201605 (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/mtd/nand/nand_base.c: In function 'nand_write_plane_page':
>> drivers/mtd/nand/nand_base.c:2463:12: error: too few arguments to function 'chip->ecc.write_page_raw'
      status = chip->ecc.write_page_raw(mtd, chip, buf,
               ^
>> drivers/mtd/nand/nand_base.c:2466:12: error: too few arguments to function 'chip->ecc.write_subpage'
      status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
               ^
>> drivers/mtd/nand/nand_base.c:2469:12: error: too few arguments to function 'chip->ecc.write_page'
      status = chip->ecc.write_page(mtd, chip, buf, oob_required);
               ^
   drivers/mtd/nand/nand_base.c: At top level:
   drivers/mtd/nand/nand_base.c:3228:12: warning: 'nand_dual_plane_write_oob' defined but not used [-Wunused-function]
    static int nand_dual_plane_write_oob(struct mtd_info *mtd, loff_t to_plane0,
               ^

vim +2463 drivers/mtd/nand/nand_base.c

  2457		else
  2458			subpage = 0;
  2459	
  2460		chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
  2461	
  2462		if (unlikely(raw))
> 2463			status = chip->ecc.write_page_raw(mtd, chip, buf,
  2464								oob_required);
  2465		else if (subpage)
> 2466			status = chip->ecc.write_subpage(mtd, chip, offset, data_len,
  2467								buf, oob_required);
  2468		else
> 2469			status = chip->ecc.write_page(mtd, chip, buf, oob_required);
  2470	
  2471		if (status < 0)
  2472			return status;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[toc] | [prev] | [next] | [standalone]


#1323746 — [PATCH v2 01/17] include:mtd:add multi-plane page program command

FromBean Huo <jackyard88@gmail.com>
Date2016-02-02 03:50 +0100
Subject[PATCH v2 01/17] include:mtd:add multi-plane page program command
Message-ID<qXzcu-3ZH-11@gated-at.bofh.it>
In reply to#1323741
From: Bean Huo <beanhuo@micron.com>

This patch file is to add multi-plane page program command,
and add dual plane page program hook pinter in nand_chip structure.

Signed-off-by: BeanHuo <beanhuo@micron.com>
---
 include/linux/mtd/nand.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 272f429..4c5be01 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -77,6 +77,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 #define NAND_CMD_READ1		1
 #define NAND_CMD_RNDOUT		5
 #define NAND_CMD_PAGEPROG	0x10
+#define NAND_CMD_MULTI_PAGEPROG	0x11
 #define NAND_CMD_READOOB	0x50
 #define NAND_CMD_ERASE1		0x60
 #define NAND_CMD_STATUS		0x70
@@ -671,6 +672,9 @@ struct nand_chip {
 	int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
 			uint32_t offset, int data_len, const uint8_t *buf,
 			int oob_required, int page, int cached, int raw);
+	int (*write_plane_page)(struct mtd_info *mtd, struct nand_chip *chip,
+			uint32_t offset, int data_len, const uint8_t *buf,
+			int oob_required, int page, int plane, int raw);
 	int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
 			int feature_addr, uint8_t *subfeature_para);
 	int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1324714 — Re: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue

FromRichard Weinberger <richard@nod.at>
Date2016-02-03 00:10 +0100
SubjectRe: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
Message-ID<qXSf8-1Ty-7@gated-at.bofh.it>
In reply to#1323741
Bean,

Am 02.02.2016 um 03:30 schrieb Bean Huo:
> This version patches based on Linux kernel 4.2-rc7.
>  
>  v2:
>    1.Add CRC32 protection for user OOB area data.
>    2.Move recovery action from attach step to ubifs mount step.
>    3.Add more comments for some key function.
>    4.standard multi-plane program function.
>    5.Standard send-mail patches

It is sad to see that you've ignored almost all review comments that have been made.
Both comments made by Boris and me on the public mailing list as well as the comments
and I made on our phone call.

To summarize, I see the following major issues with this patch series:
1. It makes use of OOB, it was very clearly stated that this violates one of UBI's design principles.

2. It is not generic, you use hard coded constants for Micron 70s/80s MLC NANDs.
   And AFAICT it is not guaranteed that all MLC NANDs support multi pane writes.

3. Not all data is protected. Most of UBI's meta data (EC&VID headers, volume table)
   are explicitly not protected, as well as UBIFS's superblock and master nodes.

4. It mixes UBI and UBIFS code. Having code like this in UBI's EBA code is not acceptable:
   ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
   This hack is here to void safe writes of UBIFS's suberblock and master nodes.
   But UBIFS specific code has no business in UBI core code. Also See 3.

5. It does not scale. Having a backup of every important page would require much more space.
   Especially UBI EC and VID headers. I bet this is also the reason why the current implementation
   does not protect them. Otherwise the bakvol would fill up immediately.
   Another scalability problem is that the whole bakvol has to be scanned which will slow down
   the attach/mount process and may void the speedup gained by Fastmap.

6. It focuses only on UBIFS. ubi_corrupted_data_recovery() is only called from UBIFS code.
   If UBI is changed, we need a solution for all users on top of UBI.
   Now I understand also why you want the "fs:ubifs:recovery:fixup UBIFS cannot recover master node issue"
   patch. As UBIFS master nodes are not protected by bakvol they will corrupt and UBIFS is not able to recover
   nor can run ubi_corrupted_data_recovery().

7. A full bakvol is not proper handled. The implementation falls back to "unsafe" writes.
                dbg_gen("Allocate new PEB for Bakvol.\n");
                pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
                if (!pbk) {
                        ubi_err(ubi, "Allocate new PEB failed.\n");
                        nobak = 1;
                        goto Only_source;
                }
   You cannot expect users to query the kernel log for such error messages.


Beside of these issues there are a lot of small implementation issues.
For example Fastmap is broken as UBI_FM_SB_VOLUME_ID clashes with UBI_BACKUP_VOLUME_ID.
Or struct list_head is part of on-Flash data structures.

That said, it don't think the bakvol approach is the solution we're looking for.
A proper solution has to fulfill the following conditions:
1. No dependency on OOB data.
2. Can work with any MLC NANDs and controllers. Boris and I have access to Hynix, Micron and Toshiba NAND so far.
3. If implemented on UBI level, it has to work for any user on top of UBI.
4. Has to be able to protect all data.
5. Must not regress current UBI or UBIFS.

Boris and I are working on such a solution and would like to invite you to join us.
The topic is complicated and not easy to solve. But with joined forces we will be able
to find a good solution. :-)

Thanks,
//richard

[toc] | [prev] | [next] | [standalone]


#1324948 — RE: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue

FromBean Huo 霍斌斌 (beanhuo) <beanhuo@micron.com>
Date2016-02-03 07:20 +0100
SubjectRE: [PATCH v2 00/17] Add a bakvol module in UBI layer for MLC paired page power loss issue
Message-ID<qXYXg-6CP-19@gated-at.bofh.it>
In reply to#1324714
Dear Richard
Thanks for reviewing my patches and valuable feedback. 
I also want to work with you and Boris on such solution, 
I know this is a complicated task, need our joint effort.

Following is my explanation for each of concerns:

> Bean,
> 
> Am 02.02.2016 um 03:30 schrieb Bean Huo:
> > This version patches based on Linux kernel 4.2-rc7.
> >
> >  v2:
> >    1.Add CRC32 protection for user OOB area data.
> >    2.Move recovery action from attach step to ubifs mount step.
> >    3.Add more comments for some key function.
> >    4.standard multi-plane program function.
> >    5.Standard send-mail patches
> 
> It is sad to see that you've ignored almost all review comments that have
> been made.
> Both comments made by Boris and me on the public mailing list as well as the
> comments and I made on our phone call.
> 
> To summarize, I see the following major issues with this patch series:
> 1. It makes use of OOB, it was very clearly stated that this violates one of
> UBI's design principles.
Currently I still cannot find a good method on how to manage backup info.
So now I still use OOB.
Backup page OOB stores source page address, and source page OOB store backup page address,
They store each other's page address, one is in order to indicate that backup page
is really one copy data of source page, in case of source block being erased and re-mapped again.
Another is in order to quickly find corresponding source page.

> 2. It is not generic, you use hard coded constants for Micron 70s/80s MLC
> NANDs.
>    And AFAICT it is not guaranteed that all MLC NANDs support multi pane
> writes.
Yes, so far ,different NAND vendor with different paired page sequence,
So if guarantee all vendor NAND, should involve every vendor NAND paired page
Sequence table or calculator function, but now I don't have other NAND vendor 
datasheet.

> 3. Not all data is protected. Most of UBI's meta data (EC&VID headers,
> volume table)
>    are explicitly not protected, as well as UBIFS's superblock and master
> nodes.
For master node: 
current UBIFS master node already has one copy for power loss,
Just not cover MLC paired page power loss issue, if my previous Master node issue 
patch be accepted, master node totally does not need to protection.

EC&VID:
For EC header, according to my testing result data and our NAND PE cycle requirement,
If EC header be damaged by power loss , mean erase count is ok, no impact on NAND life.
But for VID header, because my solution uses dual plane page program, it has special page address
Requirement on dual plane page address, that is page number should be the same.
UBI already pre-program page 0 and page 1, so no page 1 is for VID.


> 4. It mixes UBI and UBIFS code. Having code like this in UBI's EBA code is not
> acceptable:
>    ubi_io_write_data(ubi, buf, pnum, offset, len, ((lnum < 3) ? 0 : 1));
>    This hack is here to void safe writes of UBIFS's suberblock and master
> nodes.
>    But UBIFS specific code has no business in UBI core code. Also See 3.
These codes need to modify. Thanks.

> 5. It does not scale. Having a backup of every important page would require
> much more space.
>    Especially UBI EC and VID headers. I bet this is also the reason why the
> current implementation
>    does not protect them. Otherwise the bakvol would fill up immediately.
>    Another scalability problem is that the whole bakvol has to be scanned
> which will slow down
>    the attach/mount process and may void the speedup gained by Fastmap.
This is also my concern, maybe next version I can fix this by store bakvol PEB info
Into flash.

> 6. It focuses only on UBIFS. ubi_corrupted_data_recovery() is only called
> from UBIFS code.
>    If UBI is changed, we need a solution for all users on top of UBI.
>    Now I understand also why you want the "fs:ubifs:recovery:fixup UBIFS
> cannot recover master node issue"
>    patch. As UBIFS master nodes are not protected by bakvol they will
> corrupt and UBIFS is not able to recover
>    nor can run ubi_corrupted_data_recovery().
> 
> 7. A full bakvol is not proper handled. The implementation falls back to
> "unsafe" writes.
>                 dbg_gen("Allocate new PEB for Bakvol.\n");
>                 pbk = allo_new_block_for_bakvol(ubi, oppe_plane);
>                 if (!pbk) {
>                         ubi_err(ubi, "Allocate new PEB failed.\n");
>                         nobak = 1;
>                         goto Only_source;
>                 }
>    You cannot expect users to query the kernel log for such error messages.
> 
> 
> Beside of these issues there are a lot of small implementation issues.
> For example Fastmap is broken as UBI_FM_SB_VOLUME_ID clashes with
> UBI_BACKUP_VOLUME_ID.
> Or struct list_head is part of on-Flash data structures.
> 
> That said, it don't think the bakvol approach is the solution we're looking for.
> A proper solution has to fulfill the following conditions:
> 1. No dependency on OOB data.
> 2. Can work with any MLC NANDs and controllers. Boris and I have access to
> Hynix, Micron and Toshiba NAND so far.
> 3. If implemented on UBI level, it has to work for any user on top of UBI.
> 4. Has to be able to protect all data.
> 5. Must not regress current UBI or UBIFS.
> 
> Boris and I are working on such a solution and would like to invite you to join
> us.
> The topic is complicated and not easy to solve. But with joined forces we will
> be able to find a good solution. :-)
Look forward to work with you for this.

> Thanks,
> //richard

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web