Linux-mtd Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/8] MLC in SLC mode
@ 2019-12-30 16:51 Miquel Raynal
  2019-12-30 16:51 ` [PATCH 1/8] mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00 Miquel Raynal
                   ` (7 more replies)
  0 siblings, 8 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Thomas Petazzoni, Miquel Raynal

Hello,

This series has been lying since a long time in Boris tree, it is
clean enough to be upstreamed now. This work is based on the "MTD
partition handling rework" patch.

It basically allows to work "safely" with MLC NANDs, details inside.

Cheers,
Miquèl

Boris Brezillon (8):
  mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00
  mtd: rawnand: Define the "distance 3" MLC pairing scheme
  mtd: rawnand: toshiba: Set the pairing scheme for TC58TEG5DCLTA00
  mtd: Add support for emulated SLC mode on MLC NANDs
  dt-bindings: mtd: partition: Document the slc-mode property
  mtd: partitions: ofpart: Parse the slc-mode property
  mtd: cmdlinepart: Add an slc option to use SLC mode on a part
  ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode

 .../devicetree/bindings/mtd/partition.txt     |   3 +
 drivers/mtd/mtdcore.c                         | 189 ++++++++++++++++--
 drivers/mtd/mtdpart.c                         |  54 ++---
 drivers/mtd/nand/raw/internals.h              |   3 +
 drivers/mtd/nand/raw/nand_base.c              |  50 +++++
 drivers/mtd/nand/raw/nand_toshiba.c           |  14 ++
 drivers/mtd/parsers/cmdlinepart.c             |  12 +-
 drivers/mtd/parsers/ofpart.c                  |   3 +
 drivers/mtd/ubi/build.c                       |   5 +-
 include/linux/mtd/mtd.h                       |   7 +-
 include/linux/mtd/partitions.h                |   2 +
 include/uapi/mtd/mtd-abi.h                    |   1 +
 scripts/pnmtologo                             | Bin 0 -> 22416 bytes
 13 files changed, 300 insertions(+), 43 deletions(-)
 create mode 100755 scripts/pnmtologo

-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/8] mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2019-12-30 16:51 ` [PATCH 2/8] mtd: rawnand: Define the "distance 3" MLC pairing scheme Miquel Raynal
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

TC58TEG5DCLTA00 is an MLC NAND which requires scrambling and supports
SDR timings mode 5.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_toshiba.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 9c03fbb1f47d..9114b96880d7 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -140,6 +140,14 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 	}
 }
 
+static int tc58teg5dclta00_init(struct nand_chip *chip)
+{
+	chip->onfi_timing_mode_default = 5;
+	chip->options |= NAND_NEED_SCRAMBLING;
+
+	return 0;
+}
+
 static int toshiba_nand_init(struct nand_chip *chip)
 {
 	if (nand_is_slc(chip))
@@ -150,6 +158,9 @@ static int toshiba_nand_init(struct nand_chip *chip)
 	    chip->id.data[4] & TOSHIBA_NAND_ID4_IS_BENAND)
 		toshiba_nand_benand_init(chip);
 
+	if (!strcmp("TC58TEG5DCLTA00", chip->parameters.model))
+		tc58teg5dclta00_init(chip);
+
 	return 0;
 }
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/8] mtd: rawnand: Define the "distance 3" MLC pairing scheme
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
  2019-12-30 16:51 ` [PATCH 1/8] mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00 Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2019-12-30 16:51 ` [PATCH 3/8] mtd: rawnand: toshiba: Set the pairing scheme for TC58TEG5DCLTA00 Miquel Raynal
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

Define a new page pairing scheme for MLC NANDs with a distance of 3
pages between the lower and upper page.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/internals.h |  3 ++
 drivers/mtd/nand/raw/nand_base.c | 50 ++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h
index cba6fe7dd8c4..8f6fdda681cc 100644
--- a/drivers/mtd/nand/raw/internals.h
+++ b/drivers/mtd/nand/raw/internals.h
@@ -74,6 +74,9 @@ extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
 extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
 extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
 
+/* MLC pairing schemes */
+extern const struct mtd_pairing_scheme dist3_pairing_scheme;
+
 /* Core functions */
 const struct nand_manufacturer *nand_get_manufacturer(u8 id);
 int nand_bbm_get_next_page(struct nand_chip *chip, int page);
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index f64e3b6605c6..a471f5714cd6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -205,6 +205,56 @@ static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
 	.free = nand_ooblayout_free_lp_hamming,
 };
 
+static int nand_pairing_dist3_get_info(struct mtd_info *mtd, int page,
+				       struct mtd_pairing_info *info)
+{
+	int lastpage = (mtd->erasesize / mtd->writesize) - 1;
+	int dist = 3;
+
+	if (page == lastpage)
+		dist = 2;
+
+	if (!page || (page & 1)) {
+		info->group = 0;
+		info->pair = (page + 1) / 2;
+	} else {
+		info->group = 1;
+		info->pair = (page + 1 - dist) / 2;
+	}
+
+	return 0;
+}
+
+static int nand_pairing_dist3_get_wunit(struct mtd_info *mtd,
+					const struct mtd_pairing_info *info)
+{
+	int lastpair = ((mtd->erasesize / mtd->writesize) - 1) / 2;
+	int page = info->pair * 2;
+	int dist = 3;
+
+	if (!info->group && !info->pair)
+		return 0;
+
+	if (info->pair == lastpair && info->group)
+		dist = 2;
+
+	if (!info->group)
+		page--;
+	else if (info->pair)
+		page += dist - 1;
+
+	if (page >= mtd->erasesize / mtd->writesize)
+		return -EINVAL;
+
+	return page;
+}
+
+const struct mtd_pairing_scheme dist3_pairing_scheme = {
+	.ngroups = 2,
+	.get_info = nand_pairing_dist3_get_info,
+	.get_wunit = nand_pairing_dist3_get_wunit,
+};
+
 static int check_offs_len(struct nand_chip *chip, loff_t ofs, uint64_t len)
 {
 	int ret = 0;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 3/8] mtd: rawnand: toshiba: Set the pairing scheme for TC58TEG5DCLTA00
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
  2019-12-30 16:51 ` [PATCH 1/8] mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00 Miquel Raynal
  2019-12-30 16:51 ` [PATCH 2/8] mtd: rawnand: Define the "distance 3" MLC pairing scheme Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2019-12-30 16:51 ` [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs Miquel Raynal
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

TC58TEG5DCLTA00 uses a stride of 3 between its lower and upper page.
Set the appropriate pairing scheme at init time.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_toshiba.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 9114b96880d7..ed758ff80080 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -142,8 +142,11 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 
 static int tc58teg5dclta00_init(struct nand_chip *chip)
 {
+	struct mtd_info *mtd = nand_to_mtd(chip);
+
 	chip->onfi_timing_mode_default = 5;
 	chip->options |= NAND_NEED_SCRAMBLING;
+	mtd_set_pairing_scheme(mtd, &dist3_pairing_scheme);
 
 	return 0;
 }
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
                   ` (2 preceding siblings ...)
  2019-12-30 16:51 ` [PATCH 3/8] mtd: rawnand: toshiba: Set the pairing scheme for TC58TEG5DCLTA00 Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2020-01-08 23:49   ` Richard Weinberger
  2019-12-30 16:51 ` [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property Miquel Raynal
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

MLC NANDs can be made a bit more reliable if we only program the lower
page of each pair. At least, this solves the paired-pages corruption
issue.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/mtdcore.c          | 189 ++++++++++++++++++++++++++++++---
 drivers/mtd/mtdpart.c          |  54 ++++++----
 include/linux/mtd/mtd.h        |   7 +-
 include/linux/mtd/partitions.h |   2 +
 include/uapi/mtd/mtd-abi.h     |   1 +
 5 files changed, 213 insertions(+), 40 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 2916674208b3..de0a692ecb29 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -617,6 +617,19 @@ int add_mtd_device(struct mtd_info *mtd)
 		    !(mtd->flags & MTD_NO_ERASE)))
 		return -EINVAL;
 
