linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support
@ 2016-06-06 11:59 Boris Brezillon
  2016-06-06 11:59 ` [PATCH 1/3] mtd: nand: sunxi: prefer 1k ECC blocks when applicable Boris Brezillon
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Boris Brezillon @ 2016-06-06 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

Those 3 patches aims a fixing support for SLC NANDs with rather small
NAND pages (<= 4k).

The first patch promote 512 bytes ECC steps to 1k steps, which should
both save a few OOB bytes and provide stronger ECC.
The second patch checks the ECC step value, and rejects any NAND that
requires ECC steps != 512 | 1024.
The last patch implements ecc->write_subpage(), thus fixing a NULL
pointer dereference when the NAND chip supports subpage write.

Best Regards,

Boris

Boris Brezillon (3):
  mtd: nand: sunxi: prefer 1k ECC blocks when applicable
  mtd: nand: sunxi: check ecc->size values
  mtd: nand: sunxi: fix subpage write

 drivers/mtd/nand/sunxi_nand.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

-- 
2.7.4

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

* [PATCH 1/3] mtd: nand: sunxi: prefer 1k ECC blocks when applicable
  2016-06-06 11:59 [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
@ 2016-06-06 11:59 ` Boris Brezillon
  2016-06-06 11:59 ` [PATCH 2/3] mtd: nand: sunxi: check ecc->size values Boris Brezillon
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Boris Brezillon @ 2016-06-06 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

Switching to 1k ECC blocks when possible provides better resistance against
concentrated bitflips. Say you have those two configurations:

1/ 16bits/512bytes
2/ 32bits/1024bytes

Both of them require the same amount of ECC bytes (only true for this
specific engine), but the second config allows you to correct the case
where most of your bitflips are concentrated in a single 512bytes portion.

This fact makes the 1k ECC block size more advantageous than the 512bytes
one.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/mtd/nand/sunxi_nand.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 5299ab0..4f5b4ad 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1784,6 +1784,12 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
 	if (!data)
 		return -ENOMEM;
 
+	/* Prefer 1k ECC chunk over 512 ones */
+	if (ecc->size == 512 && mtd->writesize > 512) {
+		ecc->size = 1024;
+		ecc->strength *= 2;
+	}
+
 	/* Add ECC info retrieval from DT */
 	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
 		if (ecc->strength <= strengths[i])
-- 
2.7.4

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

* [PATCH 2/3] mtd: nand: sunxi: check ecc->size values
  2016-06-06 11:59 [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
  2016-06-06 11:59 ` [PATCH 1/3] mtd: nand: sunxi: prefer 1k ECC blocks when applicable Boris Brezillon
@ 2016-06-06 11:59 ` Boris Brezillon
  2016-06-06 11:59 ` [PATCH 3/3] mtd: nand: sunxi: fix subpage write Boris Brezillon
  2016-06-20 11:52 ` [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
  3 siblings, 0 replies; 6+ messages in thread
From: Boris Brezillon @ 2016-06-06 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

Verify that the ecc->size value is either 512 or 1024 bytes.
This should always be the case if this field was assigned to the
nand->ecc_step_size_ds value, but can be wrong when the user overloaded
this value with the nand-ecc-step-size DT property.

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/mtd/nand/sunxi_nand.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 4f5b4ad..252cbbf 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1784,6 +1784,9 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
 	if (!data)
 		return -ENOMEM;
 
+	if (ecc->size != 512 && ecc->size != 1024)
+		return -EINVAL;
+
 	/* Prefer 1k ECC chunk over 512 ones */
 	if (ecc->size == 512 && mtd->writesize > 512) {
 		ecc->size = 1024;
-- 
2.7.4

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

* [PATCH 3/3] mtd: nand: sunxi: fix subpage write
  2016-06-06 11:59 [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
  2016-06-06 11:59 ` [PATCH 1/3] mtd: nand: sunxi: prefer 1k ECC blocks when applicable Boris Brezillon
  2016-06-06 11:59 ` [PATCH 2/3] mtd: nand: sunxi: check ecc->size values Boris Brezillon
@ 2016-06-06 11:59 ` Boris Brezillon
  2016-06-06 12:07   ` Boris Brezillon
  2016-06-20 11:52 ` [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
  3 siblings, 1 reply; 6+ messages in thread
From: Boris Brezillon @ 2016-06-06 11:59 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
---
 drivers/mtd/nand/sunxi_nand.c | 33 ++++++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 252cbbf..409acbe 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1350,6 +1350,36 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
 	return 0;
 }
 
+static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
+					  struct nand_chip *chip,
+					  u32 data_offs, u32 data_len,
+					  const u8 *buf, int oob_required,
+					  int page)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret, i, cur_off = 0;
+
+	sunxi_nfc_hw_ecc_enable(mtd);
+
+	for (i = data_offs / ecc->size;
+	     i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
+		int data_off = i * ecc->size;
+		int oob_off = i * (ecc->bytes + 4);
+		const u8 *data = buf + data_off;
+		const u8 *oob = chip->oob_poi + oob_off;
+
+		ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
+						   oob_off + mtd->writesize,
+						   &cur_off, !i, page);
+		if (ret)
+			return ret;
+	}
+
+	sunxi_nfc_hw_ecc_disable(mtd);
+
+	return 0;
+}
+
 static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
 					   struct nand_chip *chip,
 					   const u8 *buf,
@@ -1862,7 +1892,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 		ecc->write_page = sunxi_nfc_hw_ecc_write_page;
 	}
 
