* [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).