+	/*
+	 * MTD_MLC_IN_SLC_MODE can only be set on partitions, when the master
+	 * is an MLC NAND and has a proper pairing scheme defined.
+	 * We also reject masters that implement ->_writev() for now, because
+	 * NAND controller drivers don't implement this hook, and adding the
+	 * SLC -> MLC address/length conversion to this path is useless if we
+	 * don't have a user.
+	 */
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE &&
+	    (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH ||
+	     !master->pairing || master->_writev))
+		return -EINVAL;
+
 	mutex_lock(&mtd_table_mutex);
 
 	i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
@@ -632,6 +645,14 @@ int add_mtd_device(struct mtd_info *mtd)
 	if (mtd->bitflip_threshold == 0)
 		mtd->bitflip_threshold = mtd->ecc_strength;
 
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+		int ngroups = mtd_pairing_groups(master);
+
+		mtd->erasesize /= ngroups;
+		mtd->size = (u64)mtd_div_by_eb(mtd->size, master) *
+			    mtd->erasesize;
+	}
+
 	if (is_power_of_2(mtd->erasesize))
 		mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
 	else
@@ -1074,9 +1095,11 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 	u64 mst_ofs = mtd_get_master_ofs(mtd, 0);
+	struct erase_info adjinstr;
 	int ret;
 
 	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
+	adjinstr = *instr;
 
 	if (!mtd->erasesize || !master->_erase)
 		return -ENOTSUPP;
@@ -1091,12 +1114,27 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	ledtrig_mtd_activity();
 
-	instr->addr += mst_ofs;
-	ret = master->_erase(master, instr);
-	if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
-		instr->fail_addr -= mst_ofs;
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
+				master->erasesize;
+		adjinstr.len = ((u64)mtd_div_by_eb(instr->addr + instr->len, mtd) *
+				master->erasesize) -
+			       adjinstr.addr;
+	}
+
+	adjinstr.addr += mst_ofs;
+
+	ret = master->_erase(master, &adjinstr);
+
+	if (adjinstr.fail_addr != MTD_FAIL_ADDR_UNKNOWN) {
+		instr->fail_addr = adjinstr.fail_addr - mst_ofs;
+		if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+			instr->fail_addr = mtd_div_by_eb(instr->fail_addr,
+							 master);
+			instr->fail_addr *= mtd->erasesize;
+		}
+	}
 
-	instr->addr -= mst_ofs;
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase);
@@ -1276,6 +1314,101 @@ static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs,
 	return 0;
 }
 
+static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
+			    struct mtd_oob_ops *ops)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
+
+	from = mtd_get_master_ofs(mtd, from);
+	if (master->_read_oob)
+		ret = master->_read_oob(master, from, ops);
+	else
+		ret = master->_read(master, from, ops->len, &ops->retlen,
+				    ops->datbuf);
+
+	return ret;
+}
+
+static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
+			     struct mtd_oob_ops *ops)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
+
+	to = mtd_get_master_ofs(mtd, to);
+	if (master->_write_oob)
+		ret = master->_write_oob(master, to, ops);
+	else
+		ret = master->_write(master, to, ops->len, &ops->retlen,
+				     ops->datbuf);
+
+	return ret;
+}
+
+static int mtd_oob_io_slc(struct mtd_info *mtd, loff_t start, bool read,
+			  struct mtd_oob_ops *ops)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+	int ngroups = mtd_pairing_groups(master);
+	int npairs = mtd_wunit_per_eb(master) / ngroups;
+	struct mtd_oob_ops adjops = *ops;
+	unsigned int wunit, oobavail;
+	struct mtd_pairing_info info;
+	int max_bitflips = 0;
+	u32 ebofs, pageofs;
+	loff_t base, pos;
+
+	ebofs = mtd_mod_by_eb(start, mtd);
+	base = (loff_t)mtd_div_by_eb(start, mtd) * master->erasesize;
+	info.group = 0;
+	info.pair = mtd_div_by_ws(ebofs, mtd);
+	pageofs = mtd_mod_by_ws(ebofs, mtd);
+	oobavail = mtd_oobavail(mtd, ops);
+
+	while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) {
+		int ret;
+
+		if (info.pair >= npairs) {
+			info.pair = 0;
+			base += master->erasesize;
+		}
+
+		wunit = mtd_pairing_info_to_wunit(master, &info);
+		pos = mtd_wunit_to_offset(mtd, base, wunit);
+
+		adjops.len = ops->len - ops->retlen;
+		if (adjops.len > mtd->writesize - pageofs)
+			adjops.len = mtd->writesize - pageofs;
+
+		adjops.ooblen = ops->ooblen - ops->oobretlen;
+		if (adjops.ooblen > oobavail - adjops.ooboffs)
+			adjops.ooblen = oobavail - adjops.ooboffs;
+
+		if (read) {
+			ret = mtd_read_oob_std(mtd, pos + pageofs, &adjops);
+			if (ret > 0)
+				max_bitflips = max(max_bitflips, ret);
+		} else {
+			ret = mtd_write_oob_std(mtd, pos + pageofs, &adjops);
+		}
+
+		if (ret < 0)
+			return ret;
+
+		max_bitflips = max(max_bitflips, ret);
+		ops->retlen += adjops.retlen;
+		ops->oobretlen += adjops.oobretlen;
+		adjops.datbuf += adjops.retlen;
+		adjops.oobbuf += adjops.oobretlen;
+		adjops.ooboffs = 0;
+		pageofs = 0;
+		info.pair++;
+	}
+
+	return max_bitflips;
+}
+
 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
@@ -1294,12 +1427,10 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 	if (!master->_read_oob && (!master->_read || ops->oobbuf))
 		return -EOPNOTSUPP;
 
-	from = mtd_get_master_ofs(mtd, from);
-	if (master->_read_oob)
-		ret_code = master->_read_oob(master, from, ops);
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE)
+		ret_code = mtd_oob_io_slc(mtd, from, true, ops);
 	else
-		ret_code = master->_read(master, from, ops->len, &ops->retlen,
-					 ops->datbuf);
+		ret_code = mtd_read_oob_std(mtd, from, ops);
 
 	mtd_update_ecc_stats(mtd, master, &old_stats);
 
