Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1323741 > unrolled thread
| Started by | Bean Huo <jackyard88@gmail.com> |
|---|---|
| First post | 2016-02-02 03:40 +0100 |
| Last post | 2016-02-03 07:20 +0100 |
| Articles | 7 — 4 participants |
Back to article view | Back to linux.kernel
[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
| From | Bean Huo <jackyard88@gmail.com> |
|---|---|
| Date | 2016-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]
| From | Bean Huo <jackyard88@gmail.com> |
|---|---|
| Date | 2016-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]
| From | Bean Huo <jackyard88@gmail.com> |
|---|---|
| Date | 2016-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]
| From | kbuild test robot <lkp@intel.com> |
|---|---|
| Date | 2016-02-02 04:10 +0100 |
| Subject | Re: [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]
| From | Bean Huo <jackyard88@gmail.com> |
|---|---|
| Date | 2016-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]
| From | Richard Weinberger <richard@nod.at> |
|---|---|
| Date | 2016-02-03 00:10 +0100 |
| Subject | Re: [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]
| From | Bean Huo 霍斌斌 (beanhuo) <beanhuo@micron.com> |
|---|---|
| Date | 2016-02-03 07:20 +0100 |
| Subject | RE: [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