-	/* TODO: support DMA for raw accesses */
+	/* TODO: support DMA for raw accesses and subpage write */
+	ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
 	ecc->read_oob_raw = nand_read_oob_std;
 	ecc->write_oob_raw = nand_write_oob_std;
 	ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;
-- 
2.7.4

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

* [PATCH 3/3] mtd: nand: sunxi: fix subpage write
  2016-06-06 11:59 ` [PATCH 3/3] mtd: nand: sunxi: fix subpage write Boris Brezillon
@ 2016-06-06 12:07   ` Boris Brezillon
  0 siblings, 0 replies; 6+ messages in thread
From: Boris Brezillon @ 2016-06-06 12:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon,  6 Jun 2016 13:59:14 +0200
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:

Oops, I forgot to add this commit message:

"
Implement ecc->write_subpage() to prevent core code from assigning
this hook to nand_write_subpage_hwecc(). This default implementation
tries to call ecc->hwctl() which in our case is NULL, thus leading
to a NULL pointer dereference.
"

> Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
> ---
>  drivers/mtd/nand/sunxi_nand.c | 33 ++++++++++++++++++++++++++++++++-
>  1 file changed, 32 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
> index 252cbbf..409acbe 100644
> --- a/drivers/mtd/nand/sunxi_nand.c
> +++ b/drivers/mtd/nand/sunxi_nand.c
> @@ -1350,6 +1350,36 @@ static int sunxi_nfc_hw_ecc_write_page(struct mtd_info *mtd,
>  	return 0;
>  }
>  
> +static int sunxi_nfc_hw_ecc_write_subpage(struct mtd_info *mtd,
> +					  struct nand_chip *chip,
> +					  u32 data_offs, u32 data_len,
> +					  const u8 *buf, int oob_required,
> +					  int page)
> +{
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +	int ret, i, cur_off = 0;
> +
> +	sunxi_nfc_hw_ecc_enable(mtd);
> +
> +	for (i = data_offs / ecc->size;
> +	     i < DIV_ROUND_UP(data_offs + data_len, ecc->size); i++) {
> +		int data_off = i * ecc->size;
> +		int oob_off = i * (ecc->bytes + 4);
> +		const u8 *data = buf + data_off;
> +		const u8 *oob = chip->oob_poi + oob_off;
> +
> +		ret = sunxi_nfc_hw_ecc_write_chunk(mtd, data, data_off, oob,
> +						   oob_off + mtd->writesize,
> +						   &cur_off, !i, page);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	sunxi_nfc_hw_ecc_disable(mtd);
> +
> +	return 0;
> +}
> +
>  static int sunxi_nfc_hw_ecc_write_page_dma(struct mtd_info *mtd,
>  					   struct nand_chip *chip,
>  					   const u8 *buf,
> @@ -1862,7 +1892,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
>  		ecc->write_page = sunxi_nfc_hw_ecc_write_page;
>  	}
>  
> -	/* TODO: support DMA for raw accesses */
> +	/* TODO: support DMA for raw accesses and subpage write */
> +	ecc->write_subpage = sunxi_nfc_hw_ecc_write_subpage;
>  	ecc->read_oob_raw = nand_read_oob_std;
>  	ecc->write_oob_raw = nand_write_oob_std;
>  	ecc->read_subpage = sunxi_nfc_hw_ecc_read_subpage;



-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

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

* [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support
  2016-06-06 11:59 [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
                   ` (2 preceding siblings ...)
  2016-06-06 11:59 ` [PATCH 3/3] mtd: nand: sunxi: fix subpage write Boris Brezillon
@ 2016-06-20 11:52 ` Boris Brezillon
  3 siblings, 0 replies; 6+ messages in thread
From: Boris Brezillon @ 2016-06-20 11:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon,  6 Jun 2016 13:59:11 +0200
Boris Brezillon <boris.brezillon@free-electrons.com> wrote:

> Hello,
> 
> Those 3 patches aims a fixing support for SLC NANDs with rather small
> NAND pages (<= 4k).
> 
> The first patch promote 512 bytes ECC steps to 1k steps, which should
> both save a few OOB bytes and provide stronger ECC.
> The second patch checks the ECC step value, and rejects any NAND that
> requires ECC steps != 512 | 1024.
> The last patch implements ecc->write_subpage(), thus fixing a NULL
> pointer dereference when the NAND chip supports subpage write.

Applied.

> 
> Best Regards,
> 
> Boris
> 
> Boris Brezillon (3):
>   mtd: nand: sunxi: prefer 1k ECC blocks when applicable
>   mtd: nand: sunxi: check ecc->size values
>   mtd: nand: sunxi: fix subpage write
> 
>  drivers/mtd/nand/sunxi_nand.c | 42 +++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 41 insertions(+), 1 deletion(-)
> 

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

end of thread, other threads:[~2016-06-20 11:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-06 11:59 [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon
2016-06-06 11:59 ` [PATCH 1/3] mtd: nand: sunxi: prefer 1k ECC blocks when applicable Boris Brezillon
2016-06-06 11:59 ` [PATCH 2/3] mtd: nand: sunxi: check ecc->size values Boris Brezillon
2016-06-06 11:59 ` [PATCH 3/3] mtd: nand: sunxi: fix subpage write Boris Brezillon
2016-06-06 12:07   ` Boris Brezillon
2016-06-20 11:52 ` [PATCH 0/3] mtd: nand: sunxi: fix SLC NAND support Boris Brezillon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).