@@ -1338,13 +1469,10 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	if (!master->_write_oob && (!master->_write || ops->oobbuf))
 		return -EOPNOTSUPP;
 
-	to = mtd_get_master_ofs(mtd, to);
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE)
+		return mtd_oob_io_slc(mtd, to, false, ops);
 
-	if (master->_write_oob)
-		return master->_write_oob(master, to, ops);
-	else
-		return master->_write(master, to, ops->len, &ops->retlen,
-				      ops->datbuf);
+	return mtd_write_oob_std(mtd, to, ops);
 }
 EXPORT_SYMBOL_GPL(mtd_write_oob);
 
@@ -1817,6 +1945,12 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
+
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
+	}
+
 	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
 }
 EXPORT_SYMBOL_GPL(mtd_lock);
@@ -1831,6 +1965,12 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
+
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
+	}
+
 	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
 }
 EXPORT_SYMBOL_GPL(mtd_unlock);
@@ -1845,6 +1985,12 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
+
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
+	}
+
 	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
@@ -1857,6 +2003,10 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 		return -EINVAL;
 	if (!master->_block_isreserved)
 		return 0;
+
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE)
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+
 	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
 }
 EXPORT_SYMBOL_GPL(mtd_block_isreserved);
@@ -1869,6 +2019,10 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 		return -EINVAL;
 	if (!master->_block_isbad)
 		return 0;
+
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE)
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+
 	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
@@ -1885,6 +2039,9 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (!(mtd->flags & MTD_WRITEABLE))
 		return -EROFS;
 
+	if (mtd->flags & MTD_MLC_IN_SLC_MODE)
+		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
+
 	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
 	if (ret)
 		return ret;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 93ef8fdf1634..ca2d213f70a1 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -35,9 +35,12 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 					   const struct mtd_partition *part,
 					   int partno, uint64_t cur_offset)
 {
-	int wr_alignment = (parent->flags & MTD_NO_ERASE) ? parent->writesize :
-							    parent->erasesize;
-	struct mtd_info *child, *master = mtd_get_master(parent);
+	struct mtd_info *master = mtd_get_master(parent);
+	int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
+			   master->writesize : master->erasesize;
+	u64 parent_size = mtd_is_partition(parent) ?
+			  parent->part.size : parent->size;
+	struct mtd_info *child;
 	u32 remainder;
 	char *name;
 	u64 tmp;
@@ -56,8 +59,9 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 	/* set up the MTD object for this partition */
 	child->type = parent->type;
 	child->part.flags = parent->flags & ~part->mask_flags;
+	child->part.flags |= part->add_flags;
 	child->flags = child->part.flags;
-	child->size = part->size;
+	child->part.size = part->size;
 	child->writesize = parent->writesize;
 	child->writebufsize = parent->writebufsize;
 	child->oobsize = parent->oobsize;
@@ -98,29 +102,29 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 	}
 	if (child->part.offset == MTDPART_OFS_RETAIN) {
 		child->part.offset = cur_offset;
-		if (parent->size - child->part.offset >= child->size) {
-			child->size = parent->size - child->part.offset -
-				      child->size;
+		if (parent_size - child->part.offset >= child->part.size) {
+			child->part.size = parent_size - child->part.offset -
+					   child->part.size;
 		} else {
 			printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
-				part->name, parent->size - child->part.offset,
-				child->size);
+				part->name, parent_size - child->part.offset,
+				child->part.size);
 			/* register to preserve ordering */
 			goto out_register;
 		}
 	}
-	if (child->size == MTDPART_SIZ_FULL)
-		child->size = parent->size - child->part.offset;
+	if (child->part.size == MTDPART_SIZ_FULL)
+		child->part.size = parent_size - child->part.offset;
 
 	printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n",
-	       child->part.offset, child->part.offset + child->size,
+	       child->part.offset, child->part.offset + child->part.size,
 	       child->name);
 
 	/* let's do some sanity checks */
-	if (child->part.offset >= parent->size) {
+	if (child->part.offset >= parent_size) {
 		/* let's register it anyway to preserve ordering */
 		child->part.offset = 0;
-		child->size = 0;
+		child->part.size = 0;
 
 		/* Initialize ->erasesize to make add_mtd_device() happy. */
 		child->erasesize = parent->erasesize;
@@ -128,15 +132,16 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 			part->name);
 		goto out_register;
 	}
-	if (child->part.offset + child->size > parent->size) {
-		child->size = parent->size - child->part.offset;
+	if (child->part.offset + child->part.size > parent->size) {
+		child->part.size = parent_size - child->part.offset;
 		printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",
-			part->name, parent->name, child->size);
+			part->name, parent->name, child->part.size);
 	}
+
 	if (parent->numeraseregions > 1) {
 		/* Deal with variable erase size stuff */
 		int i, max = parent->numeraseregions;
-		u64 end = child->part.offset + child->size;
+		u64 end = child->part.offset + child->part.size;
 		struct mtd_erase_region_info *regions = parent->eraseregions;
 
 		/* Find the first erase regions which is part of this
@@ -156,7 +161,7 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 		BUG_ON(child->erasesize == 0);
 	} else {
 		/* Single erase size */
-		child->erasesize = parent->erasesize;
+		child->erasesize = master->erasesize;
 	}
 
 	/*
@@ -178,7 +183,7 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 			part->name);
 	}
 
-	tmp = mtd_get_master_ofs(child, 0) + child->size;
+	tmp = mtd_get_master_ofs(child, 0) + child->part.size;
 	remainder = do_div(tmp, wr_alignment);
 	if ((child->flags & MTD_WRITEABLE) && remainder) {
 		child->flags &= ~MTD_WRITEABLE;
@@ -186,6 +191,7 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 			part->name);
 	}
 
+	child->size = child->part.size;
 	child->ecc_step_size = parent->ecc_step_size;
 	child->ecc_strength = parent->ecc_strength;
 	child->bitflip_threshold = parent->bitflip_threshold;
@@ -193,7 +199,7 @@ static struct mtd_info *allocate_partition(struct mtd_info *parent,
 	if (master->_block_isbad) {
 		uint64_t offs = 0;
 
-		while (offs < child->size) {
+		while (offs < child->part.size) {
 			if (mtd_block_isreserved(child, offs))
 				child->ecc_stats.bbtblocks++;
 			else if (mtd_block_isbad(child, offs))
@@ -234,6 +240,8 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
 		      long long offset, long long length)
 {
 	struct mtd_info *master = mtd_get_master(parent);
+	u64 parent_size = mtd_is_partition(parent) ?
+			  parent->part.size : parent->size;
 	struct mtd_partition part;
 	struct mtd_info *child;
 	int ret = 0;
@@ -244,7 +252,7 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
 		return -EINVAL;
 
 	if (length == MTDPART_SIZ_FULL)
-		length = parent->size - offset;
+		length = parent_size - offset;
 
 	if (length <= 0)
 		return -EINVAL;
@@ -419,7 +427,7 @@ int add_mtd_partitions(struct mtd_info *parent,
 		/* Look for subpartitions */
 		parse_mtd_partitions(child, parts[i].types, NULL);
 
-		cur_offset = child->part.offset + child->size;
+		cur_offset = child->part.offset + child->part.size;
 	}
 
 	return 0;
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 508d14d45439..9fcac902d989 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -200,6 +200,8 @@ struct mtd_debug_info {
  *
  * @node: list node used to add an MTD partition to the parent partition list
  * @offset: offset of the partition relatively to the parent offset
+ * @size: partition size. Should be equal to mtd->size unless
+ *	  MTD_MLC_IN_SLC_MODE is set
  * @flags: original flags (before the mtdpart logic decided to tweak them based
  *	   on flash constraints, like eraseblock/pagesize alignment)
  *
@@ -209,6 +211,7 @@ struct mtd_debug_info {
 struct mtd_part {
 	struct list_head node;
 	u64 offset;
+	u64 size;
 	u32 flags;
 };
 
@@ -619,7 +622,9 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
 
 static inline int mtd_wunit_per_eb(struct mtd_info *mtd)
 {
-	return mtd->erasesize / mtd->writesize;
+	struct mtd_info *master = mtd_get_master(mtd);
+
+	return master->erasesize / mtd->writesize;
 }
 
 static inline int mtd_offset_to_wunit(struct mtd_info *mtd, loff_t offs)
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index e545c050d3e8..b74a539ec581 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -37,6 +37,7 @@
  * 	master MTD flag set for the corresponding MTD partition.
  * 	For example, to force a read-only partition, simply adding
  * 	MTD_WRITEABLE to the mask_flags will do the trick.
+ * add_flags: contains flags to add to the parent flags
  *
  * Note: writeable partitions require their size and offset be
  * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
@@ -48,6 +49,7 @@ struct mtd_partition {
 	uint64_t size;			/* partition size */
 	uint64_t offset;		/* offset within the master MTD space */
 	uint32_t mask_flags;		/* master MTD flags to mask out for this partition */
+	uint32_t add_flags;		/* flags to add to the partition */
 	struct device_node *of_node;
 };
 
diff --git a/include/uapi/mtd/mtd-abi.h b/include/uapi/mtd/mtd-abi.h
index 47ffe3208c27..4af24cc56b88 100644
--- a/include/uapi/mtd/mtd-abi.h
+++ b/include/uapi/mtd/mtd-abi.h
@@ -104,6 +104,7 @@ struct mtd_write_req {
 #define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
 #define MTD_NO_ERASE		0x1000	/* No erase necessary */
 #define MTD_POWERUP_LOCK	0x2000	/* Always locked after reset */
+#define MTD_MLC_IN_SLC_MODE	0x4000	/* Emulate SLC behavior on MLC NANDs */
 
 /* Some common devices / combinations of capabilities */
 #define MTD_CAP_ROM		0
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
                   ` (3 preceding siblings ...)
  2019-12-30 16:51 ` [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2019-12-31  3:53   ` Florian Fainelli
  2019-12-30 16:51 ` [PATCH 6/8] mtd: partitions: ofpart: Parse " Miquel Raynal
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

Add a boolean property to force a specific partition attached to an MLC
NAND to be accessed in an emulated SLC mode this making this partition
immune to paired-pages corruptions.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 .../devicetree/bindings/mtd/partition.txt       |   3 +++
  | Bin 0 -> 22416 bytes
 2 files changed, 3 insertions(+)
 create mode 100755 scripts/pnmtologo

diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
index afbbd870496d..4a39698221a2 100644
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ b/Documentation/devicetree/bindings/mtd/partition.txt
@@ -61,6 +61,9 @@ Optional properties:
   clobbered.
 - lock : Do not unlock the partition at initialization time (not supported on
   all devices)
+- slc-mode: This parameter, if present, allows one to emulate SLC mode on a
+  partition attached to an MLC NAND thus making this partition immune to
+  paired-pages corruptions
 
 Examples:
 
 --git a/scripts/pnmtologo b/scripts/pnmtologo
new file mode 100755
index 0000000000000000000000000000000000000000..ddb4f779cfa46fd92b802097fb2dd301bbe91912
GIT binary patch
literal 22416
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

literal 0
HcmV?d00001

-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 6/8] mtd: partitions: ofpart: Parse the slc-mode property
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
                   ` (4 preceding siblings ...)
  2019-12-30 16:51 ` [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property Miquel Raynal
@ 2019-12-30 16:51 ` " Miquel Raynal
  2019-12-30 16:51 ` [PATCH 7/8] mtd: cmdlinepart: Add an slc option to use SLC mode on a part Miquel Raynal
  2019-12-30 16:51 ` [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode Miquel Raynal
  7 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

Parse the slc-mode property and set the MTD_MLC_IN_SLC_MODE flag when
present.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/parsers/ofpart.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/parsers/ofpart.c b/drivers/mtd/parsers/ofpart.c
index 3caeabf27987..0a67fd15ab54 100644
--- a/drivers/mtd/parsers/ofpart.c
+++ b/drivers/mtd/parsers/ofpart.c
@@ -117,6 +117,9 @@ static int parse_fixed_partitions(struct mtd_info *master,
 		if (of_get_property(pp, "lock", &len))
 			parts[i].mask_flags |= MTD_POWERUP_LOCK;
 
+		if (of_property_read_bool(pp, "slc-mode"))
+			parts[i].add_flags |= MTD_MLC_IN_SLC_MODE;
+
 		i++;
 	}
 
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 7/8] mtd: cmdlinepart: Add an slc option to use SLC mode on a part
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
                   ` (5 preceding siblings ...)
  2019-12-30 16:51 ` [PATCH 6/8] mtd: partitions: ofpart: Parse " Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2019-12-30 16:51 ` [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode Miquel Raynal
  7 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

Add a new option to set the MTD_MLC_IN_SLC_MODE flag.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/parsers/cmdlinepart.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/parsers/cmdlinepart.c b/drivers/mtd/parsers/cmdlinepart.c
index c86f2db8c882..089fdf83b088 100644
--- a/drivers/mtd/parsers/cmdlinepart.c
+++ b/drivers/mtd/parsers/cmdlinepart.c
@@ -9,7 +9,7 @@
  *
  * mtdparts=<mtddef>[;<mtddef]
  * <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
- * <partdef> := <size>[@<offset>][<name>][ro][lk]
+ * <partdef> := <size>[@<offset>][<name>][ro][lk][slc]
  * <mtd-id>  := unique name used in mapping driver/device (mtd->name)
  * <size>    := standard linux memsize OR "-" to denote all remaining space
  *              size is automatically truncated at end of device
@@ -92,7 +92,7 @@ static struct mtd_partition * newpart(char *s,
 	int name_len;
 	unsigned char *extra_mem;
 	char delim;
-	unsigned int mask_flags;
+	unsigned int mask_flags, add_flags;
 
 	/* fetch the partition size */
 	if (*s == '-') {
@@ -109,6 +109,7 @@ static struct mtd_partition * newpart(char *s,
 
 	/* fetch partition name and flags */
 	mask_flags = 0; /* this is going to be a regular partition */
+	add_flags = 0;
 	delim = 0;
 
 	/* check for offset */
@@ -152,6 +153,12 @@ static struct mtd_partition * newpart(char *s,
 		s += 2;
 	}
 
+	/* if slc is found use emulated SLC mode on this partition*/
+	if (!strncmp(s, "slc", 3)) {
+		add_flags |= MTD_MLC_IN_SLC_MODE;
+		s += 3;
+	}
+
 	/* test if more partitions are following */
 	if (*s == ',') {
 		if (size == SIZE_REMAINING) {
@@ -184,6 +191,7 @@ static struct mtd_partition * newpart(char *s,
 	parts[this_part].size = size;
 	parts[this_part].offset = offset;
 	parts[this_part].mask_flags = mask_flags;
+	parts[this_part].add_flags = add_flags;
 	if (name)
 		strlcpy(extra_mem, name, name_len + 1);
 	else
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode
  2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
                   ` (6 preceding siblings ...)
  2019-12-30 16:51 ` [PATCH 7/8] mtd: cmdlinepart: Add an slc option to use SLC mode on a part Miquel Raynal
@ 2019-12-30 16:51 ` Miquel Raynal
  2020-01-08 23:50   ` Richard Weinberger
  7 siblings, 1 reply; 18+ messages in thread
From: Miquel Raynal @ 2019-12-30 16:51 UTC (permalink / raw)
  To: Richard Weinberger, Vignesh Raghavendra, Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni, Miquel Raynal

From: Boris Brezillon <boris.brezillon@bootlin.com>

The MTD layer provides an SLC mode (purely software emulation of SLC
behavior) addressing the paired-pages corruption issue, which was the
main reason for refusing attaching MLC NANDs to UBI.

Relax this rule and allow partitions that have the MTD_MLC_IN_SLC_MODE
flag set to be attached.

Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/ubi/build.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index d636bbe214cb..d917cc4cd937 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -846,8 +846,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
 	 * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes.
 	 * MLC NAND is different and needs special care, otherwise UBI or UBIFS
 	 * will die soon and you will lose all your data.
+	 * Relax this rule if the partition we're attaching to operates in SLC
+	 * mode.
 	 */
-	if (mtd->type == MTD_MLCNANDFLASH) {
+	if (mtd->type == MTD_MLCNANDFLASH &&
+	    !(mtd->flags & MTD_MLC_IN_SLC_MODE)) {
 		pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n",
 			mtd->index);
 		return -EINVAL;
-- 
2.20.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property
  2019-12-30 16:51 ` [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property Miquel Raynal
@ 2019-12-31  3:53   ` Florian Fainelli
  2020-01-14  9:33     ` Miquel Raynal
  0 siblings, 1 reply; 18+ messages in thread
From: Florian Fainelli @ 2019-12-31  3:53 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Tudor Ambarus, linux-mtd
  Cc: Boris Brezillon, Boris Brezillon, Thomas Petazzoni



On 12/30/2019 8:51 AM, Miquel Raynal wrote:
> From: Boris Brezillon <boris.brezillon@bootlin.com>
> 
> Add a boolean property to force a specific partition attached to an MLC
> NAND to be accessed in an emulated SLC mode this making this partition
> immune to paired-pages corruptions.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  .../devicetree/bindings/mtd/partition.txt       |   3 +++
>  scripts/pnmtologo                               | Bin 0 -> 22416 bytes

You will probably want to remove that file from the final commit and/or
add pnmtologo to .gitignore as a separate patch.
-- 
Florian

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2019-12-30 16:51 ` [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs Miquel Raynal
@ 2020-01-08 23:49   ` Richard Weinberger
  2020-01-09 18:16     ` Miquel Raynal
  2020-01-14 10:04     ` Miquel Raynal
  0 siblings, 2 replies; 18+ messages in thread
From: Richard Weinberger @ 2020-01-08 23:49 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

----- Ursprüngliche Mail -----
> Von: "Miquel Raynal" <miquel.raynal@bootlin.com>
> An: "richard" <richard@nod.at>, "Vignesh Raghavendra" <vigneshr@ti.com>, "Tudor Ambarus" <Tudor.Ambarus@microchip.com>,
> "linux-mtd" <linux-mtd@lists.infradead.org>
> CC: "Boris Brezillon" <boris.brezillon@collabora.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Boris
> Brezillon" <boris.brezillon@bootlin.com>, "Miquel Raynal" <miquel.raynal@bootlin.com>
> Gesendet: Montag, 30. Dezember 2019 17:51:25
> Betreff: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs

> From: Boris Brezillon <boris.brezillon@bootlin.com>
> 
> MLC NANDs can be made a bit more reliable if we only program the lower
> page of each pair. At least, this solves the paired-pages corruption
> issue.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/mtdcore.c          | 189 ++++++++++++++++++++++++++++++---
> drivers/mtd/mtdpart.c          |  54 ++++++----
> include/linux/mtd/mtd.h        |   7 +-
> include/linux/mtd/partitions.h |   2 +
> include/uapi/mtd/mtd-abi.h     |   1 +
> 5 files changed, 213 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 2916674208b3..de0a692ecb29 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -617,6 +617,19 @@ int add_mtd_device(struct mtd_info *mtd)
> 		    !(mtd->flags & MTD_NO_ERASE)))
> 		return -EINVAL;
> 
> +	/*
> +	 * MTD_MLC_IN_SLC_MODE can only be set on partitions, when the master

I suggest giving a name which indicates that we are actually emulating
an SLC. Maybe MTD_SLC_EMULATION?
Some MLC NANDs support SLC mode in hardware, MTD_MLC_IN_SLC_MODE reads like
this feature.

> +	 * is an MLC NAND and has a proper pairing scheme defined.
> +	 * We also reject masters that implement ->_writev() for now, because
> +	 * NAND controller drivers don't implement this hook, and adding the
> +	 * SLC -> MLC address/length conversion to this path is useless if we
> +	 * don't have a user.
> +	 */
> +	if (mtd->flags & MTD_MLC_IN_SLC_MODE &&
> +	    (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH ||
> +	     !master->pairing || master->_writev))
> +		return -EINVAL;
> +
> 	mutex_lock(&mtd_table_mutex);
> 
> 	i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
> @@ -632,6 +645,14 @@ int add_mtd_device(struct mtd_info *mtd)
> 	if (mtd->bitflip_threshold == 0)
> 		mtd->bitflip_threshold = mtd->ecc_strength;
> 
> +	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> +		int ngroups = mtd_pairing_groups(master);
> +
> +		mtd->erasesize /= ngroups;
> +		mtd->size = (u64)mtd_div_by_eb(mtd->size, master) *
> +			    mtd->erasesize;

Can we please have a helper for this? You use this formula many times.

> +	}
> +
> 	if (is_power_of_2(mtd->erasesize))
> 		mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
> 	else
> @@ -1074,9 +1095,11 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info
> *instr)
> {
> 	struct mtd_info *master = mtd_get_master(mtd);
> 	u64 mst_ofs = mtd_get_master_ofs(mtd, 0);
> +	struct erase_info adjinstr;
> 	int ret;
> 
> 	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
> +	adjinstr = *instr;
> 
> 	if (!mtd->erasesize || !master->_erase)
> 		return -ENOTSUPP;
> @@ -1091,12 +1114,27 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info
> *instr)
> 
> 	ledtrig_mtd_activity();
> 
> -	instr->addr += mst_ofs;
> -	ret = master->_erase(master, instr);
> -	if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
> -		instr->fail_addr -= mst_ofs;
> +	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> +		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
> +				master->erasesize;
> +		adjinstr.len = ((u64)mtd_div_by_eb(instr->addr + instr->len, mtd) *
> +				master->erasesize) -
> +			       adjinstr.addr;
> +	}
> +
> +	adjinstr.addr += mst_ofs;
> +
> +	ret = master->_erase(master, &adjinstr);
> +
> +	if (adjinstr.fail_addr != MTD_FAIL_ADDR_UNKNOWN) {
> +		instr->fail_addr = adjinstr.fail_addr - mst_ofs;
> +		if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> +			instr->fail_addr = mtd_div_by_eb(instr->fail_addr,
> +							 master);
> +			instr->fail_addr *= mtd->erasesize;
> +		}
> +	}
> 
> -	instr->addr -= mst_ofs;
> 	return ret;
> }
> EXPORT_SYMBOL_GPL(mtd_erase);
> @@ -1276,6 +1314,101 @@ static int mtd_check_oob_ops(struct mtd_info *mtd,
> loff_t offs,
> 	return 0;
> }
> 
> +static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
> +			    struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
> +
> +	from = mtd_get_master_ofs(mtd, from);
> +	if (master->_read_oob)
> +		ret = master->_read_oob(master, from, ops);
> +	else
> +		ret = master->_read(master, from, ops->len, &ops->retlen,
> +				    ops->datbuf);
> +
> +	return ret;
> +}
> +
> +static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
> +			     struct mtd_oob_ops *ops)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
> +
> +	to = mtd_get_master_ofs(mtd, to);
> +	if (master->_write_oob)
> +		ret = master->_write_oob(master, to, ops);
> +	else
> +		ret = master->_write(master, to, ops->len, &ops->retlen,
> +				     ops->datbuf);
> +
> +	return ret;
> +}
> +
> +static int mtd_oob_io_slc(struct mtd_info *mtd, loff_t start, bool read,
> +			  struct mtd_oob_ops *ops)

The name is misleading. We don't do OOB IO on a SLC NAND,
we emulate SLC.

Thanks,
//richard

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode
  2019-12-30 16:51 ` [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode Miquel Raynal
@ 2020-01-08 23:50   ` Richard Weinberger
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Weinberger @ 2020-01-08 23:50 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

----- Ursprüngliche Mail -----
> Von: "Miquel Raynal" <miquel.raynal@bootlin.com>
> An: "richard" <richard@nod.at>, "Vignesh Raghavendra" <vigneshr@ti.com>, "Tudor Ambarus" <Tudor.Ambarus@microchip.com>,
> "linux-mtd" <linux-mtd@lists.infradead.org>
> CC: "Boris Brezillon" <boris.brezillon@collabora.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Boris
> Brezillon" <boris.brezillon@bootlin.com>, "Miquel Raynal" <miquel.raynal@bootlin.com>
> Gesendet: Montag, 30. Dezember 2019 17:51:29
> Betreff: [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode

> From: Boris Brezillon <boris.brezillon@bootlin.com>
> 
> The MTD layer provides an SLC mode (purely software emulation of SLC
> behavior) addressing the paired-pages corruption issue, which was the
> main reason for refusing attaching MLC NANDs to UBI.
> 
> Relax this rule and allow partitions that have the MTD_MLC_IN_SLC_MODE
> flag set to be attached.
> 
> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> drivers/mtd/ubi/build.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> index d636bbe214cb..d917cc4cd937 100644
> --- a/drivers/mtd/ubi/build.c
> +++ b/drivers/mtd/ubi/build.c
> @@ -846,8 +846,11 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
> 	 * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes.
> 	 * MLC NAND is different and needs special care, otherwise UBI or UBIFS
> 	 * will die soon and you will lose all your data.
> +	 * Relax this rule if the partition we're attaching to operates in SLC
> +	 * mode.
> 	 */
> -	if (mtd->type == MTD_MLCNANDFLASH) {
> +	if (mtd->type == MTD_MLCNANDFLASH &&
> +	    !(mtd->flags & MTD_MLC_IN_SLC_MODE)) {
> 		pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n",
> 			mtd->index);
> 		return -EINVAL;

Acked-by: Richard Weinberger <richard@nod.at>

Thanks,
//richard

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2020-01-08 23:49   ` Richard Weinberger
@ 2020-01-09 18:16     ` Miquel Raynal
  2020-01-09 18:39       ` Richard Weinberger
  2020-01-14 10:04     ` Miquel Raynal
  1 sibling, 1 reply; 18+ messages in thread
From: Miquel Raynal @ 2020-01-09 18:16 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

Hi Richard,

Richard Weinberger <richard@nod.at> wrote on Thu, 9 Jan 2020 00:49:02
+0100 (CET):

> ----- Ursprüngliche Mail -----
> > Von: "Miquel Raynal" <miquel.raynal@bootlin.com>
> > An: "richard" <richard@nod.at>, "Vignesh Raghavendra" <vigneshr@ti.com>, "Tudor Ambarus" <Tudor.Ambarus@microchip.com>,
> > "linux-mtd" <linux-mtd@lists.infradead.org>
> > CC: "Boris Brezillon" <boris.brezillon@collabora.com>, "Thomas Petazzoni" <thomas.petazzoni@bootlin.com>, "Boris
> > Brezillon" <boris.brezillon@bootlin.com>, "Miquel Raynal" <miquel.raynal@bootlin.com>
> > Gesendet: Montag, 30. Dezember 2019 17:51:25
> > Betreff: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs  
> 
> > From: Boris Brezillon <boris.brezillon@bootlin.com>
> > 
> > MLC NANDs can be made a bit more reliable if we only program the lower
> > page of each pair. At least, this solves the paired-pages corruption
> > issue.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> > drivers/mtd/mtdcore.c          | 189 ++++++++++++++++++++++++++++++---
> > drivers/mtd/mtdpart.c          |  54 ++++++----
> > include/linux/mtd/mtd.h        |   7 +-
> > include/linux/mtd/partitions.h |   2 +
> > include/uapi/mtd/mtd-abi.h     |   1 +
> > 5 files changed, 213 insertions(+), 40 deletions(-)
> > 
> > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > index 2916674208b3..de0a692ecb29 100644
> > --- a/drivers/mtd/mtdcore.c
> > +++ b/drivers/mtd/mtdcore.c
> > @@ -617,6 +617,19 @@ int add_mtd_device(struct mtd_info *mtd)
> > 		    !(mtd->flags & MTD_NO_ERASE)))
> > 		return -EINVAL;
> > 
> > +	/*
> > +	 * MTD_MLC_IN_SLC_MODE can only be set on partitions, when the master  
> 
> I suggest giving a name which indicates that we are actually emulating
> an SLC. Maybe MTD_SLC_EMULATION?
> Some MLC NANDs support SLC mode in hardware, MTD_MLC_IN_SLC_MODE reads like
> this feature.

You're right. What about MTD_SLC_ON_MLC_EMULATION?

I like to see that we are manipulating MLC NANDs.

> 
> > +	 * is an MLC NAND and has a proper pairing scheme defined.
> > +	 * We also reject masters that implement ->_writev() for now, because
> > +	 * NAND controller drivers don't implement this hook, and adding the
> > +	 * SLC -> MLC address/length conversion to this path is useless if we
> > +	 * don't have a user.
> > +	 */
> > +	if (mtd->flags & MTD_MLC_IN_SLC_MODE &&
> > +	    (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH ||
> > +	     !master->pairing || master->_writev))
> > +		return -EINVAL;
> > +
> > 	mutex_lock(&mtd_table_mutex);
> > 
> > 	i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
> > @@ -632,6 +645,14 @@ int add_mtd_device(struct mtd_info *mtd)
> > 	if (mtd->bitflip_threshold == 0)
> > 		mtd->bitflip_threshold = mtd->ecc_strength;
> > 
> > +	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> > +		int ngroups = mtd_pairing_groups(master);
> > +
> > +		mtd->erasesize /= ngroups;
> > +		mtd->size = (u64)mtd_div_by_eb(mtd->size, master) *
> > +			    mtd->erasesize;  
> 
> Can we please have a helper for this? You use this formula many times.

Absolutely!

> 
> > +	}
> > +
> > 	if (is_power_of_2(mtd->erasesize))
> > 		mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
> > 	else
> > @@ -1074,9 +1095,11 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info
> > *instr)
> > {
> > 	struct mtd_info *master = mtd_get_master(mtd);
> > 	u64 mst_ofs = mtd_get_master_ofs(mtd, 0);
> > +	struct erase_info adjinstr;
> > 	int ret;
> > 
> > 	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
> > +	adjinstr = *instr;
> > 
> > 	if (!mtd->erasesize || !master->_erase)
> > 		return -ENOTSUPP;
> > @@ -1091,12 +1114,27 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info
> > *instr)
> > 
> > 	ledtrig_mtd_activity();
> > 
> > -	instr->addr += mst_ofs;
> > -	ret = master->_erase(master, instr);
> > -	if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
> > -		instr->fail_addr -= mst_ofs;
> > +	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> > +		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
> > +				master->erasesize;
> > +		adjinstr.len = ((u64)mtd_div_by_eb(instr->addr + instr->len, mtd) *
> > +				master->erasesize) -
> > +			       adjinstr.addr;
> > +	}
> > +
> > +	adjinstr.addr += mst_ofs;
> > +
> > +	ret = master->_erase(master, &adjinstr);
> > +
> > +	if (adjinstr.fail_addr != MTD_FAIL_ADDR_UNKNOWN) {
> > +		instr->fail_addr = adjinstr.fail_addr - mst_ofs;
> > +		if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> > +			instr->fail_addr = mtd_div_by_eb(instr->fail_addr,
> > +							 master);
> > +			instr->fail_addr *= mtd->erasesize;
> > +		}
> > +	}
> > 
> > -	instr->addr -= mst_ofs;
> > 	return ret;
> > }
> > EXPORT_SYMBOL_GPL(mtd_erase);
> > @@ -1276,6 +1314,101 @@ static int mtd_check_oob_ops(struct mtd_info *mtd,
> > loff_t offs,
> > 	return 0;
> > }
> > 
> > +static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
> > +			    struct mtd_oob_ops *ops)
> > +{
> > +	struct mtd_info *master = mtd_get_master(mtd);
> > +	int ret;
> > +
> > +	from = mtd_get_master_ofs(mtd, from);
> > +	if (master->_read_oob)
> > +		ret = master->_read_oob(master, from, ops);
> > +	else
> > +		ret = master->_read(master, from, ops->len, &ops->retlen,
> > +				    ops->datbuf);
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
> > +			     struct mtd_oob_ops *ops)
> > +{
> > +	struct mtd_info *master = mtd_get_master(mtd);
> > +	int ret;
> > +
> > +	to = mtd_get_master_ofs(mtd, to);
> > +	if (master->_write_oob)
> > +		ret = master->_write_oob(master, to, ops);
> > +	else
> > +		ret = master->_write(master, to, ops->len, &ops->retlen,
> > +				     ops->datbuf);
> > +
> > +	return ret;
> > +}
> > +
> > +static int mtd_oob_io_slc(struct mtd_info *mtd, loff_t start, bool read,
> > +			  struct mtd_oob_ops *ops)  
> 
> The name is misleading. We don't do OOB IO on a SLC NAND,
> we emulate SLC.

What would you recommend? mtd_oob_io_emul_slc?

> 
> Thanks,
> //richard

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2020-01-09 18:16     ` Miquel Raynal
@ 2020-01-09 18:39       ` Richard Weinberger
  2020-01-09 19:19         ` Boris Brezillon
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Weinberger @ 2020-01-09 18:39 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

Miquel,

----- Ursprüngliche Mail -----
>> I suggest giving a name which indicates that we are actually emulating
>> an SLC. Maybe MTD_SLC_EMULATION?
>> Some MLC NANDs support SLC mode in hardware, MTD_MLC_IN_SLC_MODE reads like
>> this feature.
> 
> You're right. What about MTD_SLC_ON_MLC_EMULATION?

Makes sense.
  
>> The name is misleading. We don't do OOB IO on a SLC NAND,
>> we emulate SLC.
> 
> What would you recommend? mtd_oob_io_emul_slc?

Yes. Let's use "emul_slc" to indicate SLC emulation.

Thanks,
//richard

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2020-01-09 18:39       ` Richard Weinberger
@ 2020-01-09 19:19         ` Boris Brezillon
  2020-01-09 19:22           ` Miquel Raynal
  0 siblings, 1 reply; 18+ messages in thread
From: Boris Brezillon @ 2020-01-09 19:19 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon, linux-mtd,
	Thomas Petazzoni, Miquel Raynal

On Thu, 9 Jan 2020 19:39:42 +0100 (CET)
Richard Weinberger <richard@nod.at> wrote:

> Miquel,
> 
> ----- Ursprüngliche Mail -----
> >> I suggest giving a name which indicates that we are actually emulating
> >> an SLC. Maybe MTD_SLC_EMULATION?
> >> Some MLC NANDs support SLC mode in hardware, MTD_MLC_IN_SLC_MODE reads like
> >> this feature.  
> > 
> > You're right. What about MTD_SLC_ON_MLC_EMULATION?  
> 
> Makes sense.
>   
> >> The name is misleading. We don't do OOB IO on a SLC NAND,
> >> we emulate SLC.  

We should really replace those mtd_oob_ prefixes by something
more accurate like mtd_io_ at some point (those helpers can do more than
just read/write the OOB region).

> > 
> > What would you recommend? mtd_oob_io_emul_slc?  
> 
> Yes. Let's use "emul_slc" to indicate SLC emulation.

How about mtd_io_emulated_slc()?

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2020-01-09 19:19         ` Boris Brezillon
@ 2020-01-09 19:22           ` Miquel Raynal
  0 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2020-01-09 19:22 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Vignesh Raghavendra, Tudor Ambarus, Richard Weinberger,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Thu, 9 Jan
2020 20:19:35 +0100:

> On Thu, 9 Jan 2020 19:39:42 +0100 (CET)
> Richard Weinberger <richard@nod.at> wrote:
> 
> > Miquel,
> > 
> > ----- Ursprüngliche Mail -----  
> > >> I suggest giving a name which indicates that we are actually emulating
> > >> an SLC. Maybe MTD_SLC_EMULATION?
> > >> Some MLC NANDs support SLC mode in hardware, MTD_MLC_IN_SLC_MODE reads like
> > >> this feature.    
> > > 
> > > You're right. What about MTD_SLC_ON_MLC_EMULATION?    
> > 
> > Makes sense.
> >     
> > >> The name is misleading. We don't do OOB IO on a SLC NAND,
> > >> we emulate SLC.    
> 
> We should really replace those mtd_oob_ prefixes by something
> more accurate like mtd_io_ at some point (those helpers can do more than
> just read/write the OOB region).

I think I have some WIP about this. Not the time for everything just
during these vacations :p

> 
> > > 
> > > What would you recommend? mtd_oob_io_emul_slc?    
> > 
> > Yes. Let's use "emul_slc" to indicate SLC emulation.  
> 
> How about mtd_io_emulated_slc()?

Fine!

Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property
  2019-12-31  3:53   ` Florian Fainelli
@ 2020-01-14  9:33     ` Miquel Raynal
  0 siblings, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2020-01-14  9:33 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: Vignesh Raghavendra, Tudor Ambarus, Richard Weinberger,
	Boris Brezillon, Boris Brezillon, linux-mtd, Thomas Petazzoni

Hi Florian,

Florian Fainelli <f.fainelli@gmail.com> wrote on Mon, 30 Dec 2019
19:53:11 -0800:

> On 12/30/2019 8:51 AM, Miquel Raynal wrote:
> > From: Boris Brezillon <boris.brezillon@bootlin.com>
> > 
> > Add a boolean property to force a specific partition attached to an MLC
> > NAND to be accessed in an emulated SLC mode this making this partition
> > immune to paired-pages corruptions.
> > 
> > Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  .../devicetree/bindings/mtd/partition.txt       |   3 +++
> >  scripts/pnmtologo                               | Bin 0 -> 22416 bytes  
> 
> You will probably want to remove that file from the final commit and/or
> add pnmtologo to .gitignore as a separate patch.

Done, thanks for the warning!


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs
  2020-01-08 23:49   ` Richard Weinberger
  2020-01-09 18:16     ` Miquel Raynal
@ 2020-01-14 10:04     ` Miquel Raynal
  1 sibling, 0 replies; 18+ messages in thread
From: Miquel Raynal @ 2020-01-14 10:04 UTC (permalink / raw)
  To: Richard Weinberger
  Cc: Vignesh Raghavendra, Tudor Ambarus, Boris Brezillon,
	Boris Brezillon, linux-mtd, Thomas Petazzoni

Hi Richard,

A very simple question below.

> 
> > +	 * is an MLC NAND and has a proper pairing scheme defined.
> > +	 * We also reject masters that implement ->_writev() for now, because
> > +	 * NAND controller drivers don't implement this hook, and adding the
> > +	 * SLC -> MLC address/length conversion to this path is useless if we
> > +	 * don't have a user.
> > +	 */
> > +	if (mtd->flags & MTD_MLC_IN_SLC_MODE &&
> > +	    (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH ||
> > +	     !master->pairing || master->_writev))
> > +		return -EINVAL;
> > +
> > 	mutex_lock(&mtd_table_mutex);
> > 
> > 	i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
> > @@ -632,6 +645,14 @@ int add_mtd_device(struct mtd_info *mtd)
> > 	if (mtd->bitflip_threshold == 0)
> > 		mtd->bitflip_threshold = mtd->ecc_strength;
> > 
> > +	if (mtd->flags & MTD_MLC_IN_SLC_MODE) {
> > +		int ngroups = mtd_pairing_groups(master);
> > +
> > +		mtd->erasesize /= ngroups;
> > +		mtd->size = (u64)mtd_div_by_eb(mtd->size, master) *
> > +			    mtd->erasesize;  
> 
> Can we please have a helper for this? You use this formula many times.

I thought you were talking about the mtd->size calculation but this
line appears only once as-is. the whole 'if' block is never exactly the
same so it cannot be factored out. The only line that is actually
repeating is the if condition. Do you mean you would like something
like this?

	static bool mtd_emulates_slc(struct mtd_info *mtd)
	{
		return mtd->flags & MTD_EMULATE_SLC_ON_MLC;
	}


Thanks,
Miquèl

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, back to index

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-30 16:51 [PATCH 0/8] MLC in SLC mode Miquel Raynal
2019-12-30 16:51 ` [PATCH 1/8] mtd: rawnand: toshiba: Add a specific init for TC58TEG5DCLTA00 Miquel Raynal
2019-12-30 16:51 ` [PATCH 2/8] mtd: rawnand: Define the "distance 3" MLC pairing scheme Miquel Raynal
2019-12-30 16:51 ` [PATCH 3/8] mtd: rawnand: toshiba: Set the pairing scheme for TC58TEG5DCLTA00 Miquel Raynal
2019-12-30 16:51 ` [PATCH 4/8] mtd: Add support for emulated SLC mode on MLC NANDs Miquel Raynal
2020-01-08 23:49   ` Richard Weinberger
2020-01-09 18:16     ` Miquel Raynal
2020-01-09 18:39       ` Richard Weinberger
2020-01-09 19:19         ` Boris Brezillon
2020-01-09 19:22           ` Miquel Raynal
2020-01-14 10:04     ` Miquel Raynal
2019-12-30 16:51 ` [PATCH 5/8] dt-bindings: mtd: partition: Document the slc-mode property Miquel Raynal
2019-12-31  3:53   ` Florian Fainelli
2020-01-14  9:33     ` Miquel Raynal
2019-12-30 16:51 ` [PATCH 6/8] mtd: partitions: ofpart: Parse " Miquel Raynal
2019-12-30 16:51 ` [PATCH 7/8] mtd: cmdlinepart: Add an slc option to use SLC mode on a part Miquel Raynal
2019-12-30 16:51 ` [PATCH 8/8] ubi: Relax the 'no MLC' rule and allow MLCs operating in SLC mode Miquel Raynal
2020-01-08 23:50   ` Richard Weinberger

Linux-mtd Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-mtd/0 linux-mtd/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-mtd linux-mtd/ https://lore.kernel.org/linux-mtd \
		linux-mtd@lists.infradead.org
	public-inbox-index linux-mtd

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.infradead.lists.linux-mtd


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git