linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase
@ 2018-07-20 15:14 Miquel Raynal
  2018-07-20 15:14 ` [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan() Miquel Raynal
                   ` (35 more replies)
  0 siblings, 36 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Hello,

This series make a quite deep change in the NAND framework. Until now,
the NAND chip identification phase could be done in two manners from the
controller driver perspective:

1/ Call nand_scan()

  or

1/ Call nand_scan_ident()
2/ Do some controller-dependent configuration
3/ Call nand_scan_tail().

The fact that the identifaction could be split in two operations
involved that in the NAND framework, it was not possible to do any
dynamic allocation without risking a memory leak. What if the core
allocates a structure, then the driver between nand_scan_ident() and
nand_scan_tail() decides it cannot handle the chip and errors out?
The structure allocated by the core is lost: it is a memory leak. One
solution could have been to add a nand_scan_ident_cleanup() function,
but that would mean patching all the drivers anyway to make them call
this function when something fails between nand_scan_ident() and
nand_scan_tail().

To avoid this situation, we migrate all drivers to use nand_scan() in
conjuction with the recently added hooks ->attach_chip() and
->detach_chip() that are part of the nand_controller structure
operations. Drivers that need to tweak their configuration after
nand_scan_ident() should implement it. Any dynamically allocated space
in ->attach_chip() must be freed in the second hook: ->detach_chip().

The ->detach_chip() does not have to be called upon error in the
controller driver probe function. The nand_cleanup() helper already
exists for that and will do the call if needed. Of course, this helper
must be called on error after a successful nand_scan(), just like
before.

Once all drivers not using nand_scan() are migrated, nand_scan_ident()
and nand_scan_tail() are unexported and only available internally.

A previous work [1] removed the ONFI/JEDEC parameter pages and instead
allocated a nand_parameters structure in nand_chip, embedding both
generic entries and ONFI-related ones. The deal was, once dynamic
allocation possible, allocate in nand_scan_ident() the ONFI strcuture
only if actually needed. This is done in the last patches.

This series applies on top of nand/next.

Thank you,
Miquèl

[1] http://lists.infradead.org/pipermail/linux-mtd/2018-March/079456.html

Changes since v3:
=================
* Constified all the nand_controller_ops structure definitions.
* Fixed a build issue in fsl_elbc.
* Added a patch in the core to prevent executing nand_scan_ident if
  maxchips is NULL.
* Fixed the regression around the model name.
* Used kstrdup to allocate the model.
* The migration from char model[] to const char *model is done in a
  separate patch.

Changes since v2:
=================
* Rebased on top of nand/next.
* Adapted all drivers to declare statically a nand_controller_ops
  structure and assign it in the probe().
* Added the migration of the tegra_nand.c driver.
* Moved brcmnand controller ops affectation in the probe().

Changes since v1:
=================
* Rebased on top of nand/next.
* Light rewording of the cover letter about the possibility to have a
  nand_scan_ident_cleanup() function (just as example of how this series
  could have been done differently).
* Changed the hooks to reside in the nand_hw_ctrl structure instead of
  being part of nand_ecc_ctrl as these hooks are more
  controller-related.


Miquel Raynal (35):
  mtd: rawnand: brcmnand: convert driver to nand_scan()
  mtd: rawnand: cafe: convert driver to nand_scan()
  mtd: rawnand: davinci: convert driver to nand_scan()
  mtd: rawnand: denali: convert to nand_scan()
  mtd: rawnand: fsl_elbc: convert driver to nand_scan()
  mtd: rawnand: fsl_ifc: convert driver to nand_scan()
  mtd: rawnand: fsmc: convert driver to nand_scan()
  mtd: rawnand: gpmi: convert driver to nand_scan()
  mtd: rawnand: hisi504: convert driver to nand_scan()
  mtd: rawnand: jz4780: convert driver to nand_scan()
  mtd: rawnand: lpc32xx_mlc: convert driver to nand_scan()
  mtd: rawnand: lpc32xx_slc: convert driver to nand_scan()
  mtd: rawnand: marvell: convert driver to nand_scan()
  mtd: rawnand: mtk: convert driver to nand_scan()
  mtd: rawnand: mxc: convert driver to nand_scan()
  mtd: rawnand: nandsim: convert driver to nand_scan()
  mtd: rawnand: omap2: convert driver to nand_scan()
  mtd: rawnand: s3c2410: convert driver to nand_scan()
  mtd: rawnand: sh_flctl: move all NAND chip related setup in one
    function
  mtd: rawnand: sh_flctl: convert driver to nand_scan()
  mtd: rawnand: sunxi: convert driver to nand_scan()
  mtd: rawnand: tango: convert driver to nand_scan()
  mtd: rawnand: txx9ndfmc: rename nand controller internal structure
  mtd: rawnand: txx9ndfmc: convert driver to nand_scan()
  mtd: rawnand: vf610: convert driver to nand_scan()
  mtd: rawnand: atmel: convert driver to nand_scan()
  mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
  mtd: rawnand: allow exiting immediately nand_scan_ident()
  mtd: rawnand: docg4: convert driver to nand_scan()
  mtd: rawnand: qcom: convert driver to nand_scan()
  mtd: rawnand: jz4740: convert driver to nand_scan()
  mtd: rawnand: tegra: convert driver to nand_scan()
  mtd: rawnand: do not export nand_scan_[ident|tail]() anymore
  mtd: rawnand: allocate model parameter dynamically
  mtd: rawnand: allocate dynamically ONFI parameters during detection

 drivers/mtd/nand/raw/atmel/nand-controller.c |  83 ++---
 drivers/mtd/nand/raw/brcmnand/brcmnand.c     |  47 ++-
 drivers/mtd/nand/raw/cafe_nand.c             | 130 ++++---
 drivers/mtd/nand/raw/davinci_nand.c          | 195 +++++-----
 drivers/mtd/nand/raw/denali.c                | 138 +++----
 drivers/mtd/nand/raw/docg4.c                 |  55 +--
 drivers/mtd/nand/raw/fsl_elbc_nand.c         |  19 +-
 drivers/mtd/nand/raw/fsl_ifc_nand.c          |  19 +-
 drivers/mtd/nand/raw/fsmc_nand.c             | 148 ++++----
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  56 +--
 drivers/mtd/nand/raw/hisi504_nand.c          |  78 ++--
 drivers/mtd/nand/raw/jz4740_nand.c           |  46 ++-
 drivers/mtd/nand/raw/jz4780_nand.c           |  34 +-
 drivers/mtd/nand/raw/lpc32xx_mlc.c           | 109 +++---
 drivers/mtd/nand/raw/lpc32xx_slc.c           |  77 ++--
 drivers/mtd/nand/raw/marvell_nand.c          | 205 ++++++-----
 drivers/mtd/nand/raw/mtk_nand.c              |  75 ++--
 drivers/mtd/nand/raw/mxc_nand.c              | 136 +++----
 drivers/mtd/nand/raw/nand_base.c             | 132 +++++--
 drivers/mtd/nand/raw/nand_micron.c           |   6 +-
 drivers/mtd/nand/raw/nand_timings.c          |  12 +-
 drivers/mtd/nand/raw/nandsim.c               |  82 +++--
 drivers/mtd/nand/raw/omap2.c                 | 521 +++++++++++++--------------
 drivers/mtd/nand/raw/qcom_nandc.c            |  71 ++--
 drivers/mtd/nand/raw/s3c2410.c               |  30 +-
 drivers/mtd/nand/raw/sh_flctl.c              |  57 ++-
 drivers/mtd/nand/raw/sm_common.c             |  39 +-
 drivers/mtd/nand/raw/sunxi_nand.c            |  43 +--
 drivers/mtd/nand/raw/tango_nand.c            |  40 +-
 drivers/mtd/nand/raw/tegra_nand.c            | 162 +++++----
 drivers/mtd/nand/raw/txx9ndfmc.c             |  35 +-
 drivers/mtd/nand/raw/vf610_nfc.c             | 127 +++----
 include/linux/mtd/rawnand.h                  |  17 +-
 include/linux/mtd/sh_flctl.h                 |   1 +
 34 files changed, 1612 insertions(+), 1413 deletions(-)

-- 
2.14.1


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

* [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:23   ` Boris Brezillon
  2018-07-20 15:14 ` [PATCH v4 02/35] mtd: rawnand: cafe: " Miquel Raynal
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/brcmnand/brcmnand.c | 47 +++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
index 2e5efa0f9ea2..071f09af56dc 100644
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
@@ -2208,6 +2208,32 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
 	return 0;
 }
 
+static int brcmnand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct brcmnand_host *host = nand_get_controller_data(chip);
+	int ret;
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+	if (brcmnand_setup_dev(host))
+		return -ENXIO;
+
+	chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512;
+
+	/* only use our internal HW threshold */
+	mtd->bitflip_threshold = 1;
+
+	ret = brcmstb_choose_ecc_layout(host);
+
+	return ret;
+}
+
+static const struct nand_controller_ops brcmnand_controller_ops = {
+	.attach_chip = brcmnand_attach_chip,
+};
+
 static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
 {
 	struct brcmnand_controller *ctrl = host->ctrl;
@@ -2267,10 +2293,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
 	nand_writereg(ctrl, cfg_offs,
 		      nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		return ret;
-
 	chip->options |= NAND_NO_SUBPAGE_WRITE;
 	/*
 	 * Avoid (for instance) kmap()'d buffers from JFFS2, which we can't DMA
@@ -2279,21 +2301,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
 	 */
 	chip->options |= NAND_USE_BOUNCE_BUFFER;
 
-	if (chip->bbt_options & NAND_BBT_USE_FLASH)
-		chip->bbt_options |= NAND_BBT_NO_OOB;
-
-	if (brcmnand_setup_dev(host))
-		return -ENXIO;
-
-	chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512;
-	/* only use our internal HW threshold */
-	mtd->bitflip_threshold = 1;
-
-	ret = brcmstb_choose_ecc_layout(host);
-	if (ret)
-		return ret;
-
-	ret = nand_scan_tail(mtd);
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		return ret;
 
@@ -2434,6 +2442,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
 	init_completion(&ctrl->done);
 	init_completion(&ctrl->dma_done);
 	nand_controller_init(&ctrl->controller);
+	ctrl->controller.ops = &brcmnand_controller_ops;
 	INIT_LIST_HEAD(&ctrl->host_list);
 
 	/* NAND register range */
-- 
2.14.1


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

* [PATCH v4 02/35] mtd: rawnand: cafe: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
  2018-07-20 15:14 ` [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan() Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:35   ` Boris Brezillon
  2018-07-20 15:14 ` [PATCH v4 03/35] mtd: rawnand: davinci: " Miquel Raynal
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/cafe_nand.c | 130 +++++++++++++++++++++++----------------
 1 file changed, 76 insertions(+), 54 deletions(-)

diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
index ac0be933a490..c303c261dd8d 100644
--- a/drivers/mtd/nand/raw/cafe_nand.c
+++ b/drivers/mtd/nand/raw/cafe_nand.c
@@ -71,7 +71,9 @@ struct cafe_priv {
 	unsigned char *dmabuf;
 };
 
-static int usedma = 1;
+#define CAFE_DEFAULT_DMA	1
+
+static int usedma = CAFE_DEFAULT_DMA;
 module_param(usedma, int, 0644);
 
 static int skipbbt = 0;
@@ -593,6 +595,76 @@ static int cafe_mul(int x)
 	return gf4096_mul(x, 0xe01);
 }
 
+static int cafe_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct cafe_priv *cafe = nand_get_controller_data(chip);
+	int err = 0;
+
+	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112,
+					  &cafe->dmaaddr, GFP_KERNEL);
+	if (!cafe->dmabuf)
+		return -ENOMEM;
+
+	/* Set up DMA address */
+	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
+	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
+
+	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
+		     cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
+
+	/* Restore the DMA flag */
+	usedma = CAFE_DEFAULT_DMA;
+
+	cafe->ctl2 = BIT(27); /* Reed-Solomon ECC */
+	if (mtd->writesize == 2048)
+		cafe->ctl2 |= BIT(29); /* 2KiB page size */
+
+	/* Set up ECC according to the type of chip we found */
+	mtd_set_ooblayout(mtd, &cafe_ooblayout_ops);
+	if (mtd->writesize == 2048) {
+		cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
+		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
+	} else if (mtd->writesize == 512) {
+		cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
+		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
+	} else {
+		dev_warn(&cafe->pdev->dev,
+			 "Unexpected NAND flash writesize %d. Aborting\n",
+			 mtd->writesize);
+		err = -ENOTSUPP;
+		goto out_free_dma;
+	}
+
+	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
+	cafe->nand.ecc.size = mtd->writesize;
+	cafe->nand.ecc.bytes = 14;
+	cafe->nand.ecc.strength = 4;
+	cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
+	cafe->nand.ecc.write_oob = cafe_nand_write_oob;
+	cafe->nand.ecc.read_page = cafe_nand_read_page;
+	cafe->nand.ecc.read_oob = cafe_nand_read_oob;
+
+	return 0;
+
+ out_free_dma:
+	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+
+	return err;
+}
+
+static void cafe_nand_detach_chip(struct nand_chip *chip)
+{
+	struct cafe_priv *cafe = nand_get_controller_data(chip);
+
+	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
+}
+
+static const struct nand_controller_ops cafe_nand_controller_ops = {
+	.attach_chip = cafe_nand_attach_chip,
+	.detach_chip = cafe_nand_detach_chip,
+};
+
 static int cafe_nand_probe(struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
 {
@@ -600,7 +672,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
-	int old_dma;
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -708,62 +779,15 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 		cafe_readl(cafe, GLOBAL_CTRL),
 		cafe_readl(cafe, GLOBAL_IRQ_MASK));
 
-	/* Do not use the DMA for the nand_scan_ident() */
-	old_dma = usedma;
+	/* Do not use the DMA during the NAND identification */
 	usedma = 0;
 
 	/* Scan to find existence of the device */
-	err = nand_scan_ident(mtd, 2, NULL);
+	cafe->nand.dummy_controller.ops = &cafe_nand_controller_ops;
+	err = nand_scan(mtd, 2);
 	if (err)
 		goto out_irq;
 
-	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112,
-					  &cafe->dmaaddr, GFP_KERNEL);
-	if (!cafe->dmabuf) {
-		err = -ENOMEM;
-		goto out_irq;
-	}
-
-	/* Set up DMA address */
-	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
-	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
-
-	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
-		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
-
-	/* Restore the DMA flag */
-	usedma = old_dma;
-
-	cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */
-	if (mtd->writesize == 2048)
-		cafe->ctl2 |= 1<<29; /* 2KiB page size */
-
-	/* Set up ECC according to the type of chip we found */
-	mtd_set_ooblayout(mtd, &cafe_ooblayout_ops);
-	if (mtd->writesize == 2048) {
-		cafe->nand.bbt_td = &cafe_bbt_main_descr_2048;
-		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_2048;
-	} else if (mtd->writesize == 512) {
-		cafe->nand.bbt_td = &cafe_bbt_main_descr_512;
-		cafe->nand.bbt_md = &cafe_bbt_mirror_descr_512;
-	} else {
-		pr_warn("Unexpected NAND flash writesize %d. Aborting\n",
-			mtd->writesize);
-		goto out_free_dma;
-	}
-	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
-	cafe->nand.ecc.size = mtd->writesize;
-	cafe->nand.ecc.bytes = 14;
-	cafe->nand.ecc.strength = 4;
-	cafe->nand.ecc.write_page = cafe_nand_write_page_lowlevel;
-	cafe->nand.ecc.write_oob = cafe_nand_write_oob;
-	cafe->nand.ecc.read_page = cafe_nand_read_page;
-	cafe->nand.ecc.read_oob = cafe_nand_read_oob;
-
-	err = nand_scan_tail(mtd);
-	if (err)
-		goto out_free_dma;
-
 	pci_set_drvdata(pdev, mtd);
 
 	mtd->name = "cafe_nand";
@@ -775,8 +799,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,
 
  out_cleanup_nand:
 	nand_cleanup(&cafe->nand);
- out_free_dma:
-	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);
  out_irq:
 	/* Disable NAND IRQ in global IRQ mask register */
 	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);
-- 
2.14.1


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

* [PATCH v4 03/35] mtd: rawnand: davinci: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
  2018-07-20 15:14 ` [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan() Miquel Raynal
  2018-07-20 15:14 ` [PATCH v4 02/35] mtd: rawnand: cafe: " Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:44   ` Boris Brezillon
  2018-07-20 15:14 ` [PATCH v4 04/35] mtd: rawnand: denali: convert " Miquel Raynal
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Also change the unused "struct device *dev" parameter of the driver
structure into a platform device to reuse it in the ->attach_chip()
hook.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/davinci_nand.c | 195 +++++++++++++++++++-----------------
 1 file changed, 102 insertions(+), 93 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 626c9363e460..40145e206a6b 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -53,7 +53,7 @@
 struct davinci_nand_info {
 	struct nand_chip	chip;
 
-	struct device		*dev;
+	struct platform_device	*pdev;
 
 	bool			is_readmode;
 
@@ -605,6 +605,104 @@ static struct davinci_nand_pdata
 }
 #endif
 
+static int davinci_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct davinci_nand_info *info = to_davinci_nand(mtd);
+	struct davinci_nand_pdata *pdata = nand_davinci_get_pdata(info->pdev);
+	int ret = 0;
+
+	if (IS_ERR(pdata))
+		return PTR_ERR(pdata);
+
+	switch (info->chip.ecc.mode) {
+	case NAND_ECC_NONE:
+		pdata->ecc_bits = 0;
+		break;
+	case NAND_ECC_SOFT:
+		pdata->ecc_bits = 0;
+		/*
+		 * This driver expects Hamming based ECC when ecc_mode is set
+		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
+		 * avoid adding an extra ->ecc_algo field to
+		 * davinci_nand_pdata.
+		 */
+		info->chip.ecc.algo = NAND_ECC_HAMMING;
+		break;
+	case NAND_ECC_HW:
+		if (pdata->ecc_bits == 4) {
+			/*
+			 * No sanity checks:  CPUs must support this,
+			 * and the chips may not use NAND_BUSWIDTH_16.
+			 */
+
+			/* No sharing 4-bit hardware between chipselects yet */
+			spin_lock_irq(&davinci_nand_lock);
+			if (ecc4_busy)
+				ret = -EBUSY;
+			else
+				ecc4_busy = true;
+			spin_unlock_irq(&davinci_nand_lock);
+
+			if (ret == -EBUSY)
+				return ret;
+
+			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
+			info->chip.ecc.correct = nand_davinci_correct_4bit;
+			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
+			info->chip.ecc.bytes = 10;
+			info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
+			info->chip.ecc.algo = NAND_ECC_BCH;
+		} else {
+			/* 1bit ecc hamming */
+			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
+			info->chip.ecc.correct = nand_davinci_correct_1bit;
+			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
+			info->chip.ecc.bytes = 3;
+			info->chip.ecc.algo = NAND_ECC_HAMMING;
+		}
+		info->chip.ecc.size = 512;
+		info->chip.ecc.strength = pdata->ecc_bits;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Update ECC layout if needed ... for 1-bit HW ECC, the default
+	 * is OK, but it allocates 6 bytes when only 3 are needed (for
+	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
+	 * usable:  10 bytes are needed, not 6.
+	 */
+	if (pdata->ecc_bits == 4) {
+		int chunks = mtd->writesize / 512;
+
+		if (!chunks || mtd->oobsize < 16) {
+			dev_dbg(&info->pdev->dev, "too small\n");
+			return -EINVAL;
+		}
+
+		/* For small page chips, preserve the manufacturer's
+		 * badblock marking data ... and make sure a flash BBT
+		 * table marker fits in the free bytes.
+		 */
+		if (chunks == 1) {
+			mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
+		} else if (chunks == 4 || chunks == 8) {
+			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
+		} else {
+			return -EIO;
+		}
+	}
+
+	return ret;
+}
+
+static const struct nand_controller_ops davinci_nand_controller_ops = {
+	.attach_chip = davinci_nand_attach_chip,
+};
+
 static int nand_davinci_probe(struct platform_device *pdev)
 {
 	struct davinci_nand_pdata	*pdata;
@@ -658,7 +756,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
 		return -EADDRNOTAVAIL;
 	}
 
-	info->dev		= &pdev->dev;
+	info->pdev		= pdev;
 	info->base		= base;
 	info->vaddr		= vaddr;
 
@@ -708,97 +806,13 @@ static int nand_davinci_probe(struct platform_device *pdev)
 	spin_unlock_irq(&davinci_nand_lock);
 
 	/* Scan to find existence of the device(s) */
-	ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL);
+	info->chip.dummy_controller.ops = &davinci_nand_controller_ops;
+	ret = nand_scan(mtd, pdata->mask_chipsel ? 2 : 1);
 	if (ret < 0) {
 		dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
 		return ret;
 	}
 
-	switch (info->chip.ecc.mode) {
-	case NAND_ECC_NONE:
-		pdata->ecc_bits = 0;
-		break;
-	case NAND_ECC_SOFT:
-		pdata->ecc_bits = 0;
-		/*
-		 * This driver expects Hamming based ECC when ecc_mode is set
-		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
-		 * avoid adding an extra ->ecc_algo field to
-		 * davinci_nand_pdata.
-		 */
-		info->chip.ecc.algo = NAND_ECC_HAMMING;
-		break;
-	case NAND_ECC_HW:
-		if (pdata->ecc_bits == 4) {
-			/* No sanity checks:  CPUs must support this,
-			 * and the chips may not use NAND_BUSWIDTH_16.
-			 */
-
-			/* No sharing 4-bit hardware between chipselects yet */
-			spin_lock_irq(&davinci_nand_lock);
-			if (ecc4_busy)
-				ret = -EBUSY;
-			else
-				ecc4_busy = true;
-			spin_unlock_irq(&davinci_nand_lock);
-
-			if (ret == -EBUSY)
-				return ret;
-
-			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
-			info->chip.ecc.correct = nand_davinci_correct_4bit;
-			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
-			info->chip.ecc.bytes = 10;
-			info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
-			info->chip.ecc.algo = NAND_ECC_BCH;
-		} else {
-			/* 1bit ecc hamming */
-			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
-			info->chip.ecc.correct = nand_davinci_correct_1bit;
-			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
-			info->chip.ecc.bytes = 3;
-			info->chip.ecc.algo = NAND_ECC_HAMMING;
-		}
-		info->chip.ecc.size = 512;
-		info->chip.ecc.strength = pdata->ecc_bits;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	/* Update ECC layout if needed ... for 1-bit HW ECC, the default
-	 * is OK, but it allocates 6 bytes when only 3 are needed (for
-	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
-	 * usable:  10 bytes are needed, not 6.
-	 */
-	if (pdata->ecc_bits == 4) {
-		int	chunks = mtd->writesize / 512;
-
-		if (!chunks || mtd->oobsize < 16) {
-			dev_dbg(&pdev->dev, "too small\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		/* For small page chips, preserve the manufacturer's
-		 * badblock marking data ... and make sure a flash BBT
-		 * table marker fits in the free bytes.
-		 */
-		if (chunks == 1) {
-			mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
-		} else if (chunks == 4 || chunks == 8) {
-			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
-		} else {
-			ret = -EIO;
-			goto err;
-		}
-	}
-
-	ret = nand_scan_tail(mtd);
-	if (ret < 0)
-		goto err;
-
 	if (pdata->parts)
 		ret = mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
 	else
@@ -815,11 +829,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
 err_cleanup_nand:
 	nand_cleanup(&info->chip);
 
-err:
-	spin_lock_irq(&davinci_nand_lock);
-	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
-		ecc4_busy = false;
-	spin_unlock_irq(&davinci_nand_lock);
 	return ret;
 }
 
-- 
2.14.1


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

* [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (2 preceding siblings ...)
  2018-07-20 15:14 ` [PATCH v4 03/35] mtd: rawnand: davinci: " Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:46   ` Boris Brezillon
  2018-07-25  9:42   ` Masahiro Yamada
  2018-07-20 15:14 ` [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver " Miquel Raynal
                   ` (31 subsequent siblings)
  35 siblings, 2 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/denali.c | 138 +++++++++++++++++++++++-------------------
 1 file changed, 77 insertions(+), 61 deletions(-)

diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 4d53f41ada08..2fa92c297a66 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -1205,62 +1205,12 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
 	return 0;
 }
 
-int denali_init(struct denali_nand_info *denali)
+static int denali_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &denali->nand;
 	struct mtd_info *mtd = nand_to_mtd(chip);
-	u32 features = ioread32(denali->reg + FEATURES);
+	struct denali_nand_info *denali = mtd_to_denali(mtd);
 	int ret;
 
-	mtd->dev.parent = denali->dev;
-	denali_hw_init(denali);
-
-	init_completion(&denali->complete);
-	spin_lock_init(&denali->irq_lock);
-
-	denali_clear_irq_all(denali);
-
-	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
-			       IRQF_SHARED, DENALI_NAND_NAME, denali);
-	if (ret) {
-		dev_err(denali->dev, "Unable to request IRQ\n");
-		return ret;
-	}
-
-	denali_enable_irq(denali);
-	denali_reset_banks(denali);
-
-	denali->active_bank = DENALI_INVALID_BANK;
-
-	nand_set_flash_node(chip, denali->dev->of_node);
-	/* Fallback to the default name if DT did not give "label" property */
-	if (!mtd->name)
-		mtd->name = "denali-nand";
-
-	chip->select_chip = denali_select_chip;
-	chip->read_byte = denali_read_byte;
-	chip->write_byte = denali_write_byte;
-	chip->read_word = denali_read_word;
-	chip->cmd_ctrl = denali_cmd_ctrl;
-	chip->dev_ready = denali_dev_ready;
-	chip->waitfunc = denali_waitfunc;
-
-	if (features & FEATURES__INDEX_ADDR) {
-		denali->host_read = denali_indexed_read;
-		denali->host_write = denali_indexed_write;
-	} else {
-		denali->host_read = denali_direct_read;
-		denali->host_write = denali_direct_write;
-	}
-
-	/* clk rate info is needed for setup_data_interface */
-	if (denali->clk_rate && denali->clk_x_rate)
-		chip->setup_data_interface = denali_setup_data_interface;
-
-	ret = nand_scan_ident(mtd, denali->max_banks, NULL);
-	if (ret)
-		goto disable_irq;
-
 	if (ioread32(denali->reg + FEATURES) & FEATURES__DMA)
 		denali->dma_avail = 1;
 
@@ -1293,7 +1243,7 @@ int denali_init(struct denali_nand_info *denali)
 				   mtd->oobsize - denali->oob_skip_bytes);
 	if (ret) {
 		dev_err(denali->dev, "Failed to setup ECC settings.\n");
-		goto disable_irq;
+		return ret;
 	}
 
 	dev_dbg(denali->dev,
@@ -1337,7 +1287,7 @@ int denali_init(struct denali_nand_info *denali)
 
 	ret = denali_multidev_fixup(denali);
 	if (ret)
-		goto disable_irq;
+		return ret;
 
 	/*
 	 * This buffer is DMA-mapped by denali_{read,write}_page_raw.  Do not
@@ -1345,26 +1295,92 @@ int denali_init(struct denali_nand_info *denali)
 	 * guarantee DMA-safe alignment.
 	 */
 	denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
-	if (!denali->buf) {
-		ret = -ENOMEM;
-		goto disable_irq;
+	if (!denali->buf)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void denali_detach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct denali_nand_info *denali = mtd_to_denali(mtd);
+
+	kfree(denali->buf);
+}
+
+static const struct nand_controller_ops denali_controller_ops = {
+	.attach_chip = denali_attach_chip,
+	.detach_chip = denali_detach_chip,
+};
+
+int denali_init(struct denali_nand_info *denali)
+{
+	struct nand_chip *chip = &denali->nand;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	u32 features = ioread32(denali->reg + FEATURES);
+	int ret;
+
+	mtd->dev.parent = denali->dev;
+	denali_hw_init(denali);
+
+	init_completion(&denali->complete);
+	spin_lock_init(&denali->irq_lock);
+
+	denali_clear_irq_all(denali);
+
+	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
+			       IRQF_SHARED, DENALI_NAND_NAME, denali);
+	if (ret) {
+		dev_err(denali->dev, "Unable to request IRQ\n");
+		return ret;
+	}
+
+	denali_enable_irq(denali);
+	denali_reset_banks(denali);
+
+	denali->active_bank = DENALI_INVALID_BANK;
+
+	nand_set_flash_node(chip, denali->dev->of_node);
+	/* Fallback to the default name if DT did not give "label" property */
+	if (!mtd->name)
+		mtd->name = "denali-nand";
+
+	chip->select_chip = denali_select_chip;
+	chip->read_byte = denali_read_byte;
+	chip->write_byte = denali_write_byte;
+	chip->read_word = denali_read_word;
+	chip->cmd_ctrl = denali_cmd_ctrl;
+	chip->dev_ready = denali_dev_ready;
+	chip->waitfunc = denali_waitfunc;
+
+	if (features & FEATURES__INDEX_ADDR) {
+		denali->host_read = denali_indexed_read;
+		denali->host_write = denali_indexed_write;
+	} else {
+		denali->host_read = denali_direct_read;
+		denali->host_write = denali_direct_write;
 	}
 
-	ret = nand_scan_tail(mtd);
+	/* clk rate info is needed for setup_data_interface */
+	if (denali->clk_rate && denali->clk_x_rate)
+		chip->setup_data_interface = denali_setup_data_interface;
+
+	chip->dummy_controller.ops = &denali_controller_ops;
+	ret = nand_scan(mtd, denali->max_banks);
 	if (ret)
-		goto free_buf;
+		goto disable_irq;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(denali->dev, "Failed to register MTD: %d\n", ret);
 		goto cleanup_nand;
 	}
+
 	return 0;
 
 cleanup_nand:
 	nand_cleanup(chip);
-free_buf:
-	kfree(denali->buf);
 disable_irq:
 	denali_disable_irq(denali);
 
-- 
2.14.1


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

* [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (3 preceding siblings ...)
  2018-07-20 15:14 ` [PATCH v4 04/35] mtd: rawnand: denali: convert " Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:50   ` Boris Brezillon
  2018-07-20 15:14 ` [PATCH v4 06/35] mtd: rawnand: fsl_ifc: " Miquel Raynal
                   ` (30 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/fsl_elbc_nand.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index 0aa54a949653..44893e49b386 100644
--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
@@ -637,9 +637,9 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
 }
 
-static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
+static int fsl_elbc_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
@@ -706,6 +706,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	return 0;
 }
 
+static const struct nand_controller_ops fsl_elbc_controller_ops = {
+	.attach_chip = fsl_elbc_attach_chip,
+};
+
 static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 			      uint8_t *buf, int oob_required, int page)
 {
@@ -910,15 +914,8 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
 	if (ret)
 		goto err;
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		goto err;
-
-	ret = fsl_elbc_chip_init_tail(mtd);
-	if (ret)
-		goto err;
-
-	ret = nand_scan_tail(mtd);
+	priv->chip.controller->ops = &fsl_elbc_controller_ops;
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		goto err;
 
-- 
2.14.1


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

* [PATCH v4 06/35] mtd: rawnand: fsl_ifc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (4 preceding siblings ...)
  2018-07-20 15:14 ` [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver " Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:53   ` Boris Brezillon
  2018-07-20 15:14 ` [PATCH v4 07/35] mtd: rawnand: fsmc: " Miquel Raynal
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/fsl_ifc_nand.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index 96130d91e32c..24f59d0066af 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -714,9 +714,9 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	return nand_prog_page_end_op(chip);
 }
 
-static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
+static int fsl_ifc_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
 
 	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
@@ -757,6 +757,10 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
 	return 0;
 }
 
+static const struct nand_controller_ops fsl_ifc_controller_ops = {
+	.attach_chip = fsl_ifc_attach_chip,
+};
+
 static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
 {
 	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
@@ -1046,15 +1050,8 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
 	if (ret)
 		goto err;
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		goto err;
-
-	ret = fsl_ifc_chip_init_tail(mtd);
-	if (ret)
-		goto err;
-
-	ret = nand_scan_tail(mtd);
+	priv->chip.controller->ops = &fsl_ifc_controller_ops;
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		goto err;
 
-- 
2.14.1


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

* [PATCH v4 07/35] mtd: rawnand: fsmc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (5 preceding siblings ...)
  2018-07-20 15:14 ` [PATCH v4 06/35] mtd: rawnand: fsl_ifc: " Miquel Raynal
@ 2018-07-20 15:14 ` Miquel Raynal
  2018-07-21  6:55   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 08/35] mtd: rawnand: gpmi: " Miquel Raynal
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:14 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/fsmc_nand.c | 148 +++++++++++++++++++++------------------
 1 file changed, 78 insertions(+), 70 deletions(-)

diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 59524d181bfe..f418236fa020 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -919,6 +919,82 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
 	return 0;
 }
 
+static int fsmc_nand_attach_chip(struct nand_chip *nand)
+{
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
+
+	if (AMBA_REV_BITS(host->pid) >= 8) {
+		switch (mtd->oobsize) {
+		case 16:
+		case 64:
+		case 128:
+		case 224:
+		case 256:
+			break;
+		default:
+			dev_warn(host->dev,
+				 "No oob scheme defined for oobsize %d\n",
+				 mtd->oobsize);
+			return -EINVAL;
+		}
+
+		mtd_set_ooblayout(mtd, &fsmc_ecc4_ooblayout_ops);
+
+		return 0;
+	}
+
+	switch (nand->ecc.mode) {
+	case NAND_ECC_HW:
+		dev_info(host->dev, "Using 1-bit HW ECC scheme\n");
+		nand->ecc.calculate = fsmc_read_hwecc_ecc1;
+		nand->ecc.correct = nand_correct_data;
+		nand->ecc.bytes = 3;
+		nand->ecc.strength = 1;
+		break;
+
+	case NAND_ECC_SOFT:
+		if (nand->ecc.algo == NAND_ECC_BCH) {
+			dev_info(host->dev,
+				 "Using 4-bit SW BCH ECC scheme\n");
+			break;
+		}
+
+	case NAND_ECC_ON_DIE:
+		break;
+
+	default:
+		dev_err(host->dev, "Unsupported ECC mode!\n");
+		return -ENOTSUPP;
+	}
+
+	/*
+	 * Don't set layout for BCH4 SW ECC. This will be
+	 * generated later in nand_bch_init() later.
+	 */
+	if (nand->ecc.mode == NAND_ECC_HW) {
+		switch (mtd->oobsize) {
+		case 16:
+		case 64:
+		case 128:
+			mtd_set_ooblayout(mtd,
+					  &fsmc_ecc1_ooblayout_ops);
+			break;
+		default:
+			dev_warn(host->dev,
+				 "No oob scheme defined for oobsize %d\n",
+				 mtd->oobsize);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops fsmc_nand_controller_ops = {
+	.attach_chip = fsmc_nand_attach_chip,
+};
+
 /*
  * fsmc_nand_probe - Probe function
  * @pdev:       platform device structure
@@ -1048,76 +1124,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	/*
 	 * Scan to find existence of the device
 	 */
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret) {
-		dev_err(&pdev->dev, "No NAND Device found!\n");
-		goto release_dma_write_chan;
-	}
-
-	if (AMBA_REV_BITS(host->pid) >= 8) {
-		switch (mtd->oobsize) {
-		case 16:
-		case 64:
-		case 128:
-		case 224:
-		case 256:
-			break;
-		default:
-			dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
-				 mtd->oobsize);
-			ret = -EINVAL;
-			goto release_dma_write_chan;
-		}
-
-		mtd_set_ooblayout(mtd, &fsmc_ecc4_ooblayout_ops);
-	} else {
-		switch (nand->ecc.mode) {
-		case NAND_ECC_HW:
-			dev_info(&pdev->dev, "Using 1-bit HW ECC scheme\n");
-			nand->ecc.calculate = fsmc_read_hwecc_ecc1;
-			nand->ecc.correct = nand_correct_data;
-			nand->ecc.bytes = 3;
-			nand->ecc.strength = 1;
-			break;
-
-		case NAND_ECC_SOFT:
-			if (nand->ecc.algo == NAND_ECC_BCH) {
-				dev_info(&pdev->dev, "Using 4-bit SW BCH ECC scheme\n");
-				break;
-			}
-
-		case NAND_ECC_ON_DIE:
-			break;
-
-		default:
-			dev_err(&pdev->dev, "Unsupported ECC mode!\n");
-			goto release_dma_write_chan;
-		}
-
-		/*
-		 * Don't set layout for BCH4 SW ECC. This will be
-		 * generated later in nand_bch_init() later.
-		 */
-		if (nand->ecc.mode == NAND_ECC_HW) {
-			switch (mtd->oobsize) {
-			case 16:
-			case 64:
-			case 128:
-				mtd_set_ooblayout(mtd,
-						  &fsmc_ecc1_ooblayout_ops);
-				break;
-			default:
-				dev_warn(&pdev->dev,
-					 "No oob scheme defined for oobsize %d\n",
-					 mtd->oobsize);
-				ret = -EINVAL;
-				goto release_dma_write_chan;
-			}
-		}
-	}
-
-	/* Second stage of scan to fill MTD data-structures */
-	ret = nand_scan_tail(mtd);
+	nand->dummy_controller.ops = &fsmc_nand_controller_ops;
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		goto release_dma_write_chan;
 
-- 
2.14.1


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

* [PATCH v4 08/35] mtd: rawnand: gpmi: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (6 preceding siblings ...)
  2018-07-20 15:14 ` [PATCH v4 07/35] mtd: rawnand: fsmc: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21  6:56   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 09/35] mtd: rawnand: hisi504: " Miquel Raynal
                   ` (27 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 56 ++++++++++++++++++------------
 1 file changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 6294d018df65..1c1ebbc82824 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -744,9 +744,9 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
 	 * [2] Allocate a read/write data buffer.
 	 *     The gpmi_alloc_dma_buffer can be called twice.
 	 *     We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer
-	 *     is called before the nand_scan_ident; and we allocate a buffer
-	 *     of the real NAND page size when the gpmi_alloc_dma_buffer is
-	 *     called after the nand_scan_ident.
+	 *     is called before the NAND identification; and we allocate a
+	 *     buffer of the real NAND page size when the gpmi_alloc_dma_buffer
+	 *     is called after.
 	 */
 	this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
 					GFP_DMA | GFP_KERNEL);
@@ -1865,6 +1865,34 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
 	return 0;
 }
 
+static int gpmi_nand_attach_chip(struct nand_chip *chip)
+{
+	struct gpmi_nand_data *this = nand_get_controller_data(chip);
+	int ret;
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+		if (of_property_read_bool(this->dev->of_node,
+					  "fsl,no-blockmark-swap"))
+			this->swap_block_mark = false;
+	}
+	dev_dbg(this->dev, "Blockmark swapping %sabled\n",
+		this->swap_block_mark ? "en" : "dis");
+
+	ret = gpmi_init_last(this);
+	if (ret)
+		return ret;
+
+	chip->options |= NAND_SKIP_BBTSCAN;
+
+	return 0;
+}
+
+static const struct nand_controller_ops gpmi_nand_controller_ops = {
+	.attach_chip = gpmi_nand_attach_chip,
+};
+
 static int gpmi_nand_init(struct gpmi_nand_data *this)
 {
 	struct nand_chip *chip = &this->nand;
@@ -1905,26 +1933,8 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
 	if (ret)
 		goto err_out;
 
-	ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL);
-	if (ret)
-		goto err_out;
-
-	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
-		chip->bbt_options |= NAND_BBT_NO_OOB;
-
-		if (of_property_read_bool(this->dev->of_node,
-						"fsl,no-blockmark-swap"))
-			this->swap_block_mark = false;
-	}
-	dev_dbg(this->dev, "Blockmark swapping %sabled\n",
-		this->swap_block_mark ? "en" : "dis");
-
-	ret = gpmi_init_last(this);
-	if (ret)
-		goto err_out;
-
-	chip->options |= NAND_SKIP_BBTSCAN;
-	ret = nand_scan_tail(mtd);
+	chip->dummy_controller.ops = &gpmi_nand_controller_ops;
+	ret = nand_scan(mtd, GPMI_IS_MX6(this) ? 2 : 1);
 	if (ret)
 		goto err_out;
 
-- 
2.14.1


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

* [PATCH v4 09/35] mtd: rawnand: hisi504: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (7 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 08/35] mtd: rawnand: gpmi: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21  6:59   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 10/35] mtd: rawnand: jz4780: " Miquel Raynal
                   ` (26 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/hisi504_nand.c | 78 +++++++++++++++++++++----------------
 1 file changed, 44 insertions(+), 34 deletions(-)

diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
index a1e009c8e556..950dc7789296 100644
--- a/drivers/mtd/nand/raw/hisi504_nand.c
+++ b/drivers/mtd/nand/raw/hisi504_nand.c
@@ -709,9 +709,50 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host)
 	return 0;
 }
 
+static int hisi_nfc_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct hinfc_host *host = nand_get_controller_data(chip);
+	int flag;
+
+	host->buffer = dmam_alloc_coherent(host->dev,
+					   mtd->writesize + mtd->oobsize,
+					   &host->dma_buffer, GFP_KERNEL);
+	if (!host->buffer)
+		return -ENOMEM;
+
+	host->dma_oob = host->dma_buffer + mtd->writesize;
+	memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize);
+
+	flag = hinfc_read(host, HINFC504_CON);
+	flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT);
+	switch (mtd->writesize) {
+	case 2048:
+		flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT);
+		break;
+	/*
+	 * TODO: add more pagesize support,
+	 * default pagesize has been set in hisi_nfc_host_init
+	 */
+	default:
+		dev_err(host->dev, "NON-2KB page size nand flash\n");
+		return -EINVAL;
+	}
+	hinfc_write(host, flag, HINFC504_CON);
+
+	if (chip->ecc.mode == NAND_ECC_HW)
+		hisi_nfc_ecc_probe(host);
+
+	return 0;
+}
+
+static const struct nand_controller_ops hisi_nfc_controller_ops = {
+	.attach_chip = hisi_nfc_attach_chip,
+};
+
 static int hisi_nfc_probe(struct platform_device *pdev)
 {
-	int ret = 0, irq, flag, max_chips = HINFC504_MAX_CHIP;
+	int ret = 0, irq, max_chips = HINFC504_MAX_CHIP;
 	struct device *dev = &pdev->dev;
 	struct hinfc_host *host;
 	struct nand_chip  *chip;
@@ -769,42 +810,11 @@ static int hisi_nfc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	ret = nand_scan_ident(mtd, max_chips, NULL);
+	chip->dummy_controller.ops = &hisi_nfc_controller_ops;
+	ret = nand_scan(mtd, max_chips);
 	if (ret)
 		return ret;
 
-	host->buffer = dmam_alloc_coherent(dev, mtd->writesize + mtd->oobsize,
-		&host->dma_buffer, GFP_KERNEL);
-	if (!host->buffer)
-		return -ENOMEM;
-
-	host->dma_oob = host->dma_buffer + mtd->writesize;
-	memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize);
-
-	flag = hinfc_read(host, HINFC504_CON);
-	flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT);
-	switch (mtd->writesize) {
-	case 2048:
-		flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT); break;
-	/*
-	 * TODO: add more pagesize support,
-	 * default pagesize has been set in hisi_nfc_host_init
-	 */
-	default:
-		dev_err(dev, "NON-2KB page size nand flash\n");
-		return -EINVAL;
-	}
-	hinfc_write(host, flag, HINFC504_CON);
-
-	if (chip->ecc.mode == NAND_ECC_HW)
-		hisi_nfc_ecc_probe(host);
-
-	ret = nand_scan_tail(mtd);
-	if (ret) {
-		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
-		return ret;
-	}
-
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(dev, "Err MTD partition=%d\n", ret);
-- 
2.14.1


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

* [PATCH v4 10/35] mtd: rawnand: jz4780: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (8 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 09/35] mtd: rawnand: hisi504: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 15:23   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: " Miquel Raynal
                   ` (25 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Acked-by: Harvey Hunt <harveyhuntnexus@gmail.com>
---
 drivers/mtd/nand/raw/jz4780_nand.c | 34 ++++++++++++++++------------------
 1 file changed, 16 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
index 49841dad347c..db4fa60bd52a 100644
--- a/drivers/mtd/nand/raw/jz4780_nand.c
+++ b/drivers/mtd/nand/raw/jz4780_nand.c
@@ -158,9 +158,8 @@ static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
 	return jz4780_bch_correct(nfc->bch, &params, dat, read_ecc);
 }
 
-static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev)
+static int jz4780_nand_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &nand->chip;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller);
 	int eccbytes;
@@ -171,7 +170,8 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
 	switch (chip->ecc.mode) {
 	case NAND_ECC_HW:
 		if (!nfc->bch) {
-			dev_err(dev, "HW BCH selected, but BCH controller not found\n");
+			dev_err(nfc->dev,
+				"HW BCH selected, but BCH controller not found\n");
 			return -ENODEV;
 		}
 
@@ -180,15 +180,16 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
 		chip->ecc.correct = jz4780_nand_ecc_correct;
 		/* fall through */
 	case NAND_ECC_SOFT:
-		dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n",
-			(nfc->bch) ? "hardware BCH" : "software ECC",
-			chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
+		dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n",
+			 (nfc->bch) ? "hardware BCH" : "software ECC",
+			 chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
 		break;
 	case NAND_ECC_NONE:
-		dev_info(dev, "not using ECC\n");
+		dev_info(nfc->dev, "not using ECC\n");
 		break;
 	default:
-		dev_err(dev, "ECC mode %d not supported\n", chip->ecc.mode);
+		dev_err(nfc->dev, "ECC mode %d not supported\n",
+			chip->ecc.mode);
 		return -EINVAL;
 	}
 
@@ -200,7 +201,7 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
 	eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes;
 
 	if (eccbytes > mtd->oobsize - 2) {
-		dev_err(dev,
+		dev_err(nfc->dev,
 			"invalid ECC config: required %d ECC bytes, but only %d are available",
 			eccbytes, mtd->oobsize - 2);
 		return -EINVAL;
@@ -211,6 +212,10 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
 	return 0;
 }
 
+static const struct nand_controller_ops jz4780_nand_controller_ops = {
+	.attach_chip = jz4780_nand_attach_chip,
+};
+
 static int jz4780_nand_init_chip(struct platform_device *pdev,
 				struct jz4780_nand_controller *nfc,
 				struct device_node *np,
@@ -280,15 +285,8 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
 	chip->controller = &nfc->controller;
 	nand_set_flash_node(chip, np);
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		return ret;
-
-	ret = jz4780_nand_init_ecc(nand, dev);
-	if (ret)
-		return ret;
-
-	ret = nand_scan_tail(mtd);
+	chip->controller->ops = &jz4780_nand_controller_ops;
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		return ret;
 
-- 
2.14.1


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

* [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (9 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 10/35] mtd: rawnand: jz4780: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 15:26   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: " Miquel Raynal
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/lpc32xx_mlc.c | 109 ++++++++++++++++++++-----------------
 1 file changed, 59 insertions(+), 50 deletions(-)

diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 052d123a8304..6f73136fa863 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -184,6 +184,7 @@ static struct nand_bbt_descr lpc32xx_nand_bbt_mirror = {
 };
 
 struct lpc32xx_nand_host {
+	struct platform_device	*pdev;
 	struct nand_chip	nand_chip;
 	struct lpc32xx_mlc_platform_data *pdata;
 	struct clk		*clk;
@@ -653,6 +654,58 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
 	return ncfg;
 }
 
+static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
+	struct device *dev = &host->pdev->dev;
+
+	host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
+	if (!host->dma_buf)
+		return -ENOMEM;
+
+	host->dummy_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
+	if (!host->dummy_buf)
+		return -ENOMEM;
+
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = 512;
+	mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
+	host->mlcsubpages = mtd->writesize / 512;
+
+	/* initially clear interrupt status */
+	readb(MLC_IRQ_SR(host->io_base));
+
+	init_completion(&host->comp_nand);
+	init_completion(&host->comp_controller);
+
+	host->irq = platform_get_irq(host->pdev, 0);
+	if (host->irq < 0) {
+		dev_err(dev, "failed to get platform irq\n");
+		return -EINVAL;
+	}
+
+	if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
+			IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
+		dev_err(dev, "Error requesting NAND IRQ\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static void lpc32xx_nand_detach_chip(struct nand_chip *chip)
+{
+	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
+
+	free_irq(host->irq, host);
+}
+
+static const struct nand_controller_ops lpc32xx_nand_controller_ops = {
+	.attach_chip = lpc32xx_nand_attach_chip,
+	.detach_chip = lpc32xx_nand_detach_chip,
+};
+
 /*
  * Probe for NAND controller
  */
@@ -669,6 +722,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	if (!host)
 		return -ENOMEM;
 
+	host->pdev = pdev;
+
 	rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	host->io_base = devm_ioremap_resource(&pdev->dev, rc);
 	if (IS_ERR(host->io_base))
@@ -749,58 +804,14 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	}
 
 	/*
-	 * Scan to find existance of the device and
-	 * Get the type of NAND device SMALL block or LARGE block
+	 * Scan to find existence of the device and get the type of NAND device:
+	 * SMALL block or LARGE block.
 	 */
-	res = nand_scan_ident(mtd, 1, NULL);
+	nand_chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
+	res = nand_scan(mtd, 1);
 	if (res)
 		goto release_dma_chan;
 
-	host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
-	if (!host->dma_buf) {
-		res = -ENOMEM;
-		goto release_dma_chan;
-	}
-
-	host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
-	if (!host->dummy_buf) {
-		res = -ENOMEM;
-		goto release_dma_chan;
-	}
-
-	nand_chip->ecc.mode = NAND_ECC_HW;
-	nand_chip->ecc.size = 512;
-	mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
-	host->mlcsubpages = mtd->writesize / 512;
-
-	/* initially clear interrupt status */
-	readb(MLC_IRQ_SR(host->io_base));
-
-	init_completion(&host->comp_nand);
-	init_completion(&host->comp_controller);
-
-	host->irq = platform_get_irq(pdev, 0);
-	if (host->irq < 0) {
-		dev_err(&pdev->dev, "failed to get platform irq\n");
-		res = -EINVAL;
-		goto release_dma_chan;
-	}
-
-	if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
-			IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
-		dev_err(&pdev->dev, "Error requesting NAND IRQ\n");
-		res = -ENXIO;
-		goto release_dma_chan;
-	}
-
-	/*
-	 * Fills out all the uninitialized function pointers with the defaults
-	 * And scans for a bad block table if appropriate.
-	 */
-	res = nand_scan_tail(mtd);
-	if (res)
-		goto free_irq;
-
 	mtd->name = DRV_NAME;
 
 	res = mtd_device_register(mtd, host->ncfg->parts,
@@ -812,8 +823,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 
 cleanup_nand:
 	nand_cleanup(nand_chip);
-free_irq:
-	free_irq(host->irq, host);
 release_dma_chan:
 	if (use_dma)
 		dma_release_channel(host->dma_chan);
-- 
2.14.1


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

* [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (10 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 15:27   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 13/35] mtd: rawnand: marvell: " Miquel Raynal
                   ` (23 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/lpc32xx_slc.c | 77 +++++++++++++++++++++-----------------
 1 file changed, 42 insertions(+), 35 deletions(-)

diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index 42820aa1abab..a4e8b7e75135 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -779,6 +779,46 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
 	return ncfg;
 }
 
+static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
+
+	/* OOB and ECC CPU and DMA work areas */
+	host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
+
+	/*
+	 * Small page FLASH has a unique OOB layout, but large and huge
+	 * page FLASH use the standard layout. Small page FLASH uses a
+	 * custom BBT marker layout.
+	 */
+	if (mtd->writesize <= 512)
+		mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
+
+	/* These sizes remain the same regardless of page size */
+	chip->ecc.size = 256;
+	chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
+	chip->ecc.prepad = 0;
+	chip->ecc.postpad = 0;
+
+	/*
+	 * Use a custom BBT marker setup for small page FLASH that
+	 * won't interfere with the ECC layout. Large and huge page
+	 * FLASH use the standard layout.
+	 */
+	if ((chip->bbt_options & NAND_BBT_USE_FLASH) &&
+	    mtd->writesize <= 512) {
+		chip->bbt_td = &bbt_smallpage_main_descr;
+		chip->bbt_md = &bbt_smallpage_mirror_descr;
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops lpc32xx_nand_controller_ops = {
+	.attach_chip = lpc32xx_nand_attach_chip,
+};
+
 /*
  * Probe for NAND controller
  */
@@ -884,41 +924,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	}
 
 	/* Find NAND device */
-	res = nand_scan_ident(mtd, 1, NULL);
-	if (res)
-		goto release_dma;
-
-	/* OOB and ECC CPU and DMA work areas */
-	host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
-
-	/*
-	 * Small page FLASH has a unique OOB layout, but large and huge
-	 * page FLASH use the standard layout. Small page FLASH uses a
-	 * custom BBT marker layout.
-	 */
-	if (mtd->writesize <= 512)
-		mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
-
-	/* These sizes remain the same regardless of page size */
-	chip->ecc.size = 256;
-	chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
-	chip->ecc.prepad = chip->ecc.postpad = 0;
-
-	/*
-	 * Use a custom BBT marker setup for small page FLASH that
-	 * won't interfere with the ECC layout. Large and huge page
-	 * FLASH use the standard layout.
-	 */
-	if ((chip->bbt_options & NAND_BBT_USE_FLASH) &&
-	    mtd->writesize <= 512) {
-		chip->bbt_td = &bbt_smallpage_main_descr;
-		chip->bbt_md = &bbt_smallpage_mirror_descr;
-	}
-
-	/*
-	 * Fills out all the uninitialized function pointers with the defaults
-	 */
-	res = nand_scan_tail(mtd);
+	chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
+	res = nand_scan(mtd, 1);
 	if (res)
 		goto release_dma;
 
-- 
2.14.1


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

* [PATCH v4 13/35] mtd: rawnand: marvell: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (11 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 16:57   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 14/35] mtd: rawnand: mtk: " Miquel Raynal
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/marvell_nand.c | 205 +++++++++++++++++++-----------------
 1 file changed, 108 insertions(+), 97 deletions(-)

diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index bd5f9a4b7b16..7e5ffef0da76 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -2290,6 +2290,111 @@ static int marvell_nfc_setup_data_interface(struct mtd_info *mtd, int chipnr,
 	return 0;
 }
 
+static int marvell_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct marvell_nand_chip *marvell_nand = to_marvell_nand(chip);
+	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
+	struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(nfc->dev);
+	int ret;
+
+	if (pdata && pdata->flash_bbt)
+		chip->bbt_options |= NAND_BBT_USE_FLASH;
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
+		/*
+		 * We'll use a bad block table stored in-flash and don't
+		 * allow writing the bad block marker to the flash.
+		 */
+		chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
+		chip->bbt_td = &bbt_main_descr;
+		chip->bbt_md = &bbt_mirror_descr;
+	}
+
+	/* Save the chip-specific fields of NDCR */
+	marvell_nand->ndcr = NDCR_PAGE_SZ(mtd->writesize);
+	if (chip->options & NAND_BUSWIDTH_16)
+		marvell_nand->ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;
+
+	/*
+	 * On small page NANDs, only one cycle is needed to pass the
+	 * column address.
+	 */
+	if (mtd->writesize <= 512) {
+		marvell_nand->addr_cyc = 1;
+	} else {
+		marvell_nand->addr_cyc = 2;
+		marvell_nand->ndcr |= NDCR_RA_START;
+	}
+
+	/*
+	 * Now add the number of cycles needed to pass the row
+	 * address.
+	 *
+	 * Addressing a chip using CS 2 or 3 should also need the third row
+	 * cycle but due to inconsistance in the documentation and lack of
+	 * hardware to test this situation, this case is not supported.
+	 */
+	if (chip->options & NAND_ROW_ADDR_3)
+		marvell_nand->addr_cyc += 3;
+	else
+		marvell_nand->addr_cyc += 2;
+
+	if (pdata) {
+		chip->ecc.size = pdata->ecc_step_size;
+		chip->ecc.strength = pdata->ecc_strength;
+	}
+
+	ret = marvell_nand_ecc_init(mtd, &chip->ecc);
+	if (ret) {
+		dev_err(nfc->dev, "ECC init failed: %d\n", ret);
+		return ret;
+	}
+
+	if (chip->ecc.mode == NAND_ECC_HW) {
+		/*
+		 * Subpage write not available with hardware ECC, prohibit also
+		 * subpage read as in userspace subpage access would still be
+		 * allowed and subpage write, if used, would lead to numerous
+		 * uncorrectable ECC errors.
+		 */
+		chip->options |= NAND_NO_SUBPAGE_WRITE;
+	}
+
+	if (pdata || nfc->caps->legacy_of_bindings) {
+		/*
+		 * We keep the MTD name unchanged to avoid breaking platforms
+		 * where the MTD cmdline parser is used and the bootloader
+		 * has not been updated to use the new naming scheme.
+		 */
+		mtd->name = "pxa3xx_nand-0";
+	} else if (!mtd->name) {
+		/*
+		 * If the new bindings are used and the bootloader has not been
+		 * updated to pass a new mtdparts parameter on the cmdline, you
+		 * should define the following property in your NAND node, ie:
+		 *
+		 *	label = "main-storage";
+		 *
+		 * This way, mtd->name will be set by the core when
+		 * nand_set_flash_node() is called.
+		 */
+		mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
+					   "%s:nand.%d", dev_name(nfc->dev),
+					   marvell_nand->sels[0].cs);
+		if (!mtd->name) {
+			dev_err(nfc->dev, "Failed to allocate mtd->name\n");
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops marvell_nand_controller_ops = {
+	.attach_chip = marvell_nand_attach_chip,
+};
+
 static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
 				  struct device_node *np)
 {
@@ -2432,105 +2537,11 @@ static int marvell_nand_chip_init(struct device *dev, struct marvell_nfc *nfc,
 	marvell_nand->ndtr1 = readl_relaxed(nfc->regs + NDTR1);
 
 	chip->options |= NAND_BUSWIDTH_AUTO;
-	ret = nand_scan_ident(mtd, marvell_nand->nsels, NULL);
-	if (ret) {
-		dev_err(dev, "could not identify the nand chip\n");
-		return ret;
-	}
-
-	if (pdata && pdata->flash_bbt)
-		chip->bbt_options |= NAND_BBT_USE_FLASH;
-
-	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
-		/*
-		 * We'll use a bad block table stored in-flash and don't
-		 * allow writing the bad block marker to the flash.
-		 */
-		chip->bbt_options |= NAND_BBT_NO_OOB_BBM;
-		chip->bbt_td = &bbt_main_descr;
-		chip->bbt_md = &bbt_mirror_descr;
-	}
-
-	/* Save the chip-specific fields of NDCR */
-	marvell_nand->ndcr = NDCR_PAGE_SZ(mtd->writesize);
-	if (chip->options & NAND_BUSWIDTH_16)
-		marvell_nand->ndcr |= NDCR_DWIDTH_M | NDCR_DWIDTH_C;
-
-	/*
-	 * On small page NANDs, only one cycle is needed to pass the
-	 * column address.
-	 */
-	if (mtd->writesize <= 512) {
-		marvell_nand->addr_cyc = 1;
-	} else {
-		marvell_nand->addr_cyc = 2;
-		marvell_nand->ndcr |= NDCR_RA_START;
-	}
-
-	/*
-	 * Now add the number of cycles needed to pass the row
-	 * address.
-	 *
-	 * Addressing a chip using CS 2 or 3 should also need the third row
-	 * cycle but due to inconsistance in the documentation and lack of
-	 * hardware to test this situation, this case is not supported.
-	 */
-	if (chip->options & NAND_ROW_ADDR_3)
-		marvell_nand->addr_cyc += 3;
-	else
-		marvell_nand->addr_cyc += 2;
-
-	if (pdata) {
-		chip->ecc.size = pdata->ecc_step_size;
-		chip->ecc.strength = pdata->ecc_strength;
-	}
-
-	ret = marvell_nand_ecc_init(mtd, &chip->ecc);
-	if (ret) {
-		dev_err(dev, "ECC init failed: %d\n", ret);
-		return ret;
-	}
-
-	if (chip->ecc.mode == NAND_ECC_HW) {
-		/*
-		 * Subpage write not available with hardware ECC, prohibit also
-		 * subpage read as in userspace subpage access would still be
-		 * allowed and subpage write, if used, would lead to numerous
-		 * uncorrectable ECC errors.
-		 */
-		chip->options |= NAND_NO_SUBPAGE_WRITE;
-	}
-
-	if (pdata || nfc->caps->legacy_of_bindings) {
-		/*
-		 * We keep the MTD name unchanged to avoid breaking platforms
-		 * where the MTD cmdline parser is used and the bootloader
-		 * has not been updated to use the new naming scheme.
-		 */
-		mtd->name = "pxa3xx_nand-0";
-	} else if (!mtd->name) {
-		/*
-		 * If the new bindings are used and the bootloader has not been
-		 * updated to pass a new mtdparts parameter on the cmdline, you
-		 * should define the following property in your NAND node, ie:
-		 *
-		 *	label = "main-storage";
-		 *
-		 * This way, mtd->name will be set by the core when
-		 * nand_set_flash_node() is called.
-		 */
-		mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL,
-					   "%s:nand.%d", dev_name(nfc->dev),
-					   marvell_nand->sels[0].cs);
-		if (!mtd->name) {
-			dev_err(nfc->dev, "Failed to allocate mtd->name\n");
-			return -ENOMEM;
-		}
-	}
 
-	ret = nand_scan_tail(mtd);
+	chip->controller->ops = &marvell_nand_controller_ops;
+	ret = nand_scan(mtd, marvell_nand->nsels);
 	if (ret) {
-		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
+		dev_err(dev, "could not scan the nand chip\n");
 		return ret;
 	}
 
-- 
2.14.1


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

* [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (12 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 13/35] mtd: rawnand: marvell: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:10   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 15/35] mtd: rawnand: mxc: " Miquel Raynal
                   ` (21 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
 1 file changed, 44 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index 7bc6be3f6ec0..967418f945ea 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 	return 0;
 }
 
+static int mtk_nfc_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct device *dev = mtd->dev.parent;
+	struct mtk_nfc *nfc = nand_get_controller_data(chip);
+	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
+	int len;
+	int ret;
+
+	if (chip->options & NAND_BUSWIDTH_16) {
+		dev_err(dev, "16bits buswidth not supported");
+		return -EINVAL;
+	}
+
+	/* store bbt magic in page, cause OOB is not protected */
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+	ret = mtk_nfc_ecc_init(dev, mtd);
+	if (ret)
+		return ret;
+
+	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
+	if (ret)
+		return ret;
+
+	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
+	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
+
+	len = mtd->writesize + mtd->oobsize;
+	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
+	if (!nfc->buffer)
+		return  -ENOMEM;
+
+	return 0;
+}
+
+static const struct nand_controller_ops mtk_nfc_controller_ops = {
+	.attach_chip = mtk_nfc_attach_chip,
+};
+
 static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 				  struct device_node *np)
 {
 	struct mtk_nfc_nand_chip *chip;
 	struct nand_chip *nand;
 	struct mtd_info *mtd;
-	int nsels, len;
+	int nsels;
 	u32 tmp;
 	int ret;
 	int i;
@@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 
 	nand = &chip->nand;
 	nand->controller = &nfc->controller;
+	nand->controller->ops = &mtk_nfc_controller_ops;
 
 	nand_set_flash_node(nand, np);
 	nand_set_controller_data(nand, nfc);
@@ -1324,36 +1366,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
 
 	mtk_nfc_hw_init(nfc);
 
-	ret = nand_scan_ident(mtd, nsels, NULL);
-	if (ret)
-		return ret;
-
-	/* store bbt magic in page, cause OOB is not protected */
-	if (nand->bbt_options & NAND_BBT_USE_FLASH)
-		nand->bbt_options |= NAND_BBT_NO_OOB;
-
-	ret = mtk_nfc_ecc_init(dev, mtd);
-	if (ret)
-		return -EINVAL;
-
-	if (nand->options & NAND_BUSWIDTH_16) {
-		dev_err(dev, "16bits buswidth not supported");
-		return -EINVAL;
-	}
-
-	ret = mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
-	if (ret)
-		return ret;
-
-	mtk_nfc_set_fdm(&chip->fdm, mtd);
-	mtk_nfc_set_bad_mark_ctl(&chip->bad_mark, mtd);
-
-	len = mtd->writesize + mtd->oobsize;
-	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
-	if (!nfc->buffer)
-		return  -ENOMEM;
-
-	ret = nand_scan_tail(mtd);
+	ret = nand_scan(mtd, nsels);
 	if (ret)
 		return ret;
 
-- 
2.14.1


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

* [PATCH v4 15/35] mtd: rawnand: mxc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (13 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 14/35] mtd: rawnand: mtk: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:19   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 16/35] mtd: rawnand: nandsim: " Miquel Raynal
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/mxc_nand.c | 136 +++++++++++++++++++++-------------------
 1 file changed, 71 insertions(+), 65 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
index c6eff61e909d..4c9214dea424 100644
--- a/drivers/mtd/nand/raw/mxc_nand.c
+++ b/drivers/mtd/nand/raw/mxc_nand.c
@@ -1691,6 +1691,74 @@ static int mxcnd_probe_dt(struct mxc_nand_host *host)
 }
 #endif
 
+static int mxcnd_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct mxc_nand_host *host = nand_get_controller_data(chip);
+	struct device *dev = mtd->dev.parent;
+
+	switch (chip->ecc.mode) {
+	case NAND_ECC_HW:
+		chip->ecc.read_page = mxc_nand_read_page;
+		chip->ecc.read_page_raw = mxc_nand_read_page_raw;
+		chip->ecc.read_oob = mxc_nand_read_oob;
+		chip->ecc.write_page = mxc_nand_write_page_ecc;
+		chip->ecc.write_page_raw = mxc_nand_write_page_raw;
+		chip->ecc.write_oob = mxc_nand_write_oob;
+		break;
+
+	case NAND_ECC_SOFT:
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
+		chip->bbt_td = &bbt_main_descr;
+		chip->bbt_md = &bbt_mirror_descr;
+	}
+
+	/* Allocate the right size buffer now */
+	devm_kfree(dev, (void *)host->data_buf);
+	host->data_buf = devm_kzalloc(dev, mtd->writesize + mtd->oobsize,
+				      GFP_KERNEL);
+	if (!host->data_buf)
+		return -ENOMEM;
+
+	/* Call preset again, with correct writesize chip time */
+	host->devtype_data->preset(mtd);
+
+	if (!chip->ecc.bytes) {
+		if (host->eccsize == 8)
+			chip->ecc.bytes = 18;
+		else if (host->eccsize == 4)
+			chip->ecc.bytes = 9;
+	}
+
+	/*
+	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
+	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
+	 * into copying invalid data to/from the spare IO buffer, as this
+	 * might cause ECC data corruption when doing sub-page write to a
+	 * partially written page.
+	 */
+	host->used_oobsize = min(mtd->oobsize, 218U);
+
+	if (chip->ecc.mode == NAND_ECC_HW) {
+		if (is_imx21_nfc(host) || is_imx27_nfc(host))
+			chip->ecc.strength = 1;
+		else
+			chip->ecc.strength = (host->eccsize == 4) ? 4 : 8;
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops mxcnd_controller_ops = {
+	.attach_chip = mxcnd_attach_chip,
+};
+
 static int mxcnd_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
@@ -1830,71 +1898,9 @@ static int mxcnd_probe(struct platform_device *pdev)
 		host->devtype_data->irq_control(host, 1);
 	}
 
-	/* first scan to find the device and get the page size */
-	err = nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL);
-	if (err)
-		goto escan;
-
-	switch (this->ecc.mode) {
-	case NAND_ECC_HW:
-		this->ecc.read_page = mxc_nand_read_page;
-		this->ecc.read_page_raw = mxc_nand_read_page_raw;
-		this->ecc.read_oob = mxc_nand_read_oob;
-		this->ecc.write_page = mxc_nand_write_page_ecc;
-		this->ecc.write_page_raw = mxc_nand_write_page_raw;
-		this->ecc.write_oob = mxc_nand_write_oob;
-		break;
-
-	case NAND_ECC_SOFT:
-		break;
-
-	default:
-		err = -EINVAL;
-		goto escan;
-	}
-
-	if (this->bbt_options & NAND_BBT_USE_FLASH) {
-		this->bbt_td = &bbt_main_descr;
-		this->bbt_md = &bbt_mirror_descr;
-	}
-
-	/* allocate the right size buffer now */
-	devm_kfree(&pdev->dev, (void *)host->data_buf);
-	host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
-					GFP_KERNEL);
-	if (!host->data_buf) {
-		err = -ENOMEM;
-		goto escan;
-	}
-
-	/* Call preset again, with correct writesize this time */
-	host->devtype_data->preset(mtd);
-
-	if (!this->ecc.bytes) {
-		if (host->eccsize == 8)
-			this->ecc.bytes = 18;
-		else if (host->eccsize == 4)
-			this->ecc.bytes = 9;
-	}
-
-	/*
-	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
-	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
-	 * into copying invalid data to/from the spare IO buffer, as this
-	 * might cause ECC data corruption when doing sub-page write to a
-	 * partially written page.
-	 */
-	host->used_oobsize = min(mtd->oobsize, 218U);
-
-	if (this->ecc.mode == NAND_ECC_HW) {
-		if (is_imx21_nfc(host) || is_imx27_nfc(host))
-			this->ecc.strength = 1;
-		else
-			this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
-	}
-
-	/* second phase scan */
-	err = nand_scan_tail(mtd);
+	/* Scan the NAND device */
+	this->dummy_controller.ops = &mxcnd_controller_ops;
+	err = nand_scan(mtd, is_imx25_nfc(host) ? 4 : 1);
 	if (err)
 		goto escan;
 
-- 
2.14.1


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

* [PATCH v4 16/35] mtd: rawnand: nandsim: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (14 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 15/35] mtd: rawnand: mxc: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:21   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 17/35] mtd: rawnand: omap2: " Miquel Raynal
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nandsim.c | 82 +++++++++++++++++++++++-------------------
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 8a3b36cfe5ea..71ac034aee9c 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -2192,6 +2192,48 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 	return;
 }
 
+static int ns_attach_chip(struct nand_chip *chip)
+{
+	unsigned int eccsteps, eccbytes;
+
+	if (!bch)
+		return 0;
+
+	if (!mtd_nand_has_bch()) {
+		NS_ERR("BCH ECC support is disabled\n");
+		return -EINVAL;
+	}
+
+	/* Use 512-byte ecc blocks */
+	eccsteps = nsmtd->writesize / 512;
+	eccbytes = ((bch * 13) + 7) / 8;
+
+	/* Do not bother supporting small page devices */
+	if (nsmtd->oobsize < 64 || !eccsteps) {
+		NS_ERR("BCH not available on small page devices\n");
+		return -EINVAL;
+	}
+
+	if (((eccbytes * eccsteps) + 2) > nsmtd->oobsize) {
+		NS_ERR("Invalid BCH value %u\n", bch);
+		return -EINVAL;
+	}
+
+	chip->ecc.mode = NAND_ECC_SOFT;
+	chip->ecc.algo = NAND_ECC_BCH;
+	chip->ecc.size = 512;
+	chip->ecc.strength = bch;
+	chip->ecc.bytes = eccbytes;
+
+	NS_INFO("Using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
+
+	return 0;
+}
+
+static const struct nand_controller_ops ns_controller_ops = {
+	.attach_chip = ns_attach_chip,
+};
+
 /*
  * Module initialization function
  */
@@ -2276,44 +2318,10 @@ static int __init ns_init_module(void)
 	if ((retval = parse_gravepages()) != 0)
 		goto error;
 
-	retval = nand_scan_ident(nsmtd, 1, NULL);
+	chip->dummy_controller.ops = &ns_controller_ops;
+	retval = nand_scan(nsmtd, 1);
 	if (retval) {
-		NS_ERR("cannot scan NAND Simulator device\n");
-		goto error;
-	}
-
-	if (bch) {
-		unsigned int eccsteps, eccbytes;
-		if (!mtd_nand_has_bch()) {
-			NS_ERR("BCH ECC support is disabled\n");
-			retval = -EINVAL;
-			goto error;
-		}
-		/* use 512-byte ecc blocks */
-		eccsteps = nsmtd->writesize/512;
-		eccbytes = (bch*13+7)/8;
-		/* do not bother supporting small page devices */
-		if ((nsmtd->oobsize < 64) || !eccsteps) {
-			NS_ERR("bch not available on small page devices\n");
-			retval = -EINVAL;
-			goto error;
-		}
-		if ((eccbytes*eccsteps+2) > nsmtd->oobsize) {
-			NS_ERR("invalid bch value %u\n", bch);
-			retval = -EINVAL;
-			goto error;
-		}
-		chip->ecc.mode = NAND_ECC_SOFT;
-		chip->ecc.algo = NAND_ECC_BCH;
-		chip->ecc.size = 512;
-		chip->ecc.strength = bch;
-		chip->ecc.bytes = eccbytes;
-		NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
-	}
-
-	retval = nand_scan_tail(nsmtd);
-	if (retval) {
-		NS_ERR("can't register NAND Simulator\n");
+		NS_ERR("Could not scan NAND Simulator device\n");
 		goto error;
 	}
 
-- 
2.14.1


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

* [PATCH v4 17/35] mtd: rawnand: omap2: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (15 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 16/35] mtd: rawnand: nandsim: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:34   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 18/35] mtd: rawnand: s3c2410: " Miquel Raynal
                   ` (18 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/omap2.c | 521 +++++++++++++++++++++----------------------
 1 file changed, 259 insertions(+), 262 deletions(-)

diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index e943b2e5a5e2..73ffb1a9b99f 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -1915,17 +1915,271 @@ static const struct mtd_ooblayout_ops omap_sw_ooblayout_ops = {
 	.free = omap_sw_ooblayout_free,
 };
 
+static int omap_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct omap_nand_info *info = mtd_to_omap(mtd);
+	struct device *dev = &info->pdev->dev;
+	int min_oobbytes = BADBLOCK_MARKER_LENGTH;
+	int oobbytes_per_step;
+	dma_cap_mask_t mask;
+	int err;
+
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+	else
+		chip->options |= NAND_SKIP_BBTSCAN;
+
+	/* Re-populate low-level callbacks based on xfer modes */
+	switch (info->xfer_type) {
+	case NAND_OMAP_PREFETCH_POLLED:
+		chip->read_buf = omap_read_buf_pref;
+		chip->write_buf = omap_write_buf_pref;
+		break;
+
+	case NAND_OMAP_POLLED:
+		/* Use nand_base defaults for {read,write}_buf */
+		break;
+
+	case NAND_OMAP_PREFETCH_DMA:
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		info->dma = dma_request_chan(dev, "rxtx");
+
+		if (IS_ERR(info->dma)) {
+			dev_err(dev, "DMA engine request failed\n");
+			return PTR_ERR(info->dma);
+		} else {
+			struct dma_slave_config cfg;
+
+			memset(&cfg, 0, sizeof(cfg));
+			cfg.src_addr = info->phys_base;
+			cfg.dst_addr = info->phys_base;
+			cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+			cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+			cfg.src_maxburst = 16;
+			cfg.dst_maxburst = 16;
+			err = dmaengine_slave_config(info->dma, &cfg);
+			if (err) {
+				dev_err(dev,
+					"DMA engine slave config failed: %d\n",
+					err);
+				return err;
+			}
+			chip->read_buf = omap_read_buf_dma_pref;
+			chip->write_buf = omap_write_buf_dma_pref;
+		}
+		break;
+
+	case NAND_OMAP_PREFETCH_IRQ:
+		info->gpmc_irq_fifo = platform_get_irq(info->pdev, 0);
+		if (info->gpmc_irq_fifo <= 0) {
+			dev_err(dev, "Error getting fifo IRQ\n");
+			return -ENODEV;
+		}
+		err = devm_request_irq(dev, info->gpmc_irq_fifo,
+				       omap_nand_irq, IRQF_SHARED,
+				       "gpmc-nand-fifo", info);
+		if (err) {
+			dev_err(dev, "Requesting IRQ %d, error %d\n",
+				info->gpmc_irq_fifo, err);
+			info->gpmc_irq_fifo = 0;
+			return err;
+		}
+
+		info->gpmc_irq_count = platform_get_irq(info->pdev, 1);
+		if (info->gpmc_irq_count <= 0) {
+			dev_err(dev, "Error getting IRQ count\n");
+			return -ENODEV;
+		}
+		err = devm_request_irq(dev, info->gpmc_irq_count,
+				       omap_nand_irq, IRQF_SHARED,
+				       "gpmc-nand-count", info);
+		if (err) {
+			dev_err(dev, "Requesting IRQ %d, error %d\n",
+				info->gpmc_irq_count, err);
+			info->gpmc_irq_count = 0;
+			return err;
+		}
+
+		chip->read_buf = omap_read_buf_irq_pref;
+		chip->write_buf = omap_write_buf_irq_pref;
+
+		break;
+
+	default:
+		dev_err(dev, "xfer_type %d not supported!\n", info->xfer_type);
+		return -EINVAL;
+	}
+
+	if (!omap2_nand_ecc_check(info))
+		return -EINVAL;
+
+	/*
+	 * Bail out earlier to let NAND_ECC_SOFT code create its own
+	 * ooblayout instead of using ours.
+	 */
+	if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) {
+		chip->ecc.mode = NAND_ECC_SOFT;
+		chip->ecc.algo = NAND_ECC_HAMMING;
+		return 0;
+	}
+
+	/* Populate MTD interface based on ECC scheme */
+	switch (info->ecc_opt) {
+	case OMAP_ECC_HAM1_CODE_HW:
+		dev_info(dev, "nand: using OMAP_ECC_HAM1_CODE_HW\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.bytes		= 3;
+		chip->ecc.size		= 512;
+		chip->ecc.strength	= 1;
+		chip->ecc.calculate	= omap_calculate_ecc;
+		chip->ecc.hwctl		= omap_enable_hwecc;
+		chip->ecc.correct	= omap_correct_data;
+		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
+		oobbytes_per_step	= chip->ecc.bytes;
+
+		if (!(chip->options & NAND_BUSWIDTH_16))
+			min_oobbytes	= 1;
+
+		break;
+
+	case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
+		pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.size		= 512;
+		chip->ecc.bytes		= 7;
+		chip->ecc.strength	= 4;
+		chip->ecc.hwctl		= omap_enable_hwecc_bch;
+		chip->ecc.correct	= nand_bch_correct_data;
+		chip->ecc.calculate	= omap_calculate_ecc_bch_sw;
+		mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
+		/* Reserve one byte for the OMAP marker */
+		oobbytes_per_step	= chip->ecc.bytes + 1;
+		/* Software BCH library is used for locating errors */
+		chip->ecc.priv		= nand_bch_init(mtd);
+		if (!chip->ecc.priv) {
+			dev_err(dev, "Unable to use BCH library\n");
+			return -EINVAL;
+		}
+		break;
+
+	case OMAP_ECC_BCH4_CODE_HW:
+		pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.size		= 512;
+		/* 14th bit is kept reserved for ROM-code compatibility */
+		chip->ecc.bytes		= 7 + 1;
+		chip->ecc.strength	= 4;
+		chip->ecc.hwctl		= omap_enable_hwecc_bch;
+		chip->ecc.correct	= omap_elm_correct_data;
+		chip->ecc.read_page	= omap_read_page_bch;
+		chip->ecc.write_page	= omap_write_page_bch;
+		chip->ecc.write_subpage	= omap_write_subpage_bch;
+		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
+		oobbytes_per_step	= chip->ecc.bytes;
+
+		err = elm_config(info->elm_dev, BCH4_ECC,
+				 mtd->writesize / chip->ecc.size,
+				 chip->ecc.size, chip->ecc.bytes);
+		if (err < 0)
+			return err;
+		break;
+
+	case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+		pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.size		= 512;
+		chip->ecc.bytes		= 13;
+		chip->ecc.strength	= 8;
+		chip->ecc.hwctl		= omap_enable_hwecc_bch;
+		chip->ecc.correct	= nand_bch_correct_data;
+		chip->ecc.calculate	= omap_calculate_ecc_bch_sw;
+		mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
+		/* Reserve one byte for the OMAP marker */
+		oobbytes_per_step	= chip->ecc.bytes + 1;
+		/* Software BCH library is used for locating errors */
+		chip->ecc.priv		= nand_bch_init(mtd);
+		if (!chip->ecc.priv) {
+			dev_err(dev, "unable to use BCH library\n");
+			return -EINVAL;
+		}
+		break;
+
+	case OMAP_ECC_BCH8_CODE_HW:
+		pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.size		= 512;
+		/* 14th bit is kept reserved for ROM-code compatibility */
+		chip->ecc.bytes		= 13 + 1;
+		chip->ecc.strength	= 8;
+		chip->ecc.hwctl		= omap_enable_hwecc_bch;
+		chip->ecc.correct	= omap_elm_correct_data;
+		chip->ecc.read_page	= omap_read_page_bch;
+		chip->ecc.write_page	= omap_write_page_bch;
+		chip->ecc.write_subpage	= omap_write_subpage_bch;
+		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
+		oobbytes_per_step	= chip->ecc.bytes;
+
+		err = elm_config(info->elm_dev, BCH8_ECC,
+				 mtd->writesize / chip->ecc.size,
+				 chip->ecc.size, chip->ecc.bytes);
+		if (err < 0)
+			return err;
+
+		break;
+
+	case OMAP_ECC_BCH16_CODE_HW:
+		pr_info("Using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
+		chip->ecc.mode		= NAND_ECC_HW;
+		chip->ecc.size		= 512;
+		chip->ecc.bytes		= 26;
+		chip->ecc.strength	= 16;
+		chip->ecc.hwctl		= omap_enable_hwecc_bch;
+		chip->ecc.correct	= omap_elm_correct_data;
+		chip->ecc.read_page	= omap_read_page_bch;
+		chip->ecc.write_page	= omap_write_page_bch;
+		chip->ecc.write_subpage	= omap_write_subpage_bch;
+		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
+		oobbytes_per_step	= chip->ecc.bytes;
+
+		err = elm_config(info->elm_dev, BCH16_ECC,
+				 mtd->writesize / chip->ecc.size,
+				 chip->ecc.size, chip->ecc.bytes);
+		if (err < 0)
+			return err;
+
+		break;
+	default:
+		dev_err(dev, "Invalid or unsupported ECC scheme\n");
+		return -EINVAL;
+	}
+
+	/* Check if NAND device's OOB is enough to store ECC signatures */
+	min_oobbytes += (oobbytes_per_step *
+			 (mtd->writesize / chip->ecc.size));
+	if (mtd->oobsize < min_oobbytes) {
+		dev_err(dev,
+			"Not enough OOB bytes: required = %d, available=%d\n",
+			min_oobbytes, mtd->oobsize);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops omap_nand_controller_ops = {
+	.attach_chip = omap_nand_attach_chip,
+};
+
 static int omap_nand_probe(struct platform_device *pdev)
 {
 	struct omap_nand_info		*info;
 	struct mtd_info			*mtd;
 	struct nand_chip		*nand_chip;
 	int				err;
-	dma_cap_mask_t			mask;
 	struct resource			*res;
 	struct device			*dev = &pdev->dev;
-	int				min_oobbytes = BADBLOCK_MARKER_LENGTH;
-	int				oobbytes_per_step;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
 				GFP_KERNEL);
@@ -1967,6 +2221,7 @@ static int omap_nand_probe(struct platform_device *pdev)
 	info->phys_base = res->start;
 
 	nand_chip->controller = &omap_gpmc_controller;
+	nand_chip->controller->ops = &omap_nand_controller_ops;
 
 	nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
 	nand_chip->cmd_ctrl  = omap_hwcontrol;
@@ -1998,266 +2253,8 @@ static int omap_nand_probe(struct platform_device *pdev)
 
 	/* scan NAND device connected to chip controller */
 	nand_chip->options |= info->devsize & NAND_BUSWIDTH_16;
-	err = nand_scan_ident(mtd, 1, NULL);
-	if (err) {
-		dev_err(&info->pdev->dev,
-			"scan failed, may be bus-width mismatch\n");
-		goto return_error;
-	}
 
-	if (nand_chip->bbt_options & NAND_BBT_USE_FLASH)
-		nand_chip->bbt_options |= NAND_BBT_NO_OOB;
-	else
-		nand_chip->options |= NAND_SKIP_BBTSCAN;
-
-	/* re-populate low-level callbacks based on xfer modes */
-	switch (info->xfer_type) {
-	case NAND_OMAP_PREFETCH_POLLED:
-		nand_chip->read_buf   = omap_read_buf_pref;
-		nand_chip->write_buf  = omap_write_buf_pref;
-		break;
-
-	case NAND_OMAP_POLLED:
-		/* Use nand_base defaults for {read,write}_buf */
-		break;
-
-	case NAND_OMAP_PREFETCH_DMA:
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
-		info->dma = dma_request_chan(pdev->dev.parent, "rxtx");
-
-		if (IS_ERR(info->dma)) {
-			dev_err(&pdev->dev, "DMA engine request failed\n");
-			err = PTR_ERR(info->dma);
-			goto return_error;
-		} else {
-			struct dma_slave_config cfg;
-
-			memset(&cfg, 0, sizeof(cfg));
-			cfg.src_addr = info->phys_base;
-			cfg.dst_addr = info->phys_base;
-			cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-			cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-			cfg.src_maxburst = 16;
-			cfg.dst_maxburst = 16;
-			err = dmaengine_slave_config(info->dma, &cfg);
-			if (err) {
-				dev_err(&pdev->dev, "DMA engine slave config failed: %d\n",
-					err);
-				goto return_error;
-			}
-			nand_chip->read_buf   = omap_read_buf_dma_pref;
-			nand_chip->write_buf  = omap_write_buf_dma_pref;
-		}
-		break;
-
-	case NAND_OMAP_PREFETCH_IRQ:
-		info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
-		if (info->gpmc_irq_fifo <= 0) {
-			dev_err(&pdev->dev, "error getting fifo irq\n");
-			err = -ENODEV;
-			goto return_error;
-		}
-		err = devm_request_irq(&pdev->dev, info->gpmc_irq_fifo,
-					omap_nand_irq, IRQF_SHARED,
-					"gpmc-nand-fifo", info);
-		if (err) {
-			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-						info->gpmc_irq_fifo, err);
-			info->gpmc_irq_fifo = 0;
-			goto return_error;
-		}
-
-		info->gpmc_irq_count = platform_get_irq(pdev, 1);
-		if (info->gpmc_irq_count <= 0) {
-			dev_err(&pdev->dev, "error getting count irq\n");
-			err = -ENODEV;
-			goto return_error;
-		}
-		err = devm_request_irq(&pdev->dev, info->gpmc_irq_count,
-					omap_nand_irq, IRQF_SHARED,
-					"gpmc-nand-count", info);
-		if (err) {
-			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
-						info->gpmc_irq_count, err);
-			info->gpmc_irq_count = 0;
-			goto return_error;
-		}
-
-		nand_chip->read_buf  = omap_read_buf_irq_pref;
-		nand_chip->write_buf = omap_write_buf_irq_pref;
-
-		break;
-
-	default:
-		dev_err(&pdev->dev,
-			"xfer_type(%d) not supported!\n", info->xfer_type);
-		err = -EINVAL;
-		goto return_error;
-	}
-
-	if (!omap2_nand_ecc_check(info)) {
-		err = -EINVAL;
-		goto return_error;
-	}
-
-	/*
-	 * Bail out earlier to let NAND_ECC_SOFT code create its own
-	 * ooblayout instead of using ours.
-	 */
-	if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW) {
-		nand_chip->ecc.mode = NAND_ECC_SOFT;
-		nand_chip->ecc.algo = NAND_ECC_HAMMING;
-		goto scan_tail;
-	}
-
-	/* populate MTD interface based on ECC scheme */
-	switch (info->ecc_opt) {
-	case OMAP_ECC_HAM1_CODE_HW:
-		pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
-		nand_chip->ecc.mode             = NAND_ECC_HW;
-		nand_chip->ecc.bytes            = 3;
-		nand_chip->ecc.size             = 512;
-		nand_chip->ecc.strength         = 1;
-		nand_chip->ecc.calculate        = omap_calculate_ecc;
-		nand_chip->ecc.hwctl            = omap_enable_hwecc;
-		nand_chip->ecc.correct          = omap_correct_data;
-		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
-		oobbytes_per_step		= nand_chip->ecc.bytes;
-
-		if (!(nand_chip->options & NAND_BUSWIDTH_16))
-			min_oobbytes		= 1;
-
-		break;
-
-	case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW:
-		pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n");
-		nand_chip->ecc.mode		= NAND_ECC_HW;
-		nand_chip->ecc.size		= 512;
-		nand_chip->ecc.bytes		= 7;
-		nand_chip->ecc.strength		= 4;
-		nand_chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		nand_chip->ecc.correct		= nand_bch_correct_data;
-		nand_chip->ecc.calculate	= omap_calculate_ecc_bch_sw;
-		mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
-		/* Reserve one byte for the OMAP marker */
-		oobbytes_per_step		= nand_chip->ecc.bytes + 1;
-		/* software bch library is used for locating errors */
-		nand_chip->ecc.priv		= nand_bch_init(mtd);
-		if (!nand_chip->ecc.priv) {
-			dev_err(&info->pdev->dev, "unable to use BCH library\n");
-			err = -EINVAL;
-			goto return_error;
-		}
-		break;
-
-	case OMAP_ECC_BCH4_CODE_HW:
-		pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n");
-		nand_chip->ecc.mode		= NAND_ECC_HW;
-		nand_chip->ecc.size		= 512;
-		/* 14th bit is kept reserved for ROM-code compatibility */
-		nand_chip->ecc.bytes		= 7 + 1;
-		nand_chip->ecc.strength		= 4;
-		nand_chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		nand_chip->ecc.correct		= omap_elm_correct_data;
-		nand_chip->ecc.read_page	= omap_read_page_bch;
-		nand_chip->ecc.write_page	= omap_write_page_bch;
-		nand_chip->ecc.write_subpage	= omap_write_subpage_bch;
-		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
-		oobbytes_per_step		= nand_chip->ecc.bytes;
-
-		err = elm_config(info->elm_dev, BCH4_ECC,
-				 mtd->writesize / nand_chip->ecc.size,
-				 nand_chip->ecc.size, nand_chip->ecc.bytes);
-		if (err < 0)
-			goto return_error;
-		break;
-
-	case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
-		pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
-		nand_chip->ecc.mode		= NAND_ECC_HW;
-		nand_chip->ecc.size		= 512;
-		nand_chip->ecc.bytes		= 13;
-		nand_chip->ecc.strength		= 8;
-		nand_chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		nand_chip->ecc.correct		= nand_bch_correct_data;
-		nand_chip->ecc.calculate	= omap_calculate_ecc_bch_sw;
-		mtd_set_ooblayout(mtd, &omap_sw_ooblayout_ops);
-		/* Reserve one byte for the OMAP marker */
-		oobbytes_per_step		= nand_chip->ecc.bytes + 1;
-		/* software bch library is used for locating errors */
-		nand_chip->ecc.priv		= nand_bch_init(mtd);
-		if (!nand_chip->ecc.priv) {
-			dev_err(&info->pdev->dev, "unable to use BCH library\n");
-			err = -EINVAL;
-			goto return_error;
-		}
-		break;
-
-	case OMAP_ECC_BCH8_CODE_HW:
-		pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n");
-		nand_chip->ecc.mode		= NAND_ECC_HW;
-		nand_chip->ecc.size		= 512;
-		/* 14th bit is kept reserved for ROM-code compatibility */
-		nand_chip->ecc.bytes		= 13 + 1;
-		nand_chip->ecc.strength		= 8;
-		nand_chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		nand_chip->ecc.correct		= omap_elm_correct_data;
-		nand_chip->ecc.read_page	= omap_read_page_bch;
-		nand_chip->ecc.write_page	= omap_write_page_bch;
-		nand_chip->ecc.write_subpage	= omap_write_subpage_bch;
-		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
-		oobbytes_per_step		= nand_chip->ecc.bytes;
-
-		err = elm_config(info->elm_dev, BCH8_ECC,
-				 mtd->writesize / nand_chip->ecc.size,
-				 nand_chip->ecc.size, nand_chip->ecc.bytes);
-		if (err < 0)
-			goto return_error;
-
-		break;
-
-	case OMAP_ECC_BCH16_CODE_HW:
-		pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
-		nand_chip->ecc.mode		= NAND_ECC_HW;
-		nand_chip->ecc.size		= 512;
-		nand_chip->ecc.bytes		= 26;
-		nand_chip->ecc.strength		= 16;
-		nand_chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		nand_chip->ecc.correct		= omap_elm_correct_data;
-		nand_chip->ecc.read_page	= omap_read_page_bch;
-		nand_chip->ecc.write_page	= omap_write_page_bch;
-		nand_chip->ecc.write_subpage	= omap_write_subpage_bch;
-		mtd_set_ooblayout(mtd, &omap_ooblayout_ops);
-		oobbytes_per_step		= nand_chip->ecc.bytes;
-
-		err = elm_config(info->elm_dev, BCH16_ECC,
-				 mtd->writesize / nand_chip->ecc.size,
-				 nand_chip->ecc.size, nand_chip->ecc.bytes);
-		if (err < 0)
-			goto return_error;
-
-		break;
-	default:
-		dev_err(&info->pdev->dev, "invalid or unsupported ECC scheme\n");
-		err = -EINVAL;
-		goto return_error;
-	}
-
-	/* check if NAND device's OOB is enough to store ECC signatures */
-	min_oobbytes += (oobbytes_per_step *
-			 (mtd->writesize / nand_chip->ecc.size));
-	if (mtd->oobsize < min_oobbytes) {
-		dev_err(&info->pdev->dev,
-			"not enough OOB bytes required = %d, available=%d\n",
-			min_oobbytes, mtd->oobsize);
-		err = -EINVAL;
-		goto return_error;
-	}
-
-scan_tail:
-	/* second phase scan */
-	err = nand_scan_tail(mtd);
+	err = nand_scan(mtd, 1);
 	if (err)
 		goto return_error;
 
-- 
2.14.1


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

* [PATCH v4 18/35] mtd: rawnand: s3c2410: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (16 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 17/35] mtd: rawnand: omap2: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:38   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function Miquel Raynal
                   ` (17 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/s3c2410.c | 30 +++++++++++++-----------------
 1 file changed, 13 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index e8bf64832213..c21e8892394a 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -915,20 +915,19 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
 }
 
 /**
- * s3c2410_nand_update_chip - post probe update
- * @info: The controller instance.
- * @nmtd: The driver version of the MTD instance.
+ * s3c2410_nand_attach_chip - Init the ECC engine after NAND scan
+ * @chip: The NAND chip
  *
- * This routine is called after the chip probe has successfully completed
- * and the relevant per-chip information updated. This call ensure that
+ * This hook is called by the core after the identification of the NAND chip,
+ * once the relevant per-chip information is up to date.. This call ensure that
  * we update the internal state accordingly.
  *
  * The internal state is currently limited to the ECC state information.
 */
-static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
-				    struct s3c2410_nand_mtd *nmtd)
+static int s3c2410_nand_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &nmtd->chip;
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
 
 	switch (chip->ecc.mode) {
 
@@ -998,6 +997,10 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
 	return 0;
 }
 
+static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
+	.attach_chip = s3c2410_nand_attach_chip,
+};
+
 static const struct of_device_id s3c24xx_nand_dt_ids[] = {
 	{
 		.compatible = "samsung,s3c2410-nand",
@@ -1095,6 +1098,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, info);
 
 	nand_controller_init(&info->controller);
+	info->controller.ops = &s3c24xx_nand_controller_ops;
 
 	/* get the clock source and enable it */
 
@@ -1166,15 +1170,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
 		mtd->dev.parent = &pdev->dev;
 		s3c2410_nand_init_chip(info, nmtd, sets);
 
-		err = nand_scan_ident(mtd, (sets) ? sets->nr_chips : 1, NULL);
-		if (err)
-			goto exit_error;
-
-		err = s3c2410_nand_update_chip(info, nmtd);
-		if (err < 0)
-			goto exit_error;
-
-		err = nand_scan_tail(mtd);
+		err = nand_scan(mtd, sets ? sets->nr_chips : 1);
 		if (err)
 			goto exit_error;
 
-- 
2.14.1


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

* [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (17 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 18/35] mtd: rawnand: s3c2410: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:48   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan() Miquel Raynal
                   ` (16 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Prepare the conversion of the sh_flctl driver to nand_scan() by moving
all the configuration that must be made after nand_scan_ident() in one
single function. Create a pdata entry in the controller structure for
that.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/sh_flctl.c | 38 +++++++++++++++++++-------------------
 include/linux/mtd/sh_flctl.h    |  1 +
 2 files changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index c7abceffcc40..d37d1d3ccbf9 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -1007,6 +1007,16 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
 	struct nand_chip *chip = &flctl->chip;
 
+	if (chip->options & NAND_BUSWIDTH_16) {
+		/*
+		 * NAND_BUSWIDTH_16 may have been set by nand_scan_ident().
+		 * Add the SEL_16BIT flag in pdata->flcmncr_val and re-assign
+		 * flctl->flcmncr_base to pdata->flcmncr_val.
+		 */
+		flctl->pdata->flcmncr_val |= SEL_16BIT;
+		flctl->flcmncr_base = flctl->pdata->flcmncr_val;
+	}
+
 	if (mtd->writesize == 512) {
 		flctl->page_size = 0;
 		if (chip->chipsize > (32 << 20)) {
@@ -1122,7 +1132,6 @@ static int flctl_probe(struct platform_device *pdev)
 	struct sh_flctl *flctl;
 	struct mtd_info *flctl_mtd;
 	struct nand_chip *nand;
-	struct sh_flctl_platform_data *pdata;
 	int ret;
 	int irq;
 
@@ -1150,11 +1159,11 @@ static int flctl_probe(struct platform_device *pdev)
 	}
 
 	if (pdev->dev.of_node)
-		pdata = flctl_parse_dt(&pdev->dev);
+		flctl->pdata = flctl_parse_dt(&pdev->dev);
 	else
-		pdata = dev_get_platdata(&pdev->dev);
+		flctl->pdata = dev_get_platdata(&pdev->dev);
 
-	if (!pdata) {
+	if (!flctl->pdata) {
 		dev_err(&pdev->dev, "no setup data defined\n");
 		return -EINVAL;
 	}
@@ -1165,9 +1174,9 @@ static int flctl_probe(struct platform_device *pdev)
 	nand_set_flash_node(nand, pdev->dev.of_node);
 	flctl_mtd->dev.parent = &pdev->dev;
 	flctl->pdev = pdev;
-	flctl->hwecc = pdata->has_hwecc;
-	flctl->holden = pdata->use_holden;
-	flctl->flcmncr_base = pdata->flcmncr_val;
+	flctl->hwecc = flctl->pdata->has_hwecc;
+	flctl->holden = flctl->pdata->use_holden;
+	flctl->flcmncr_base = flctl->pdata->flcmncr_val;
 	flctl->flintdmacr_base = flctl->hwecc ? (STERINTE | ECERB) : STERINTE;
 
 	/* Set address of hardware control function */
@@ -1183,7 +1192,7 @@ static int flctl_probe(struct platform_device *pdev)
 	nand->set_features = nand_get_set_features_notsupp;
 	nand->get_features = nand_get_set_features_notsupp;
 
-	if (pdata->flcmncr_val & SEL_16BIT)
+	if (flctl->pdata->flcmncr_val & SEL_16BIT)
 		nand->options |= NAND_BUSWIDTH_16;
 
 	pm_runtime_enable(&pdev->dev);
@@ -1195,16 +1204,6 @@ static int flctl_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_chip;
 
-	if (nand->options & NAND_BUSWIDTH_16) {
-		/*
-		 * NAND_BUSWIDTH_16 may have been set by nand_scan_ident().
-		 * Add the SEL_16BIT flag in pdata->flcmncr_val and re-assign
-		 * flctl->flcmncr_base to pdata->flcmncr_val.
-		 */
-		pdata->flcmncr_val |= SEL_16BIT;
-		flctl->flcmncr_base = pdata->flcmncr_val;
-	}
-
 	ret = flctl_chip_init_tail(flctl_mtd);
 	if (ret)
 		goto err_chip;
@@ -1213,7 +1212,8 @@ static int flctl_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_chip;
 
-	ret = mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
+	ret = mtd_device_register(flctl_mtd, flctl->pdata->parts,
+				  flctl->pdata->nr_parts);
 	if (ret)
 		goto cleanup_nand;
 
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
index c759d403cbc0..c9f486c6c019 100644
--- a/include/linux/mtd/sh_flctl.h
+++ b/include/linux/mtd/sh_flctl.h
@@ -148,6 +148,7 @@ struct sh_flctl {
 	struct dev_pm_qos_request pm_qos;
 	void __iomem		*reg;
 	resource_size_t		fifo;
+	struct sh_flctl_platform_data *pdata;
 
 	uint8_t	done_buff[2048 + 64];	/* max size 2048 + 64 */
 	int	read_bytes;
-- 
2.14.1


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

* [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (18 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:49   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 21/35] mtd: rawnand: sunxi: " Miquel Raynal
                   ` (15 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/sh_flctl.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
index d37d1d3ccbf9..663c75005ac9 100644
--- a/drivers/mtd/nand/raw/sh_flctl.c
+++ b/drivers/mtd/nand/raw/sh_flctl.c
@@ -1002,10 +1002,10 @@ static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 	flctl->index += len;
 }
 
-static int flctl_chip_init_tail(struct mtd_info *mtd)
+static int flctl_chip_attach_chip(struct nand_chip *chip)
 {
+	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct sh_flctl *flctl = mtd_to_flctl(mtd);
-	struct nand_chip *chip = &flctl->chip;
 
 	if (chip->options & NAND_BUSWIDTH_16) {
 		/*
@@ -1073,6 +1073,10 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
 	return 0;
 }
 
+static const struct nand_controller_ops flctl_nand_controller_ops = {
+	.attach_chip = flctl_chip_attach_chip,
+};
+
 static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
 {
 	struct sh_flctl *flctl = dev_id;
@@ -1200,15 +1204,8 @@ static int flctl_probe(struct platform_device *pdev)
 
 	flctl_setup_dma(flctl);
 
-	ret = nand_scan_ident(flctl_mtd, 1, NULL);
-	if (ret)
-		goto err_chip;
-
-	ret = flctl_chip_init_tail(flctl_mtd);
-	if (ret)
-		goto err_chip;
-
-	ret = nand_scan_tail(flctl_mtd);
+	nand->dummy_controller.ops = &flctl_nand_controller_ops;
+	ret = nand_scan(flctl_mtd, 1);
 	if (ret)
 		goto err_chip;
 
-- 
2.14.1


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

* [PATCH v4 21/35] mtd: rawnand: sunxi: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (19 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan() Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:50   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 22/35] mtd: rawnand: tango: " Miquel Raynal
                   ` (14 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 43 +++++++++++++++++----------------------
 1 file changed, 19 insertions(+), 24 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 07f3ff9a28f2..a4d23381003d 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1816,12 +1816,21 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
 	}
 }
 
-static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
-			       struct device_node *np)
+static int sunxi_nand_attach_chip(struct nand_chip *nand)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mtd_info *mtd = nand_to_mtd(nand);
+	struct nand_ecc_ctrl *ecc = &nand->ecc;
+	struct device_node *np = nand_get_flash_node(nand);
 	int ret;
 
+	if (nand->bbt_options & NAND_BBT_USE_FLASH)
+		nand->bbt_options |= NAND_BBT_NO_OOB;
+
+	if (nand->options & NAND_NEED_SCRAMBLING)
+		nand->options |= NAND_NO_SUBPAGE_WRITE;
+
+	nand->options |= NAND_SUBPAGE_READ;
+
 	if (!ecc->size) {
 		ecc->size = nand->ecc_step_ds;
 		ecc->strength = nand->ecc_strength_ds;
@@ -1846,6 +1855,10 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
 	return 0;
 }
 
+static const struct nand_controller_ops sunxi_nand_controller_ops = {
+	.attach_chip = sunxi_nand_attach_chip,
+};
+
 static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
 				struct device_node *np)
 {
@@ -1911,6 +1924,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
 	/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
 	nand->chip_delay = 200;
 	nand->controller = &nfc->controller;
+	nand->controller->ops = &sunxi_nand_controller_ops;
+
 	/*
 	 * Set the ECC mode to the default value in case nothing is specified
 	 * in the DT.
@@ -1927,30 +1942,10 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
 	mtd = nand_to_mtd(nand);
 	mtd->dev.parent = dev;
 
-	ret = nand_scan_ident(mtd, nsels, NULL);
+	ret = nand_scan(mtd, nsels);
 	if (ret)
 		return ret;
 
-	if (nand->bbt_options & NAND_BBT_USE_FLASH)
-		nand->bbt_options |= NAND_BBT_NO_OOB;
-
-	if (nand->options & NAND_NEED_SCRAMBLING)
-		nand->options |= NAND_NO_SUBPAGE_WRITE;
-
-	nand->options |= NAND_SUBPAGE_READ;
-
-	ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
-	if (ret) {
-		dev_err(dev, "ECC init failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = nand_scan_tail(mtd);
-	if (ret) {
-		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
-		return ret;
-	}
-
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret) {
 		dev_err(dev, "failed to register mtd device: %d\n", ret);
-- 
2.14.1


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

* [PATCH v4 22/35] mtd: rawnand: tango: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (20 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 21/35] mtd: rawnand: sunxi: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:52   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure Miquel Raynal
                   ` (13 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/tango_nand.c | 40 +++++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
index dd7a26efdf4f..a448d0797cd5 100644
--- a/drivers/mtd/nand/raw/tango_nand.c
+++ b/drivers/mtd/nand/raw/tango_nand.c
@@ -517,6 +517,28 @@ static int tango_set_timings(struct mtd_info *mtd, int csline,
 	return 0;
 }
 
+static int tango_attach_chip(struct nand_chip *chip)
+{
+	struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+	ecc->mode = NAND_ECC_HW;
+	ecc->algo = NAND_ECC_BCH;
+	ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE);
+
+	ecc->read_page_raw = tango_read_page_raw;
+	ecc->write_page_raw = tango_write_page_raw;
+	ecc->read_page = tango_read_page;
+	ecc->write_page = tango_write_page;
+	ecc->read_oob = tango_read_oob;
+	ecc->write_oob = tango_write_oob;
+
+	return 0;
+}
+
+static const struct nand_controller_ops tango_controller_ops = {
+	.attach_chip = tango_attach_chip,
+};
+
 static int chip_init(struct device *dev, struct device_node *np)
 {
 	u32 cs;
@@ -560,28 +582,14 @@ static int chip_init(struct device *dev, struct device_node *np)
 			NAND_NO_SUBPAGE_WRITE |
 			NAND_WAIT_TCCS;
 	chip->controller = &nfc->hw;
+	chip->controller->ops = &tango_controller_ops;
 	tchip->base = nfc->pbus_base + (cs * 256);
 
 	nand_set_flash_node(chip, np);
 	mtd_set_ooblayout(mtd, &tango_nand_ooblayout_ops);
 	mtd->dev.parent = dev;
 
-	err = nand_scan_ident(mtd, 1, NULL);
-	if (err)
-		return err;
-
-	ecc->mode = NAND_ECC_HW;
-	ecc->algo = NAND_ECC_BCH;
-	ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE);
-
-	ecc->read_page_raw = tango_read_page_raw;
-	ecc->write_page_raw = tango_write_page_raw;
-	ecc->read_page = tango_read_page;
-	ecc->write_page = tango_write_page;
-	ecc->read_oob = tango_read_oob;
-	ecc->write_oob = tango_write_oob;
-
-	err = nand_scan_tail(mtd);
+	err = nand_scan(mtd, 1);
 	if (err)
 		return err;
 
-- 
2.14.1


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

* [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (21 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 22/35] mtd: rawnand: tango: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:53   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan() Miquel Raynal
                   ` (12 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

As already done in the core, calling a struct nand_controller
'hw_control' is misleading. Use the same name as in nand_base.c:
'controller'.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/txx9ndfmc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index 8f5bbbac4612..9019022774f7 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -73,7 +73,7 @@ struct txx9ndfmc_drvdata {
 	void __iomem *base;
 	unsigned char hold;	/* in gbusclock */
 	unsigned char spw;	/* in gbusclock */
-	struct nand_controller hw_control;
+	struct nand_controller controller;
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -303,7 +303,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 	dev_info(&dev->dev, "CLK:%ldMHz HOLD:%d SPW:%d\n",
 		 (gbusclk + 500000) / 1000000, hold, spw);
 
-	nand_controller_init(&drvdata->hw_control);
+	nand_controller_init(&drvdata->controller);
 
 	platform_set_drvdata(dev, drvdata);
 	txx9ndfmc_initialize(dev);
@@ -337,7 +337,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		chip->ecc.bytes = 3;
 		chip->ecc.strength = 1;
 		chip->chip_delay = 100;
-		chip->controller = &drvdata->hw_control;
+		chip->controller = &drvdata->controller;
 
 		nand_set_controller_data(chip, txx9_priv);
 		txx9_priv->dev = dev;
-- 
2.14.1


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

* [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (22 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 17:54   ` Boris Brezillon
  2018-07-21 18:04   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 25/35] mtd: rawnand: vf610: " Miquel Raynal
                   ` (11 subsequent siblings)
  35 siblings, 2 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/txx9ndfmc.c | 29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index 9019022774f7..0134beb1136d 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -254,23 +254,23 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
 #define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \
 	DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000)
 
-static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
+static int txx9ndfmc_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	struct mtd_info *mtd = nand_to_mtd(chip);
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (!ret) {
-		if (mtd->writesize >= 512) {
-			/* Hardware ECC 6 byte ECC per 512 Byte data */
-			chip->ecc.size = 512;
-			chip->ecc.bytes = 6;
-		}
-		ret = nand_scan_tail(mtd);
+	if (mtd->writesize >= 512) {
+		/* Hardware ECC 6 byte ECC per 512 Byte data */
+		chip->ecc.size = 512;
+		chip->ecc.bytes = 6;
 	}
-	return ret;
+
+	return 0;
 }
 
+static const struct nand_controller_ops txx9ndfmc_controller_ops = {
+	.attach_chip = txx9ndfmc_attach_chip,
+};
+
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
 	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
@@ -304,6 +304,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		 (gbusclk + 500000) / 1000000, hold, spw);
 
 	nand_controller_init(&drvdata->controller);
+	drvdata->controller.ops = &txx9ndfmc_controller_ops;
 
 	platform_set_drvdata(dev, drvdata);
 	txx9ndfmc_initialize(dev);
@@ -332,7 +333,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		chip->ecc.correct = txx9ndfmc_correct_data;
 		chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
 		chip->ecc.mode = NAND_ECC_HW;
-		/* txx9ndfmc_nand_scan will overwrite ecc.size and ecc.bytes */
+		/* nand_scan() will overwrite ecc.size and ecc.bytes */
 		chip->ecc.size = 256;
 		chip->ecc.bytes = 3;
 		chip->ecc.strength = 1;
@@ -359,7 +360,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		if (plat->wide_mask & (1 << i))
 			chip->options |= NAND_BUSWIDTH_16;
 
-		if (txx9ndfmc_nand_scan(mtd)) {
+		if (nand_scan(mtd, 1)) {
 			kfree(txx9_priv->mtdname);
 			kfree(txx9_priv);
 			continue;
-- 
2.14.1


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

* [PATCH v4 25/35] mtd: rawnand: vf610: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (23 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan() Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-21 18:05   ` Boris Brezillon
  2018-07-25  8:57   ` Stefan Agner
  2018-07-20 15:15 ` [PATCH v4 26/35] mtd: rawnand: atmel: " Miquel Raynal
                   ` (10 subsequent siblings)
  35 siblings, 2 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/vf610_nfc.c | 127 ++++++++++++++++++++-------------------
 1 file changed, 66 insertions(+), 61 deletions(-)

diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
index d5a22fc96878..6f6dcbf9095b 100644
--- a/drivers/mtd/nand/raw/vf610_nfc.c
+++ b/drivers/mtd/nand/raw/vf610_nfc.c
@@ -747,6 +747,69 @@ static void vf610_nfc_init_controller(struct vf610_nfc *nfc)
 	}
 }
 
+static int vf610_nfc_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct vf610_nfc *nfc = mtd_to_nfc(mtd);
+
+	vf610_nfc_init_controller(nfc);
+
+	/* Bad block options. */
+	if (chip->bbt_options & NAND_BBT_USE_FLASH)
+		chip->bbt_options |= NAND_BBT_NO_OOB;
+
+	/* Single buffer only, max 256 OOB minus ECC status */
+	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
+		dev_err(nfc->dev, "Unsupported flash page size\n");
+		return -ENXIO;
+	}
+
+	if (chip->ecc.mode != NAND_ECC_HW)
+		return 0;
+
+	if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
+		dev_err(nfc->dev, "Unsupported flash with hwecc\n");
+		return -ENXIO;
+	}
+
+	if (chip->ecc.size != mtd->writesize) {
+		dev_err(nfc->dev, "Step size needs to be page size\n");
+		return -ENXIO;
+	}
+
+	/* Only 64 byte ECC layouts known */
+	if (mtd->oobsize > 64)
+		mtd->oobsize = 64;
+
+	/* Use default large page ECC layout defined in NAND core */
+	mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+	if (chip->ecc.strength == 32) {
+		nfc->ecc_mode = ECC_60_BYTE;
+		chip->ecc.bytes = 60;
+	} else if (chip->ecc.strength == 24) {
+		nfc->ecc_mode = ECC_45_BYTE;
+		chip->ecc.bytes = 45;
+	} else {
+		dev_err(nfc->dev, "Unsupported ECC strength\n");
+		return -ENXIO;
+	}
+
+	chip->ecc.read_page = vf610_nfc_read_page;
+	chip->ecc.write_page = vf610_nfc_write_page;
+	chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
+	chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
+	chip->ecc.read_oob = vf610_nfc_read_oob;
+	chip->ecc.write_oob = vf610_nfc_write_oob;
+
+	chip->ecc.size = PAGE_2K;
+
+	return 0;
+}
+
+static const struct nand_controller_ops vf610_nfc_controller_ops = {
+	.attach_chip = vf610_nfc_attach_chip,
+};
+
 static int vf610_nfc_probe(struct platform_device *pdev)
 {
 	struct vf610_nfc *nfc;
@@ -827,67 +890,9 @@ static int vf610_nfc_probe(struct platform_device *pdev)
 
 	vf610_nfc_preinit_controller(nfc);
 
-	/* first scan to find the device and get the page size */
-	err = nand_scan_ident(mtd, 1, NULL);
-	if (err)
-		goto err_disable_clk;
-
-	vf610_nfc_init_controller(nfc);
-
-	/* Bad block options. */
-	if (chip->bbt_options & NAND_BBT_USE_FLASH)
-		chip->bbt_options |= NAND_BBT_NO_OOB;
-
-	/* Single buffer only, max 256 OOB minus ECC status */
-	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
-		dev_err(nfc->dev, "Unsupported flash page size\n");
-		err = -ENXIO;
-		goto err_disable_clk;
-	}
-
-	if (chip->ecc.mode == NAND_ECC_HW) {
-		if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
-			dev_err(nfc->dev, "Unsupported flash with hwecc\n");
-			err = -ENXIO;
-			goto err_disable_clk;
-		}
-
-		if (chip->ecc.size != mtd->writesize) {
-			dev_err(nfc->dev, "Step size needs to be page size\n");
-			err = -ENXIO;
-			goto err_disable_clk;
-		}
-
-		/* Only 64 byte ECC layouts known */
-		if (mtd->oobsize > 64)
-			mtd->oobsize = 64;
-
-		/* Use default large page ECC layout defined in NAND core */
-		mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-		if (chip->ecc.strength == 32) {
-			nfc->ecc_mode = ECC_60_BYTE;
-			chip->ecc.bytes = 60;
-		} else if (chip->ecc.strength == 24) {
-			nfc->ecc_mode = ECC_45_BYTE;
-			chip->ecc.bytes = 45;
-		} else {
-			dev_err(nfc->dev, "Unsupported ECC strength\n");
-			err = -ENXIO;
-			goto err_disable_clk;
-		}
-
-		chip->ecc.read_page = vf610_nfc_read_page;
-		chip->ecc.write_page = vf610_nfc_write_page;
-		chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
-		chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
-		chip->ecc.read_oob = vf610_nfc_read_oob;
-		chip->ecc.write_oob = vf610_nfc_write_oob;
-
-		chip->ecc.size = PAGE_2K;
-	}
-
-	/* second phase scan */
-	err = nand_scan_tail(mtd);
+	/* Scan the NAND chip */
+	chip->dummy_controller.ops = &vf610_nfc_controller_ops;
+	err = nand_scan(mtd, 1);
 	if (err)
 		goto err_disable_clk;
 
-- 
2.14.1


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

* [PATCH v4 26/35] mtd: rawnand: atmel: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (24 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 25/35] mtd: rawnand: vf610: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  6:40   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids() Miquel Raynal
                   ` (9 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/atmel/nand-controller.c | 83 ++++++++++++++--------------
 1 file changed, 40 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index 855cc7729c43..0bc7e2abc885 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -202,7 +202,7 @@ struct atmel_nand_controller_ops {
 	int (*remove)(struct atmel_nand_controller *nc);
 	void (*nand_init)(struct atmel_nand_controller *nc,
 			  struct atmel_nand *nand);
-	int (*ecc_init)(struct atmel_nand *nand);
+	int (*ecc_init)(struct nand_chip *chip);
 	int (*setup_data_interface)(struct atmel_nand *nand, int csline,
 				    const struct nand_data_interface *conf);
 };
@@ -1133,9 +1133,8 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
 	return 0;
 }
 
-static int atmel_nand_ecc_init(struct atmel_nand *nand)
+static int atmel_nand_ecc_init(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &nand->base;
 	struct atmel_nand_controller *nc;
 	int ret;
 
@@ -1170,12 +1169,11 @@ static int atmel_nand_ecc_init(struct atmel_nand *nand)
 	return 0;
 }
 
-static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
+static int atmel_hsmc_nand_ecc_init(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &nand->base;
 	int ret;
 
-	ret = atmel_nand_ecc_init(nand);
+	ret = atmel_nand_ecc_init(chip);
 	if (ret)
 		return ret;
 
@@ -1558,22 +1556,6 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
 	chip->select_chip = atmel_hsmc_nand_select_chip;
 }
 
-static int atmel_nand_detect(struct atmel_nand *nand)
-{
-	struct nand_chip *chip = &nand->base;
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct atmel_nand_controller *nc;
-	int ret;
-
-	nc = to_nand_controller(chip->controller);
-
-	ret = nand_scan_ident(mtd, nand->numcs, NULL);
-	if (ret)
-		dev_err(nc->dev, "nand_scan_ident() failed: %d\n", ret);
-
-	return ret;
-}
-
 static int atmel_nand_unregister(struct atmel_nand *nand)
 {
 	struct nand_chip *chip = &nand->base;
@@ -1595,7 +1577,6 @@ static int atmel_nand_register(struct atmel_nand *nand)
 	struct nand_chip *chip = &nand->base;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct atmel_nand_controller *nc;
-	int ret;
 
 	nc = to_nand_controller(chip->controller);
 
@@ -1626,21 +1607,6 @@ static int atmel_nand_register(struct atmel_nand *nand)
 		}
 	}
 
-	ret = nand_scan_tail(mtd);
-	if (ret) {
-		dev_err(nc->dev, "nand_scan_tail() failed: %d\n", ret);
-		return ret;
-	}
-
-	ret = mtd_device_register(mtd, NULL, 0);
-	if (ret) {
-		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
-		nand_cleanup(chip);
-		return ret;
-	}
-
-	list_add_tail(&nand->node, &nc->chips);
-
 	return 0;
 }
 
@@ -1755,6 +1721,8 @@ static int
 atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
 			       struct atmel_nand *nand)
 {
+	struct nand_chip *chip = &nand->base;
+	struct mtd_info *mtd = nand_to_mtd(chip);
 	int ret;
 
 	/* No card inserted, skip this NAND. */
@@ -1765,15 +1733,30 @@ atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
 
 	nc->caps->ops->nand_init(nc, nand);
 
-	ret = atmel_nand_detect(nand);
-	if (ret)
+	ret = nand_scan(mtd, nand->numcs);
+	if (ret) {
+		dev_err(nc->dev, "NAND scan failed: %d\n", ret);
 		return ret;
+	}
 
-	ret = nc->caps->ops->ecc_init(nand);
+	ret = atmel_nand_register(nand);
 	if (ret)
-		return ret;
+		goto cleanup_nand;
+
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (ret) {
+		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
+		goto cleanup_nand;
+	}
+
+	list_add_tail(&nand->node, &nc->chips);
+
+	return 0;
+
+cleanup_nand:
+	nand_cleanup(chip);
 
-	return atmel_nand_register(nand);
+	return ret;
 }
 
 static int
@@ -1958,6 +1941,19 @@ static const struct of_device_id atmel_matrix_of_ids[] = {
 	{ /* sentinel */ },
 };
 
+static int atmel_nand_attach_chip(struct nand_chip *chip)
+{
+	struct atmel_nand_controller *nc;
+
+	nc = to_nand_controller(chip->controller);
+
+	return nc->caps->ops->ecc_init(chip);
+}
+
+static const struct nand_controller_ops atmel_nand_controller_ops = {
+	.attach_chip = atmel_nand_attach_chip,
+};
+
 static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
 				struct platform_device *pdev,
 				const struct atmel_nand_controller_caps *caps)
@@ -1967,6 +1963,7 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
 	int ret;
 
 	nand_controller_init(&nc->base);
+	nc->base.ops = &atmel_nand_controller_ops;
 	INIT_LIST_HEAD(&nc->chips);
 	nc->dev = dev;
 	nc->caps = caps;
-- 
2.14.1


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

* [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (25 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 26/35] mtd: rawnand: atmel: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  6:44   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident() Miquel Raynal
                   ` (8 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan_with_ids()
(alternative to nand_scan() for passing a flash IDs table) instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/sm_common.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
index 7f5044a79f01..d05e3f976a5e 100644
--- a/drivers/mtd/nand/raw/sm_common.c
+++ b/drivers/mtd/nand/raw/sm_common.c
@@ -160,19 +160,9 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
 	{NULL}
 };
 
-int sm_register_device(struct mtd_info *mtd, int smartmedia)
+static int sm_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
-
-	chip->options |= NAND_SKIP_BBTSCAN;
-
-	/* Scan for card properties */
-	ret = nand_scan_ident(mtd, 1, smartmedia ?
-		nand_smartmedia_flash_ids : nand_xd_flash_ids);
-
-	if (ret)
-		return ret;
+	struct mtd_info *mtd = nand_to_mtd(chip);
 
 	/* Bad block marker position */
 	chip->badblockpos = 0x05;
@@ -187,12 +177,33 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia)
 	else
 		return -ENODEV;
 
-	ret = nand_scan_tail(mtd);
+	return 0;
+}
 
+static const struct nand_controller_ops sm_controller_ops = {
+	.attach_chip = sm_attach_chip,
+};
+
+int sm_register_device(struct mtd_info *mtd, int smartmedia)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_flash_dev *flash_ids;
+	int ret;
+
+	chip->options |= NAND_SKIP_BBTSCAN;
+
+	/* Scan for card properties */
+	chip->dummy_controller.ops = &sm_controller_ops;
+	flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids;
+	ret = nand_scan_with_ids(mtd, 1, flash_ids);
 	if (ret)
 		return ret;
 
-	return mtd_device_register(mtd, NULL, 0);
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (ret)
+		nand_release(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(sm_register_device);
 
-- 
2.14.1


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

* [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (26 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids() Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  8:49   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan() Miquel Raynal
                   ` (7 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Some driver (eg. docg4) will need to handle themselves the
identification phase. As part of the migration to use nand_scan()
everywhere (which will unconditionnaly call nand_scan_ident()), we add
a condition at the start of nand_scan_ident() to just "do nothing" if
the maxchips parameters is zero, meaning that the driver does not want
the core to handle this phase.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index dea41fa25be1..e7f135c100c2 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5926,7 +5926,7 @@ static int nand_dt_init(struct nand_chip *chip)
 /**
  * nand_scan_ident - [NAND Interface] Scan for the NAND device
  * @mtd: MTD device structure
- * @maxchips: number of chips to scan for
+ * @maxchips: number of chips to scan for, returns immediately if 0
  * @table: alternative NAND ID table
  *
  * This is the first phase of the normal nand_scan() function. It reads the
@@ -5940,6 +5940,14 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	int ret;
 
+	/*
+	 * If the number of chips to scan for is null, just return silently.
+	 * This is for specific drivers that must handle this part of the
+	 * probe process themselves (e.g docg4).
+	 */
+	if (!maxchips)
+		return 0;
+
 	/* Enforce the right timings for reset/detection */
 	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
 
-- 
2.14.1


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

* [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (27 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident() Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  8:52   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 30/35] mtd: rawnand: qcom: " Miquel Raynal
                   ` (6 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/docg4.c | 55 ++++++++++++++++++++++++++------------------
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c
index 4dccdfba6140..fec4353ff4ef 100644
--- a/drivers/mtd/nand/raw/docg4.c
+++ b/drivers/mtd/nand/raw/docg4.c
@@ -1227,10 +1227,9 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
 	 * required within a nand driver because they are performed by the nand
 	 * infrastructure code as part of nand_scan().  In this case they need
 	 * to be initialized here because we skip call to nand_scan_ident() (the
-	 * first half of nand_scan()).  The call to nand_scan_ident() is skipped
-	 * because for this device the chip id is not read in the manner of a
-	 * standard nand device.  Unfortunately, nand_scan_ident() does other
-	 * things as well, such as call nand_set_defaults().
+	 * first half of nand_scan()).  The call to nand_scan_ident() could be
+	 * skipped because for this device the chip id is not read in the manner
+	 * of a standard nand device.
 	 */
 
 	struct nand_chip *nand = mtd_to_nand(mtd);
@@ -1315,6 +1314,27 @@ static int __init read_id_reg(struct mtd_info *mtd)
 
 static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
 
+static int docg4_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct docg4_priv *doc = (struct docg4_priv *)(chip + 1);
+
+	init_mtd_structs(mtd);
+
+	/* Initialize kernel BCH algorithm */
+	doc->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
+	if (!doc->bch)
+		return -EINVAL;
+
+	reset(mtd);
+
+	return read_id_reg(mtd);
+}
+
+static const struct nand_controller_ops docg4_controller_ops = {
+	.attach_chip = docg4_attach_chip,
+};
+
 static int __init probe_docg4(struct platform_device *pdev)
 {
 	struct mtd_info *mtd;
@@ -1350,26 +1370,16 @@ static int __init probe_docg4(struct platform_device *pdev)
 	mtd->dev.parent = &pdev->dev;
 	doc->virtadr = virtadr;
 	doc->dev = dev;
-
-	init_mtd_structs(mtd);
-
-	/* initialize kernel bch algorithm */
-	doc->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
-	if (doc->bch == NULL) {
-		retval = -EINVAL;
-		goto free_nand;
-	}
-
 	platform_set_drvdata(pdev, doc);
 
-	reset(mtd);
-	retval = read_id_reg(mtd);
-	if (retval == -ENODEV) {
-		dev_warn(dev, "No diskonchip G4 device found.\n");
-		goto free_bch;
-	}
-
-	retval = nand_scan_tail(mtd);
+	/*
+	 * Asking for 0 chips is useless here but it warns the user that the use
+	 * of the nand_scan() function is a bit abused here because the
+	 * initialization is actually a bit specific and re-handled again in the
+	 * ->attach_chip() hook. It will probably leak some memory though.
+	 */
+	nand->dummy_controller.ops = &docg4_controller_ops;
+	retval = nand_scan(mtd, 0);
 	if (retval)
 		goto free_bch;
 
@@ -1389,7 +1399,6 @@ static int __init probe_docg4(struct platform_device *pdev)
 	nand_cleanup(nand);
 free_bch:
 	free_bch(doc->bch);
-free_nand:
 	kfree(nand);
 unmap:
 	iounmap(virtadr);
-- 
2.14.1


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

* [PATCH v4 30/35] mtd: rawnand: qcom: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (28 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan() Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  8:59   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 31/35] mtd: rawnand: jz4740: " Miquel Raynal
                   ` (5 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/qcom_nandc.c | 71 +++++++++++++--------------------------
 1 file changed, 24 insertions(+), 47 deletions(-)

diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index aa6c3e026ef1..dc895b846b84 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2475,10 +2475,10 @@ qcom_nandc_calc_ecc_bytes(int step_size, int strength)
 NAND_ECC_CAPS_SINGLE(qcom_nandc_ecc_caps, qcom_nandc_calc_ecc_bytes,
 		     NANDC_STEP_SIZE, 4, 8);
 
-static int qcom_nand_host_setup(struct qcom_nand_host *host)
+static int qcom_nand_attach_chip(struct nand_chip *chip)
 {
-	struct nand_chip *chip = &host->chip;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct qcom_nand_host *host = to_qcom_nand_host(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);
 	int cwperpage, bad_block_byte, ret;
@@ -2640,6 +2640,10 @@ static int qcom_nand_host_setup(struct qcom_nand_host *host)
 	return 0;
 }
 
+static const struct nand_controller_ops qcom_nandc_ops = {
+	.attach_chip = qcom_nand_attach_chip,
+};
+
 static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
 {
 	int ret;
@@ -2781,9 +2785,9 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc)
 	return 0;
 }
 
-static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
-			       struct qcom_nand_host *host,
-			       struct device_node *dn)
+static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
+					    struct qcom_nand_host *host,
+					    struct device_node *dn)
 {
 	struct nand_chip *chip = &host->chip;
 	struct mtd_info *mtd = nand_to_mtd(chip);
@@ -2824,36 +2828,20 @@ static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
 	chip->block_markbad	= qcom_nandc_block_markbad;
 
 	chip->controller = &nandc->controller;
+	chip->controller->ops = &qcom_nandc_ops;
 	chip->options |= NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER |
 			 NAND_SKIP_BBTSCAN;
 
 	/* set up initial status value */
 	host->status = NAND_STATUS_READY | NAND_STATUS_WP;
 
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		return ret;
-
-	ret = qcom_nand_host_setup(host);
-
-	return ret;
-}
-
-static int qcom_nand_mtd_register(struct qcom_nand_controller *nandc,
-				  struct qcom_nand_host *host,
-				  struct device_node *dn)
-{
-	struct nand_chip *chip = &host->chip;
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	int ret;
-
-	ret = nand_scan_tail(mtd);
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		return ret;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret)
-		nand_cleanup(mtd_to_nand(mtd));
+		nand_cleanup(chip);
 
 	return ret;
 }
@@ -2862,9 +2850,19 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
 {
 	struct device *dev = nandc->dev;
 	struct device_node *dn = dev->of_node, *child;
-	struct qcom_nand_host *host, *tmp;
+	struct qcom_nand_host *host;
 	int ret;
 
+	if (nandc->props->is_bam) {
+		free_bam_transaction(nandc);
+		nandc->bam_txn = alloc_bam_transaction(nandc);
+		if (!nandc->bam_txn) {
+			dev_err(nandc->dev,
+				"failed to allocate bam transaction\n");
+			return -ENOMEM;
+		}
+	}
+
 	for_each_available_child_of_node(dn, child) {
 		host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
 		if (!host) {
@@ -2872,7 +2870,7 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
 			return -ENOMEM;
 		}
 
-		ret = qcom_nand_host_init(nandc, host, child);
+		ret = qcom_nand_host_init_and_register(nandc, host, child);
 		if (ret) {
 			devm_kfree(dev, host);
 			continue;
@@ -2881,27 +2879,6 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
 		list_add_tail(&host->node, &nandc->host_list);
 	}
 
-	if (list_empty(&nandc->host_list))
-		return -ENODEV;
-
-	if (nandc->props->is_bam) {
-		free_bam_transaction(nandc);
-		nandc->bam_txn = alloc_bam_transaction(nandc);
-		if (!nandc->bam_txn) {
-			dev_err(nandc->dev,
-				"failed to allocate bam transaction\n");
-			return -ENOMEM;
-		}
-	}
-
-	list_for_each_entry_safe(host, tmp, &nandc->host_list, node) {
-		ret = qcom_nand_mtd_register(nandc, host, child);
-		if (ret) {
-			list_del(&host->node);
-			devm_kfree(dev, host);
-		}
-	}
-
 	if (list_empty(&nandc->host_list))
 		return -ENODEV;
 
-- 
2.14.1


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

* [PATCH v4 31/35] mtd: rawnand: jz4740: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (29 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 30/35] mtd: rawnand: qcom: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  9:29   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 32/35] mtd: rawnand: tegra: " Miquel Raynal
                   ` (4 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/jz4740_nand.c | 46 ++++++++++++++++++++++++--------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
index 9bb8a89e09f9..8f821fdf8a1c 100644
--- a/drivers/mtd/nand/raw/jz4740_nand.c
+++ b/drivers/mtd/nand/raw/jz4740_nand.c
@@ -59,6 +59,7 @@
 
 struct jz_nand {
 	struct nand_chip chip;
+	struct platform_device *pdev;
 	void __iomem *base;
 	struct resource *mem;
 
@@ -329,8 +330,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
 	writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
 
 	if (chipnr == 0) {
-		/* Detect first chip. */
-		ret = nand_scan_ident(mtd, 1, NULL);
+		/* Detect the first chip and register it */
+		ret = nand_scan(mtd, 1);
 		if (ret)
 			goto notfound_id;
 
@@ -367,6 +368,25 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
 	return ret;
 }
 
+static int jz_nand_attach_chip(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct jz_nand *nand = mtd_to_jz_nand(mtd);
+	struct device *dev = mtd->dev.parent;
+	struct jz_nand_platform_data *pdata = dev_get_platdata(dev);
+
+	if (pdata && pdata->ident_callback) {
+		pdata->ident_callback(nand->pdev, mtd, &pdata->partitions,
+				      &pdata->num_partitions);
+	}
+
+	return 0;
+}
+
+static const struct nand_controller_ops jz_nand_controller_ops = {
+	.attach_chip = jz_nand_attach_chip,
+};
+
 static int jz_nand_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -397,6 +417,7 @@ static int jz_nand_probe(struct platform_device *pdev)
 	mtd		= nand_to_mtd(chip);
 	mtd->dev.parent = &pdev->dev;
 	mtd->name	= "jz4740-nand";
+	nand->pdev	= pdev;
 
 	chip->ecc.hwctl		= jz_nand_hwctl;
 	chip->ecc.calculate	= jz_nand_calculate_ecc_rs;
@@ -410,6 +431,7 @@ static int jz_nand_probe(struct platform_device *pdev)
 	chip->chip_delay = 50;
 	chip->cmd_ctrl = jz_nand_cmd_ctrl;
 	chip->select_chip = jz_nand_select_chip;
+	chip->dummy_controller.ops = &jz_nand_controller_ops;
 
 	if (nand->busy_gpio)
 		chip->dev_ready = jz_nand_dev_ready;
@@ -450,20 +472,10 @@ static int jz_nand_probe(struct platform_device *pdev)
 		else
 			nand->banks[chipnr] = 0;
 	}
+
 	if (chipnr == 0) {
 		dev_err(&pdev->dev, "No NAND chips found\n");
-		goto err_iounmap_mmio;
-	}
-
-	if (pdata && pdata->ident_callback) {
-		pdata->ident_callback(pdev, mtd, &pdata->partitions,
-					&pdata->num_partitions);
-	}
-
-	ret = nand_scan_tail(mtd);
-	if (ret) {
-		dev_err(&pdev->dev,  "Failed to scan NAND\n");
-		goto err_unclaim_banks;
+		goto err_nand_release;
 	}
 
 	ret = mtd_device_register(mtd, pdata ? pdata->partitions : NULL,
@@ -471,15 +483,13 @@ static int jz_nand_probe(struct platform_device *pdev)
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add mtd device\n");
-		goto err_nand_release;
+		goto err_unclaim_banks;
 	}
 
 	dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
 
 	return 0;
 
-err_nand_release:
-	nand_release(mtd);
 err_unclaim_banks:
 	while (chipnr--) {
 		unsigned char bank = nand->banks[chipnr];
@@ -487,6 +497,8 @@ static int jz_nand_probe(struct platform_device *pdev)
 					 nand->bank_base[bank - 1]);
 	}
 	writel(0, nand->base + JZ_REG_NAND_CTRL);
+err_nand_release:
+	nand_release(mtd);
 err_iounmap_mmio:
 	jz_nand_iounmap_resource(nand->mem, nand->base);
 err_free:
-- 
2.14.1


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

* [PATCH v4 32/35] mtd: rawnand: tegra: convert driver to nand_scan()
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (30 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 31/35] mtd: rawnand: jz4740: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22  9:31   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore Miquel Raynal
                   ` (3 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Two helpers have been added to the core to make ECC-related
configuration between the detection phase and the final NAND scan. Use
these hooks and convert the driver to just use nand_scan() instead of
both nand_scan_ident() and nand_scan_tail().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/tegra_nand.c | 162 +++++++++++++++++++++-----------------
 1 file changed, 88 insertions(+), 74 deletions(-)

diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index 31c0d9ca9d23..c40a53066cee 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -906,74 +906,13 @@ static int tegra_nand_select_strength(struct nand_chip *chip, int oobsize)
 				       bits_per_step, oobsize);
 }
 
-static int tegra_nand_chips_init(struct device *dev,
-				 struct tegra_nand_controller *ctrl)
+static int tegra_nand_attach_chip(struct nand_chip *chip)
 {
-	struct device_node *np = dev->of_node;
-	struct device_node *np_nand;
-	int nsels, nchips = of_get_child_count(np);
-	struct tegra_nand_chip *nand;
-	struct mtd_info *mtd;
-	struct nand_chip *chip;
+	struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
+	struct tegra_nand_chip *nand = to_tegra_chip(chip);
+	struct mtd_info *mtd = nand_to_mtd(chip);
 	int bits_per_step;
 	int ret;
-	u32 cs;
-
-	if (nchips != 1) {
-		dev_err(dev, "Currently only one NAND chip supported\n");
-		return -EINVAL;
-	}
-
-	np_nand = of_get_next_child(np, NULL);
-
-	nsels = of_property_count_elems_of_size(np_nand, "reg", sizeof(u32));
-	if (nsels != 1) {
-		dev_err(dev, "Missing/invalid reg property\n");
-		return -EINVAL;
-	}
-
-	/* Retrieve CS id, currently only single die NAND supported */
-	ret = of_property_read_u32(np_nand, "reg", &cs);
-	if (ret) {
-		dev_err(dev, "could not retrieve reg property: %d\n", ret);
-		return ret;
-	}
-
-	nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL);
-	if (!nand)
-		return -ENOMEM;
-
-	nand->cs[0] = cs;
-
-	nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
-
-	if (IS_ERR(nand->wp_gpio)) {
-		ret = PTR_ERR(nand->wp_gpio);
-		dev_err(dev, "Failed to request WP GPIO: %d\n", ret);
-		return ret;
-	}
-
-	chip = &nand->chip;
-	chip->controller = &ctrl->controller;
-
-	mtd = nand_to_mtd(chip);
-
-	mtd->dev.parent = dev;
-	mtd->owner = THIS_MODULE;
-
-	nand_set_flash_node(chip, np_nand);
-
-	if (!mtd->name)
-		mtd->name = "tegra_nand";
-
-	chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER;
-	chip->exec_op = tegra_nand_exec_op;
-	chip->select_chip = tegra_nand_select_chip;
-	chip->setup_data_interface = tegra_nand_setup_data_interface;
-
-	ret = nand_scan_ident(mtd, 1, NULL);
-	if (ret)
-		return ret;
 
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
@@ -982,7 +921,8 @@ static int tegra_nand_chips_init(struct device *dev,
 	chip->ecc.size = 512;
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
 	if (chip->ecc_step_ds != 512) {
-		dev_err(dev, "Unsupported step size %d\n", chip->ecc_step_ds);
+		dev_err(ctrl->dev, "Unsupported step size %d\n",
+			chip->ecc_step_ds);
 		return -EINVAL;
 	}
 
@@ -1004,14 +944,15 @@ static int tegra_nand_chips_init(struct device *dev,
 	}
 
 	if (chip->ecc.algo == NAND_ECC_BCH && mtd->writesize < 2048) {
-		dev_err(dev, "BCH supports 2K or 4K page size only\n");
+		dev_err(ctrl->dev, "BCH supports 2K or 4K page size only\n");
 		return -EINVAL;
 	}
 
 	if (!chip->ecc.strength) {
 		ret = tegra_nand_select_strength(chip, mtd->oobsize);
 		if (ret < 0) {
-			dev_err(dev, "No valid strength found, minimum %d\n",
+			dev_err(ctrl->dev,
+				"No valid strength found, minimum %d\n",
 				chip->ecc_strength_ds);
 			return ret;
 		}
@@ -1039,7 +980,7 @@ static int tegra_nand_chips_init(struct device *dev,
 			nand->config_ecc |= CONFIG_TVAL_8;
 			break;
 		default:
-			dev_err(dev, "ECC strength %d not supported\n",
+			dev_err(ctrl->dev, "ECC strength %d not supported\n",
 				chip->ecc.strength);
 			return -EINVAL;
 		}
@@ -1062,17 +1003,17 @@ static int tegra_nand_chips_init(struct device *dev,
 			nand->bch_config |= BCH_TVAL_16;
 			break;
 		default:
-			dev_err(dev, "ECC strength %d not supported\n",
+			dev_err(ctrl->dev, "ECC strength %d not supported\n",
 				chip->ecc.strength);
 			return -EINVAL;
 		}
 		break;
 	default:
-		dev_err(dev, "ECC algorithm not supported\n");
+		dev_err(ctrl->dev, "ECC algorithm not supported\n");
 		return -EINVAL;
 	}
 
-	dev_info(dev, "Using %s with strength %d per 512 byte step\n",
+	dev_info(ctrl->dev, "Using %s with strength %d per 512 byte step\n",
 		 chip->ecc.algo == NAND_ECC_BCH ? "BCH" : "RS",
 		 chip->ecc.strength);
 
@@ -1095,7 +1036,8 @@ static int tegra_nand_chips_init(struct device *dev,
 		nand->config |= CONFIG_PS_4096;
 		break;
 	default:
-		dev_err(dev, "Unsupported writesize %d\n", mtd->writesize);
+		dev_err(ctrl->dev, "Unsupported writesize %d\n",
+			mtd->writesize);
 		return -ENODEV;
 	}
 
@@ -1106,7 +1048,79 @@ static int tegra_nand_chips_init(struct device *dev,
 	nand->config |= CONFIG_TAG_BYTE_SIZE(mtd->oobsize - 1);
 	writel_relaxed(nand->config, ctrl->regs + CONFIG);
 
-	ret = nand_scan_tail(mtd);
+	return 0;
+}
+
+static const struct nand_controller_ops tegra_nand_controller_ops = {
+	.attach_chip = &tegra_nand_attach_chip,
+};
+
+static int tegra_nand_chips_init(struct device *dev,
+				 struct tegra_nand_controller *ctrl)
+{
+	struct device_node *np = dev->of_node;
+	struct device_node *np_nand;
+	int nsels, nchips = of_get_child_count(np);
+	struct tegra_nand_chip *nand;
+	struct mtd_info *mtd;
+	struct nand_chip *chip;
+	int ret;
+	u32 cs;
+
+	if (nchips != 1) {
+		dev_err(dev, "Currently only one NAND chip supported\n");
+		return -EINVAL;
+	}
+
+	np_nand = of_get_next_child(np, NULL);
+
+	nsels = of_property_count_elems_of_size(np_nand, "reg", sizeof(u32));
+	if (nsels != 1) {
+		dev_err(dev, "Missing/invalid reg property\n");
+		return -EINVAL;
+	}
+
+	/* Retrieve CS id, currently only single die NAND supported */
+	ret = of_property_read_u32(np_nand, "reg", &cs);
+	if (ret) {
+		dev_err(dev, "could not retrieve reg property: %d\n", ret);
+		return ret;
+	}
+
+	nand = devm_kzalloc(dev, sizeof(*nand), GFP_KERNEL);
+	if (!nand)
+		return -ENOMEM;
+
+	nand->cs[0] = cs;
+
+	nand->wp_gpio = devm_gpiod_get_optional(dev, "wp", GPIOD_OUT_LOW);
+
+	if (IS_ERR(nand->wp_gpio)) {
+		ret = PTR_ERR(nand->wp_gpio);
+		dev_err(dev, "Failed to request WP GPIO: %d\n", ret);
+		return ret;
+	}
+
+	chip = &nand->chip;
+	chip->controller = &ctrl->controller;
+	chip->controller->ops = &tegra_nand_controller_ops;
+
+	mtd = nand_to_mtd(chip);
+
+	mtd->dev.parent = dev;
+	mtd->owner = THIS_MODULE;
+
+	nand_set_flash_node(chip, np_nand);
+
+	if (!mtd->name)
+		mtd->name = "tegra_nand";
+
+	chip->options = NAND_NO_SUBPAGE_WRITE | NAND_USE_BOUNCE_BUFFER;
+	chip->exec_op = tegra_nand_exec_op;
+	chip->select_chip = tegra_nand_select_chip;
+	chip->setup_data_interface = tegra_nand_setup_data_interface;
+
+	ret = nand_scan(mtd, 1);
 	if (ret)
 		return ret;
 
-- 
2.14.1


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

* [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (31 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 32/35] mtd: rawnand: tegra: " Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22 10:30   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically Miquel Raynal
                   ` (2 subsequent siblings)
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Both nand_scan_ident() and nand_scan_tail() helpers used to be called
directly from controller drivers that needed to tweak some ECC-related
parameters before nand_scan_tail(). This separation prevented dynamic
allocations during the phase of NAND identification, which was
inconvenient.

All controller drivers have been moved to use nand_scan(), in
conjunction with the chip->ecc.[attach|detach]_chip() hooks that
actually do the required tweaking sequence between both ident/tail
calls, allowing programmers to use dynamic allocation as they need all
across the scanning sequence.

Declare nand_scan_[ident|tail]() statically now.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 16 +++++++++-------
 include/linux/mtd/rawnand.h      |  9 ++-------
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index e7f135c100c2..da99232702a4 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5924,7 +5924,7 @@ static int nand_dt_init(struct nand_chip *chip)
 }
 
 /**
- * nand_scan_ident - [NAND Interface] Scan for the NAND device
+ * nand_scan_ident - Scan for the NAND device
  * @mtd: MTD device structure
  * @maxchips: number of chips to scan for, returns immediately if 0
  * @table: alternative NAND ID table
@@ -5932,9 +5932,13 @@ static int nand_dt_init(struct nand_chip *chip)
  * This is the first phase of the normal nand_scan() function. It reads the
  * flash ID and sets up MTD fields accordingly.
  *
+ * This helper used to be called directly from controller drivers that needed
+ * to tweak some ECC-related parameters before nand_scan_tail(). This separation
+ * prevented dynamic allocations during this phase which was unconvenient and
+ * as been banned for the benefit of the ->init_ecc()/cleanup_ecc() hooks.
  */
-int nand_scan_ident(struct mtd_info *mtd, int maxchips,
-		    struct nand_flash_dev *table)
+static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
+			   struct nand_flash_dev *table)
 {
 	int i, nand_maf_id, nand_dev_id;
 	struct nand_chip *chip = mtd_to_nand(mtd);
@@ -6016,7 +6020,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 
 	return 0;
 }
-EXPORT_SYMBOL(nand_scan_ident);
 
 static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
 {
@@ -6393,14 +6396,14 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
 }
 
 /**
- * nand_scan_tail - [NAND Interface] Scan for the NAND device
+ * nand_scan_tail - Scan for the NAND device
  * @mtd: MTD device structure
  *
  * This is the second phase of the normal nand_scan() function. It fills out
  * all the uninitialized function pointers with the defaults and scans for a
  * bad block table if appropriate.
  */
-int nand_scan_tail(struct mtd_info *mtd)
+static int nand_scan_tail(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
@@ -6724,7 +6727,6 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 	return ret;
 }
-EXPORT_SYMBOL(nand_scan_tail);
 
 static int nand_attach(struct nand_chip *chip)
 {
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index a20c78e25878..a928771a7ae4 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -36,14 +36,9 @@ static inline int nand_scan(struct mtd_info *mtd, int max_chips)
 }
 
 /*
- * Separate phases of nand_scan(), allowing board driver to intervene
- * and override command or ECC setup according to flash type.
+ * Unregister the MTD device and free resources held by the NAND device, must be
+ * called on error after a successful nand_scan().
  */
-int nand_scan_ident(struct mtd_info *mtd, int max_chips,
-			   struct nand_flash_dev *table);
-int nand_scan_tail(struct mtd_info *mtd);
-
-/* Unregister the MTD device and free resources held by the NAND device */
 void nand_release(struct mtd_info *mtd);
 
 /* Internal helper for board drivers which need to override command function */
-- 
2.14.1


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

* [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (32 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22 10:32   ` Boris Brezillon
  2018-07-20 15:15 ` [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection Miquel Raynal
  2018-07-26 23:34 ` [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Thanks to the migration of all drivers to use nand_scan() and the
related nand_controller_ops, we can now allocate data during the
detection phase. Let's do it first for the NAND model parameter which
is allocated in nand_detect().

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c | 52 +++++++++++++++++++++++++++++++---------
 include/linux/mtd/rawnand.h      |  2 +-
 2 files changed, 42 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index da99232702a4..8645f655e5b0 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5225,8 +5225,11 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
 
 	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
 	sanitize_string(p->model, sizeof(p->model));
-	strncpy(chip->parameters.model, p->model,
-		sizeof(chip->parameters.model) - 1);
+	chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
+	if (!chip->parameters.model) {
+		ret = -ENOMEM;
+		goto free_onfi_param_page;
+	}
 
 	mtd->writesize = le32_to_cpu(p->byte_per_page);
 
@@ -5356,8 +5359,11 @@ static int nand_flash_detect_jedec(struct nand_chip *chip)
 
 	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
 	sanitize_string(p->model, sizeof(p->model));
-	strncpy(chip->parameters.model, p->model,
-		sizeof(chip->parameters.model) - 1);
+	chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
+	if (!chip->parameters.model) {
+		ret = -ENOMEM;
+		goto free_jedec_param_page;
+	}
 
 	mtd->writesize = le32_to_cpu(p->byte_per_page);
 
@@ -5546,8 +5552,9 @@ static bool find_full_id_nand(struct nand_chip *chip,
 		chip->onfi_timing_mode_default =
 					type->onfi_timing_mode_default;
 
-		strncpy(chip->parameters.model, type->name,
-			sizeof(chip->parameters.model) - 1);
+		chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
+		if (!chip->parameters.model)
+			return false;
 
 		return true;
 	}
@@ -5706,8 +5713,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 	if (!type->name)
 		return -ENODEV;
 
-	strncpy(chip->parameters.model, type->name,
-		sizeof(chip->parameters.model) - 1);
+	chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
+	if (!chip->parameters.model)
+		return -ENOMEM;
 
 	chip->chipsize = (uint64_t)type->chipsize << 20;
 
@@ -5737,7 +5745,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 			mtd->name);
 		pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8,
 			(chip->options & NAND_BUSWIDTH_16) ? 16 : 8);
-		return -EINVAL;
+		ret = -EINVAL;
+
+		goto free_detect_allocation;
 	}
 
 	nand_decode_bbm_options(chip);
@@ -5774,6 +5784,11 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
 		mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
 	return 0;
+
+free_detect_allocation:
+	kfree(chip->parameters.model);
+
+	return ret;
 }
 
 static const char * const nand_ecc_modes[] = {
@@ -6021,6 +6036,11 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 	return 0;
 }
 
+static void nand_scan_ident_cleanup(struct nand_chip *chip)
+{
+	kfree(chip->parameters.model);
+}
+
 static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
@@ -6764,11 +6784,18 @@ int nand_scan_with_ids(struct mtd_info *mtd, int maxchips,
 
 	ret = nand_attach(chip);
 	if (ret)
-		return ret;
+		goto cleanup_ident;
 
 	ret = nand_scan_tail(mtd);
 	if (ret)
-		nand_detach(chip);
+		goto detach_chip;
+
+	return 0;
+
+detach_chip:
+	nand_detach(chip);
+cleanup_ident:
+	nand_scan_ident_cleanup(chip);
 
 	return ret;
 }
@@ -6800,6 +6827,9 @@ void nand_cleanup(struct nand_chip *chip)
 
 	/* Free controller specific allocations after chip identification */
 	nand_detach(chip);
+
+	/* Free identification phase allocations */
+	nand_scan_ident_cleanup(chip);
 }
 
 EXPORT_SYMBOL_GPL(nand_cleanup);
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index a928771a7ae4..5723d940a47d 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -482,7 +482,7 @@ struct onfi_params {
  */
 struct nand_parameters {
 	/* Generic parameters */
-	char model[100];
+	const char *model;
 	bool supports_set_get_features;
 	DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
 	DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);
-- 
2.14.1


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

* [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (33 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically Miquel Raynal
@ 2018-07-20 15:15 ` Miquel Raynal
  2018-07-22 10:35   ` Boris Brezillon
  2018-07-26 23:34 ` [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
  35 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-20 15:15 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek

Now that it is possible to do dynamic allocations during the
identification phase, convert the onfi_params structure (which is only
needed with ONFI compliant chips) into a pointer that will be allocated
only if needed.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/nand_base.c    | 54 +++++++++++++++++++++++--------------
 drivers/mtd/nand/raw/nand_micron.c  |  6 ++---
 drivers/mtd/nand/raw/nand_timings.c | 12 ++++-----
 include/linux/mtd/rawnand.h         |  6 ++---
 4 files changed, 46 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8645f655e5b0..ed9e2f1578e6 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5151,6 +5151,8 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_onfi_params *p;
+	struct onfi_params *onfi;
+	int onfi_version = 0;
 	char id[4];
 	int i, ret, val;
 
@@ -5206,21 +5208,19 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
 	/* Check version */
 	val = le16_to_cpu(p->revision);
 	if (val & ONFI_VERSION_2_3)
-		chip->parameters.onfi.version = 23;
+		onfi_version = 23;
 	else if (val & ONFI_VERSION_2_2)
-		chip->parameters.onfi.version = 22;
+		onfi_version = 22;
 	else if (val & ONFI_VERSION_2_1)
-		chip->parameters.onfi.version = 21;
+		onfi_version = 21;
 	else if (val & ONFI_VERSION_2_0)
-		chip->parameters.onfi.version = 20;
+		onfi_version = 20;
 	else if (val & ONFI_VERSION_1_0)
-		chip->parameters.onfi.version = 10;
+		onfi_version = 10;
 
-	if (!chip->parameters.onfi.version) {
+	if (!onfi_version) {
 		pr_info("unsupported ONFI version: %d\n", val);
 		goto free_onfi_param_page;
-	} else {
-		ret = 1;
 	}
 
 	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
@@ -5257,7 +5257,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
 	if (p->ecc_bits != 0xff) {
 		chip->ecc_strength_ds = p->ecc_bits;
 		chip->ecc_step_ds = 512;
-	} else if (chip->parameters.onfi.version >= 21 &&
+	} else if (onfi_version >= 21 &&
 		(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
 
 		/*
@@ -5284,19 +5284,33 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
 		bitmap_set(chip->parameters.set_feature_list,
 			   ONFI_FEATURE_ADDR_TIMING_MODE, 1);
 	}
-	chip->parameters.onfi.tPROG = le16_to_cpu(p->t_prog);
-	chip->parameters.onfi.tBERS = le16_to_cpu(p->t_bers);
-	chip->parameters.onfi.tR = le16_to_cpu(p->t_r);
-	chip->parameters.onfi.tCCS = le16_to_cpu(p->t_ccs);
-	chip->parameters.onfi.async_timing_mode =
-		le16_to_cpu(p->async_timing_mode);
-	chip->parameters.onfi.vendor_revision =
-		le16_to_cpu(p->vendor_revision);
-	memcpy(chip->parameters.onfi.vendor, p->vendor,
-	       sizeof(p->vendor));
 
+	onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
+	if (!onfi) {
+		ret = -ENOMEM;
+		goto free_model;
+	}
+
+	onfi->version = onfi_version;
+	onfi->tPROG = le16_to_cpu(p->t_prog);
+	onfi->tBERS = le16_to_cpu(p->t_bers);
+	onfi->tR = le16_to_cpu(p->t_r);
+	onfi->tCCS = le16_to_cpu(p->t_ccs);
+	onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
+	onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
+	memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
+	chip->parameters.onfi = onfi;
+
+	/* Identification done, free the full ONFI parameter page and exit */
+	kfree(p);
+
+	return 1;
+
+free_model:
+	kfree(chip->parameters.model);
 free_onfi_param_page:
 	kfree(p);
+
 	return ret;
 }
 
@@ -5693,7 +5707,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 		}
 	}
 
-	chip->parameters.onfi.version = 0;
 	if (!type->name || !type->pagesize) {
 		/* Check if the chip is ONFI compliant */
 		ret = nand_flash_detect_onfi(chip);
@@ -6039,6 +6052,7 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 static void nand_scan_ident_cleanup(struct nand_chip *chip)
 {
 	kfree(chip->parameters.model);
+	kfree(chip->parameters.onfi);
 }
 
 static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 656947d91841..8466a1740b3b 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -88,9 +88,9 @@ static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
 static int micron_nand_onfi_init(struct nand_chip *chip)
 {
 	struct nand_parameters *p = &chip->parameters;
-	struct nand_onfi_vendor_micron *micron = (void *)p->onfi.vendor;
+	struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor;
 
-	if (chip->parameters.onfi.version && p->onfi.vendor_revision) {
+	if (p->onfi && p->onfi->vendor_revision) {
 		chip->read_retries = micron->read_retry_options;
 		chip->setup_read_retry = micron_nand_setup_read_retry;
 	}
@@ -382,7 +382,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 	u8 id[5];
 	int ret;
 
-	if (!chip->parameters.onfi.version)
+	if (!chip->parameters.onfi)
 		return MICRON_ON_DIE_UNSUPPORTED;
 
 	if (chip->bits_per_cell != 1)
diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
index 9bb599106a31..ebc7b5f76f77 100644
--- a/drivers/mtd/nand/raw/nand_timings.c
+++ b/drivers/mtd/nand/raw/nand_timings.c
@@ -294,6 +294,7 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 			     int timing_mode)
 {
 	struct nand_data_interface *iface = &chip->data_interface;
+	struct onfi_params *onfi = chip->parameters.onfi;
 
 	if (type != NAND_SDR_IFACE)
 		return -EINVAL;
@@ -308,17 +309,16 @@ int onfi_fill_data_interface(struct nand_chip *chip,
 	 * tPROG, tBERS, tR and tCCS.
 	 * These information are part of the ONFI parameter page.
 	 */
-	if (chip->parameters.onfi.version) {
-		struct nand_parameters *params = &chip->parameters;
+	if (onfi) {
 		struct nand_sdr_timings *timings = &iface->timings.sdr;
 
 		/* microseconds -> picoseconds */
-		timings->tPROG_max = 1000000ULL * params->onfi.tPROG;
-		timings->tBERS_max = 1000000ULL * params->onfi.tBERS;
-		timings->tR_max = 1000000ULL * params->onfi.tR;
+		timings->tPROG_max = 1000000ULL * onfi->tPROG;
+		timings->tBERS_max = 1000000ULL * onfi->tBERS;
+		timings->tR_max = 1000000ULL * onfi->tR;
 
 		/* nanoseconds -> picoseconds */
-		timings->tCCS_min = 1000UL * params->onfi.tCCS;
+		timings->tCCS_min = 1000UL * onfi->tCCS;
 	} else {
 		struct nand_sdr_timings *timings = &iface->timings.sdr;
 		/*
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 5723d940a47d..8074cbd4e3fe 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -488,7 +488,7 @@ struct nand_parameters {
 	DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);
 
 	/* ONFI parameters */
-	struct onfi_params onfi;
+	struct onfi_params *onfi;
 };
 
 /* The maximum expected count of bytes in the NAND ID sequence */
@@ -1618,10 +1618,10 @@ struct platform_nand_data {
 /* return the supported asynchronous timing mode. */
 static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
 {
-	if (!chip->parameters.onfi.version)
+	if (!chip->parameters.onfi)
 		return ONFI_TIMING_MODE_UNKNOWN;
 
-	return chip->parameters.onfi.async_timing_mode;
+	return chip->parameters.onfi->async_timing_mode;
 }
 
 int onfi_fill_data_interface(struct nand_chip *chip,
-- 
2.14.1


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

* Re: [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan() Miquel Raynal
@ 2018-07-21  6:23   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:23 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:53 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/brcmnand/brcmnand.c | 47 +++++++++++++++++++-------------
>  1 file changed, 28 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> index 2e5efa0f9ea2..071f09af56dc 100644
> --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
> @@ -2208,6 +2208,32 @@ static int brcmnand_setup_dev(struct brcmnand_host *host)
>  	return 0;
>  }
>  
> +static int brcmnand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct brcmnand_host *host = nand_get_controller_data(chip);
> +	int ret;
> +
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> +		chip->bbt_options |= NAND_BBT_NO_OOB;
> +
> +	if (brcmnand_setup_dev(host))
> +		return -ENXIO;
> +
> +	chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512;
> +
> +	/* only use our internal HW threshold */
> +	mtd->bitflip_threshold = 1;
> +
> +	ret = brcmstb_choose_ecc_layout(host);
> +
> +	return ret;
> +}
> +
> +static const struct nand_controller_ops brcmnand_controller_ops = {
> +	.attach_chip = brcmnand_attach_chip,
> +};
> +
>  static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
>  {
>  	struct brcmnand_controller *ctrl = host->ctrl;
> @@ -2267,10 +2293,6 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
>  	nand_writereg(ctrl, cfg_offs,
>  		      nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH);
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (ret)
> -		return ret;
> -
>  	chip->options |= NAND_NO_SUBPAGE_WRITE;
>  	/*
>  	 * Avoid (for instance) kmap()'d buffers from JFFS2, which we can't DMA
> @@ -2279,21 +2301,7 @@ static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn)
>  	 */
>  	chip->options |= NAND_USE_BOUNCE_BUFFER;
>  

Any reason for not moving the above chunk in brcmnand_attach_chip()?

Since ->attach_chip() is called between nand_scan_ident() and
nand_scan_tail() in nand_scan(), I'd recommend simply copying all the
code found between those 2 calls (applies to all drivers).

> -	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> -		chip->bbt_options |= NAND_BBT_NO_OOB;
> -
> -	if (brcmnand_setup_dev(host))
> -		return -ENXIO;
> -
> -	chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512;
> -	/* only use our internal HW threshold */
> -	mtd->bitflip_threshold = 1;
> -
> -	ret = brcmstb_choose_ecc_layout(host);
> -	if (ret)
> -		return ret;
> -
> -	ret = nand_scan_tail(mtd);
> +	ret = nand_scan(mtd, 1);
>  	if (ret)
>  		return ret;
>  
> @@ -2434,6 +2442,7 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
>  	init_completion(&ctrl->done);
>  	init_completion(&ctrl->dma_done);
>  	nand_controller_init(&ctrl->controller);
> +	ctrl->controller.ops = &brcmnand_controller_ops;
>  	INIT_LIST_HEAD(&ctrl->host_list);
>  
>  	/* NAND register range */


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

* Re: [PATCH v4 02/35] mtd: rawnand: cafe: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 02/35] mtd: rawnand: cafe: " Miquel Raynal
@ 2018-07-21  6:35   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:35 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:54 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/cafe_nand.c | 130 +++++++++++++++++++++++----------------
>  1 file changed, 76 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c
> index ac0be933a490..c303c261dd8d 100644
> --- a/drivers/mtd/nand/raw/cafe_nand.c
> +++ b/drivers/mtd/nand/raw/cafe_nand.c
> @@ -71,7 +71,9 @@ struct cafe_priv {
>  	unsigned char *dmabuf;
>  };
>  
> -static int usedma = 1;
> +#define CAFE_DEFAULT_DMA	1
> +
> +static int usedma = CAFE_DEFAULT_DMA;

Not sure you need a macro for that.

>  module_param(usedma, int, 0644);
>  
>  static int skipbbt = 0;
> @@ -593,6 +595,76 @@ static int cafe_mul(int x)
>  	return gf4096_mul(x, 0xe01);
>  }
>  
> +static int cafe_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct cafe_priv *cafe = nand_get_controller_data(chip);
> +	int err = 0;
> +
> +	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112,
> +					  &cafe->dmaaddr, GFP_KERNEL);
> +	if (!cafe->dmabuf)
> +		return -ENOMEM;
> +
> +	/* Set up DMA address */
> +	cafe_writel(cafe, lower_32_bits(cafe->dmaaddr), NAND_DMA_ADDR0);
> +	cafe_writel(cafe, upper_32_bits(cafe->dmaaddr), NAND_DMA_ADDR1);
> +
> +	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",
> +		     cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf);
> +
> +	/* Restore the DMA flag */
> +	usedma = CAFE_DEFAULT_DMA;

This is wrong. The user might have passed a different value to usedma
when loading the module (or on the kernel cmdline), and you're simply
ignoring it. I see 2 solutions to solve that:

1/ add a ->usedma field to the cafe_priv struct which you initialize to
   0 in the probe function (already done if you kzalloc() the struct)
   and update it here:

	cafe->usedma = usedma.

   then you have to patch all places where usedma was tested and
   replace this test by a test on cafe->usedma

2/ add a static in old_usedma which you assign to usedma value in the
   probe and then restore the usedma value here:

	usedma = old_usedma

I prefer option #1.

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

* Re: [PATCH v4 03/35] mtd: rawnand: davinci: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 03/35] mtd: rawnand: davinci: " Miquel Raynal
@ 2018-07-21  6:44   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:44 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:55 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Also change the unused "struct device *dev" parameter of the driver
> structure into a platform device to reuse it in the ->attach_chip()
> hook.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/davinci_nand.c | 195 +++++++++++++++++++-----------------
>  1 file changed, 102 insertions(+), 93 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
> index 626c9363e460..40145e206a6b 100644
> --- a/drivers/mtd/nand/raw/davinci_nand.c
> +++ b/drivers/mtd/nand/raw/davinci_nand.c
> @@ -53,7 +53,7 @@
>  struct davinci_nand_info {
>  	struct nand_chip	chip;
>  
> -	struct device		*dev;
> +	struct platform_device	*pdev;

For the record, there's a to_platform_device() macro you can use to get
a platform_device object from a device one, so this change was not
really needed. Actually, you should not even need a ->dev field here
because it can be retrieved from mtd->dev.parent. Anyway, if you
patched all places using davinci->dev to now use &davinci->pdev->dev
we should be good.

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>  
>  	bool			is_readmode;
>  
> @@ -605,6 +605,104 @@ static struct davinci_nand_pdata
>  }
>  #endif
>  
> +static int davinci_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct davinci_nand_info *info = to_davinci_nand(mtd);
> +	struct davinci_nand_pdata *pdata = nand_davinci_get_pdata(info->pdev);
> +	int ret = 0;
> +
> +	if (IS_ERR(pdata))
> +		return PTR_ERR(pdata);
> +
> +	switch (info->chip.ecc.mode) {
> +	case NAND_ECC_NONE:
> +		pdata->ecc_bits = 0;
> +		break;
> +	case NAND_ECC_SOFT:
> +		pdata->ecc_bits = 0;
> +		/*
> +		 * This driver expects Hamming based ECC when ecc_mode is set
> +		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
> +		 * avoid adding an extra ->ecc_algo field to
> +		 * davinci_nand_pdata.
> +		 */
> +		info->chip.ecc.algo = NAND_ECC_HAMMING;
> +		break;
> +	case NAND_ECC_HW:
> +		if (pdata->ecc_bits == 4) {
> +			/*
> +			 * No sanity checks:  CPUs must support this,
> +			 * and the chips may not use NAND_BUSWIDTH_16.
> +			 */
> +
> +			/* No sharing 4-bit hardware between chipselects yet */
> +			spin_lock_irq(&davinci_nand_lock);
> +			if (ecc4_busy)
> +				ret = -EBUSY;
> +			else
> +				ecc4_busy = true;
> +			spin_unlock_irq(&davinci_nand_lock);
> +
> +			if (ret == -EBUSY)
> +				return ret;
> +
> +			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
> +			info->chip.ecc.correct = nand_davinci_correct_4bit;
> +			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
> +			info->chip.ecc.bytes = 10;
> +			info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
> +			info->chip.ecc.algo = NAND_ECC_BCH;
> +		} else {
> +			/* 1bit ecc hamming */
> +			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
> +			info->chip.ecc.correct = nand_davinci_correct_1bit;
> +			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
> +			info->chip.ecc.bytes = 3;
> +			info->chip.ecc.algo = NAND_ECC_HAMMING;
> +		}
> +		info->chip.ecc.size = 512;
> +		info->chip.ecc.strength = pdata->ecc_bits;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Update ECC layout if needed ... for 1-bit HW ECC, the default
> +	 * is OK, but it allocates 6 bytes when only 3 are needed (for
> +	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
> +	 * usable:  10 bytes are needed, not 6.
> +	 */
> +	if (pdata->ecc_bits == 4) {
> +		int chunks = mtd->writesize / 512;
> +
> +		if (!chunks || mtd->oobsize < 16) {
> +			dev_dbg(&info->pdev->dev, "too small\n");
> +			return -EINVAL;
> +		}
> +
> +		/* For small page chips, preserve the manufacturer's
> +		 * badblock marking data ... and make sure a flash BBT
> +		 * table marker fits in the free bytes.
> +		 */
> +		if (chunks == 1) {
> +			mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
> +		} else if (chunks == 4 || chunks == 8) {
> +			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> +			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> +		} else {
> +			return -EIO;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
> +static const struct nand_controller_ops davinci_nand_controller_ops = {
> +	.attach_chip = davinci_nand_attach_chip,
> +};
> +
>  static int nand_davinci_probe(struct platform_device *pdev)
>  {
>  	struct davinci_nand_pdata	*pdata;
> @@ -658,7 +756,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
>  		return -EADDRNOTAVAIL;
>  	}
>  
> -	info->dev		= &pdev->dev;
> +	info->pdev		= pdev;
>  	info->base		= base;
>  	info->vaddr		= vaddr;
>  
> @@ -708,97 +806,13 @@ static int nand_davinci_probe(struct platform_device *pdev)
>  	spin_unlock_irq(&davinci_nand_lock);
>  
>  	/* Scan to find existence of the device(s) */
> -	ret = nand_scan_ident(mtd, pdata->mask_chipsel ? 2 : 1, NULL);
> +	info->chip.dummy_controller.ops = &davinci_nand_controller_ops;
> +	ret = nand_scan(mtd, pdata->mask_chipsel ? 2 : 1);
>  	if (ret < 0) {
>  		dev_dbg(&pdev->dev, "no NAND chip(s) found\n");
>  		return ret;
>  	}
>  
> -	switch (info->chip.ecc.mode) {
> -	case NAND_ECC_NONE:
> -		pdata->ecc_bits = 0;
> -		break;
> -	case NAND_ECC_SOFT:
> -		pdata->ecc_bits = 0;
> -		/*
> -		 * This driver expects Hamming based ECC when ecc_mode is set
> -		 * to NAND_ECC_SOFT. Force ecc.algo to NAND_ECC_HAMMING to
> -		 * avoid adding an extra ->ecc_algo field to
> -		 * davinci_nand_pdata.
> -		 */
> -		info->chip.ecc.algo = NAND_ECC_HAMMING;
> -		break;
> -	case NAND_ECC_HW:
> -		if (pdata->ecc_bits == 4) {
> -			/* No sanity checks:  CPUs must support this,
> -			 * and the chips may not use NAND_BUSWIDTH_16.
> -			 */
> -
> -			/* No sharing 4-bit hardware between chipselects yet */
> -			spin_lock_irq(&davinci_nand_lock);
> -			if (ecc4_busy)
> -				ret = -EBUSY;
> -			else
> -				ecc4_busy = true;
> -			spin_unlock_irq(&davinci_nand_lock);
> -
> -			if (ret == -EBUSY)
> -				return ret;
> -
> -			info->chip.ecc.calculate = nand_davinci_calculate_4bit;
> -			info->chip.ecc.correct = nand_davinci_correct_4bit;
> -			info->chip.ecc.hwctl = nand_davinci_hwctl_4bit;
> -			info->chip.ecc.bytes = 10;
> -			info->chip.ecc.options = NAND_ECC_GENERIC_ERASED_CHECK;
> -			info->chip.ecc.algo = NAND_ECC_BCH;
> -		} else {
> -			/* 1bit ecc hamming */
> -			info->chip.ecc.calculate = nand_davinci_calculate_1bit;
> -			info->chip.ecc.correct = nand_davinci_correct_1bit;
> -			info->chip.ecc.hwctl = nand_davinci_hwctl_1bit;
> -			info->chip.ecc.bytes = 3;
> -			info->chip.ecc.algo = NAND_ECC_HAMMING;
> -		}
> -		info->chip.ecc.size = 512;
> -		info->chip.ecc.strength = pdata->ecc_bits;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	/* Update ECC layout if needed ... for 1-bit HW ECC, the default
> -	 * is OK, but it allocates 6 bytes when only 3 are needed (for
> -	 * each 512 bytes).  For the 4-bit HW ECC, that default is not
> -	 * usable:  10 bytes are needed, not 6.
> -	 */
> -	if (pdata->ecc_bits == 4) {
> -		int	chunks = mtd->writesize / 512;
> -
> -		if (!chunks || mtd->oobsize < 16) {
> -			dev_dbg(&pdev->dev, "too small\n");
> -			ret = -EINVAL;
> -			goto err;
> -		}
> -
> -		/* For small page chips, preserve the manufacturer's
> -		 * badblock marking data ... and make sure a flash BBT
> -		 * table marker fits in the free bytes.
> -		 */
> -		if (chunks == 1) {
> -			mtd_set_ooblayout(mtd, &hwecc4_small_ooblayout_ops);
> -		} else if (chunks == 4 || chunks == 8) {
> -			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> -			info->chip.ecc.mode = NAND_ECC_HW_OOB_FIRST;
> -		} else {
> -			ret = -EIO;
> -			goto err;
> -		}
> -	}
> -
> -	ret = nand_scan_tail(mtd);
> -	if (ret < 0)
> -		goto err;
> -
>  	if (pdata->parts)
>  		ret = mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
>  	else
> @@ -815,11 +829,6 @@ static int nand_davinci_probe(struct platform_device *pdev)
>  err_cleanup_nand:
>  	nand_cleanup(&info->chip);
>  
> -err:
> -	spin_lock_irq(&davinci_nand_lock);
> -	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
> -		ecc4_busy = false;
> -	spin_unlock_irq(&davinci_nand_lock);
>  	return ret;
>  }
>  


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

* Re: [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 04/35] mtd: rawnand: denali: convert " Miquel Raynal
@ 2018-07-21  6:46   ` Boris Brezillon
  2018-07-25  9:42   ` Masahiro Yamada
  1 sibling, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:46 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:56 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/denali.c | 138 +++++++++++++++++++++++-------------------
>  1 file changed, 77 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
> index 4d53f41ada08..2fa92c297a66 100644
> --- a/drivers/mtd/nand/raw/denali.c
> +++ b/drivers/mtd/nand/raw/denali.c
> @@ -1205,62 +1205,12 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
>  	return 0;
>  }
>  
> -int denali_init(struct denali_nand_info *denali)
> +static int denali_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = &denali->nand;
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> -	u32 features = ioread32(denali->reg + FEATURES);
> +	struct denali_nand_info *denali = mtd_to_denali(mtd);
>  	int ret;
>  
> -	mtd->dev.parent = denali->dev;
> -	denali_hw_init(denali);
> -
> -	init_completion(&denali->complete);
> -	spin_lock_init(&denali->irq_lock);
> -
> -	denali_clear_irq_all(denali);
> -
> -	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
> -			       IRQF_SHARED, DENALI_NAND_NAME, denali);
> -	if (ret) {
> -		dev_err(denali->dev, "Unable to request IRQ\n");
> -		return ret;
> -	}
> -
> -	denali_enable_irq(denali);
> -	denali_reset_banks(denali);
> -
> -	denali->active_bank = DENALI_INVALID_BANK;
> -
> -	nand_set_flash_node(chip, denali->dev->of_node);
> -	/* Fallback to the default name if DT did not give "label" property */
> -	if (!mtd->name)
> -		mtd->name = "denali-nand";
> -
> -	chip->select_chip = denali_select_chip;
> -	chip->read_byte = denali_read_byte;
> -	chip->write_byte = denali_write_byte;
> -	chip->read_word = denali_read_word;
> -	chip->cmd_ctrl = denali_cmd_ctrl;
> -	chip->dev_ready = denali_dev_ready;
> -	chip->waitfunc = denali_waitfunc;
> -
> -	if (features & FEATURES__INDEX_ADDR) {
> -		denali->host_read = denali_indexed_read;
> -		denali->host_write = denali_indexed_write;
> -	} else {
> -		denali->host_read = denali_direct_read;
> -		denali->host_write = denali_direct_write;
> -	}
> -
> -	/* clk rate info is needed for setup_data_interface */
> -	if (denali->clk_rate && denali->clk_x_rate)
> -		chip->setup_data_interface = denali_setup_data_interface;
> -
> -	ret = nand_scan_ident(mtd, denali->max_banks, NULL);
> -	if (ret)
> -		goto disable_irq;
> -
>  	if (ioread32(denali->reg + FEATURES) & FEATURES__DMA)
>  		denali->dma_avail = 1;
>  
> @@ -1293,7 +1243,7 @@ int denali_init(struct denali_nand_info *denali)
>  				   mtd->oobsize - denali->oob_skip_bytes);
>  	if (ret) {
>  		dev_err(denali->dev, "Failed to setup ECC settings.\n");
> -		goto disable_irq;
> +		return ret;
>  	}
>  
>  	dev_dbg(denali->dev,
> @@ -1337,7 +1287,7 @@ int denali_init(struct denali_nand_info *denali)
>  
>  	ret = denali_multidev_fixup(denali);
>  	if (ret)
> -		goto disable_irq;
> +		return ret;
>  
>  	/*
>  	 * This buffer is DMA-mapped by denali_{read,write}_page_raw.  Do not
> @@ -1345,26 +1295,92 @@ int denali_init(struct denali_nand_info *denali)
>  	 * guarantee DMA-safe alignment.
>  	 */
>  	denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> -	if (!denali->buf) {
> -		ret = -ENOMEM;
> -		goto disable_irq;
> +	if (!denali->buf)
> +		return -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static void denali_detach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct denali_nand_info *denali = mtd_to_denali(mtd);
> +
> +	kfree(denali->buf);
> +}
> +
> +static const struct nand_controller_ops denali_controller_ops = {
> +	.attach_chip = denali_attach_chip,
> +	.detach_chip = denali_detach_chip,
> +};
> +
> +int denali_init(struct denali_nand_info *denali)
> +{
> +	struct nand_chip *chip = &denali->nand;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	u32 features = ioread32(denali->reg + FEATURES);
> +	int ret;
> +
> +	mtd->dev.parent = denali->dev;
> +	denali_hw_init(denali);
> +
> +	init_completion(&denali->complete);
> +	spin_lock_init(&denali->irq_lock);
> +
> +	denali_clear_irq_all(denali);
> +
> +	ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
> +			       IRQF_SHARED, DENALI_NAND_NAME, denali);
> +	if (ret) {
> +		dev_err(denali->dev, "Unable to request IRQ\n");
> +		return ret;
> +	}
> +
> +	denali_enable_irq(denali);
> +	denali_reset_banks(denali);
> +
> +	denali->active_bank = DENALI_INVALID_BANK;
> +
> +	nand_set_flash_node(chip, denali->dev->of_node);
> +	/* Fallback to the default name if DT did not give "label" property */
> +	if (!mtd->name)
> +		mtd->name = "denali-nand";
> +
> +	chip->select_chip = denali_select_chip;
> +	chip->read_byte = denali_read_byte;
> +	chip->write_byte = denali_write_byte;
> +	chip->read_word = denali_read_word;
> +	chip->cmd_ctrl = denali_cmd_ctrl;
> +	chip->dev_ready = denali_dev_ready;
> +	chip->waitfunc = denali_waitfunc;
> +
> +	if (features & FEATURES__INDEX_ADDR) {
> +		denali->host_read = denali_indexed_read;
> +		denali->host_write = denali_indexed_write;
> +	} else {
> +		denali->host_read = denali_direct_read;
> +		denali->host_write = denali_direct_write;
>  	}
>  
> -	ret = nand_scan_tail(mtd);
> +	/* clk rate info is needed for setup_data_interface */
> +	if (denali->clk_rate && denali->clk_x_rate)
> +		chip->setup_data_interface = denali_setup_data_interface;
> +
> +	chip->dummy_controller.ops = &denali_controller_ops;
> +	ret = nand_scan(mtd, denali->max_banks);
>  	if (ret)
> -		goto free_buf;
> +		goto disable_irq;
>  
>  	ret = mtd_device_register(mtd, NULL, 0);
>  	if (ret) {
>  		dev_err(denali->dev, "Failed to register MTD: %d\n", ret);
>  		goto cleanup_nand;
>  	}
> +
>  	return 0;
>  
>  cleanup_nand:
>  	nand_cleanup(chip);
> -free_buf:
> -	kfree(denali->buf);
>  disable_irq:
>  	denali_disable_irq(denali);
>  


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

* Re: [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver " Miquel Raynal
@ 2018-07-21  6:50   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:50 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:57 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/fsl_elbc_nand.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
> index 0aa54a949653..44893e49b386 100644
> --- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
> @@ -637,9 +637,9 @@ static int fsl_elbc_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  	return (elbc_fcm_ctrl->mdr & 0xff) | NAND_STATUS_WP;
>  }
>  
> -static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
> +static int fsl_elbc_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct fsl_elbc_mtd *priv = nand_get_controller_data(chip);
>  	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
>  	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
> @@ -706,6 +706,10 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)

Looks like fsl_elbc_chip_init_tail() was returning -1 here [1]. Please
change that for a -ENOTSUPP. With that fixed:

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>  	return 0;
>  }
>  
> +static const struct nand_controller_ops fsl_elbc_controller_ops = {
> +	.attach_chip = fsl_elbc_attach_chip,
> +};
> +
>  static int fsl_elbc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
>  			      uint8_t *buf, int oob_required, int page)
>  {
> @@ -910,15 +914,8 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto err;
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (ret)
> -		goto err;
> -
> -	ret = fsl_elbc_chip_init_tail(mtd);
> -	if (ret)
> -		goto err;
> -
> -	ret = nand_scan_tail(mtd);
> +	priv->chip.controller->ops = &fsl_elbc_controller_ops;
> +	ret = nand_scan(mtd, 1);
>  	if (ret)
>  		goto err;
>  

[1]https://elixir.bootlin.com/linux/v4.18-rc5/source/drivers/mtd/nand/raw/fsl_elbc_nand.c#L699

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

* Re: [PATCH v4 06/35] mtd: rawnand: fsl_ifc: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 06/35] mtd: rawnand: fsl_ifc: " Miquel Raynal
@ 2018-07-21  6:53   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:53 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:58 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/fsl_ifc_nand.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
> index 96130d91e32c..24f59d0066af 100644
> --- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
> +++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
> @@ -714,9 +714,9 @@ static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
>  	return nand_prog_page_end_op(chip);
>  }
>  
> -static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
> +static int fsl_ifc_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct fsl_ifc_mtd *priv = nand_get_controller_data(chip);
>  
>  	dev_dbg(priv->dev, "%s: nand->numchips = %d\n", __func__,
> @@ -757,6 +757,10 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
>  	return 0;
>  }
>  
> +static const struct nand_controller_ops fsl_ifc_controller_ops = {
> +	.attach_chip = fsl_ifc_attach_chip,
> +};
> +
>  static void fsl_ifc_sram_init(struct fsl_ifc_mtd *priv)
>  {
>  	struct fsl_ifc_ctrl *ctrl = priv->ctrl;
> @@ -1046,15 +1050,8 @@ static int fsl_ifc_nand_probe(struct platform_device *dev)
>  	if (ret)
>  		goto err;
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (ret)
> -		goto err;
> -
> -	ret = fsl_ifc_chip_init_tail(mtd);
> -	if (ret)
> -		goto err;
> -
> -	ret = nand_scan_tail(mtd);
> +	priv->chip.controller->ops = &fsl_ifc_controller_ops;
> +	ret = nand_scan(mtd, 1);
>  	if (ret)
>  		goto err;
>  


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

* Re: [PATCH v4 07/35] mtd: rawnand: fsmc: convert driver to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 07/35] mtd: rawnand: fsmc: " Miquel Raynal
@ 2018-07-21  6:55   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:55 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:14:59 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/fsmc_nand.c | 148 +++++++++++++++++++++------------------
>  1 file changed, 78 insertions(+), 70 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
> index 59524d181bfe..f418236fa020 100644
> --- a/drivers/mtd/nand/raw/fsmc_nand.c
> +++ b/drivers/mtd/nand/raw/fsmc_nand.c
> @@ -919,6 +919,82 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int fsmc_nand_attach_chip(struct nand_chip *nand)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	struct fsmc_nand_data *host = mtd_to_fsmc(mtd);
> +
> +	if (AMBA_REV_BITS(host->pid) >= 8) {
> +		switch (mtd->oobsize) {
> +		case 16:
> +		case 64:
> +		case 128:
> +		case 224:
> +		case 256:
> +			break;
> +		default:
> +			dev_warn(host->dev,
> +				 "No oob scheme defined for oobsize %d\n",
> +				 mtd->oobsize);
> +			return -EINVAL;
> +		}
> +
> +		mtd_set_ooblayout(mtd, &fsmc_ecc4_ooblayout_ops);
> +
> +		return 0;
> +	}
> +
> +	switch (nand->ecc.mode) {
> +	case NAND_ECC_HW:
> +		dev_info(host->dev, "Using 1-bit HW ECC scheme\n");
> +		nand->ecc.calculate = fsmc_read_hwecc_ecc1;
> +		nand->ecc.correct = nand_correct_data;
> +		nand->ecc.bytes = 3;
> +		nand->ecc.strength = 1;
> +		break;
> +
> +	case NAND_ECC_SOFT:
> +		if (nand->ecc.algo == NAND_ECC_BCH) {
> +			dev_info(host->dev,
> +				 "Using 4-bit SW BCH ECC scheme\n");
> +			break;
> +		}
> +
> +	case NAND_ECC_ON_DIE:
> +		break;
> +
> +	default:
> +		dev_err(host->dev, "Unsupported ECC mode!\n");
> +		return -ENOTSUPP;
> +	}
> +
> +	/*
> +	 * Don't set layout for BCH4 SW ECC. This will be
> +	 * generated later in nand_bch_init() later.
> +	 */
> +	if (nand->ecc.mode == NAND_ECC_HW) {
> +		switch (mtd->oobsize) {
> +		case 16:
> +		case 64:
> +		case 128:
> +			mtd_set_ooblayout(mtd,
> +					  &fsmc_ecc1_ooblayout_ops);
> +			break;
> +		default:
> +			dev_warn(host->dev,
> +				 "No oob scheme defined for oobsize %d\n",
> +				 mtd->oobsize);
> +			return -EINVAL;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops fsmc_nand_controller_ops = {
> +	.attach_chip = fsmc_nand_attach_chip,
> +};
> +
>  /*
>   * fsmc_nand_probe - Probe function
>   * @pdev:       platform device structure
> @@ -1048,76 +1124,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
>  	/*
>  	 * Scan to find existence of the device
>  	 */
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (ret) {
> -		dev_err(&pdev->dev, "No NAND Device found!\n");
> -		goto release_dma_write_chan;
> -	}
> -
> -	if (AMBA_REV_BITS(host->pid) >= 8) {
> -		switch (mtd->oobsize) {
> -		case 16:
> -		case 64:
> -		case 128:
> -		case 224:
> -		case 256:
> -			break;
> -		default:
> -			dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n",
> -				 mtd->oobsize);
> -			ret = -EINVAL;
> -			goto release_dma_write_chan;
> -		}
> -
> -		mtd_set_ooblayout(mtd, &fsmc_ecc4_ooblayout_ops);
> -	} else {
> -		switch (nand->ecc.mode) {
> -		case NAND_ECC_HW:
> -			dev_info(&pdev->dev, "Using 1-bit HW ECC scheme\n");
> -			nand->ecc.calculate = fsmc_read_hwecc_ecc1;
> -			nand->ecc.correct = nand_correct_data;
> -			nand->ecc.bytes = 3;
> -			nand->ecc.strength = 1;
> -			break;
> -
> -		case NAND_ECC_SOFT:
> -			if (nand->ecc.algo == NAND_ECC_BCH) {
> -				dev_info(&pdev->dev, "Using 4-bit SW BCH ECC scheme\n");
> -				break;
> -			}
> -
> -		case NAND_ECC_ON_DIE:
> -			break;
> -
> -		default:
> -			dev_err(&pdev->dev, "Unsupported ECC mode!\n");
> -			goto release_dma_write_chan;
> -		}
> -
> -		/*
> -		 * Don't set layout for BCH4 SW ECC. This will be
> -		 * generated later in nand_bch_init() later.
> -		 */
> -		if (nand->ecc.mode == NAND_ECC_HW) {
> -			switch (mtd->oobsize) {
> -			case 16:
> -			case 64:
> -			case 128:
> -				mtd_set_ooblayout(mtd,
> -						  &fsmc_ecc1_ooblayout_ops);
> -				break;
> -			default:
> -				dev_warn(&pdev->dev,
> -					 "No oob scheme defined for oobsize %d\n",
> -					 mtd->oobsize);
> -				ret = -EINVAL;
> -				goto release_dma_write_chan;
> -			}
> -		}
> -	}
> -
> -	/* Second stage of scan to fill MTD data-structures */
> -	ret = nand_scan_tail(mtd);
> +	nand->dummy_controller.ops = &fsmc_nand_controller_ops;
> +	ret = nand_scan(mtd, 1);
>  	if (ret)
>  		goto release_dma_write_chan;
>  


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

* Re: [PATCH v4 08/35] mtd: rawnand: gpmi: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 08/35] mtd: rawnand: gpmi: " Miquel Raynal
@ 2018-07-21  6:56   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:56 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:00 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 56 ++++++++++++++++++------------
>  1 file changed, 33 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 6294d018df65..1c1ebbc82824 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -744,9 +744,9 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this)
>  	 * [2] Allocate a read/write data buffer.
>  	 *     The gpmi_alloc_dma_buffer can be called twice.
>  	 *     We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer
> -	 *     is called before the nand_scan_ident; and we allocate a buffer
> -	 *     of the real NAND page size when the gpmi_alloc_dma_buffer is
> -	 *     called after the nand_scan_ident.
> +	 *     is called before the NAND identification; and we allocate a
> +	 *     buffer of the real NAND page size when the gpmi_alloc_dma_buffer
> +	 *     is called after.
>  	 */
>  	this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE,
>  					GFP_DMA | GFP_KERNEL);
> @@ -1865,6 +1865,34 @@ static int gpmi_init_last(struct gpmi_nand_data *this)
>  	return 0;
>  }
>  
> +static int gpmi_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct gpmi_nand_data *this = nand_get_controller_data(chip);
> +	int ret;
> +
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
> +		chip->bbt_options |= NAND_BBT_NO_OOB;
> +
> +		if (of_property_read_bool(this->dev->of_node,
> +					  "fsl,no-blockmark-swap"))
> +			this->swap_block_mark = false;
> +	}
> +	dev_dbg(this->dev, "Blockmark swapping %sabled\n",
> +		this->swap_block_mark ? "en" : "dis");
> +
> +	ret = gpmi_init_last(this);
> +	if (ret)
> +		return ret;
> +
> +	chip->options |= NAND_SKIP_BBTSCAN;
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops gpmi_nand_controller_ops = {
> +	.attach_chip = gpmi_nand_attach_chip,
> +};
> +
>  static int gpmi_nand_init(struct gpmi_nand_data *this)
>  {
>  	struct nand_chip *chip = &this->nand;
> @@ -1905,26 +1933,8 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
>  	if (ret)
>  		goto err_out;
>  
> -	ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL);
> -	if (ret)
> -		goto err_out;
> -
> -	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
> -		chip->bbt_options |= NAND_BBT_NO_OOB;
> -
> -		if (of_property_read_bool(this->dev->of_node,
> -						"fsl,no-blockmark-swap"))
> -			this->swap_block_mark = false;
> -	}
> -	dev_dbg(this->dev, "Blockmark swapping %sabled\n",
> -		this->swap_block_mark ? "en" : "dis");
> -
> -	ret = gpmi_init_last(this);
> -	if (ret)
> -		goto err_out;
> -
> -	chip->options |= NAND_SKIP_BBTSCAN;
> -	ret = nand_scan_tail(mtd);
> +	chip->dummy_controller.ops = &gpmi_nand_controller_ops;
> +	ret = nand_scan(mtd, GPMI_IS_MX6(this) ? 2 : 1);
>  	if (ret)
>  		goto err_out;
>  


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

* Re: [PATCH v4 09/35] mtd: rawnand: hisi504: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 09/35] mtd: rawnand: hisi504: " Miquel Raynal
@ 2018-07-21  6:59   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21  6:59 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:01 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/hisi504_nand.c | 78 +++++++++++++++++++++----------------
>  1 file changed, 44 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/hisi504_nand.c b/drivers/mtd/nand/raw/hisi504_nand.c
> index a1e009c8e556..950dc7789296 100644
> --- a/drivers/mtd/nand/raw/hisi504_nand.c
> +++ b/drivers/mtd/nand/raw/hisi504_nand.c
> @@ -709,9 +709,50 @@ static int hisi_nfc_ecc_probe(struct hinfc_host *host)
>  	return 0;
>  }
>  
> +static int hisi_nfc_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct hinfc_host *host = nand_get_controller_data(chip);
> +	int flag;
> +
> +	host->buffer = dmam_alloc_coherent(host->dev,
> +					   mtd->writesize + mtd->oobsize,
> +					   &host->dma_buffer, GFP_KERNEL);
> +	if (!host->buffer)
> +		return -ENOMEM;
> +
> +	host->dma_oob = host->dma_buffer + mtd->writesize;
> +	memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize);
> +
> +	flag = hinfc_read(host, HINFC504_CON);
> +	flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT);
> +	switch (mtd->writesize) {
> +	case 2048:
> +		flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT);
> +		break;
> +	/*
> +	 * TODO: add more pagesize support,
> +	 * default pagesize has been set in hisi_nfc_host_init
> +	 */
> +	default:
> +		dev_err(host->dev, "NON-2KB page size nand flash\n");
> +		return -EINVAL;

We should probably return ENOTSUPP, but that's not related to the
change you do, so let's keep that for later.

> +	}
> +	hinfc_write(host, flag, HINFC504_CON);
> +
> +	if (chip->ecc.mode == NAND_ECC_HW)
> +		hisi_nfc_ecc_probe(host);
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops hisi_nfc_controller_ops = {
> +	.attach_chip = hisi_nfc_attach_chip,
> +};
> +
>  static int hisi_nfc_probe(struct platform_device *pdev)
>  {
> -	int ret = 0, irq, flag, max_chips = HINFC504_MAX_CHIP;
> +	int ret = 0, irq, max_chips = HINFC504_MAX_CHIP;
>  	struct device *dev = &pdev->dev;
>  	struct hinfc_host *host;
>  	struct nand_chip  *chip;
> @@ -769,42 +810,11 @@ static int hisi_nfc_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	ret = nand_scan_ident(mtd, max_chips, NULL);
> +	chip->dummy_controller.ops = &hisi_nfc_controller_ops;
> +	ret = nand_scan(mtd, max_chips);
>  	if (ret)
>  		return ret;
>  
> -	host->buffer = dmam_alloc_coherent(dev, mtd->writesize + mtd->oobsize,
> -		&host->dma_buffer, GFP_KERNEL);
> -	if (!host->buffer)
> -		return -ENOMEM;
> -
> -	host->dma_oob = host->dma_buffer + mtd->writesize;
> -	memset(host->buffer, 0xff, mtd->writesize + mtd->oobsize);
> -
> -	flag = hinfc_read(host, HINFC504_CON);
> -	flag &= ~(HINFC504_CON_PAGESIZE_MASK << HINFC504_CON_PAGEISZE_SHIFT);
> -	switch (mtd->writesize) {
> -	case 2048:
> -		flag |= (0x001 << HINFC504_CON_PAGEISZE_SHIFT); break;
> -	/*
> -	 * TODO: add more pagesize support,
> -	 * default pagesize has been set in hisi_nfc_host_init
> -	 */
> -	default:
> -		dev_err(dev, "NON-2KB page size nand flash\n");
> -		return -EINVAL;
> -	}
> -	hinfc_write(host, flag, HINFC504_CON);
> -
> -	if (chip->ecc.mode == NAND_ECC_HW)
> -		hisi_nfc_ecc_probe(host);
> -
> -	ret = nand_scan_tail(mtd);
> -	if (ret) {
> -		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
> -		return ret;
> -	}
> -
>  	ret = mtd_device_register(mtd, NULL, 0);
>  	if (ret) {
>  		dev_err(dev, "Err MTD partition=%d\n", ret);


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

* Re: [PATCH v4 10/35] mtd: rawnand: jz4780: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 10/35] mtd: rawnand: jz4780: " Miquel Raynal
@ 2018-07-21 15:23   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 15:23 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:02 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> Acked-by: Harvey Hunt <harveyhuntnexus@gmail.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/jz4780_nand.c | 34 ++++++++++++++++------------------
>  1 file changed, 16 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/jz4780_nand.c b/drivers/mtd/nand/raw/jz4780_nand.c
> index 49841dad347c..db4fa60bd52a 100644
> --- a/drivers/mtd/nand/raw/jz4780_nand.c
> +++ b/drivers/mtd/nand/raw/jz4780_nand.c
> @@ -158,9 +158,8 @@ static int jz4780_nand_ecc_correct(struct mtd_info *mtd, u8 *dat,
>  	return jz4780_bch_correct(nfc->bch, &params, dat, read_ecc);
>  }
>  
> -static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *dev)
> +static int jz4780_nand_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = &nand->chip;
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct jz4780_nand_controller *nfc = to_jz4780_nand_controller(chip->controller);
>  	int eccbytes;
> @@ -171,7 +170,8 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
>  	switch (chip->ecc.mode) {
>  	case NAND_ECC_HW:
>  		if (!nfc->bch) {
> -			dev_err(dev, "HW BCH selected, but BCH controller not found\n");
> +			dev_err(nfc->dev,
> +				"HW BCH selected, but BCH controller not found\n");
>  			return -ENODEV;
>  		}
>  
> @@ -180,15 +180,16 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
>  		chip->ecc.correct = jz4780_nand_ecc_correct;
>  		/* fall through */
>  	case NAND_ECC_SOFT:
> -		dev_info(dev, "using %s (strength %d, size %d, bytes %d)\n",
> -			(nfc->bch) ? "hardware BCH" : "software ECC",
> -			chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
> +		dev_info(nfc->dev, "using %s (strength %d, size %d, bytes %d)\n",
> +			 (nfc->bch) ? "hardware BCH" : "software ECC",
> +			 chip->ecc.strength, chip->ecc.size, chip->ecc.bytes);
>  		break;
>  	case NAND_ECC_NONE:
> -		dev_info(dev, "not using ECC\n");
> +		dev_info(nfc->dev, "not using ECC\n");
>  		break;
>  	default:
> -		dev_err(dev, "ECC mode %d not supported\n", chip->ecc.mode);
> +		dev_err(nfc->dev, "ECC mode %d not supported\n",
> +			chip->ecc.mode);
>  		return -EINVAL;
>  	}
>  
> @@ -200,7 +201,7 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
>  	eccbytes = mtd->writesize / chip->ecc.size * chip->ecc.bytes;
>  
>  	if (eccbytes > mtd->oobsize - 2) {
> -		dev_err(dev,
> +		dev_err(nfc->dev,
>  			"invalid ECC config: required %d ECC bytes, but only %d are available",
>  			eccbytes, mtd->oobsize - 2);
>  		return -EINVAL;
> @@ -211,6 +212,10 @@ static int jz4780_nand_init_ecc(struct jz4780_nand_chip *nand, struct device *de
>  	return 0;
>  }
>  
> +static const struct nand_controller_ops jz4780_nand_controller_ops = {
> +	.attach_chip = jz4780_nand_attach_chip,
> +};
> +
>  static int jz4780_nand_init_chip(struct platform_device *pdev,
>  				struct jz4780_nand_controller *nfc,
>  				struct device_node *np,
> @@ -280,15 +285,8 @@ static int jz4780_nand_init_chip(struct platform_device *pdev,
>  	chip->controller = &nfc->controller;
>  	nand_set_flash_node(chip, np);
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (ret)
> -		return ret;
> -
> -	ret = jz4780_nand_init_ecc(nand, dev);
> -	if (ret)
> -		return ret;
> -
> -	ret = nand_scan_tail(mtd);
> +	chip->controller->ops = &jz4780_nand_controller_ops;
> +	ret = nand_scan(mtd, 1);
>  	if (ret)
>  		return ret;
>  


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

* Re: [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: " Miquel Raynal
@ 2018-07-21 15:26   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 15:26 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:03 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/lpc32xx_mlc.c | 109 ++++++++++++++++++++-----------------
>  1 file changed, 59 insertions(+), 50 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
> index 052d123a8304..6f73136fa863 100644
> --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
> +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
> @@ -184,6 +184,7 @@ static struct nand_bbt_descr lpc32xx_nand_bbt_mirror = {
>  };
>  
>  struct lpc32xx_nand_host {
> +	struct platform_device	*pdev;
>  	struct nand_chip	nand_chip;
>  	struct lpc32xx_mlc_platform_data *pdata;
>  	struct clk		*clk;
> @@ -653,6 +654,58 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev)
>  	return ncfg;
>  }
>  
> +static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
> +	struct device *dev = &host->pdev->dev;
> +
> +	host->dma_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
> +	if (!host->dma_buf)
> +		return -ENOMEM;
> +
> +	host->dummy_buf = devm_kzalloc(dev, mtd->writesize, GFP_KERNEL);
> +	if (!host->dummy_buf)
> +		return -ENOMEM;
> +
> +	chip->ecc.mode = NAND_ECC_HW;
> +	chip->ecc.size = 512;
> +	mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
> +	host->mlcsubpages = mtd->writesize / 512;
> +
> +	/* initially clear interrupt status */
> +	readb(MLC_IRQ_SR(host->io_base));
> +
> +	init_completion(&host->comp_nand);
> +	init_completion(&host->comp_controller);
> +
> +	host->irq = platform_get_irq(host->pdev, 0);
> +	if (host->irq < 0) {
> +		dev_err(dev, "failed to get platform irq\n");
> +		return -EINVAL;
> +	}
> +
> +	if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
> +			IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
> +		dev_err(dev, "Error requesting NAND IRQ\n");
> +		return -ENXIO;
> +	}
> +
> +	return 0;
> +}
> +
> +static void lpc32xx_nand_detach_chip(struct nand_chip *chip)
> +{
> +	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
> +
> +	free_irq(host->irq, host);

Now you call 2 times free_irq() in the ->remove() path.

> +}
> +
> +static const struct nand_controller_ops lpc32xx_nand_controller_ops = {
> +	.attach_chip = lpc32xx_nand_attach_chip,
> +	.detach_chip = lpc32xx_nand_detach_chip,
> +};
> +
>  /*
>   * Probe for NAND controller
>   */
> @@ -669,6 +722,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  	if (!host)
>  		return -ENOMEM;
>  
> +	host->pdev = pdev;
> +
>  	rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	host->io_base = devm_ioremap_resource(&pdev->dev, rc);
>  	if (IS_ERR(host->io_base))
> @@ -749,58 +804,14 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  	}
>  
>  	/*
> -	 * Scan to find existance of the device and
> -	 * Get the type of NAND device SMALL block or LARGE block
> +	 * Scan to find existence of the device and get the type of NAND device:
> +	 * SMALL block or LARGE block.
>  	 */
> -	res = nand_scan_ident(mtd, 1, NULL);
> +	nand_chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
> +	res = nand_scan(mtd, 1);
>  	if (res)
>  		goto release_dma_chan;
>  
> -	host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
> -	if (!host->dma_buf) {
> -		res = -ENOMEM;
> -		goto release_dma_chan;
> -	}
> -
> -	host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL);
> -	if (!host->dummy_buf) {
> -		res = -ENOMEM;
> -		goto release_dma_chan;
> -	}
> -
> -	nand_chip->ecc.mode = NAND_ECC_HW;
> -	nand_chip->ecc.size = 512;
> -	mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
> -	host->mlcsubpages = mtd->writesize / 512;
> -

Starting here...

> -	/* initially clear interrupt status */
> -	readb(MLC_IRQ_SR(host->io_base));
> -
> -	init_completion(&host->comp_nand);
> -	init_completion(&host->comp_controller);
> -
> -	host->irq = platform_get_irq(pdev, 0);
> -	if (host->irq < 0) {
> -		dev_err(&pdev->dev, "failed to get platform irq\n");
> -		res = -EINVAL;
> -		goto release_dma_chan;
> -	}
> -
> -	if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
> -			IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
> -		dev_err(&pdev->dev, "Error requesting NAND IRQ\n");
> -		res = -ENXIO;
> -		goto release_dma_chan;
> -	}

till there: maybe we should just move this block before nand_scan().
Registering an IRQ handler is not really something you should do in
->attach_chip() IMO.

> -
> -	/*
> -	 * Fills out all the uninitialized function pointers with the defaults
> -	 * And scans for a bad block table if appropriate.
> -	 */
> -	res = nand_scan_tail(mtd);
> -	if (res)
> -		goto free_irq;
> -
>  	mtd->name = DRV_NAME;
>  
>  	res = mtd_device_register(mtd, host->ncfg->parts,
> @@ -812,8 +823,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  
>  cleanup_nand:
>  	nand_cleanup(nand_chip);
> -free_irq:
> -	free_irq(host->irq, host);
>  release_dma_chan:
>  	if (use_dma)
>  		dma_release_channel(host->dma_chan);


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

* Re: [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: " Miquel Raynal
@ 2018-07-21 15:27   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 15:27 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:04 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/lpc32xx_slc.c | 77 +++++++++++++++++++++-----------------
>  1 file changed, 42 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
> index 42820aa1abab..a4e8b7e75135 100644
> --- a/drivers/mtd/nand/raw/lpc32xx_slc.c
> +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
> @@ -779,6 +779,46 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev)
>  	return ncfg;
>  }
>  
> +static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct lpc32xx_nand_host *host = nand_get_controller_data(chip);
> +
> +	/* OOB and ECC CPU and DMA work areas */
> +	host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
> +
> +	/*
> +	 * Small page FLASH has a unique OOB layout, but large and huge
> +	 * page FLASH use the standard layout. Small page FLASH uses a
> +	 * custom BBT marker layout.
> +	 */
> +	if (mtd->writesize <= 512)
> +		mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
> +
> +	/* These sizes remain the same regardless of page size */
> +	chip->ecc.size = 256;
> +	chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
> +	chip->ecc.prepad = 0;
> +	chip->ecc.postpad = 0;
> +
> +	/*
> +	 * Use a custom BBT marker setup for small page FLASH that
> +	 * won't interfere with the ECC layout. Large and huge page
> +	 * FLASH use the standard layout.
> +	 */
> +	if ((chip->bbt_options & NAND_BBT_USE_FLASH) &&
> +	    mtd->writesize <= 512) {
> +		chip->bbt_td = &bbt_smallpage_main_descr;
> +		chip->bbt_md = &bbt_smallpage_mirror_descr;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops lpc32xx_nand_controller_ops = {
> +	.attach_chip = lpc32xx_nand_attach_chip,
> +};
> +
>  /*
>   * Probe for NAND controller
>   */
> @@ -884,41 +924,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
>  	}
>  
>  	/* Find NAND device */
> -	res = nand_scan_ident(mtd, 1, NULL);
> -	if (res)
> -		goto release_dma;
> -
> -	/* OOB and ECC CPU and DMA work areas */
> -	host->ecc_buf = (uint32_t *)(host->data_buf + LPC32XX_DMA_DATA_SIZE);
> -
> -	/*
> -	 * Small page FLASH has a unique OOB layout, but large and huge
> -	 * page FLASH use the standard layout. Small page FLASH uses a
> -	 * custom BBT marker layout.
> -	 */
> -	if (mtd->writesize <= 512)
> -		mtd_set_ooblayout(mtd, &lpc32xx_ooblayout_ops);
> -
> -	/* These sizes remain the same regardless of page size */
> -	chip->ecc.size = 256;
> -	chip->ecc.bytes = LPC32XX_SLC_DEV_ECC_BYTES;
> -	chip->ecc.prepad = chip->ecc.postpad = 0;
> -
> -	/*
> -	 * Use a custom BBT marker setup for small page FLASH that
> -	 * won't interfere with the ECC layout. Large and huge page
> -	 * FLASH use the standard layout.
> -	 */
> -	if ((chip->bbt_options & NAND_BBT_USE_FLASH) &&
> -	    mtd->writesize <= 512) {
> -		chip->bbt_td = &bbt_smallpage_main_descr;
> -		chip->bbt_md = &bbt_smallpage_mirror_descr;
> -	}
> -
> -	/*
> -	 * Fills out all the uninitialized function pointers with the defaults
> -	 */
> -	res = nand_scan_tail(mtd);
> +	chip->dummy_controller.ops = &lpc32xx_nand_controller_ops;
> +	res = nand_scan(mtd, 1);
>  	if (res)
>  		goto release_dma;
>  


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

* Re: [PATCH v4 13/35] mtd: rawnand: marvell: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 13/35] mtd: rawnand: marvell: " Miquel Raynal
@ 2018-07-21 16:57   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 16:57 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:05 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

>  
> -	ret = nand_scan_tail(mtd);
> +	chip->controller->ops = &marvell_nand_controller_ops;

Assigning ->ops to &marvell_nand_controller_ops should be done only
once in the probe function (here [1]). With that fixed, you can add

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> +	ret = nand_scan(mtd, marvell_nand->nsels);
>  	if (ret) {
> -		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
> +		dev_err(dev, "could not scan the nand chip\n");
>  		return ret;
>  	}
>  


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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 14/35] mtd: rawnand: mtk: " Miquel Raynal
@ 2018-07-21 17:10   ` Boris Brezillon
  2018-07-26  6:06     ` xiaolei li
  0 siblings, 1 reply; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:10 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:06 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
>  1 file changed, 44 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> index 7bc6be3f6ec0..967418f945ea 100644
> --- a/drivers/mtd/nand/raw/mtk_nand.c
> +++ b/drivers/mtd/nand/raw/mtk_nand.c
> @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
>  	return 0;
>  }
>  
> +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct device *dev = mtd->dev.parent;
> +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> +	int len;
> +	int ret;
> +
> +	if (chip->options & NAND_BUSWIDTH_16) {
> +		dev_err(dev, "16bits buswidth not supported");
> +		return -EINVAL;
> +	}
> +
> +	/* store bbt magic in page, cause OOB is not protected */
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> +		chip->bbt_options |= NAND_BBT_NO_OOB;
> +
> +	ret = mtk_nfc_ecc_init(dev, mtd);
> +	if (ret)
> +		return ret;
> +
> +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> +	if (ret)
> +		return ret;
> +
> +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> +
> +	len = mtd->writesize + mtd->oobsize;
> +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> +	if (!nfc->buffer)
> +		return  -ENOMEM;
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> +	.attach_chip = mtk_nfc_attach_chip,
> +};
> +
>  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
>  				  struct device_node *np)
>  {
>  	struct mtk_nfc_nand_chip *chip;
>  	struct nand_chip *nand;
>  	struct mtd_info *mtd;
> -	int nsels, len;
> +	int nsels;
>  	u32 tmp;
>  	int ret;
>  	int i;
> @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
>  
>  	nand = &chip->nand;
>  	nand->controller = &nfc->controller;
> +	nand->controller->ops = &mtk_nfc_controller_ops;

Just like for the marvell driver, this assignment should be moved here
[1]. Also, it looks like this driver is open-coding
nand_controller_init(), probably something we should fix (in a separate
patch).

With this fixed:

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>  
>  	nand_set_flash_node(nand, np);
>  	nand_set_controller_data(nand, nfc);
> @@ -1324,36 +1366,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
>  
>  	mtk_nfc_hw_init(nfc);
>  
> -	ret = nand_scan_ident(mtd, nsels, NULL);
> -	if (ret)
> -		return ret;
> -
> -	/* store bbt magic in page, cause OOB is not protected */
> -	if (nand->bbt_options & NAND_BBT_USE_FLASH)
> -		nand->bbt_options |= NAND_BBT_NO_OOB;
> -
> -	ret = mtk_nfc_ecc_init(dev, mtd);
> -	if (ret)
> -		return -EINVAL;
> -
> -	if (nand->options & NAND_BUSWIDTH_16) {
> -		dev_err(dev, "16bits buswidth not supported");
> -		return -EINVAL;
> -	}
> -
> -	ret = mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
> -	if (ret)
> -		return ret;
> -
> -	mtk_nfc_set_fdm(&chip->fdm, mtd);
> -	mtk_nfc_set_bad_mark_ctl(&chip->bad_mark, mtd);
> -
> -	len = mtd->writesize + mtd->oobsize;
> -	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> -	if (!nfc->buffer)
> -		return  -ENOMEM;
> -
> -	ret = nand_scan_tail(mtd);
> +	ret = nand_scan(mtd, nsels);
>  	if (ret)
>  		return ret;
>  


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

* Re: [PATCH v4 15/35] mtd: rawnand: mxc: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 15/35] mtd: rawnand: mxc: " Miquel Raynal
@ 2018-07-21 17:19   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:19 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:07 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/mxc_nand.c | 136 +++++++++++++++++++++-------------------
>  1 file changed, 71 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c
> index c6eff61e909d..4c9214dea424 100644
> --- a/drivers/mtd/nand/raw/mxc_nand.c
> +++ b/drivers/mtd/nand/raw/mxc_nand.c
> @@ -1691,6 +1691,74 @@ static int mxcnd_probe_dt(struct mxc_nand_host *host)
>  }
>  #endif
>  
> +static int mxcnd_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct mxc_nand_host *host = nand_get_controller_data(chip);
> +	struct device *dev = mtd->dev.parent;
> +
> +	switch (chip->ecc.mode) {
> +	case NAND_ECC_HW:
> +		chip->ecc.read_page = mxc_nand_read_page;
> +		chip->ecc.read_page_raw = mxc_nand_read_page_raw;
> +		chip->ecc.read_oob = mxc_nand_read_oob;
> +		chip->ecc.write_page = mxc_nand_write_page_ecc;
> +		chip->ecc.write_page_raw = mxc_nand_write_page_raw;
> +		chip->ecc.write_oob = mxc_nand_write_oob;
> +		break;
> +
> +	case NAND_ECC_SOFT:
> +		break;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH) {
> +		chip->bbt_td = &bbt_main_descr;
> +		chip->bbt_md = &bbt_mirror_descr;
> +	}
> +
> +	/* Allocate the right size buffer now */
> +	devm_kfree(dev, (void *)host->data_buf);
> +	host->data_buf = devm_kzalloc(dev, mtd->writesize + mtd->oobsize,
> +				      GFP_KERNEL);
> +	if (!host->data_buf)
> +		return -ENOMEM;
> +
> +	/* Call preset again, with correct writesize chip time */
> +	host->devtype_data->preset(mtd);
> +
> +	if (!chip->ecc.bytes) {
> +		if (host->eccsize == 8)
> +			chip->ecc.bytes = 18;
> +		else if (host->eccsize == 4)
> +			chip->ecc.bytes = 9;
> +	}
> +
> +	/*
> +	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
> +	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
> +	 * into copying invalid data to/from the spare IO buffer, as this
> +	 * might cause ECC data corruption when doing sub-page write to a
> +	 * partially written page.
> +	 */
> +	host->used_oobsize = min(mtd->oobsize, 218U);
> +
> +	if (chip->ecc.mode == NAND_ECC_HW) {
> +		if (is_imx21_nfc(host) || is_imx27_nfc(host))
> +			chip->ecc.strength = 1;
> +		else
> +			chip->ecc.strength = (host->eccsize == 4) ? 4 : 8;
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops mxcnd_controller_ops = {
> +	.attach_chip = mxcnd_attach_chip,
> +};
> +
>  static int mxcnd_probe(struct platform_device *pdev)
>  {
>  	struct nand_chip *this;
> @@ -1830,71 +1898,9 @@ static int mxcnd_probe(struct platform_device *pdev)
>  		host->devtype_data->irq_control(host, 1);
>  	}
>  
> -	/* first scan to find the device and get the page size */
> -	err = nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL);
> -	if (err)
> -		goto escan;
> -
> -	switch (this->ecc.mode) {
> -	case NAND_ECC_HW:
> -		this->ecc.read_page = mxc_nand_read_page;
> -		this->ecc.read_page_raw = mxc_nand_read_page_raw;
> -		this->ecc.read_oob = mxc_nand_read_oob;
> -		this->ecc.write_page = mxc_nand_write_page_ecc;
> -		this->ecc.write_page_raw = mxc_nand_write_page_raw;
> -		this->ecc.write_oob = mxc_nand_write_oob;
> -		break;
> -
> -	case NAND_ECC_SOFT:
> -		break;
> -
> -	default:
> -		err = -EINVAL;
> -		goto escan;
> -	}
> -
> -	if (this->bbt_options & NAND_BBT_USE_FLASH) {
> -		this->bbt_td = &bbt_main_descr;
> -		this->bbt_md = &bbt_mirror_descr;
> -	}
> -
> -	/* allocate the right size buffer now */
> -	devm_kfree(&pdev->dev, (void *)host->data_buf);
> -	host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize,
> -					GFP_KERNEL);
> -	if (!host->data_buf) {
> -		err = -ENOMEM;
> -		goto escan;
> -	}
> -
> -	/* Call preset again, with correct writesize this time */
> -	host->devtype_data->preset(mtd);
> -
> -	if (!this->ecc.bytes) {
> -		if (host->eccsize == 8)
> -			this->ecc.bytes = 18;
> -		else if (host->eccsize == 4)
> -			this->ecc.bytes = 9;
> -	}
> -
> -	/*
> -	 * Experimentation shows that i.MX NFC can only handle up to 218 oob
> -	 * bytes. Limit used_oobsize to 218 so as to not confuse copy_spare()
> -	 * into copying invalid data to/from the spare IO buffer, as this
> -	 * might cause ECC data corruption when doing sub-page write to a
> -	 * partially written page.
> -	 */
> -	host->used_oobsize = min(mtd->oobsize, 218U);
> -
> -	if (this->ecc.mode == NAND_ECC_HW) {
> -		if (is_imx21_nfc(host) || is_imx27_nfc(host))
> -			this->ecc.strength = 1;
> -		else
> -			this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
> -	}
> -
> -	/* second phase scan */
> -	err = nand_scan_tail(mtd);
> +	/* Scan the NAND device */
> +	this->dummy_controller.ops = &mxcnd_controller_ops;
> +	err = nand_scan(mtd, is_imx25_nfc(host) ? 4 : 1);
>  	if (err)
>  		goto escan;
>  


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

* Re: [PATCH v4 16/35] mtd: rawnand: nandsim: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 16/35] mtd: rawnand: nandsim: " Miquel Raynal
@ 2018-07-21 17:21   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:21 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:08 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/nandsim.c | 82 +++++++++++++++++++++++-------------------
>  1 file changed, 45 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
> index 8a3b36cfe5ea..71ac034aee9c 100644
> --- a/drivers/mtd/nand/raw/nandsim.c
> +++ b/drivers/mtd/nand/raw/nandsim.c
> @@ -2192,6 +2192,48 @@ static void ns_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
>  	return;
>  }
>  
> +static int ns_attach_chip(struct nand_chip *chip)
> +{
> +	unsigned int eccsteps, eccbytes;
> +
> +	if (!bch)
> +		return 0;
> +
> +	if (!mtd_nand_has_bch()) {
> +		NS_ERR("BCH ECC support is disabled\n");
> +		return -EINVAL;
> +	}
> +
> +	/* Use 512-byte ecc blocks */
> +	eccsteps = nsmtd->writesize / 512;
> +	eccbytes = ((bch * 13) + 7) / 8;
> +
> +	/* Do not bother supporting small page devices */
> +	if (nsmtd->oobsize < 64 || !eccsteps) {
> +		NS_ERR("BCH not available on small page devices\n");
> +		return -EINVAL;
> +	}
> +
> +	if (((eccbytes * eccsteps) + 2) > nsmtd->oobsize) {
> +		NS_ERR("Invalid BCH value %u\n", bch);
> +		return -EINVAL;
> +	}
> +
> +	chip->ecc.mode = NAND_ECC_SOFT;
> +	chip->ecc.algo = NAND_ECC_BCH;
> +	chip->ecc.size = 512;
> +	chip->ecc.strength = bch;
> +	chip->ecc.bytes = eccbytes;
> +
> +	NS_INFO("Using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops ns_controller_ops = {
> +	.attach_chip = ns_attach_chip,
> +};
> +
>  /*
>   * Module initialization function
>   */
> @@ -2276,44 +2318,10 @@ static int __init ns_init_module(void)
>  	if ((retval = parse_gravepages()) != 0)
>  		goto error;
>  
> -	retval = nand_scan_ident(nsmtd, 1, NULL);
> +	chip->dummy_controller.ops = &ns_controller_ops;
> +	retval = nand_scan(nsmtd, 1);
>  	if (retval) {
> -		NS_ERR("cannot scan NAND Simulator device\n");
> -		goto error;
> -	}
> -
> -	if (bch) {
> -		unsigned int eccsteps, eccbytes;
> -		if (!mtd_nand_has_bch()) {
> -			NS_ERR("BCH ECC support is disabled\n");
> -			retval = -EINVAL;
> -			goto error;
> -		}
> -		/* use 512-byte ecc blocks */
> -		eccsteps = nsmtd->writesize/512;
> -		eccbytes = (bch*13+7)/8;
> -		/* do not bother supporting small page devices */
> -		if ((nsmtd->oobsize < 64) || !eccsteps) {
> -			NS_ERR("bch not available on small page devices\n");
> -			retval = -EINVAL;
> -			goto error;
> -		}
> -		if ((eccbytes*eccsteps+2) > nsmtd->oobsize) {
> -			NS_ERR("invalid bch value %u\n", bch);
> -			retval = -EINVAL;
> -			goto error;
> -		}
> -		chip->ecc.mode = NAND_ECC_SOFT;
> -		chip->ecc.algo = NAND_ECC_BCH;
> -		chip->ecc.size = 512;
> -		chip->ecc.strength = bch;
> -		chip->ecc.bytes = eccbytes;
> -		NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
> -	}
> -
> -	retval = nand_scan_tail(nsmtd);
> -	if (retval) {
> -		NS_ERR("can't register NAND Simulator\n");
> +		NS_ERR("Could not scan NAND Simulator device\n");
>  		goto error;
>  	}
>  


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

* Re: [PATCH v4 17/35] mtd: rawnand: omap2: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 17/35] mtd: rawnand: omap2: " Miquel Raynal
@ 2018-07-21 17:34   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:34 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:09 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

>  static int omap_nand_probe(struct platform_device *pdev)
>  {
>  	struct omap_nand_info		*info;
>  	struct mtd_info			*mtd;
>  	struct nand_chip		*nand_chip;
>  	int				err;
> -	dma_cap_mask_t			mask;
>  	struct resource			*res;
>  	struct device			*dev = &pdev->dev;
> -	int				min_oobbytes = BADBLOCK_MARKER_LENGTH;
> -	int				oobbytes_per_step;
>  
>  	info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info),
>  				GFP_KERNEL);
> @@ -1967,6 +2221,7 @@ static int omap_nand_probe(struct platform_device *pdev)
>  	info->phys_base = res->start;
>  
>  	nand_chip->controller = &omap_gpmc_controller;
> +	nand_chip->controller->ops = &omap_nand_controller_ops;

Move this assignment here [1].

>  
>  	nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R;
>  	nand_chip->cmd_ctrl  = omap_hwcontrol;

[1]https://elixir.bootlin.com/linux/v4.18-rc5/source/drivers/mtd/nand/raw/omap2.c#L148

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

* Re: [PATCH v4 18/35] mtd: rawnand: s3c2410: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 18/35] mtd: rawnand: s3c2410: " Miquel Raynal
@ 2018-07-21 17:38   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:38 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:10 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/s3c2410.c | 30 +++++++++++++-----------------
>  1 file changed, 13 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
> index e8bf64832213..c21e8892394a 100644
> --- a/drivers/mtd/nand/raw/s3c2410.c
> +++ b/drivers/mtd/nand/raw/s3c2410.c
> @@ -915,20 +915,19 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
>  }
>  
>  /**
> - * s3c2410_nand_update_chip - post probe update
> - * @info: The controller instance.
> - * @nmtd: The driver version of the MTD instance.
> + * s3c2410_nand_attach_chip - Init the ECC engine after NAND scan
> + * @chip: The NAND chip
>   *
> - * This routine is called after the chip probe has successfully completed
> - * and the relevant per-chip information updated. This call ensure that
> + * This hook is called by the core after the identification of the NAND chip,
> + * once the relevant per-chip information is up to date.. This call ensure that
>   * we update the internal state accordingly.
>   *
>   * The internal state is currently limited to the ECC state information.
>  */
> -static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
> -				    struct s3c2410_nand_mtd *nmtd)
> +static int s3c2410_nand_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = &nmtd->chip;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
>  
>  	switch (chip->ecc.mode) {
>  
> @@ -998,6 +997,10 @@ static int s3c2410_nand_update_chip(struct s3c2410_nand_info *info,
>  	return 0;
>  }
>  
> +static const struct nand_controller_ops s3c24xx_nand_controller_ops = {
> +	.attach_chip = s3c2410_nand_attach_chip,
> +};
> +
>  static const struct of_device_id s3c24xx_nand_dt_ids[] = {
>  	{
>  		.compatible = "samsung,s3c2410-nand",
> @@ -1095,6 +1098,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, info);
>  
>  	nand_controller_init(&info->controller);
> +	info->controller.ops = &s3c24xx_nand_controller_ops;
>  
>  	/* get the clock source and enable it */
>  
> @@ -1166,15 +1170,7 @@ static int s3c24xx_nand_probe(struct platform_device *pdev)
>  		mtd->dev.parent = &pdev->dev;
>  		s3c2410_nand_init_chip(info, nmtd, sets);
>  
> -		err = nand_scan_ident(mtd, (sets) ? sets->nr_chips : 1, NULL);
> -		if (err)
> -			goto exit_error;
> -
> -		err = s3c2410_nand_update_chip(info, nmtd);
> -		if (err < 0)
> -			goto exit_error;
> -
> -		err = nand_scan_tail(mtd);
> +		err = nand_scan(mtd, sets ? sets->nr_chips : 1);
>  		if (err)
>  			goto exit_error;
>  


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

* Re: [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function
  2018-07-20 15:15 ` [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function Miquel Raynal
@ 2018-07-21 17:48   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:48 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:11 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> @@ -1007,6 +1007,16 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
>  	struct sh_flctl *flctl = mtd_to_flctl(mtd);
>  	struct nand_chip *chip = &flctl->chip;
>  
> +	if (chip->options & NAND_BUSWIDTH_16) {
> +		/*
> +		 * NAND_BUSWIDTH_16 may have been set by nand_scan_ident().
> +		 * Add the SEL_16BIT flag in pdata->flcmncr_val and re-assign
> +		 * flctl->flcmncr_base to pdata->flcmncr_val.
> +		 */
> +		flctl->pdata->flcmncr_val |= SEL_16BIT;
> +		flctl->flcmncr_base = flctl->pdata->flcmncr_val;

pdata->flcmncr_val is not used after this point. I think you can just do

		flctl->flcmncr_base |= SEL_16BIT;

and get rid of the ftcl->pdata field you add in this patch.

> +	}
> +



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

* Re: [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan() Miquel Raynal
@ 2018-07-21 17:49   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:49 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:12 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/sh_flctl.c | 19 ++++++++-----------
>  1 file changed, 8 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/sh_flctl.c b/drivers/mtd/nand/raw/sh_flctl.c
> index d37d1d3ccbf9..663c75005ac9 100644
> --- a/drivers/mtd/nand/raw/sh_flctl.c
> +++ b/drivers/mtd/nand/raw/sh_flctl.c
> @@ -1002,10 +1002,10 @@ static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  	flctl->index += len;
>  }
>  
> -static int flctl_chip_init_tail(struct mtd_info *mtd)
> +static int flctl_chip_attach_chip(struct nand_chip *chip)
>  {
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct sh_flctl *flctl = mtd_to_flctl(mtd);
> -	struct nand_chip *chip = &flctl->chip;
>  
>  	if (chip->options & NAND_BUSWIDTH_16) {
>  		/*
> @@ -1073,6 +1073,10 @@ static int flctl_chip_init_tail(struct mtd_info *mtd)
>  	return 0;
>  }
>  
> +static const struct nand_controller_ops flctl_nand_controller_ops = {
> +	.attach_chip = flctl_chip_attach_chip,
> +};
> +
>  static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
>  {
>  	struct sh_flctl *flctl = dev_id;
> @@ -1200,15 +1204,8 @@ static int flctl_probe(struct platform_device *pdev)
>  
>  	flctl_setup_dma(flctl);
>  
> -	ret = nand_scan_ident(flctl_mtd, 1, NULL);
> -	if (ret)
> -		goto err_chip;
> -
> -	ret = flctl_chip_init_tail(flctl_mtd);
> -	if (ret)
> -		goto err_chip;
> -
> -	ret = nand_scan_tail(flctl_mtd);
> +	nand->dummy_controller.ops = &flctl_nand_controller_ops;
> +	ret = nand_scan(flctl_mtd, 1);
>  	if (ret)
>  		goto err_chip;
>  


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

* Re: [PATCH v4 21/35] mtd: rawnand: sunxi: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 21/35] mtd: rawnand: sunxi: " Miquel Raynal
@ 2018-07-21 17:50   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:50 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:13 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/sunxi_nand.c | 43 +++++++++++++++++----------------------
>  1 file changed, 19 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 07f3ff9a28f2..a4d23381003d 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -1816,12 +1816,21 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
>  	}
>  }
>  
> -static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
> -			       struct device_node *np)
> +static int sunxi_nand_attach_chip(struct nand_chip *nand)
>  {
> -	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct mtd_info *mtd = nand_to_mtd(nand);
> +	struct nand_ecc_ctrl *ecc = &nand->ecc;
> +	struct device_node *np = nand_get_flash_node(nand);
>  	int ret;
>  
> +	if (nand->bbt_options & NAND_BBT_USE_FLASH)
> +		nand->bbt_options |= NAND_BBT_NO_OOB;
> +
> +	if (nand->options & NAND_NEED_SCRAMBLING)
> +		nand->options |= NAND_NO_SUBPAGE_WRITE;
> +
> +	nand->options |= NAND_SUBPAGE_READ;
> +
>  	if (!ecc->size) {
>  		ecc->size = nand->ecc_step_ds;
>  		ecc->strength = nand->ecc_strength_ds;
> @@ -1846,6 +1855,10 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc,
>  	return 0;
>  }
>  
> +static const struct nand_controller_ops sunxi_nand_controller_ops = {
> +	.attach_chip = sunxi_nand_attach_chip,
> +};
> +
>  static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
>  				struct device_node *np)
>  {
> @@ -1911,6 +1924,8 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
>  	/* Default tR value specified in the ONFI spec (chapter 4.15.1) */
>  	nand->chip_delay = 200;
>  	nand->controller = &nfc->controller;
> +	nand->controller->ops = &sunxi_nand_controller_ops;
> +
>  	/*
>  	 * Set the ECC mode to the default value in case nothing is specified
>  	 * in the DT.
> @@ -1927,30 +1942,10 @@ static int sunxi_nand_chip_init(struct device *dev, struct sunxi_nfc *nfc,
>  	mtd = nand_to_mtd(nand);
>  	mtd->dev.parent = dev;
>  
> -	ret = nand_scan_ident(mtd, nsels, NULL);
> +	ret = nand_scan(mtd, nsels);
>  	if (ret)
>  		return ret;
>  
> -	if (nand->bbt_options & NAND_BBT_USE_FLASH)
> -		nand->bbt_options |= NAND_BBT_NO_OOB;
> -
> -	if (nand->options & NAND_NEED_SCRAMBLING)
> -		nand->options |= NAND_NO_SUBPAGE_WRITE;
> -
> -	nand->options |= NAND_SUBPAGE_READ;
> -
> -	ret = sunxi_nand_ecc_init(mtd, &nand->ecc, np);
> -	if (ret) {
> -		dev_err(dev, "ECC init failed: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = nand_scan_tail(mtd);
> -	if (ret) {
> -		dev_err(dev, "nand_scan_tail failed: %d\n", ret);
> -		return ret;
> -	}
> -
>  	ret = mtd_device_register(mtd, NULL, 0);
>  	if (ret) {
>  		dev_err(dev, "failed to register mtd device: %d\n", ret);


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

* Re: [PATCH v4 22/35] mtd: rawnand: tango: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 22/35] mtd: rawnand: tango: " Miquel Raynal
@ 2018-07-21 17:52   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:52 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:14 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/tango_nand.c | 40 +++++++++++++++++++++++----------------
>  1 file changed, 24 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/tango_nand.c b/drivers/mtd/nand/raw/tango_nand.c
> index dd7a26efdf4f..a448d0797cd5 100644
> --- a/drivers/mtd/nand/raw/tango_nand.c
> +++ b/drivers/mtd/nand/raw/tango_nand.c
> @@ -517,6 +517,28 @@ static int tango_set_timings(struct mtd_info *mtd, int csline,
>  	return 0;
>  }
>  
> +static int tango_attach_chip(struct nand_chip *chip)
> +{
> +	struct nand_ecc_ctrl *ecc = &chip->ecc;
> +
> +	ecc->mode = NAND_ECC_HW;
> +	ecc->algo = NAND_ECC_BCH;
> +	ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE);
> +
> +	ecc->read_page_raw = tango_read_page_raw;
> +	ecc->write_page_raw = tango_write_page_raw;
> +	ecc->read_page = tango_read_page;
> +	ecc->write_page = tango_write_page;
> +	ecc->read_oob = tango_read_oob;
> +	ecc->write_oob = tango_write_oob;
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops tango_controller_ops = {
> +	.attach_chip = tango_attach_chip,
> +};
> +
>  static int chip_init(struct device *dev, struct device_node *np)
>  {
>  	u32 cs;
> @@ -560,28 +582,14 @@ static int chip_init(struct device *dev, struct device_node *np)
>  			NAND_NO_SUBPAGE_WRITE |
>  			NAND_WAIT_TCCS;
>  	chip->controller = &nfc->hw;
> +	chip->controller->ops = &tango_controller_ops;

Move this assignment here [1]. With that fixed:

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>  	tchip->base = nfc->pbus_base + (cs * 256);
>  
>  	nand_set_flash_node(chip, np);
>  	mtd_set_ooblayout(mtd, &tango_nand_ooblayout_ops);
>  	mtd->dev.parent = dev;
>  
> -	err = nand_scan_ident(mtd, 1, NULL);
> -	if (err)
> -		return err;
> -
> -	ecc->mode = NAND_ECC_HW;
> -	ecc->algo = NAND_ECC_BCH;
> -	ecc->bytes = DIV_ROUND_UP(ecc->strength * FIELD_ORDER, BITS_PER_BYTE);
> -
> -	ecc->read_page_raw = tango_read_page_raw;
> -	ecc->write_page_raw = tango_write_page_raw;
> -	ecc->read_page = tango_read_page;
> -	ecc->write_page = tango_write_page;
> -	ecc->read_oob = tango_read_oob;
> -	ecc->write_oob = tango_write_oob;
> -
> -	err = nand_scan_tail(mtd);
> +	err = nand_scan(mtd, 1);
>  	if (err)
>  		return err;
>  

[1]https://elixir.bootlin.com/linux/v4.18-rc5/source/drivers/mtd/nand/raw/tango_nand.c#L657

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

* Re: [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure
  2018-07-20 15:15 ` [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure Miquel Raynal
@ 2018-07-21 17:53   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:53 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:15 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> As already done in the core, calling a struct nand_controller
> 'hw_control' is misleading. Use the same name as in nand_base.c:
> 'controller'.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/txx9ndfmc.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
> index 8f5bbbac4612..9019022774f7 100644
> --- a/drivers/mtd/nand/raw/txx9ndfmc.c
> +++ b/drivers/mtd/nand/raw/txx9ndfmc.c
> @@ -73,7 +73,7 @@ struct txx9ndfmc_drvdata {
>  	void __iomem *base;
>  	unsigned char hold;	/* in gbusclock */
>  	unsigned char spw;	/* in gbusclock */
> -	struct nand_controller hw_control;
> +	struct nand_controller controller;
>  };
>  
>  static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
> @@ -303,7 +303,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  	dev_info(&dev->dev, "CLK:%ldMHz HOLD:%d SPW:%d\n",
>  		 (gbusclk + 500000) / 1000000, hold, spw);
>  
> -	nand_controller_init(&drvdata->hw_control);
> +	nand_controller_init(&drvdata->controller);
>  
>  	platform_set_drvdata(dev, drvdata);
>  	txx9ndfmc_initialize(dev);
> @@ -337,7 +337,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		chip->ecc.bytes = 3;
>  		chip->ecc.strength = 1;
>  		chip->chip_delay = 100;
> -		chip->controller = &drvdata->hw_control;
> +		chip->controller = &drvdata->controller;
>  
>  		nand_set_controller_data(chip, txx9_priv);
>  		txx9_priv->dev = dev;


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

* Re: [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan() Miquel Raynal
@ 2018-07-21 17:54   ` Boris Brezillon
  2018-07-21 18:04   ` Boris Brezillon
  1 sibling, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 17:54 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:16 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/txx9ndfmc.c | 29 +++++++++++++++--------------
>  1 file changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
> index 9019022774f7..0134beb1136d 100644
> --- a/drivers/mtd/nand/raw/txx9ndfmc.c
> +++ b/drivers/mtd/nand/raw/txx9ndfmc.c
> @@ -254,23 +254,23 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
>  #define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \
>  	DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000)
>  
> -static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
> +static int txx9ndfmc_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> -	int ret;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (!ret) {
> -		if (mtd->writesize >= 512) {
> -			/* Hardware ECC 6 byte ECC per 512 Byte data */
> -			chip->ecc.size = 512;
> -			chip->ecc.bytes = 6;
> -		}
> -		ret = nand_scan_tail(mtd);
> +	if (mtd->writesize >= 512) {
> +		/* Hardware ECC 6 byte ECC per 512 Byte data */
> +		chip->ecc.size = 512;
> +		chip->ecc.bytes = 6;
>  	}
> -	return ret;
> +
> +	return 0;
>  }
>  
> +static const struct nand_controller_ops txx9ndfmc_controller_ops = {
> +	.attach_chip = txx9ndfmc_attach_chip,
> +};
> +
>  static int __init txx9ndfmc_probe(struct platform_device *dev)
>  {
>  	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
> @@ -304,6 +304,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		 (gbusclk + 500000) / 1000000, hold, spw);
>  
>  	nand_controller_init(&drvdata->controller);
> +	drvdata->controller.ops = &txx9ndfmc_controller_ops;
>  
>  	platform_set_drvdata(dev, drvdata);
>  	txx9ndfmc_initialize(dev);
> @@ -332,7 +333,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		chip->ecc.correct = txx9ndfmc_correct_data;
>  		chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
>  		chip->ecc.mode = NAND_ECC_HW;
> -		/* txx9ndfmc_nand_scan will overwrite ecc.size and ecc.bytes */
> +		/* nand_scan() will overwrite ecc.size and ecc.bytes */
>  		chip->ecc.size = 256;
>  		chip->ecc.bytes = 3;
>  		chip->ecc.strength = 1;
> @@ -359,7 +360,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		if (plat->wide_mask & (1 << i))
>  			chip->options |= NAND_BUSWIDTH_16;
>  
> -		if (txx9ndfmc_nand_scan(mtd)) {
> +		if (nand_scan(mtd, 1)) {
>  			kfree(txx9_priv->mtdname);
>  			kfree(txx9_priv);
>  			continue;


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

* Re: [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan() Miquel Raynal
  2018-07-21 17:54   ` Boris Brezillon
@ 2018-07-21 18:04   ` Boris Brezillon
  1 sibling, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 18:04 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:16 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/txx9ndfmc.c | 29 +++++++++++++++--------------
>  1 file changed, 15 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
> index 9019022774f7..0134beb1136d 100644
> --- a/drivers/mtd/nand/raw/txx9ndfmc.c
> +++ b/drivers/mtd/nand/raw/txx9ndfmc.c
> @@ -254,23 +254,23 @@ static void txx9ndfmc_initialize(struct platform_device *dev)
>  #define TXX9NDFMC_NS_TO_CYC(gbusclk, ns) \
>  	DIV_ROUND_UP((ns) * DIV_ROUND_UP(gbusclk, 1000), 1000000)
>  
> -static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
> +static int txx9ndfmc_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> -	int ret;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  
> -	ret = nand_scan_ident(mtd, 1, NULL);
> -	if (!ret) {
> -		if (mtd->writesize >= 512) {
> -			/* Hardware ECC 6 byte ECC per 512 Byte data */
> -			chip->ecc.size = 512;
> -			chip->ecc.bytes = 6;
> -		}
> -		ret = nand_scan_tail(mtd);
> +	if (mtd->writesize >= 512) {
> +		/* Hardware ECC 6 byte ECC per 512 Byte data */
> +		chip->ecc.size = 512;
> +		chip->ecc.bytes = 6;
>  	}
> -	return ret;
> +
> +	return 0;
>  }
>  
> +static const struct nand_controller_ops txx9ndfmc_controller_ops = {
> +	.attach_chip = txx9ndfmc_attach_chip,
> +};
> +
>  static int __init txx9ndfmc_probe(struct platform_device *dev)
>  {
>  	struct txx9ndfmc_platform_data *plat = dev_get_platdata(&dev->dev);
> @@ -304,6 +304,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		 (gbusclk + 500000) / 1000000, hold, spw);
>  
>  	nand_controller_init(&drvdata->controller);
> +	drvdata->controller.ops = &txx9ndfmc_controller_ops;
>  
>  	platform_set_drvdata(dev, drvdata);
>  	txx9ndfmc_initialize(dev);
> @@ -332,7 +333,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		chip->ecc.correct = txx9ndfmc_correct_data;
>  		chip->ecc.hwctl = txx9ndfmc_enable_hwecc;
>  		chip->ecc.mode = NAND_ECC_HW;
> -		/* txx9ndfmc_nand_scan will overwrite ecc.size and ecc.bytes */
> +		/* nand_scan() will overwrite ecc.size and ecc.bytes */
>  		chip->ecc.size = 256;
>  		chip->ecc.bytes = 3;

I had a hard time understanding what was the point of assigning
values that would later be overwritten. Actually the comment is
inaccurate, it's only overwritten if mtd->writesize >= 512. Can you had
a patch that moves this block in txx9ndfmc_nand_scan() before doing the
->attach_chip() conversion?

>  		chip->ecc.strength = 1;
> @@ -359,7 +360,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
>  		if (plat->wide_mask & (1 << i))
>  			chip->options |= NAND_BUSWIDTH_16;
>  
> -		if (txx9ndfmc_nand_scan(mtd)) {
> +		if (nand_scan(mtd, 1)) {
>  			kfree(txx9_priv->mtdname);
>  			kfree(txx9_priv);
>  			continue;


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

* Re: [PATCH v4 25/35] mtd: rawnand: vf610: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 25/35] mtd: rawnand: vf610: " Miquel Raynal
@ 2018-07-21 18:05   ` Boris Brezillon
  2018-07-25  8:57   ` Stefan Agner
  1 sibling, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-21 18:05 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:17 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/vf610_nfc.c | 127 ++++++++++++++++++++-------------------
>  1 file changed, 66 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
> index d5a22fc96878..6f6dcbf9095b 100644
> --- a/drivers/mtd/nand/raw/vf610_nfc.c
> +++ b/drivers/mtd/nand/raw/vf610_nfc.c
> @@ -747,6 +747,69 @@ static void vf610_nfc_init_controller(struct vf610_nfc *nfc)
>  	}
>  }
>  
> +static int vf610_nfc_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct vf610_nfc *nfc = mtd_to_nfc(mtd);
> +
> +	vf610_nfc_init_controller(nfc);
> +
> +	/* Bad block options. */
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> +		chip->bbt_options |= NAND_BBT_NO_OOB;
> +
> +	/* Single buffer only, max 256 OOB minus ECC status */
> +	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
> +		dev_err(nfc->dev, "Unsupported flash page size\n");
> +		return -ENXIO;
> +	}
> +
> +	if (chip->ecc.mode != NAND_ECC_HW)
> +		return 0;
> +
> +	if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
> +		dev_err(nfc->dev, "Unsupported flash with hwecc\n");
> +		return -ENXIO;
> +	}
> +
> +	if (chip->ecc.size != mtd->writesize) {
> +		dev_err(nfc->dev, "Step size needs to be page size\n");
> +		return -ENXIO;
> +	}
> +
> +	/* Only 64 byte ECC layouts known */
> +	if (mtd->oobsize > 64)
> +		mtd->oobsize = 64;
> +
> +	/* Use default large page ECC layout defined in NAND core */
> +	mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> +	if (chip->ecc.strength == 32) {
> +		nfc->ecc_mode = ECC_60_BYTE;
> +		chip->ecc.bytes = 60;
> +	} else if (chip->ecc.strength == 24) {
> +		nfc->ecc_mode = ECC_45_BYTE;
> +		chip->ecc.bytes = 45;
> +	} else {
> +		dev_err(nfc->dev, "Unsupported ECC strength\n");
> +		return -ENXIO;
> +	}
> +
> +	chip->ecc.read_page = vf610_nfc_read_page;
> +	chip->ecc.write_page = vf610_nfc_write_page;
> +	chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
> +	chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
> +	chip->ecc.read_oob = vf610_nfc_read_oob;
> +	chip->ecc.write_oob = vf610_nfc_write_oob;
> +
> +	chip->ecc.size = PAGE_2K;
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops vf610_nfc_controller_ops = {
> +	.attach_chip = vf610_nfc_attach_chip,
> +};
> +
>  static int vf610_nfc_probe(struct platform_device *pdev)
>  {
>  	struct vf610_nfc *nfc;
> @@ -827,67 +890,9 @@ static int vf610_nfc_probe(struct platform_device *pdev)
>  
>  	vf610_nfc_preinit_controller(nfc);
>  
> -	/* first scan to find the device and get the page size */
> -	err = nand_scan_ident(mtd, 1, NULL);
> -	if (err)
> -		goto err_disable_clk;
> -
> -	vf610_nfc_init_controller(nfc);
> -
> -	/* Bad block options. */
> -	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> -		chip->bbt_options |= NAND_BBT_NO_OOB;
> -
> -	/* Single buffer only, max 256 OOB minus ECC status */
> -	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
> -		dev_err(nfc->dev, "Unsupported flash page size\n");
> -		err = -ENXIO;
> -		goto err_disable_clk;
> -	}
> -
> -	if (chip->ecc.mode == NAND_ECC_HW) {
> -		if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
> -			dev_err(nfc->dev, "Unsupported flash with hwecc\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		if (chip->ecc.size != mtd->writesize) {
> -			dev_err(nfc->dev, "Step size needs to be page size\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		/* Only 64 byte ECC layouts known */
> -		if (mtd->oobsize > 64)
> -			mtd->oobsize = 64;
> -
> -		/* Use default large page ECC layout defined in NAND core */
> -		mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> -		if (chip->ecc.strength == 32) {
> -			nfc->ecc_mode = ECC_60_BYTE;
> -			chip->ecc.bytes = 60;
> -		} else if (chip->ecc.strength == 24) {
> -			nfc->ecc_mode = ECC_45_BYTE;
> -			chip->ecc.bytes = 45;
> -		} else {
> -			dev_err(nfc->dev, "Unsupported ECC strength\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		chip->ecc.read_page = vf610_nfc_read_page;
> -		chip->ecc.write_page = vf610_nfc_write_page;
> -		chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
> -		chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
> -		chip->ecc.read_oob = vf610_nfc_read_oob;
> -		chip->ecc.write_oob = vf610_nfc_write_oob;
> -
> -		chip->ecc.size = PAGE_2K;
> -	}
> -
> -	/* second phase scan */
> -	err = nand_scan_tail(mtd);
> +	/* Scan the NAND chip */
> +	chip->dummy_controller.ops = &vf610_nfc_controller_ops;
> +	err = nand_scan(mtd, 1);
>  	if (err)
>  		goto err_disable_clk;
>  


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

* Re: [PATCH v4 26/35] mtd: rawnand: atmel: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 26/35] mtd: rawnand: atmel: " Miquel Raynal
@ 2018-07-22  6:40   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  6:40 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:18 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/atmel/nand-controller.c | 83 ++++++++++++++--------------
>  1 file changed, 40 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
> index 855cc7729c43..0bc7e2abc885 100644
> --- a/drivers/mtd/nand/raw/atmel/nand-controller.c
> +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
> @@ -202,7 +202,7 @@ struct atmel_nand_controller_ops {
>  	int (*remove)(struct atmel_nand_controller *nc);
>  	void (*nand_init)(struct atmel_nand_controller *nc,
>  			  struct atmel_nand *nand);
> -	int (*ecc_init)(struct atmel_nand *nand);
> +	int (*ecc_init)(struct nand_chip *chip);
>  	int (*setup_data_interface)(struct atmel_nand *nand, int csline,
>  				    const struct nand_data_interface *conf);
>  };
> @@ -1133,9 +1133,8 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
>  	return 0;
>  }
>  
> -static int atmel_nand_ecc_init(struct atmel_nand *nand)
> +static int atmel_nand_ecc_init(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = &nand->base;
>  	struct atmel_nand_controller *nc;
>  	int ret;
>  
> @@ -1170,12 +1169,11 @@ static int atmel_nand_ecc_init(struct atmel_nand *nand)
>  	return 0;
>  }
>  
> -static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
> +static int atmel_hsmc_nand_ecc_init(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = &nand->base;
>  	int ret;
>  
> -	ret = atmel_nand_ecc_init(nand);
> +	ret = atmel_nand_ecc_init(chip);
>  	if (ret)
>  		return ret;
>  
> @@ -1558,22 +1556,6 @@ static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
>  	chip->select_chip = atmel_hsmc_nand_select_chip;
>  }
>  
> -static int atmel_nand_detect(struct atmel_nand *nand)
> -{
> -	struct nand_chip *chip = &nand->base;
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> -	struct atmel_nand_controller *nc;
> -	int ret;
> -
> -	nc = to_nand_controller(chip->controller);
> -
> -	ret = nand_scan_ident(mtd, nand->numcs, NULL);
> -	if (ret)
> -		dev_err(nc->dev, "nand_scan_ident() failed: %d\n", ret);
> -
> -	return ret;
> -}
> -
>  static int atmel_nand_unregister(struct atmel_nand *nand)
>  {
>  	struct nand_chip *chip = &nand->base;
> @@ -1595,7 +1577,6 @@ static int atmel_nand_register(struct atmel_nand *nand)
>  	struct nand_chip *chip = &nand->base;
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct atmel_nand_controller *nc;
> -	int ret;
>  
>  	nc = to_nand_controller(chip->controller);
>  
> @@ -1626,21 +1607,6 @@ static int atmel_nand_register(struct atmel_nand *nand)
>  		}
>  	}
>  
> -	ret = nand_scan_tail(mtd);
> -	if (ret) {
> -		dev_err(nc->dev, "nand_scan_tail() failed: %d\n", ret);
> -		return ret;
> -	}
> -
> -	ret = mtd_device_register(mtd, NULL, 0);
> -	if (ret) {
> -		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
> -		nand_cleanup(chip);
> -		return ret;
> -	}
> -
> -	list_add_tail(&nand->node, &nc->chips);
> -

You can move all the code in atmel_nand_register() directly in
atmel_nand_controller_add_nand() + rename atmel_nand_unregister() into
atmel_nand_controller_remove_nand(). This should be done in a separate
patch so that the transition to nand_scan() is easier to review.

>  	return 0;
>  }
>  
> @@ -1755,6 +1721,8 @@ static int
>  atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
>  			       struct atmel_nand *nand)
>  {
> +	struct nand_chip *chip = &nand->base;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  	int ret;
>  
>  	/* No card inserted, skip this NAND. */
> @@ -1765,15 +1733,30 @@ atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
>  
>  	nc->caps->ops->nand_init(nc, nand);
>  
> -	ret = atmel_nand_detect(nand);
> -	if (ret)
> +	ret = nand_scan(mtd, nand->numcs);
> +	if (ret) {
> +		dev_err(nc->dev, "NAND scan failed: %d\n", ret);
>  		return ret;
> +	}
>  
> -	ret = nc->caps->ops->ecc_init(nand);
> +	ret = atmel_nand_register(nand);
>  	if (ret)
> -		return ret;
> +		goto cleanup_nand;
> +
> +	ret = mtd_device_register(mtd, NULL, 0);
> +	if (ret) {
> +		dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
> +		goto cleanup_nand;
> +	}
> +
> +	list_add_tail(&nand->node, &nc->chips);
> +
> +	return 0;
> +
> +cleanup_nand:
> +	nand_cleanup(chip);
>  
> -	return atmel_nand_register(nand);
> +	return ret;
>  }
>  
>  static int
> @@ -1958,6 +1941,19 @@ static const struct of_device_id atmel_matrix_of_ids[] = {
>  	{ /* sentinel */ },
>  };
>  
> +static int atmel_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct atmel_nand_controller *nc;
> +
> +	nc = to_nand_controller(chip->controller);
> +
> +	return nc->caps->ops->ecc_init(chip);
> +}
> +
> +static const struct nand_controller_ops atmel_nand_controller_ops = {
> +	.attach_chip = atmel_nand_attach_chip,
> +};
> +
>  static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
>  				struct platform_device *pdev,
>  				const struct atmel_nand_controller_caps *caps)
> @@ -1967,6 +1963,7 @@ static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
>  	int ret;
>  
>  	nand_controller_init(&nc->base);
> +	nc->base.ops = &atmel_nand_controller_ops;
>  	INIT_LIST_HEAD(&nc->chips);
>  	nc->dev = dev;
>  	nc->caps = caps;


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

* Re: [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
  2018-07-20 15:15 ` [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids() Miquel Raynal
@ 2018-07-22  6:44   ` Boris Brezillon
  2018-07-26 19:06     ` Boris Brezillon
  0 siblings, 1 reply; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  6:44 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:19 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan_with_ids()
> (alternative to nand_scan() for passing a flash IDs table) instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/sm_common.c | 39 +++++++++++++++++++++++++--------------
>  1 file changed, 25 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
> index 7f5044a79f01..d05e3f976a5e 100644
> --- a/drivers/mtd/nand/raw/sm_common.c
> +++ b/drivers/mtd/nand/raw/sm_common.c
> @@ -160,19 +160,9 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
>  	{NULL}
>  };
>  
> -int sm_register_device(struct mtd_info *mtd, int smartmedia)
> +static int sm_attach_chip(struct nand_chip *chip)
>  {
> -	struct nand_chip *chip = mtd_to_nand(mtd);
> -	int ret;
> -
> -	chip->options |= NAND_SKIP_BBTSCAN;
> -
> -	/* Scan for card properties */
> -	ret = nand_scan_ident(mtd, 1, smartmedia ?
> -		nand_smartmedia_flash_ids : nand_xd_flash_ids);
> -
> -	if (ret)
> -		return ret;
> +	struct mtd_info *mtd = nand_to_mtd(chip);
>  
>  	/* Bad block marker position */
>  	chip->badblockpos = 0x05;
> @@ -187,12 +177,33 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia)
>  	else
>  		return -ENODEV;
>  
> -	ret = nand_scan_tail(mtd);
> +	return 0;
> +}
>  
> +static const struct nand_controller_ops sm_controller_ops = {
> +	.attach_chip = sm_attach_chip,
> +};
> +
> +int sm_register_device(struct mtd_info *mtd, int smartmedia)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct nand_flash_dev *flash_ids;
> +	int ret;
> +
> +	chip->options |= NAND_SKIP_BBTSCAN;
> +
> +	/* Scan for card properties */
> +	chip->dummy_controller.ops = &sm_controller_ops;
> +	flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids;
> +	ret = nand_scan_with_ids(mtd, 1, flash_ids);
>  	if (ret)
>  		return ret;
>  
> -	return mtd_device_register(mtd, NULL, 0);
> +	ret = mtd_device_register(mtd, NULL, 0);
> +	if (ret)
> +		nand_release(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(sm_register_device);
>  


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

* Re: [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident()
  2018-07-20 15:15 ` [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident() Miquel Raynal
@ 2018-07-22  8:49   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  8:49 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:20 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Some driver (eg. docg4) will need to handle themselves the
> identification phase. As part of the migration to use nand_scan()
> everywhere (which will unconditionnaly call nand_scan_ident()), we add
> a condition at the start of nand_scan_ident() to just "do nothing" if
> the maxchips parameters is zero, meaning that the driver does not want
> the core to handle this phase.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index dea41fa25be1..e7f135c100c2 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5926,7 +5926,7 @@ static int nand_dt_init(struct nand_chip *chip)
>  /**
>   * nand_scan_ident - [NAND Interface] Scan for the NAND device
>   * @mtd: MTD device structure
> - * @maxchips: number of chips to scan for
> + * @maxchips: number of chips to scan for, returns immediately if 0
>   * @table: alternative NAND ID table
>   *
>   * This is the first phase of the normal nand_scan() function. It reads the
> @@ -5940,6 +5940,14 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	int ret;
>  
> +	/*
> +	 * If the number of chips to scan for is null, just return silently.

						 ^ zero


> +	 * This is for specific drivers that must handle this part of the
> +	 * probe process themselves (e.g docg4).
> +	 */

I think that description of the special case maxchips == 0 should be
placed in the kernel doc header.

> +	if (!maxchips)
> +		return 0;

Can we move this check in nand_scan_with_ids()?

> +
>  	/* Enforce the right timings for reset/detection */
>  	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
>  


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

* Re: [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan() Miquel Raynal
@ 2018-07-22  8:52   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  8:52 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:21 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/docg4.c | 55 ++++++++++++++++++++++++++------------------
>  1 file changed, 32 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/docg4.c b/drivers/mtd/nand/raw/docg4.c
> index 4dccdfba6140..fec4353ff4ef 100644
> --- a/drivers/mtd/nand/raw/docg4.c
> +++ b/drivers/mtd/nand/raw/docg4.c
> @@ -1227,10 +1227,9 @@ static void __init init_mtd_structs(struct mtd_info *mtd)
>  	 * required within a nand driver because they are performed by the nand
>  	 * infrastructure code as part of nand_scan().  In this case they need
>  	 * to be initialized here because we skip call to nand_scan_ident() (the
> -	 * first half of nand_scan()).  The call to nand_scan_ident() is skipped
> -	 * because for this device the chip id is not read in the manner of a
> -	 * standard nand device.  Unfortunately, nand_scan_ident() does other
> -	 * things as well, such as call nand_set_defaults().
> +	 * first half of nand_scan()).  The call to nand_scan_ident() could be
> +	 * skipped because for this device the chip id is not read in the manner
> +	 * of a standard nand device.
>  	 */
>  
>  	struct nand_chip *nand = mtd_to_nand(mtd);
> @@ -1315,6 +1314,27 @@ static int __init read_id_reg(struct mtd_info *mtd)
>  
>  static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
>  
> +static int docg4_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct docg4_priv *doc = (struct docg4_priv *)(chip + 1);
> +
> +	init_mtd_structs(mtd);
> +
> +	/* Initialize kernel BCH algorithm */
> +	doc->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
> +	if (!doc->bch)
> +		return -EINVAL;
> +

You need a ->detach_chip() hook to free the BCH context, don't you?

> +	reset(mtd);
> +
> +	return read_id_reg(mtd);
> +}
> +
> +static const struct nand_controller_ops docg4_controller_ops = {
> +	.attach_chip = docg4_attach_chip,
> +};
> +
>  static int __init probe_docg4(struct platform_device *pdev)
>  {
>  	struct mtd_info *mtd;
> @@ -1350,26 +1370,16 @@ static int __init probe_docg4(struct platform_device *pdev)
>  	mtd->dev.parent = &pdev->dev;
>  	doc->virtadr = virtadr;
>  	doc->dev = dev;
> -
> -	init_mtd_structs(mtd);
> -
> -	/* initialize kernel bch algorithm */
> -	doc->bch = init_bch(DOCG4_M, DOCG4_T, DOCG4_PRIMITIVE_POLY);
> -	if (doc->bch == NULL) {
> -		retval = -EINVAL;
> -		goto free_nand;
> -	}
> -
>  	platform_set_drvdata(pdev, doc);
>  
> -	reset(mtd);
> -	retval = read_id_reg(mtd);
> -	if (retval == -ENODEV) {
> -		dev_warn(dev, "No diskonchip G4 device found.\n");
> -		goto free_bch;
> -	}
> -
> -	retval = nand_scan_tail(mtd);
> +	/*
> +	 * Asking for 0 chips is useless here but it warns the user that the use
> +	 * of the nand_scan() function is a bit abused here because the
> +	 * initialization is actually a bit specific and re-handled again in the
> +	 * ->attach_chip() hook. It will probably leak some memory though.

I don't get the last part. Is there really a memory leak? In that case
we should find a solution to prevent that.

> +	 */
> +	nand->dummy_controller.ops = &docg4_controller_ops;
> +	retval = nand_scan(mtd, 0);
>  	if (retval)
>  		goto free_bch;
>  
> @@ -1389,7 +1399,6 @@ static int __init probe_docg4(struct platform_device *pdev)
>  	nand_cleanup(nand);
>  free_bch:
>  	free_bch(doc->bch);

This should be done in the ->detach_chip() hook.

> -free_nand:
>  	kfree(nand);
>  unmap:
>  	iounmap(virtadr);


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

* Re: [PATCH v4 30/35] mtd: rawnand: qcom: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 30/35] mtd: rawnand: qcom: " Miquel Raynal
@ 2018-07-22  8:59   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  8:59 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:22 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

>  
> -static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
> -			       struct qcom_nand_host *host,
> -			       struct device_node *dn)
> +static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
> +					    struct qcom_nand_host *host,
> +					    struct device_node *dn)
>  {
>  	struct nand_chip *chip = &host->chip;
>  	struct mtd_info *mtd = nand_to_mtd(chip);
> @@ -2824,36 +2828,20 @@ static int qcom_nand_host_init(struct qcom_nand_controller *nandc,
>  	chip->block_markbad	= qcom_nandc_block_markbad;
>  
>  	chip->controller = &nandc->controller;
> +	chip->controller->ops = &qcom_nandc_ops;

This assignment should be moved here [1].

Once fixed you can add

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>


[1]https://elixir.bootlin.com/linux/v4.18-rc5/source/drivers/mtd/nand/raw/qcom_nandc.c#L2574

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

* Re: [PATCH v4 31/35] mtd: rawnand: jz4740: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 31/35] mtd: rawnand: jz4740: " Miquel Raynal
@ 2018-07-22  9:29   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  9:29 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:23 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/jz4740_nand.c | 46 ++++++++++++++++++++++++--------------
>  1 file changed, 29 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
> index 9bb8a89e09f9..8f821fdf8a1c 100644
> --- a/drivers/mtd/nand/raw/jz4740_nand.c
> +++ b/drivers/mtd/nand/raw/jz4740_nand.c
> @@ -59,6 +59,7 @@
>  
>  struct jz_nand {
>  	struct nand_chip chip;
> +	struct platform_device *pdev;

You don't need this field. You can just do
to_platform_device(mtd->dev.parent) to get the platform_device.

>  	void __iomem *base;
>  	struct resource *mem;
>  
> @@ -329,8 +330,8 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
>  	writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
>  
>  	if (chipnr == 0) {
> -		/* Detect first chip. */
> -		ret = nand_scan_ident(mtd, 1, NULL);
> +		/* Detect the first chip and register it */
> +		ret = nand_scan(mtd, 1);
>  		if (ret)
>  			goto notfound_id;
>  
> @@ -367,6 +368,25 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
>  	return ret;
>  }
>  
> +static int jz_nand_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct jz_nand *nand = mtd_to_jz_nand(mtd);
> +	struct device *dev = mtd->dev.parent;
> +	struct jz_nand_platform_data *pdata = dev_get_platdata(dev);
> +
> +	if (pdata && pdata->ident_callback) {
> +		pdata->ident_callback(nand->pdev, mtd, &pdata->partitions,
> +				      &pdata->num_partitions);
> +	}

Curly braces are not needed.

> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops jz_nand_controller_ops = {
> +	.attach_chip = jz_nand_attach_chip,
> +};
> +
>  static int jz_nand_probe(struct platform_device *pdev)
>  {
>  	int ret;
> @@ -397,6 +417,7 @@ static int jz_nand_probe(struct platform_device *pdev)
>  	mtd		= nand_to_mtd(chip);
>  	mtd->dev.parent = &pdev->dev;
>  	mtd->name	= "jz4740-nand";
> +	nand->pdev	= pdev;
>  
>  	chip->ecc.hwctl		= jz_nand_hwctl;
>  	chip->ecc.calculate	= jz_nand_calculate_ecc_rs;
> @@ -410,6 +431,7 @@ static int jz_nand_probe(struct platform_device *pdev)
>  	chip->chip_delay = 50;
>  	chip->cmd_ctrl = jz_nand_cmd_ctrl;
>  	chip->select_chip = jz_nand_select_chip;
> +	chip->dummy_controller.ops = &jz_nand_controller_ops;
>  
>  	if (nand->busy_gpio)
>  		chip->dev_ready = jz_nand_dev_ready;
> @@ -450,20 +472,10 @@ static int jz_nand_probe(struct platform_device *pdev)
>  		else
>  			nand->banks[chipnr] = 0;
>  	}
> +
>  	if (chipnr == 0) {
>  		dev_err(&pdev->dev, "No NAND chips found\n");
> -		goto err_iounmap_mmio;
> -	}
> -
> -	if (pdata && pdata->ident_callback) {
> -		pdata->ident_callback(pdev, mtd, &pdata->partitions,
> -					&pdata->num_partitions);
> -	}
> -
> -	ret = nand_scan_tail(mtd);
> -	if (ret) {
> -		dev_err(&pdev->dev,  "Failed to scan NAND\n");
> -		goto err_unclaim_banks;
> +		goto err_nand_release;
>  	}

As for the atmel driver, I'd prefer to have one patch to moves
nand_scan_ident() and nand_scan_tail() in the same function so that the
transition to nand_scan()+attach_chip is easier to review.

>  
>  	ret = mtd_device_register(mtd, pdata ? pdata->partitions : NULL,
> @@ -471,15 +483,13 @@ static int jz_nand_probe(struct platform_device *pdev)
>  
>  	if (ret) {
>  		dev_err(&pdev->dev, "Failed to add mtd device\n");
> -		goto err_nand_release;
> +		goto err_unclaim_banks;
>  	}
>  
>  	dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
>  
>  	return 0;
>  
> -err_nand_release:
> -	nand_release(mtd);
>  err_unclaim_banks:
>  	while (chipnr--) {
>  		unsigned char bank = nand->banks[chipnr];
> @@ -487,6 +497,8 @@ static int jz_nand_probe(struct platform_device *pdev)
>  					 nand->bank_base[bank - 1]);
>  	}
>  	writel(0, nand->base + JZ_REG_NAND_CTRL);
> +err_nand_release:
> +	nand_release(mtd);
>  err_iounmap_mmio:
>  	jz_nand_iounmap_resource(nand->mem, nand->base);
>  err_free:


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

* Re: [PATCH v4 32/35] mtd: rawnand: tegra: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 32/35] mtd: rawnand: tegra: " Miquel Raynal
@ 2018-07-22  9:31   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22  9:31 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:24 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> +	chip = &nand->chip;
> +	chip->controller = &ctrl->controller;
> +	chip->controller->ops = &tegra_nand_controller_ops;

Should be moved next to the controller initialization.


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

* Re: [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore
  2018-07-20 15:15 ` [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore Miquel Raynal
@ 2018-07-22 10:30   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22 10:30 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:25 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Both nand_scan_ident() and nand_scan_tail() helpers used to be called
> directly from controller drivers that needed to tweak some ECC-related
> parameters before nand_scan_tail(). This separation prevented dynamic
> allocations during the phase of NAND identification, which was
> inconvenient.
> 
> All controller drivers have been moved to use nand_scan(), in
> conjunction with the chip->ecc.[attach|detach]_chip() hooks that
> actually do the required tweaking sequence between both ident/tail
> calls, allowing programmers to use dynamic allocation as they need all
> across the scanning sequence.
> 
> Declare nand_scan_[ident|tail]() statically now.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 16 +++++++++-------
>  include/linux/mtd/rawnand.h      |  9 ++-------
>  2 files changed, 11 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index e7f135c100c2..da99232702a4 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5924,7 +5924,7 @@ static int nand_dt_init(struct nand_chip *chip)
>  }
>  
>  /**
> - * nand_scan_ident - [NAND Interface] Scan for the NAND device
> + * nand_scan_ident - Scan for the NAND device
>   * @mtd: MTD device structure
>   * @maxchips: number of chips to scan for, returns immediately if 0
>   * @table: alternative NAND ID table
> @@ -5932,9 +5932,13 @@ static int nand_dt_init(struct nand_chip *chip)
>   * This is the first phase of the normal nand_scan() function. It reads the
>   * flash ID and sets up MTD fields accordingly.
>   *
> + * This helper used to be called directly from controller drivers that needed
> + * to tweak some ECC-related parameters before nand_scan_tail(). This separation
> + * prevented dynamic allocations during this phase which was unconvenient and
> + * as been banned for the benefit of the ->init_ecc()/cleanup_ecc() hooks.
>   */
> -int nand_scan_ident(struct mtd_info *mtd, int maxchips,
> -		    struct nand_flash_dev *table)
> +static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
> +			   struct nand_flash_dev *table)
>  {
>  	int i, nand_maf_id, nand_dev_id;
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> @@ -6016,7 +6020,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  
>  	return 0;
>  }
> -EXPORT_SYMBOL(nand_scan_ident);
>  
>  static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
>  {
> @@ -6393,14 +6396,14 @@ static bool nand_ecc_strength_good(struct mtd_info *mtd)
>  }
>  
>  /**
> - * nand_scan_tail - [NAND Interface] Scan for the NAND device
> + * nand_scan_tail - Scan for the NAND device
>   * @mtd: MTD device structure
>   *
>   * This is the second phase of the normal nand_scan() function. It fills out
>   * all the uninitialized function pointers with the defaults and scans for a
>   * bad block table if appropriate.
>   */
> -int nand_scan_tail(struct mtd_info *mtd)
> +static int nand_scan_tail(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	struct nand_ecc_ctrl *ecc = &chip->ecc;
> @@ -6724,7 +6727,6 @@ int nand_scan_tail(struct mtd_info *mtd)
>  
>  	return ret;
>  }
> -EXPORT_SYMBOL(nand_scan_tail);
>  
>  static int nand_attach(struct nand_chip *chip)
>  {
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index a20c78e25878..a928771a7ae4 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -36,14 +36,9 @@ static inline int nand_scan(struct mtd_info *mtd, int max_chips)
>  }
>  
>  /*
> - * Separate phases of nand_scan(), allowing board driver to intervene
> - * and override command or ECC setup according to flash type.
> + * Unregister the MTD device and free resources held by the NAND device, must be
> + * called on error after a successful nand_scan().

Nope. You're mixing nand_cleanup() and nand_release(). nand_release()
should not be used because it ignores mtd_device_unregister() and might
call nand_cleanup() on an object that is still being exposed to the MTD
layer. Your comment applies to nand_cleanup() though ;-).

>   */
> -int nand_scan_ident(struct mtd_info *mtd, int max_chips,
> -			   struct nand_flash_dev *table);
> -int nand_scan_tail(struct mtd_info *mtd);
> -
> -/* Unregister the MTD device and free resources held by the NAND device */
>  void nand_release(struct mtd_info *mtd);
>  
>  /* Internal helper for board drivers which need to override command function */


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

* Re: [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically
  2018-07-20 15:15 ` [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically Miquel Raynal
@ 2018-07-22 10:32   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22 10:32 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:26 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Thanks to the migration of all drivers to use nand_scan() and the
> related nand_controller_ops, we can now allocate data during the
> detection phase. Let's do it first for the NAND model parameter which
> is allocated in nand_detect().
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

> ---
>  drivers/mtd/nand/raw/nand_base.c | 52 +++++++++++++++++++++++++++++++---------
>  include/linux/mtd/rawnand.h      |  2 +-
>  2 files changed, 42 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index da99232702a4..8645f655e5b0 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5225,8 +5225,11 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>  
>  	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
>  	sanitize_string(p->model, sizeof(p->model));
> -	strncpy(chip->parameters.model, p->model,
> -		sizeof(chip->parameters.model) - 1);
> +	chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
> +	if (!chip->parameters.model) {
> +		ret = -ENOMEM;
> +		goto free_onfi_param_page;
> +	}
>  
>  	mtd->writesize = le32_to_cpu(p->byte_per_page);
>  
> @@ -5356,8 +5359,11 @@ static int nand_flash_detect_jedec(struct nand_chip *chip)
>  
>  	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
>  	sanitize_string(p->model, sizeof(p->model));
> -	strncpy(chip->parameters.model, p->model,
> -		sizeof(chip->parameters.model) - 1);
> +	chip->parameters.model = kstrdup(p->model, GFP_KERNEL);
> +	if (!chip->parameters.model) {
> +		ret = -ENOMEM;
> +		goto free_jedec_param_page;
> +	}
>  
>  	mtd->writesize = le32_to_cpu(p->byte_per_page);
>  
> @@ -5546,8 +5552,9 @@ static bool find_full_id_nand(struct nand_chip *chip,
>  		chip->onfi_timing_mode_default =
>  					type->onfi_timing_mode_default;
>  
> -		strncpy(chip->parameters.model, type->name,
> -			sizeof(chip->parameters.model) - 1);
> +		chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
> +		if (!chip->parameters.model)
> +			return false;
>  
>  		return true;
>  	}
> @@ -5706,8 +5713,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>  	if (!type->name)
>  		return -ENODEV;
>  
> -	strncpy(chip->parameters.model, type->name,
> -		sizeof(chip->parameters.model) - 1);
> +	chip->parameters.model = kstrdup(type->name, GFP_KERNEL);
> +	if (!chip->parameters.model)
> +		return -ENOMEM;
>  
>  	chip->chipsize = (uint64_t)type->chipsize << 20;
>  
> @@ -5737,7 +5745,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>  			mtd->name);
>  		pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8,
>  			(chip->options & NAND_BUSWIDTH_16) ? 16 : 8);
> -		return -EINVAL;
> +		ret = -EINVAL;
> +
> +		goto free_detect_allocation;
>  	}
>  
>  	nand_decode_bbm_options(chip);
> @@ -5774,6 +5784,11 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>  		(int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
>  		mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
>  	return 0;
> +
> +free_detect_allocation:
> +	kfree(chip->parameters.model);
> +
> +	return ret;
>  }
>  
>  static const char * const nand_ecc_modes[] = {
> @@ -6021,6 +6036,11 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  	return 0;
>  }
>  
> +static void nand_scan_ident_cleanup(struct nand_chip *chip)
> +{
> +	kfree(chip->parameters.model);
> +}
> +
>  static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> @@ -6764,11 +6784,18 @@ int nand_scan_with_ids(struct mtd_info *mtd, int maxchips,
>  
>  	ret = nand_attach(chip);
>  	if (ret)
> -		return ret;
> +		goto cleanup_ident;
>  
>  	ret = nand_scan_tail(mtd);
>  	if (ret)
> -		nand_detach(chip);
> +		goto detach_chip;
> +
> +	return 0;
> +
> +detach_chip:
> +	nand_detach(chip);
> +cleanup_ident:
> +	nand_scan_ident_cleanup(chip);
>  
>  	return ret;
>  }
> @@ -6800,6 +6827,9 @@ void nand_cleanup(struct nand_chip *chip)
>  
>  	/* Free controller specific allocations after chip identification */
>  	nand_detach(chip);
> +
> +	/* Free identification phase allocations */
> +	nand_scan_ident_cleanup(chip);
>  }
>  
>  EXPORT_SYMBOL_GPL(nand_cleanup);
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index a928771a7ae4..5723d940a47d 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -482,7 +482,7 @@ struct onfi_params {
>   */
>  struct nand_parameters {
>  	/* Generic parameters */
> -	char model[100];
> +	const char *model;
>  	bool supports_set_get_features;
>  	DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
>  	DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);


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

* Re: [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection
  2018-07-20 15:15 ` [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection Miquel Raynal
@ 2018-07-22 10:35   ` Boris Brezillon
  0 siblings, 0 replies; 85+ messages in thread
From: Boris Brezillon @ 2018-07-22 10:35 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Richard Weinberger,
	David Woodhouse, Brian Norris, Marek Vasut, Nicolas Ferre,
	Alexandre Belloni, Kamal Dasu, Masahiro Yamada, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Fri, 20 Jul 2018 17:15:27 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Now that it is possible to do dynamic allocations during the
> identification phase, convert the onfi_params structure (which is only
> needed with ONFI compliant chips) into a pointer that will be allocated
> only if needed.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c    | 54 +++++++++++++++++++++++--------------
>  drivers/mtd/nand/raw/nand_micron.c  |  6 ++---
>  drivers/mtd/nand/raw/nand_timings.c | 12 ++++-----
>  include/linux/mtd/rawnand.h         |  6 ++---
>  4 files changed, 46 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 8645f655e5b0..ed9e2f1578e6 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -5151,6 +5151,8 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>  {
>  	struct mtd_info *mtd = nand_to_mtd(chip);
>  	struct nand_onfi_params *p;
> +	struct onfi_params *onfi;
> +	int onfi_version = 0;
>  	char id[4];
>  	int i, ret, val;
>  
> @@ -5206,21 +5208,19 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>  	/* Check version */
>  	val = le16_to_cpu(p->revision);
>  	if (val & ONFI_VERSION_2_3)
> -		chip->parameters.onfi.version = 23;
> +		onfi_version = 23;
>  	else if (val & ONFI_VERSION_2_2)
> -		chip->parameters.onfi.version = 22;
> +		onfi_version = 22;
>  	else if (val & ONFI_VERSION_2_1)
> -		chip->parameters.onfi.version = 21;
> +		onfi_version = 21;
>  	else if (val & ONFI_VERSION_2_0)
> -		chip->parameters.onfi.version = 20;
> +		onfi_version = 20;
>  	else if (val & ONFI_VERSION_1_0)
> -		chip->parameters.onfi.version = 10;
> +		onfi_version = 10;
>  
> -	if (!chip->parameters.onfi.version) {
> +	if (!onfi_version) {
>  		pr_info("unsupported ONFI version: %d\n", val);
>  		goto free_onfi_param_page;
> -	} else {
> -		ret = 1;
>  	}
>  
>  	sanitize_string(p->manufacturer, sizeof(p->manufacturer));
> @@ -5257,7 +5257,7 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>  	if (p->ecc_bits != 0xff) {
>  		chip->ecc_strength_ds = p->ecc_bits;
>  		chip->ecc_step_ds = 512;
> -	} else if (chip->parameters.onfi.version >= 21 &&
> +	} else if (onfi_version >= 21 &&
>  		(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
>  
>  		/*
> @@ -5284,19 +5284,33 @@ static int nand_flash_detect_onfi(struct nand_chip *chip)
>  		bitmap_set(chip->parameters.set_feature_list,
>  			   ONFI_FEATURE_ADDR_TIMING_MODE, 1);
>  	}
> -	chip->parameters.onfi.tPROG = le16_to_cpu(p->t_prog);
> -	chip->parameters.onfi.tBERS = le16_to_cpu(p->t_bers);
> -	chip->parameters.onfi.tR = le16_to_cpu(p->t_r);
> -	chip->parameters.onfi.tCCS = le16_to_cpu(p->t_ccs);
> -	chip->parameters.onfi.async_timing_mode =
> -		le16_to_cpu(p->async_timing_mode);
> -	chip->parameters.onfi.vendor_revision =
> -		le16_to_cpu(p->vendor_revision);
> -	memcpy(chip->parameters.onfi.vendor, p->vendor,
> -	       sizeof(p->vendor));
>  
> +	onfi = kzalloc(sizeof(*onfi), GFP_KERNEL);
> +	if (!onfi) {
> +		ret = -ENOMEM;
> +		goto free_model;
> +	}
> +
> +	onfi->version = onfi_version;
> +	onfi->tPROG = le16_to_cpu(p->t_prog);
> +	onfi->tBERS = le16_to_cpu(p->t_bers);
> +	onfi->tR = le16_to_cpu(p->t_r);
> +	onfi->tCCS = le16_to_cpu(p->t_ccs);
> +	onfi->async_timing_mode = le16_to_cpu(p->async_timing_mode);
> +	onfi->vendor_revision = le16_to_cpu(p->vendor_revision);
> +	memcpy(onfi->vendor, p->vendor, sizeof(p->vendor));
> +	chip->parameters.onfi = onfi;
> +
> +	/* Identification done, free the full ONFI parameter page and exit */
> +	kfree(p);
> +
> +	return 1;
> +
> +free_model:
> +	kfree(chip->parameters.model);
>  free_onfi_param_page:
>  	kfree(p);
> +
>  	return ret;
>  }
>  
> @@ -5693,7 +5707,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>  		}
>  	}
>  
> -	chip->parameters.onfi.version = 0;
>  	if (!type->name || !type->pagesize) {
>  		/* Check if the chip is ONFI compliant */
>  		ret = nand_flash_detect_onfi(chip);
> @@ -6039,6 +6052,7 @@ static int nand_scan_ident(struct mtd_info *mtd, int maxchips,
>  static void nand_scan_ident_cleanup(struct nand_chip *chip)
>  {
>  	kfree(chip->parameters.model);
> +	kfree(chip->parameters.onfi);
>  }
>  
>  static int nand_set_ecc_soft_ops(struct mtd_info *mtd)
> diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
> index 656947d91841..8466a1740b3b 100644
> --- a/drivers/mtd/nand/raw/nand_micron.c
> +++ b/drivers/mtd/nand/raw/nand_micron.c
> @@ -88,9 +88,9 @@ static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
>  static int micron_nand_onfi_init(struct nand_chip *chip)
>  {
>  	struct nand_parameters *p = &chip->parameters;
> -	struct nand_onfi_vendor_micron *micron = (void *)p->onfi.vendor;
> +	struct nand_onfi_vendor_micron *micron = (void *)p->onfi->vendor;
>  
> -	if (chip->parameters.onfi.version && p->onfi.vendor_revision) {
> +	if (p->onfi && p->onfi->vendor_revision) {

I think p->onfi != NULL guarantees that p->onfi->vendor_revision != 0.
if (p->onfi) should be enough.

Looks good otherwise.

Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>

>  		chip->read_retries = micron->read_retry_options;
>  		chip->setup_read_retry = micron_nand_setup_read_retry;
>  	}
> @@ -382,7 +382,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
>  	u8 id[5];
>  	int ret;
>  
> -	if (!chip->parameters.onfi.version)
> +	if (!chip->parameters.onfi)
>  		return MICRON_ON_DIE_UNSUPPORTED;
>  
>  	if (chip->bits_per_cell != 1)
> diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
> index 9bb599106a31..ebc7b5f76f77 100644
> --- a/drivers/mtd/nand/raw/nand_timings.c
> +++ b/drivers/mtd/nand/raw/nand_timings.c
> @@ -294,6 +294,7 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  			     int timing_mode)
>  {
>  	struct nand_data_interface *iface = &chip->data_interface;
> +	struct onfi_params *onfi = chip->parameters.onfi;
>  
>  	if (type != NAND_SDR_IFACE)
>  		return -EINVAL;
> @@ -308,17 +309,16 @@ int onfi_fill_data_interface(struct nand_chip *chip,
>  	 * tPROG, tBERS, tR and tCCS.
>  	 * These information are part of the ONFI parameter page.
>  	 */
> -	if (chip->parameters.onfi.version) {
> -		struct nand_parameters *params = &chip->parameters;
> +	if (onfi) {
>  		struct nand_sdr_timings *timings = &iface->timings.sdr;
>  
>  		/* microseconds -> picoseconds */
> -		timings->tPROG_max = 1000000ULL * params->onfi.tPROG;
> -		timings->tBERS_max = 1000000ULL * params->onfi.tBERS;
> -		timings->tR_max = 1000000ULL * params->onfi.tR;
> +		timings->tPROG_max = 1000000ULL * onfi->tPROG;
> +		timings->tBERS_max = 1000000ULL * onfi->tBERS;
> +		timings->tR_max = 1000000ULL * onfi->tR;
>  
>  		/* nanoseconds -> picoseconds */
> -		timings->tCCS_min = 1000UL * params->onfi.tCCS;
> +		timings->tCCS_min = 1000UL * onfi->tCCS;
>  	} else {
>  		struct nand_sdr_timings *timings = &iface->timings.sdr;
>  		/*
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 5723d940a47d..8074cbd4e3fe 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -488,7 +488,7 @@ struct nand_parameters {
>  	DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);
>  
>  	/* ONFI parameters */
> -	struct onfi_params onfi;
> +	struct onfi_params *onfi;
>  };
>  
>  /* The maximum expected count of bytes in the NAND ID sequence */
> @@ -1618,10 +1618,10 @@ struct platform_nand_data {
>  /* return the supported asynchronous timing mode. */
>  static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
>  {
> -	if (!chip->parameters.onfi.version)
> +	if (!chip->parameters.onfi)
>  		return ONFI_TIMING_MODE_UNKNOWN;
>  
> -	return chip->parameters.onfi.async_timing_mode;
> +	return chip->parameters.onfi->async_timing_mode;
>  }
>  
>  int onfi_fill_data_interface(struct nand_chip *chip,


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

* Re: [PATCH v4 25/35] mtd: rawnand: vf610: convert driver to nand_scan()
  2018-07-20 15:15 ` [PATCH v4 25/35] mtd: rawnand: vf610: " Miquel Raynal
  2018-07-21 18:05   ` Boris Brezillon
@ 2018-07-25  8:57   ` Stefan Agner
  1 sibling, 0 replies; 85+ messages in thread
From: Stefan Agner @ 2018-07-25  8:57 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Xiaolei Li, Matthias Brugger, Maxime Ripard, Chen-Yu Tsai,
	Marc Gonzalez, Mans Rullgard, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On 20.07.2018 17:15, Miquel Raynal wrote:
> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().

Reviewed-by: Stefan Agner <stefan@agner.ch>

> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/vf610_nfc.c | 127 ++++++++++++++++++++-------------------
>  1 file changed, 66 insertions(+), 61 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/vf610_nfc.c b/drivers/mtd/nand/raw/vf610_nfc.c
> index d5a22fc96878..6f6dcbf9095b 100644
> --- a/drivers/mtd/nand/raw/vf610_nfc.c
> +++ b/drivers/mtd/nand/raw/vf610_nfc.c
> @@ -747,6 +747,69 @@ static void vf610_nfc_init_controller(struct
> vf610_nfc *nfc)
>  	}
>  }
>  
> +static int vf610_nfc_attach_chip(struct nand_chip *chip)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct vf610_nfc *nfc = mtd_to_nfc(mtd);
> +
> +	vf610_nfc_init_controller(nfc);
> +
> +	/* Bad block options. */
> +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> +		chip->bbt_options |= NAND_BBT_NO_OOB;
> +
> +	/* Single buffer only, max 256 OOB minus ECC status */
> +	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
> +		dev_err(nfc->dev, "Unsupported flash page size\n");
> +		return -ENXIO;
> +	}
> +
> +	if (chip->ecc.mode != NAND_ECC_HW)
> +		return 0;
> +
> +	if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
> +		dev_err(nfc->dev, "Unsupported flash with hwecc\n");
> +		return -ENXIO;
> +	}
> +
> +	if (chip->ecc.size != mtd->writesize) {
> +		dev_err(nfc->dev, "Step size needs to be page size\n");
> +		return -ENXIO;
> +	}
> +
> +	/* Only 64 byte ECC layouts known */
> +	if (mtd->oobsize > 64)
> +		mtd->oobsize = 64;
> +
> +	/* Use default large page ECC layout defined in NAND core */
> +	mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> +	if (chip->ecc.strength == 32) {
> +		nfc->ecc_mode = ECC_60_BYTE;
> +		chip->ecc.bytes = 60;
> +	} else if (chip->ecc.strength == 24) {
> +		nfc->ecc_mode = ECC_45_BYTE;
> +		chip->ecc.bytes = 45;
> +	} else {
> +		dev_err(nfc->dev, "Unsupported ECC strength\n");
> +		return -ENXIO;
> +	}
> +
> +	chip->ecc.read_page = vf610_nfc_read_page;
> +	chip->ecc.write_page = vf610_nfc_write_page;
> +	chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
> +	chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
> +	chip->ecc.read_oob = vf610_nfc_read_oob;
> +	chip->ecc.write_oob = vf610_nfc_write_oob;
> +
> +	chip->ecc.size = PAGE_2K;
> +
> +	return 0;
> +}
> +
> +static const struct nand_controller_ops vf610_nfc_controller_ops = {
> +	.attach_chip = vf610_nfc_attach_chip,
> +};
> +
>  static int vf610_nfc_probe(struct platform_device *pdev)
>  {
>  	struct vf610_nfc *nfc;
> @@ -827,67 +890,9 @@ static int vf610_nfc_probe(struct platform_device *pdev)
>  
>  	vf610_nfc_preinit_controller(nfc);
>  
> -	/* first scan to find the device and get the page size */
> -	err = nand_scan_ident(mtd, 1, NULL);
> -	if (err)
> -		goto err_disable_clk;
> -
> -	vf610_nfc_init_controller(nfc);
> -
> -	/* Bad block options. */
> -	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> -		chip->bbt_options |= NAND_BBT_NO_OOB;
> -
> -	/* Single buffer only, max 256 OOB minus ECC status */
> -	if (mtd->writesize + mtd->oobsize > PAGE_2K + OOB_MAX - 8) {
> -		dev_err(nfc->dev, "Unsupported flash page size\n");
> -		err = -ENXIO;
> -		goto err_disable_clk;
> -	}
> -
> -	if (chip->ecc.mode == NAND_ECC_HW) {
> -		if (mtd->writesize != PAGE_2K && mtd->oobsize < 64) {
> -			dev_err(nfc->dev, "Unsupported flash with hwecc\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		if (chip->ecc.size != mtd->writesize) {
> -			dev_err(nfc->dev, "Step size needs to be page size\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		/* Only 64 byte ECC layouts known */
> -		if (mtd->oobsize > 64)
> -			mtd->oobsize = 64;
> -
> -		/* Use default large page ECC layout defined in NAND core */
> -		mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
> -		if (chip->ecc.strength == 32) {
> -			nfc->ecc_mode = ECC_60_BYTE;
> -			chip->ecc.bytes = 60;
> -		} else if (chip->ecc.strength == 24) {
> -			nfc->ecc_mode = ECC_45_BYTE;
> -			chip->ecc.bytes = 45;
> -		} else {
> -			dev_err(nfc->dev, "Unsupported ECC strength\n");
> -			err = -ENXIO;
> -			goto err_disable_clk;
> -		}
> -
> -		chip->ecc.read_page = vf610_nfc_read_page;
> -		chip->ecc.write_page = vf610_nfc_write_page;
> -		chip->ecc.read_page_raw = vf610_nfc_read_page_raw;
> -		chip->ecc.write_page_raw = vf610_nfc_write_page_raw;
> -		chip->ecc.read_oob = vf610_nfc_read_oob;
> -		chip->ecc.write_oob = vf610_nfc_write_oob;
> -
> -		chip->ecc.size = PAGE_2K;
> -	}
> -
> -	/* second phase scan */
> -	err = nand_scan_tail(mtd);
> +	/* Scan the NAND chip */
> +	chip->dummy_controller.ops = &vf610_nfc_controller_ops;
> +	err = nand_scan(mtd, 1);
>  	if (err)
>  		goto err_disable_clk;

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

* Re: [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-20 15:14 ` [PATCH v4 04/35] mtd: rawnand: denali: convert " Miquel Raynal
  2018-07-21  6:46   ` Boris Brezillon
@ 2018-07-25  9:42   ` Masahiro Yamada
  2018-07-25  9:51     ` Boris Brezillon
  1 sibling, 1 reply; 85+ messages in thread
From: Masahiro Yamada @ 2018-07-25  9:42 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Han Xu,
	Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux, Xiaolei Li,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, Broadcom Kernel Feedback List,
	moderated list:ARM/Mediatek SoC support, linux-mtd,
	Linux Kernel Mailing List, linux-arm-kernel

Hi.


2018-07-21 0:14 GMT+09:00 Miquel Raynal <miquel.raynal@bootlin.com>:
> Two helpers have been added to the core to make ECC-related
> configuration between the detection phase and the final NAND scan. Use
> these hooks and convert the driver to just use nand_scan() instead of
> both nand_scan_ident() and nand_scan_tail().
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/denali.c | 138 +++++++++++++++++++++++-------------------
>  1 file changed, 77 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
> index 4d53f41ada08..2fa92c297a66 100644
> --- a/drivers/mtd/nand/raw/denali.c
> +++ b/drivers/mtd/nand/raw/denali.c
> @@ -1205,62 +1205,12 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
>         return 0;
>  }
>
> -int denali_init(struct denali_nand_info *denali)
> +static int denali_attach_chip(struct nand_chip *chip)
>  {
> -       struct nand_chip *chip = &denali->nand;
>         struct mtd_info *mtd = nand_to_mtd(chip);
> -       u32 features = ioread32(denali->reg + FEATURES);
> +       struct denali_nand_info *denali = mtd_to_denali(mtd);
>         int ret;
>
> -       mtd->dev.parent = denali->dev;
> -       denali_hw_init(denali);
> -
> -       init_completion(&denali->complete);
> -       spin_lock_init(&denali->irq_lock);
> -
> -       denali_clear_irq_all(denali);
> -
> -       ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
> -                              IRQF_SHARED, DENALI_NAND_NAME, denali);
> -       if (ret) {
> -               dev_err(denali->dev, "Unable to request IRQ\n");
> -               return ret;
> -       }
> -
> -       denali_enable_irq(denali);
> -       denali_reset_banks(denali);
> -
> -       denali->active_bank = DENALI_INVALID_BANK;
> -
> -       nand_set_flash_node(chip, denali->dev->of_node);
> -       /* Fallback to the default name if DT did not give "label" property */
> -       if (!mtd->name)
> -               mtd->name = "denali-nand";
> -
> -       chip->select_chip = denali_select_chip;
> -       chip->read_byte = denali_read_byte;
> -       chip->write_byte = denali_write_byte;
> -       chip->read_word = denali_read_word;
> -       chip->cmd_ctrl = denali_cmd_ctrl;
> -       chip->dev_ready = denali_dev_ready;
> -       chip->waitfunc = denali_waitfunc;
> -
> -       if (features & FEATURES__INDEX_ADDR) {
> -               denali->host_read = denali_indexed_read;
> -               denali->host_write = denali_indexed_write;
> -       } else {
> -               denali->host_read = denali_direct_read;
> -               denali->host_write = denali_direct_write;
> -       }
> -
> -       /* clk rate info is needed for setup_data_interface */
> -       if (denali->clk_rate && denali->clk_x_rate)
> -               chip->setup_data_interface = denali_setup_data_interface;
> -
> -       ret = nand_scan_ident(mtd, denali->max_banks, NULL);
> -       if (ret)
> -               goto disable_irq;
> -
>         if (ioread32(denali->reg + FEATURES) & FEATURES__DMA)
>                 denali->dma_avail = 1;
>
> @@ -1293,7 +1243,7 @@ int denali_init(struct denali_nand_info *denali)
>                                    mtd->oobsize - denali->oob_skip_bytes);
>         if (ret) {
>                 dev_err(denali->dev, "Failed to setup ECC settings.\n");
> -               goto disable_irq;
> +               return ret;
>         }
>
>         dev_dbg(denali->dev,
> @@ -1337,7 +1287,7 @@ int denali_init(struct denali_nand_info *denali)
>
>         ret = denali_multidev_fixup(denali);
>         if (ret)
> -               goto disable_irq;
> +               return ret;
>
>         /*
>          * This buffer is DMA-mapped by denali_{read,write}_page_raw.  Do not
> @@ -1345,26 +1295,92 @@ int denali_init(struct denali_nand_info *denali)
>          * guarantee DMA-safe alignment.
>          */
>         denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> -       if (!denali->buf) {
> -               ret = -ENOMEM;
> -               goto disable_irq;
> +       if (!denali->buf)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
> +static void denali_detach_chip(struct nand_chip *chip)
> +{
> +       struct mtd_info *mtd = nand_to_mtd(chip);
> +       struct denali_nand_info *denali = mtd_to_denali(mtd);
> +
> +       kfree(denali->buf);
> +}
> +
> +static const struct nand_controller_ops denali_controller_ops = {
> +       .attach_chip = denali_attach_chip,
> +       .detach_chip = denali_detach_chip,
> +};
> +
> +int denali_init(struct denali_nand_info *denali)
> +{
> +       struct nand_chip *chip = &denali->nand;
> +       struct mtd_info *mtd = nand_to_mtd(chip);
> +       u32 features = ioread32(denali->reg + FEATURES);
> +       int ret;
> +
> +       mtd->dev.parent = denali->dev;
> +       denali_hw_init(denali);
> +
> +       init_completion(&denali->complete);
> +       spin_lock_init(&denali->irq_lock);
> +
> +       denali_clear_irq_all(denali);
> +
> +       ret = devm_request_irq(denali->dev, denali->irq, denali_isr,
> +                              IRQF_SHARED, DENALI_NAND_NAME, denali);
> +       if (ret) {
> +               dev_err(denali->dev, "Unable to request IRQ\n");
> +               return ret;
> +       }
> +
> +       denali_enable_irq(denali);
> +       denali_reset_banks(denali);
> +
> +       denali->active_bank = DENALI_INVALID_BANK;
> +
> +       nand_set_flash_node(chip, denali->dev->of_node);
> +       /* Fallback to the default name if DT did not give "label" property */
> +       if (!mtd->name)
> +               mtd->name = "denali-nand";
> +
> +       chip->select_chip = denali_select_chip;
> +       chip->read_byte = denali_read_byte;
> +       chip->write_byte = denali_write_byte;
> +       chip->read_word = denali_read_word;
> +       chip->cmd_ctrl = denali_cmd_ctrl;
> +       chip->dev_ready = denali_dev_ready;
> +       chip->waitfunc = denali_waitfunc;
> +
> +       if (features & FEATURES__INDEX_ADDR) {
> +               denali->host_read = denali_indexed_read;
> +               denali->host_write = denali_indexed_write;
> +       } else {
> +               denali->host_read = denali_direct_read;
> +               denali->host_write = denali_direct_write;
>         }
>
> -       ret = nand_scan_tail(mtd);
> +       /* clk rate info is needed for setup_data_interface */
> +       if (denali->clk_rate && denali->clk_x_rate)
> +               chip->setup_data_interface = denali_setup_data_interface;
> +
> +       chip->dummy_controller.ops = &denali_controller_ops;
> +       ret = nand_scan(mtd, denali->max_banks);
>         if (ret)
> -               goto free_buf;
> +               goto disable_irq;
>
>         ret = mtd_device_register(mtd, NULL, 0);
>         if (ret) {
>                 dev_err(denali->dev, "Failed to register MTD: %d\n", ret);
>                 goto cleanup_nand;
>         }
> +
>         return 0;
>
>  cleanup_nand:
>         nand_cleanup(chip);
> -free_buf:
> -       kfree(denali->buf);
>  disable_irq:
>         denali_disable_irq(denali);
>
> --
> 2.14.1
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/





You need to remove kfree(denali->buf)
from denali_remove(), right?



void denali_remove(struct denali_nand_info *denali)
{
        struct mtd_info *mtd = nand_to_mtd(&denali->nand);

        nand_release(mtd);
        kfree(denali->buf);       <---- REMOVE !!
        denali_disable_irq(denali);
}




Otherwise, denali_remove() will free denali->buf twice
because kfree(denali->buf) is called from denali_detach_chip().






-- 
Best Regards
Masahiro Yamada

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

* Re: [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-25  9:42   ` Masahiro Yamada
@ 2018-07-25  9:51     ` Boris Brezillon
  2018-07-25 12:47       ` Miquel Raynal
  0 siblings, 1 reply; 85+ messages in thread
From: Boris Brezillon @ 2018-07-25  9:51 UTC (permalink / raw)
  To: Masahiro Yamada
  Cc: Miquel Raynal, Alexandre Belloni, Mans Rullgard, Maxime Ripard,
	Stefan Agner, Linux Kernel Mailing List, linux-mtd, Kamal Dasu,
	Josh Wu, Marc Gonzalez, Marek Vasut, Chen-Yu Tsai,
	Broadcom Kernel Feedback List, Sylvain Lemieux, Wenyou Yang,
	Tudor Ambarus, Vladimir Zapolskiy, Harvey Hunt,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Han Xu, Xiaolei Li, linux-arm-kernel, Nicolas Ferre,
	Richard Weinberger, Brian Norris, David Woodhouse

On Wed, 25 Jul 2018 18:42:44 +0900
Masahiro Yamada <yamada.masahiro@socionext.com> wrote:

> 
> You need to remove kfree(denali->buf)
> from denali_remove(), right?

Absolutely.

> 
> void denali_remove(struct denali_nand_info *denali)
> {
>         struct mtd_info *mtd = nand_to_mtd(&denali->nand);
> 
>         nand_release(mtd);
>         kfree(denali->buf);       <---- REMOVE !!
>         denali_disable_irq(denali);
> }
> 
> 
> Otherwise, denali_remove() will free denali->buf twice
> because kfree(denali->buf) is called from denali_detach_chip().


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

* Re: [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-25  9:51     ` Boris Brezillon
@ 2018-07-25 12:47       ` Miquel Raynal
  2018-07-25 14:16         ` Masahiro Yamada
  0 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-25 12:47 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Masahiro Yamada, Alexandre Belloni, Mans Rullgard, Maxime Ripard,
	Stefan Agner, Linux Kernel Mailing List, linux-mtd, Kamal Dasu,
	Josh Wu, Marc Gonzalez, Marek Vasut, Chen-Yu Tsai,
	Broadcom Kernel Feedback List, Sylvain Lemieux, Wenyou Yang,
	Tudor Ambarus, Vladimir Zapolskiy, Harvey Hunt,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Han Xu, Xiaolei Li, linux-arm-kernel, Nicolas Ferre,
	Richard Weinberger, Brian Norris, David Woodhouse

Hi Boris,

Boris Brezillon <boris.brezillon@bootlin.com> wrote on Wed, 25 Jul 2018
11:51:16 +0200:

> On Wed, 25 Jul 2018 18:42:44 +0900
> Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> 
> > 
> > You need to remove kfree(denali->buf)
> > from denali_remove(), right?  
> 
> Absolutely.
> 
> > 
> > void denali_remove(struct denali_nand_info *denali)
> > {
> >         struct mtd_info *mtd = nand_to_mtd(&denali->nand);
> > 
> >         nand_release(mtd);
> >         kfree(denali->buf);       <---- REMOVE !!
> >         denali_disable_irq(denali);
> > }
> > 
> > 
> > Otherwise, denali_remove() will free denali->buf twice
> > because kfree(denali->buf) is called from denali_detach_chip().  
> 

Absolutely, thanks for reviewing!

I'll apply with this changed.

Miquèl

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

* Re: [PATCH v4 04/35] mtd: rawnand: denali: convert to nand_scan()
  2018-07-25 12:47       ` Miquel Raynal
@ 2018-07-25 14:16         ` Masahiro Yamada
  0 siblings, 0 replies; 85+ messages in thread
From: Masahiro Yamada @ 2018-07-25 14:16 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Boris Brezillon, Alexandre Belloni, Mans Rullgard, Maxime Ripard,
	Stefan Agner, Nicolas Ferre, linux-mtd, Kamal Dasu, Josh Wu,
	Tudor Ambarus, Marek Vasut, Chen-Yu Tsai,
	Broadcom Kernel Feedback List, Sylvain Lemieux, Wenyou Yang,
	Marc Gonzalez, Vladimir Zapolskiy, Harvey Hunt,
	moderated list:ARM/Mediatek SoC support, Matthias Brugger,
	Han Xu, Xiaolei Li, linux-arm-kernel, Linux Kernel Mailing List,
	Richard Weinberger, Brian Norris, David Woodhouse

2018-07-25 21:47 GMT+09:00 Miquel Raynal <miquel.raynal@bootlin.com>:
> Hi Boris,
>
> Boris Brezillon <boris.brezillon@bootlin.com> wrote on Wed, 25 Jul 2018
> 11:51:16 +0200:
>
>> On Wed, 25 Jul 2018 18:42:44 +0900
>> Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>>
>> >
>> > You need to remove kfree(denali->buf)
>> > from denali_remove(), right?
>>
>> Absolutely.
>>
>> >
>> > void denali_remove(struct denali_nand_info *denali)
>> > {
>> >         struct mtd_info *mtd = nand_to_mtd(&denali->nand);
>> >
>> >         nand_release(mtd);
>> >         kfree(denali->buf);       <---- REMOVE !!
>> >         denali_disable_irq(denali);
>> > }
>> >
>> >
>> > Otherwise, denali_remove() will free denali->buf twice
>> > because kfree(denali->buf) is called from denali_detach_chip().
>>
>
> Absolutely, thanks for reviewing!
>
> I'll apply with this changed.
>
> Miquèl


Assuming you will fix this,

Acked-by: Masahiro Yamada <yamada.masahiro@socionext.com>


-- 
Best Regards
Masahiro Yamada

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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-21 17:10   ` Boris Brezillon
@ 2018-07-26  6:06     ` xiaolei li
  2018-07-26  6:14       ` Boris Brezillon
  0 siblings, 1 reply; 85+ messages in thread
From: xiaolei li @ 2018-07-26  6:06 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Miquel Raynal, Wenyou Yang, Josh Wu, Tudor Ambarus,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Sat, 2018-07-21 at 19:10 +0200, Boris Brezillon wrote:
> On Fri, 20 Jul 2018 17:15:06 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Two helpers have been added to the core to make ECC-related
> > configuration between the detection phase and the final NAND scan. Use
> > these hooks and convert the driver to just use nand_scan() instead of
> > both nand_scan_ident() and nand_scan_tail().
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
> >  1 file changed, 44 insertions(+), 31 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> > index 7bc6be3f6ec0..967418f945ea 100644
> > --- a/drivers/mtd/nand/raw/mtk_nand.c
> > +++ b/drivers/mtd/nand/raw/mtk_nand.c
> > @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
> >  	return 0;
> >  }
> >  
> > +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> > +{
> > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > +	struct device *dev = mtd->dev.parent;
> > +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> > +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> > +	int len;
> > +	int ret;
> > +
> > +	if (chip->options & NAND_BUSWIDTH_16) {
> > +		dev_err(dev, "16bits buswidth not supported");
> > +		return -EINVAL;
> > +	}
> > +
> > +	/* store bbt magic in page, cause OOB is not protected */
> > +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> > +		chip->bbt_options |= NAND_BBT_NO_OOB;
> > +
> > +	ret = mtk_nfc_ecc_init(dev, mtd);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> > +	if (ret)
> > +		return ret;
> > +
> > +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> > +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> > +
> > +	len = mtd->writesize + mtd->oobsize;
> > +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > +	if (!nfc->buffer)
> > +		return  -ENOMEM;
> > +
> > +	return 0;
> > +}
> > +
> > +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> > +	.attach_chip = mtk_nfc_attach_chip,
> > +};
> > +
> >  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> >  				  struct device_node *np)
> >  {
> >  	struct mtk_nfc_nand_chip *chip;
> >  	struct nand_chip *nand;
> >  	struct mtd_info *mtd;
> > -	int nsels, len;
> > +	int nsels;
> >  	u32 tmp;
> >  	int ret;
> >  	int i;
> > @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> >  
> >  	nand = &chip->nand;
> >  	nand->controller = &nfc->controller;
> > +	nand->controller->ops = &mtk_nfc_controller_ops;
> 
> Just like for the marvell driver, this assignment should be moved here
> [1]. 
Agree to this.

> Also, it looks like this driver is open-coding
> nand_controller_init(), probably something we should fix (in a separate
> patch).
May I ask if you mean driver should use nand_hw_control_init helper to
do controller_init?

Thanks,
Xiaolei

> 
> With this fixed:
> 
> Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
> 
> >  
> >  	nand_set_flash_node(nand, np);
> >  	nand_set_controller_data(nand, nfc);
> > @@ -1324,36 +1366,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> >  
> >  	mtk_nfc_hw_init(nfc);
> >  
> > -	ret = nand_scan_ident(mtd, nsels, NULL);
> > -	if (ret)
> > -		return ret;
> > -
> > -	/* store bbt magic in page, cause OOB is not protected */
> > -	if (nand->bbt_options & NAND_BBT_USE_FLASH)
> > -		nand->bbt_options |= NAND_BBT_NO_OOB;
> > -
> > -	ret = mtk_nfc_ecc_init(dev, mtd);
> > -	if (ret)
> > -		return -EINVAL;
> > -
> > -	if (nand->options & NAND_BUSWIDTH_16) {
> > -		dev_err(dev, "16bits buswidth not supported");
> > -		return -EINVAL;
> > -	}
> > -
> > -	ret = mtk_nfc_set_spare_per_sector(&chip->spare_per_sector, mtd);
> > -	if (ret)
> > -		return ret;
> > -
> > -	mtk_nfc_set_fdm(&chip->fdm, mtd);
> > -	mtk_nfc_set_bad_mark_ctl(&chip->bad_mark, mtd);
> > -
> > -	len = mtd->writesize + mtd->oobsize;
> > -	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > -	if (!nfc->buffer)
> > -		return  -ENOMEM;
> > -
> > -	ret = nand_scan_tail(mtd);
> > +	ret = nand_scan(mtd, nsels);
> >  	if (ret)
> >  		return ret;
> >  
> 



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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-26  6:06     ` xiaolei li
@ 2018-07-26  6:14       ` Boris Brezillon
  2018-07-26  6:46         ` xiaolei li
  0 siblings, 1 reply; 85+ messages in thread
From: Boris Brezillon @ 2018-07-26  6:14 UTC (permalink / raw)
  To: xiaolei li
  Cc: Miquel Raynal, Wenyou Yang, Josh Wu, Tudor Ambarus,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Thu, 26 Jul 2018 14:06:41 +0800
xiaolei li <xiaolei.li@mediatek.com> wrote:

> On Sat, 2018-07-21 at 19:10 +0200, Boris Brezillon wrote:
> > On Fri, 20 Jul 2018 17:15:06 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > Two helpers have been added to the core to make ECC-related
> > > configuration between the detection phase and the final NAND scan. Use
> > > these hooks and convert the driver to just use nand_scan() instead of
> > > both nand_scan_ident() and nand_scan_tail().
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
> > >  1 file changed, 44 insertions(+), 31 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> > > index 7bc6be3f6ec0..967418f945ea 100644
> > > --- a/drivers/mtd/nand/raw/mtk_nand.c
> > > +++ b/drivers/mtd/nand/raw/mtk_nand.c
> > > @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
> > >  	return 0;
> > >  }
> > >  
> > > +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> > > +{
> > > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > > +	struct device *dev = mtd->dev.parent;
> > > +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> > > +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> > > +	int len;
> > > +	int ret;
> > > +
> > > +	if (chip->options & NAND_BUSWIDTH_16) {
> > > +		dev_err(dev, "16bits buswidth not supported");
> > > +		return -EINVAL;
> > > +	}
> > > +
> > > +	/* store bbt magic in page, cause OOB is not protected */
> > > +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> > > +		chip->bbt_options |= NAND_BBT_NO_OOB;
> > > +
> > > +	ret = mtk_nfc_ecc_init(dev, mtd);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> > > +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> > > +
> > > +	len = mtd->writesize + mtd->oobsize;
> > > +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > > +	if (!nfc->buffer)
> > > +		return  -ENOMEM;
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> > > +	.attach_chip = mtk_nfc_attach_chip,
> > > +};
> > > +
> > >  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > >  				  struct device_node *np)
> > >  {
> > >  	struct mtk_nfc_nand_chip *chip;
> > >  	struct nand_chip *nand;
> > >  	struct mtd_info *mtd;
> > > -	int nsels, len;
> > > +	int nsels;
> > >  	u32 tmp;
> > >  	int ret;
> > >  	int i;
> > > @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > >  
> > >  	nand = &chip->nand;
> > >  	nand->controller = &nfc->controller;
> > > +	nand->controller->ops = &mtk_nfc_controller_ops;  
> > 
> > Just like for the marvell driver, this assignment should be moved here
> > [1].   
> Agree to this.
> 
> > Also, it looks like this driver is open-coding
> > nand_controller_init(), probably something we should fix (in a separate
> > patch).  
> May I ask if you mean driver should use nand_hw_control_init helper to
> do controller_init?

Well, now it's named nand_controller_init(), but yes, that's what I
meant.

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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-26  6:14       ` Boris Brezillon
@ 2018-07-26  6:46         ` xiaolei li
  2018-07-26  6:49           ` Miquel Raynal
  0 siblings, 1 reply; 85+ messages in thread
From: xiaolei li @ 2018-07-26  6:46 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Miquel Raynal, Wenyou Yang, Josh Wu, Tudor Ambarus,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Thu, 2018-07-26 at 08:14 +0200, Boris Brezillon wrote:
> On Thu, 26 Jul 2018 14:06:41 +0800
> xiaolei li <xiaolei.li@mediatek.com> wrote:
> 
> > On Sat, 2018-07-21 at 19:10 +0200, Boris Brezillon wrote:
> > > On Fri, 20 Jul 2018 17:15:06 +0200
> > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >   
> > > > Two helpers have been added to the core to make ECC-related
> > > > configuration between the detection phase and the final NAND scan. Use
> > > > these hooks and convert the driver to just use nand_scan() instead of
> > > > both nand_scan_ident() and nand_scan_tail().
> > > > 
> > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > ---
> > > >  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
> > > >  1 file changed, 44 insertions(+), 31 deletions(-)
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> > > > index 7bc6be3f6ec0..967418f945ea 100644
> > > > --- a/drivers/mtd/nand/raw/mtk_nand.c
> > > > +++ b/drivers/mtd/nand/raw/mtk_nand.c
> > > > @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
> > > >  	return 0;
> > > >  }
> > > >  
> > > > +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> > > > +{
> > > > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > > > +	struct device *dev = mtd->dev.parent;
> > > > +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> > > > +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> > > > +	int len;
> > > > +	int ret;
> > > > +
> > > > +	if (chip->options & NAND_BUSWIDTH_16) {
> > > > +		dev_err(dev, "16bits buswidth not supported");
> > > > +		return -EINVAL;
> > > > +	}
> > > > +
> > > > +	/* store bbt magic in page, cause OOB is not protected */
> > > > +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> > > > +		chip->bbt_options |= NAND_BBT_NO_OOB;
> > > > +
> > > > +	ret = mtk_nfc_ecc_init(dev, mtd);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +
> > > > +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> > > > +	if (ret)
> > > > +		return ret;
> > > > +
> > > > +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> > > > +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> > > > +
> > > > +	len = mtd->writesize + mtd->oobsize;
> > > > +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > > > +	if (!nfc->buffer)
> > > > +		return  -ENOMEM;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> > > > +	.attach_chip = mtk_nfc_attach_chip,
> > > > +};
> > > > +
> > > >  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > >  				  struct device_node *np)
> > > >  {
> > > >  	struct mtk_nfc_nand_chip *chip;
> > > >  	struct nand_chip *nand;
> > > >  	struct mtd_info *mtd;
> > > > -	int nsels, len;
> > > > +	int nsels;
> > > >  	u32 tmp;
> > > >  	int ret;
> > > >  	int i;
> > > > @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > >  
> > > >  	nand = &chip->nand;
> > > >  	nand->controller = &nfc->controller;
> > > > +	nand->controller->ops = &mtk_nfc_controller_ops;  
> > > 
> > > Just like for the marvell driver, this assignment should be moved here
> > > [1].   
> > Agree to this.
> >
>  
> > > Also, it looks like this driver is open-coding
> > > nand_controller_init(), probably something we should fix (in a separate
> > > patch).  
> > May I ask if you mean driver should use nand_hw_control_init helper to
> > do controller_init?
> 
> Well, now it's named nand_controller_init(), but yes, that's what I
> meant.

OK. I will fix it base on this patch series later.
Thanks!



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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-26  6:46         ` xiaolei li
@ 2018-07-26  6:49           ` Miquel Raynal
  2018-07-26  6:53             ` xiaolei li
  0 siblings, 1 reply; 85+ messages in thread
From: Miquel Raynal @ 2018-07-26  6:49 UTC (permalink / raw)
  To: xiaolei li
  Cc: Boris Brezillon, Wenyou Yang, Josh Wu, Tudor Ambarus,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

Hi xiaolei,

xiaolei li <xiaolei.li@mediatek.com> wrote on Thu, 26 Jul 2018 14:46:29
+0800:

> On Thu, 2018-07-26 at 08:14 +0200, Boris Brezillon wrote:
> > On Thu, 26 Jul 2018 14:06:41 +0800
> > xiaolei li <xiaolei.li@mediatek.com> wrote:
> >   
> > > On Sat, 2018-07-21 at 19:10 +0200, Boris Brezillon wrote:  
> > > > On Fri, 20 Jul 2018 17:15:06 +0200
> > > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > > >     
> > > > > Two helpers have been added to the core to make ECC-related
> > > > > configuration between the detection phase and the final NAND scan. Use
> > > > > these hooks and convert the driver to just use nand_scan() instead of
> > > > > both nand_scan_ident() and nand_scan_tail().
> > > > > 
> > > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > > ---
> > > > >  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
> > > > >  1 file changed, 44 insertions(+), 31 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> > > > > index 7bc6be3f6ec0..967418f945ea 100644
> > > > > --- a/drivers/mtd/nand/raw/mtk_nand.c
> > > > > +++ b/drivers/mtd/nand/raw/mtk_nand.c
> > > > > @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
> > > > >  	return 0;
> > > > >  }
> > > > >  
> > > > > +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> > > > > +{
> > > > > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > > > > +	struct device *dev = mtd->dev.parent;
> > > > > +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> > > > > +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> > > > > +	int len;
> > > > > +	int ret;
> > > > > +
> > > > > +	if (chip->options & NAND_BUSWIDTH_16) {
> > > > > +		dev_err(dev, "16bits buswidth not supported");
> > > > > +		return -EINVAL;
> > > > > +	}
> > > > > +
> > > > > +	/* store bbt magic in page, cause OOB is not protected */
> > > > > +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> > > > > +		chip->bbt_options |= NAND_BBT_NO_OOB;
> > > > > +
> > > > > +	ret = mtk_nfc_ecc_init(dev, mtd);
> > > > > +	if (ret)
> > > > > +		return ret;
> > > > > +
> > > > > +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> > > > > +	if (ret)
> > > > > +		return ret;
> > > > > +
> > > > > +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> > > > > +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> > > > > +
> > > > > +	len = mtd->writesize + mtd->oobsize;
> > > > > +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > > > > +	if (!nfc->buffer)
> > > > > +		return  -ENOMEM;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > > > +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> > > > > +	.attach_chip = mtk_nfc_attach_chip,
> > > > > +};
> > > > > +
> > > > >  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > > >  				  struct device_node *np)
> > > > >  {
> > > > >  	struct mtk_nfc_nand_chip *chip;
> > > > >  	struct nand_chip *nand;
> > > > >  	struct mtd_info *mtd;
> > > > > -	int nsels, len;
> > > > > +	int nsels;
> > > > >  	u32 tmp;
> > > > >  	int ret;
> > > > >  	int i;
> > > > > @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > > >  
> > > > >  	nand = &chip->nand;
> > > > >  	nand->controller = &nfc->controller;
> > > > > +	nand->controller->ops = &mtk_nfc_controller_ops;    
> > > > 
> > > > Just like for the marvell driver, this assignment should be moved here
> > > > [1].     
> > > Agree to this.
> > >  
> >    
> > > > Also, it looks like this driver is open-coding
> > > > nand_controller_init(), probably something we should fix (in a separate
> > > > patch).    
> > > May I ask if you mean driver should use nand_hw_control_init helper to
> > > do controller_init?  
> > 
> > Well, now it's named nand_controller_init(), but yes, that's what I
> > meant.  
> 
> OK. I will fix it base on this patch series later.

Nice!

Then you can just wait for the next -rc1, this series should be
available.

Thanks,
Miquèl

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

* Re: [PATCH v4 14/35] mtd: rawnand: mtk: convert driver to nand_scan()
  2018-07-26  6:49           ` Miquel Raynal
@ 2018-07-26  6:53             ` xiaolei li
  0 siblings, 0 replies; 85+ messages in thread
From: xiaolei li @ 2018-07-26  6:53 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Boris Brezillon, Wenyou Yang, Josh Wu, Tudor Ambarus,
	Richard Weinberger, David Woodhouse, Brian Norris, Marek Vasut,
	Nicolas Ferre, Alexandre Belloni, Kamal Dasu, Masahiro Yamada,
	Han Xu, Harvey Hunt, Vladimir Zapolskiy, Sylvain Lemieux,
	Matthias Brugger, Maxime Ripard, Chen-Yu Tsai, Marc Gonzalez,
	Mans Rullgard, Stefan Agner, linux-mtd, linux-arm-kernel,
	linux-kernel, bcm-kernel-feedback-list, linux-mediatek

On Thu, 2018-07-26 at 08:49 +0200, Miquel Raynal wrote:
> Hi xiaolei,
> 
> xiaolei li <xiaolei.li@mediatek.com> wrote on Thu, 26 Jul 2018 14:46:29
> +0800:
> 
> > On Thu, 2018-07-26 at 08:14 +0200, Boris Brezillon wrote:
> > > On Thu, 26 Jul 2018 14:06:41 +0800
> > > xiaolei li <xiaolei.li@mediatek.com> wrote:
> > >   
> > > > On Sat, 2018-07-21 at 19:10 +0200, Boris Brezillon wrote:  
> > > > > On Fri, 20 Jul 2018 17:15:06 +0200
> > > > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > > > >     
> > > > > > Two helpers have been added to the core to make ECC-related
> > > > > > configuration between the detection phase and the final NAND scan. Use
> > > > > > these hooks and convert the driver to just use nand_scan() instead of
> > > > > > both nand_scan_ident() and nand_scan_tail().
> > > > > > 
> > > > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > > > ---
> > > > > >  drivers/mtd/nand/raw/mtk_nand.c | 75 ++++++++++++++++++++++++-----------------
> > > > > >  1 file changed, 44 insertions(+), 31 deletions(-)
> > > > > > 
> > > > > > diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
> > > > > > index 7bc6be3f6ec0..967418f945ea 100644
> > > > > > --- a/drivers/mtd/nand/raw/mtk_nand.c
> > > > > > +++ b/drivers/mtd/nand/raw/mtk_nand.c
> > > > > > @@ -1250,13 +1250,54 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
> > > > > >  	return 0;
> > > > > >  }
> > > > > >  
> > > > > > +static int mtk_nfc_attach_chip(struct nand_chip *chip)
> > > > > > +{
> > > > > > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > > > > > +	struct device *dev = mtd->dev.parent;
> > > > > > +	struct mtk_nfc *nfc = nand_get_controller_data(chip);
> > > > > > +	struct mtk_nfc_nand_chip *mtk_nand = to_mtk_nand(chip);
> > > > > > +	int len;
> > > > > > +	int ret;
> > > > > > +
> > > > > > +	if (chip->options & NAND_BUSWIDTH_16) {
> > > > > > +		dev_err(dev, "16bits buswidth not supported");
> > > > > > +		return -EINVAL;
> > > > > > +	}
> > > > > > +
> > > > > > +	/* store bbt magic in page, cause OOB is not protected */
> > > > > > +	if (chip->bbt_options & NAND_BBT_USE_FLASH)
> > > > > > +		chip->bbt_options |= NAND_BBT_NO_OOB;
> > > > > > +
> > > > > > +	ret = mtk_nfc_ecc_init(dev, mtd);
> > > > > > +	if (ret)
> > > > > > +		return ret;
> > > > > > +
> > > > > > +	ret = mtk_nfc_set_spare_per_sector(&mtk_nand->spare_per_sector, mtd);
> > > > > > +	if (ret)
> > > > > > +		return ret;
> > > > > > +
> > > > > > +	mtk_nfc_set_fdm(&mtk_nand->fdm, mtd);
> > > > > > +	mtk_nfc_set_bad_mark_ctl(&mtk_nand->bad_mark, mtd);
> > > > > > +
> > > > > > +	len = mtd->writesize + mtd->oobsize;
> > > > > > +	nfc->buffer = devm_kzalloc(dev, len, GFP_KERNEL);
> > > > > > +	if (!nfc->buffer)
> > > > > > +		return  -ENOMEM;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > > > +static const struct nand_controller_ops mtk_nfc_controller_ops = {
> > > > > > +	.attach_chip = mtk_nfc_attach_chip,
> > > > > > +};
> > > > > > +
> > > > > >  static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > > > >  				  struct device_node *np)
> > > > > >  {
> > > > > >  	struct mtk_nfc_nand_chip *chip;
> > > > > >  	struct nand_chip *nand;
> > > > > >  	struct mtd_info *mtd;
> > > > > > -	int nsels, len;
> > > > > > +	int nsels;
> > > > > >  	u32 tmp;
> > > > > >  	int ret;
> > > > > >  	int i;
> > > > > > @@ -1287,6 +1328,7 @@ static int mtk_nfc_nand_chip_init(struct device *dev, struct mtk_nfc *nfc,
> > > > > >  
> > > > > >  	nand = &chip->nand;
> > > > > >  	nand->controller = &nfc->controller;
> > > > > > +	nand->controller->ops = &mtk_nfc_controller_ops;    
> > > > > 
> > > > > Just like for the marvell driver, this assignment should be moved here
> > > > > [1].     
> > > > Agree to this.
> > > >  
> > >    
> > > > > Also, it looks like this driver is open-coding
> > > > > nand_controller_init(), probably something we should fix (in a separate
> > > > > patch).    
> > > > May I ask if you mean driver should use nand_hw_control_init helper to
> > > > do controller_init?  
> > > 
> > > Well, now it's named nand_controller_init(), but yes, that's what I
> > > meant.  
> > 
> > OK. I will fix it base on this patch series later.
> 
> Nice!
> 
> Then you can just wait for the next -rc1, this series should be
> available.
> 
OK. Thanks for your improvement!

Assuming ->controller->ops assignment will be fixed,

Acked-by: Xiaolei Li <xiaolei.li@mediatek.com>

> Thanks,
> Miquèl



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

* Re: [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
  2018-07-22  6:44   ` Boris Brezillon
@ 2018-07-26 19:06     ` Boris Brezillon
  2018-07-26 23:13       ` Miquel Raynal
  0 siblings, 1 reply; 85+ messages in thread
From: Boris Brezillon @ 2018-07-26 19:06 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Alexandre Belloni, Mans Rullgard, Maxime Ripard, Stefan Agner,
	linux-kernel, Masahiro Yamada, linux-mtd, Kamal Dasu, Josh Wu,
	Marc Gonzalez, Marek Vasut, Chen-Yu Tsai,
	bcm-kernel-feedback-list, Sylvain Lemieux, Wenyou Yang,
	Tudor Ambarus, Vladimir Zapolskiy, Harvey Hunt, linux-mediatek,
	Matthias Brugger, Han Xu, Xiaolei Li, linux-arm-kernel,
	Nicolas Ferre, Richard Weinberger, Brian Norris, David Woodhouse

On Sun, 22 Jul 2018 08:44:32 +0200
Boris Brezillon <boris.brezillon@bootlin.com> wrote:

> On Fri, 20 Jul 2018 17:15:19 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Two helpers have been added to the core to make ECC-related
> > configuration between the detection phase and the final NAND scan. Use
> > these hooks and convert the driver to just use nand_scan_with_ids()
> > (alternative to nand_scan() for passing a flash IDs table) instead of
> > both nand_scan_ident() and nand_scan_tail().
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>  
> 
> Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
> 
> > ---
> >  drivers/mtd/nand/raw/sm_common.c | 39 +++++++++++++++++++++++++--------------
> >  1 file changed, 25 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
> > index 7f5044a79f01..d05e3f976a5e 100644
> > --- a/drivers/mtd/nand/raw/sm_common.c
> > +++ b/drivers/mtd/nand/raw/sm_common.c
> > @@ -160,19 +160,9 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
> >  	{NULL}
> >  };
> >  
> > -int sm_register_device(struct mtd_info *mtd, int smartmedia)
> > +static int sm_attach_chip(struct nand_chip *chip)
> >  {
> > -	struct nand_chip *chip = mtd_to_nand(mtd);
> > -	int ret;
> > -
> > -	chip->options |= NAND_SKIP_BBTSCAN;
> > -
> > -	/* Scan for card properties */
> > -	ret = nand_scan_ident(mtd, 1, smartmedia ?
> > -		nand_smartmedia_flash_ids : nand_xd_flash_ids);
> > -
> > -	if (ret)
> > -		return ret;
> > +	struct mtd_info *mtd = nand_to_mtd(chip);
> >  
> >  	/* Bad block marker position */
> >  	chip->badblockpos = 0x05;
> > @@ -187,12 +177,33 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia)
> >  	else
> >  		return -ENODEV;
> >  
> > -	ret = nand_scan_tail(mtd);
> > +	return 0;
> > +}
> >  
> > +static const struct nand_controller_ops sm_controller_ops = {
> > +	.attach_chip = sm_attach_chip,
> > +};
> > +
> > +int sm_register_device(struct mtd_info *mtd, int smartmedia)
> > +{
> > +	struct nand_chip *chip = mtd_to_nand(mtd);
> > +	struct nand_flash_dev *flash_ids;
> > +	int ret;
> > +
> > +	chip->options |= NAND_SKIP_BBTSCAN;
> > +
> > +	/* Scan for card properties */
> > +	chip->dummy_controller.ops = &sm_controller_ops;
> > +	flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids;
> > +	ret = nand_scan_with_ids(mtd, 1, flash_ids);
> >  	if (ret)
> >  		return ret;
> >  
> > -	return mtd_device_register(mtd, NULL, 0);
> > +	ret = mtd_device_register(mtd, NULL, 0);
> > +	if (ret)
> > +		nand_release(mtd);

Didn't notice that while reviewing, but it would have been better to
use nand_cleanup() and do this change separately.

> > +
> > +	return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(sm_register_device);
> >    
> 
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/


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

* Re: [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
  2018-07-26 19:06     ` Boris Brezillon
@ 2018-07-26 23:13       ` Miquel Raynal
  0 siblings, 0 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-26 23:13 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Alexandre Belloni, Mans Rullgard, Maxime Ripard, Stefan Agner,
	linux-kernel, Masahiro Yamada, linux-mtd, Kamal Dasu, Josh Wu,
	Marc Gonzalez, Marek Vasut, Chen-Yu Tsai,
	bcm-kernel-feedback-list, Sylvain Lemieux, Wenyou Yang,
	Tudor Ambarus, Vladimir Zapolskiy, Harvey Hunt, linux-mediatek,
	Matthias Brugger, Han Xu, Xiaolei Li, linux-arm-kernel,
	Nicolas Ferre, Richard Weinberger, Brian Norris, David Woodhouse

Hi Boris,

Boris Brezillon <boris.brezillon@bootlin.com> wrote on Thu, 26 Jul 2018
21:06:55 +0200:

> On Sun, 22 Jul 2018 08:44:32 +0200
> Boris Brezillon <boris.brezillon@bootlin.com> wrote:
> 
> > On Fri, 20 Jul 2018 17:15:19 +0200
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > Two helpers have been added to the core to make ECC-related
> > > configuration between the detection phase and the final NAND scan. Use
> > > these hooks and convert the driver to just use nand_scan_with_ids()
> > > (alternative to nand_scan() for passing a flash IDs table) instead of
> > > both nand_scan_ident() and nand_scan_tail().
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>    
> > 
> > Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com>
> >   
> > > ---
> > >  drivers/mtd/nand/raw/sm_common.c | 39 +++++++++++++++++++++++++--------------
> > >  1 file changed, 25 insertions(+), 14 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/sm_common.c b/drivers/mtd/nand/raw/sm_common.c
> > > index 7f5044a79f01..d05e3f976a5e 100644
> > > --- a/drivers/mtd/nand/raw/sm_common.c
> > > +++ b/drivers/mtd/nand/raw/sm_common.c
> > > @@ -160,19 +160,9 @@ static struct nand_flash_dev nand_xd_flash_ids[] = {
> > >  	{NULL}
> > >  };
> > >  
> > > -int sm_register_device(struct mtd_info *mtd, int smartmedia)
> > > +static int sm_attach_chip(struct nand_chip *chip)
> > >  {
> > > -	struct nand_chip *chip = mtd_to_nand(mtd);
> > > -	int ret;
> > > -
> > > -	chip->options |= NAND_SKIP_BBTSCAN;
> > > -
> > > -	/* Scan for card properties */
> > > -	ret = nand_scan_ident(mtd, 1, smartmedia ?
> > > -		nand_smartmedia_flash_ids : nand_xd_flash_ids);
> > > -
> > > -	if (ret)
> > > -		return ret;
> > > +	struct mtd_info *mtd = nand_to_mtd(chip);
> > >  
> > >  	/* Bad block marker position */
> > >  	chip->badblockpos = 0x05;
> > > @@ -187,12 +177,33 @@ int sm_register_device(struct mtd_info *mtd, int smartmedia)
> > >  	else
> > >  		return -ENODEV;
> > >  
> > > -	ret = nand_scan_tail(mtd);
> > > +	return 0;
> > > +}
> > >  
> > > +static const struct nand_controller_ops sm_controller_ops = {
> > > +	.attach_chip = sm_attach_chip,
> > > +};
> > > +
> > > +int sm_register_device(struct mtd_info *mtd, int smartmedia)
> > > +{
> > > +	struct nand_chip *chip = mtd_to_nand(mtd);
> > > +	struct nand_flash_dev *flash_ids;
> > > +	int ret;
> > > +
> > > +	chip->options |= NAND_SKIP_BBTSCAN;
> > > +
> > > +	/* Scan for card properties */
> > > +	chip->dummy_controller.ops = &sm_controller_ops;
> > > +	flash_ids = smartmedia ? nand_smartmedia_flash_ids : nand_xd_flash_ids;
> > > +	ret = nand_scan_with_ids(mtd, 1, flash_ids);
> > >  	if (ret)
> > >  		return ret;
> > >  
> > > -	return mtd_device_register(mtd, NULL, 0);
> > > +	ret = mtd_device_register(mtd, NULL, 0);
> > > +	if (ret)
> > > +		nand_release(mtd);  
> 
> Didn't notice that while reviewing, but it would have been better to
> use nand_cleanup() and do this change separately.

Indeed, will fix it.

Miquèl

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

* Re: [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase
  2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
                   ` (34 preceding siblings ...)
  2018-07-20 15:15 ` [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection Miquel Raynal
@ 2018-07-26 23:34 ` Miquel Raynal
  35 siblings, 0 replies; 85+ messages in thread
From: Miquel Raynal @ 2018-07-26 23:34 UTC (permalink / raw)
  To: Wenyou Yang, Josh Wu, Tudor Ambarus, Boris Brezillon,
	Miquel Raynal, Richard Weinberger, David Woodhouse, Brian Norris,
	Marek Vasut, Nicolas Ferre, Alexandre Belloni, Kamal Dasu,
	Masahiro Yamada, Han Xu, Harvey Hunt, Vladimir Zapolskiy,
	Sylvain Lemieux, Xiaolei Li, Matthias Brugger, Maxime Ripard,
	Chen-Yu Tsai, Marc Gonzalez, Mans Rullgard, Stefan Agner
  Cc: linux-mtd, linux-arm-kernel, linux-kernel,
	bcm-kernel-feedback-list, linux-mediatek


Miquel Raynal <miquel.raynal@bootlin.com> wrote on Fri, 20 Jul 2018
17:14:52 +0200:

> Hello,
> 
> This series make a quite deep change in the NAND framework. Until now,
> the NAND chip identification phase could be done in two manners from the
> controller driver perspective:
> 
> 1/ Call nand_scan()
> 
>   or
> 
> 1/ Call nand_scan_ident()
> 2/ Do some controller-dependent configuration
> 3/ Call nand_scan_tail().
> 
> The fact that the identifaction could be split in two operations
> involved that in the NAND framework, it was not possible to do any
> dynamic allocation without risking a memory leak. What if the core
> allocates a structure, then the driver between nand_scan_ident() and
> nand_scan_tail() decides it cannot handle the chip and errors out?
> The structure allocated by the core is lost: it is a memory leak. One
> solution could have been to add a nand_scan_ident_cleanup() function,
> but that would mean patching all the drivers anyway to make them call
> this function when something fails between nand_scan_ident() and
> nand_scan_tail().
> 
> To avoid this situation, we migrate all drivers to use nand_scan() in
> conjuction with the recently added hooks ->attach_chip() and
> ->detach_chip() that are part of the nand_controller structure  
> operations. Drivers that need to tweak their configuration after
> nand_scan_ident() should implement it. Any dynamically allocated space
> in ->attach_chip() must be freed in the second hook: ->detach_chip().
> 
> The ->detach_chip() does not have to be called upon error in the
> controller driver probe function. The nand_cleanup() helper already
> exists for that and will do the call if needed. Of course, this helper
> must be called on error after a successful nand_scan(), just like
> before.
> 
> Once all drivers not using nand_scan() are migrated, nand_scan_ident()
> and nand_scan_tail() are unexported and only available internally.
> 
> A previous work [1] removed the ONFI/JEDEC parameter pages and instead
> allocated a nand_parameters structure in nand_chip, embedding both
> generic entries and ONFI-related ones. The deal was, once dynamic
> allocation possible, allocate in nand_scan_ident() the ONFI strcuture
> only if actually needed. This is done in the last patches.
> 
> This series applies on top of nand/next.
> 
> Thank you,
> Miquèl
> 
> [1] http://lists.infradead.org/pipermail/linux-mtd/2018-March/079456.html
> 
> Changes since v3:
> =================
> * Constified all the nand_controller_ops structure definitions.
> * Fixed a build issue in fsl_elbc.
> * Added a patch in the core to prevent executing nand_scan_ident if
>   maxchips is NULL.
> * Fixed the regression around the model name.
> * Used kstrdup to allocate the model.
> * The migration from char model[] to const char *model is done in a
>   separate patch.
> 
> Changes since v2:
> =================
> * Rebased on top of nand/next.
> * Adapted all drivers to declare statically a nand_controller_ops
>   structure and assign it in the probe().
> * Added the migration of the tegra_nand.c driver.
> * Moved brcmnand controller ops affectation in the probe().
> 
> Changes since v1:
> =================
> * Rebased on top of nand/next.
> * Light rewording of the cover letter about the possibility to have a
>   nand_scan_ident_cleanup() function (just as example of how this series
>   could have been done differently).
> * Changed the hooks to reside in the nand_hw_ctrl structure instead of
>   being part of nand_ecc_ctrl as these hooks are more
>   controller-related.
> 
> 
> Miquel Raynal (35):
>   mtd: rawnand: brcmnand: convert driver to nand_scan()
>   mtd: rawnand: cafe: convert driver to nand_scan()
>   mtd: rawnand: davinci: convert driver to nand_scan()
>   mtd: rawnand: denali: convert to nand_scan()
>   mtd: rawnand: fsl_elbc: convert driver to nand_scan()
>   mtd: rawnand: fsl_ifc: convert driver to nand_scan()
>   mtd: rawnand: fsmc: convert driver to nand_scan()
>   mtd: rawnand: gpmi: convert driver to nand_scan()
>   mtd: rawnand: hisi504: convert driver to nand_scan()
>   mtd: rawnand: jz4780: convert driver to nand_scan()
>   mtd: rawnand: lpc32xx_mlc: convert driver to nand_scan()
>   mtd: rawnand: lpc32xx_slc: convert driver to nand_scan()
>   mtd: rawnand: marvell: convert driver to nand_scan()
>   mtd: rawnand: mtk: convert driver to nand_scan()
>   mtd: rawnand: mxc: convert driver to nand_scan()
>   mtd: rawnand: nandsim: convert driver to nand_scan()
>   mtd: rawnand: omap2: convert driver to nand_scan()
>   mtd: rawnand: s3c2410: convert driver to nand_scan()
>   mtd: rawnand: sh_flctl: move all NAND chip related setup in one
>     function
>   mtd: rawnand: sh_flctl: convert driver to nand_scan()
>   mtd: rawnand: sunxi: convert driver to nand_scan()
>   mtd: rawnand: tango: convert driver to nand_scan()
>   mtd: rawnand: txx9ndfmc: rename nand controller internal structure
>   mtd: rawnand: txx9ndfmc: convert driver to nand_scan()
>   mtd: rawnand: vf610: convert driver to nand_scan()
>   mtd: rawnand: atmel: convert driver to nand_scan()
>   mtd: rawnand: sm_common: convert driver to nand_scan_with_ids()
>   mtd: rawnand: allow exiting immediately nand_scan_ident()
>   mtd: rawnand: docg4: convert driver to nand_scan()
>   mtd: rawnand: qcom: convert driver to nand_scan()
>   mtd: rawnand: jz4740: convert driver to nand_scan()
>   mtd: rawnand: tegra: convert driver to nand_scan()
>   mtd: rawnand: do not export nand_scan_[ident|tail]() anymore
>   mtd: rawnand: allocate model parameter dynamically
>   mtd: rawnand: allocate dynamically ONFI parameters during detection
> 
>  drivers/mtd/nand/raw/atmel/nand-controller.c |  83 ++---
>  drivers/mtd/nand/raw/brcmnand/brcmnand.c     |  47 ++-
>  drivers/mtd/nand/raw/cafe_nand.c             | 130 ++++---
>  drivers/mtd/nand/raw/davinci_nand.c          | 195 +++++-----
>  drivers/mtd/nand/raw/denali.c                | 138 +++----
>  drivers/mtd/nand/raw/docg4.c                 |  55 +--
>  drivers/mtd/nand/raw/fsl_elbc_nand.c         |  19 +-
>  drivers/mtd/nand/raw/fsl_ifc_nand.c          |  19 +-
>  drivers/mtd/nand/raw/fsmc_nand.c             | 148 ++++----
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  56 +--
>  drivers/mtd/nand/raw/hisi504_nand.c          |  78 ++--
>  drivers/mtd/nand/raw/jz4740_nand.c           |  46 ++-
>  drivers/mtd/nand/raw/jz4780_nand.c           |  34 +-
>  drivers/mtd/nand/raw/lpc32xx_mlc.c           | 109 +++---
>  drivers/mtd/nand/raw/lpc32xx_slc.c           |  77 ++--
>  drivers/mtd/nand/raw/marvell_nand.c          | 205 ++++++-----
>  drivers/mtd/nand/raw/mtk_nand.c              |  75 ++--
>  drivers/mtd/nand/raw/mxc_nand.c              | 136 +++----
>  drivers/mtd/nand/raw/nand_base.c             | 132 +++++--
>  drivers/mtd/nand/raw/nand_micron.c           |   6 +-
>  drivers/mtd/nand/raw/nand_timings.c          |  12 +-
>  drivers/mtd/nand/raw/nandsim.c               |  82 +++--
>  drivers/mtd/nand/raw/omap2.c                 | 521 +++++++++++++--------------
>  drivers/mtd/nand/raw/qcom_nandc.c            |  71 ++--
>  drivers/mtd/nand/raw/s3c2410.c               |  30 +-
>  drivers/mtd/nand/raw/sh_flctl.c              |  57 ++-
>  drivers/mtd/nand/raw/sm_common.c             |  39 +-
>  drivers/mtd/nand/raw/sunxi_nand.c            |  43 +--
>  drivers/mtd/nand/raw/tango_nand.c            |  40 +-
>  drivers/mtd/nand/raw/tegra_nand.c            | 162 +++++----
>  drivers/mtd/nand/raw/txx9ndfmc.c             |  35 +-
>  drivers/mtd/nand/raw/vf610_nfc.c             | 127 +++----
>  include/linux/mtd/rawnand.h                  |  17 +-
>  include/linux/mtd/sh_flctl.h                 |   1 +
>  34 files changed, 1612 insertions(+), 1413 deletions(-)
> 

After doing the requested modifications applied to nand/next:
- 3-10, 12-16, 18-22, 25, 27, 30 from v4
- then the rest from v5.

Thanks,
Miquèl

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

end of thread, other threads:[~2018-07-26 23:34 UTC | newest]

Thread overview: 85+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-20 15:14 [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal
2018-07-20 15:14 ` [PATCH v4 01/35] mtd: rawnand: brcmnand: convert driver to nand_scan() Miquel Raynal
2018-07-21  6:23   ` Boris Brezillon
2018-07-20 15:14 ` [PATCH v4 02/35] mtd: rawnand: cafe: " Miquel Raynal
2018-07-21  6:35   ` Boris Brezillon
2018-07-20 15:14 ` [PATCH v4 03/35] mtd: rawnand: davinci: " Miquel Raynal
2018-07-21  6:44   ` Boris Brezillon
2018-07-20 15:14 ` [PATCH v4 04/35] mtd: rawnand: denali: convert " Miquel Raynal
2018-07-21  6:46   ` Boris Brezillon
2018-07-25  9:42   ` Masahiro Yamada
2018-07-25  9:51     ` Boris Brezillon
2018-07-25 12:47       ` Miquel Raynal
2018-07-25 14:16         ` Masahiro Yamada
2018-07-20 15:14 ` [PATCH v4 05/35] mtd: rawnand: fsl_elbc: convert driver " Miquel Raynal
2018-07-21  6:50   ` Boris Brezillon
2018-07-20 15:14 ` [PATCH v4 06/35] mtd: rawnand: fsl_ifc: " Miquel Raynal
2018-07-21  6:53   ` Boris Brezillon
2018-07-20 15:14 ` [PATCH v4 07/35] mtd: rawnand: fsmc: " Miquel Raynal
2018-07-21  6:55   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 08/35] mtd: rawnand: gpmi: " Miquel Raynal
2018-07-21  6:56   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 09/35] mtd: rawnand: hisi504: " Miquel Raynal
2018-07-21  6:59   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 10/35] mtd: rawnand: jz4780: " Miquel Raynal
2018-07-21 15:23   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 11/35] mtd: rawnand: lpc32xx_mlc: " Miquel Raynal
2018-07-21 15:26   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 12/35] mtd: rawnand: lpc32xx_slc: " Miquel Raynal
2018-07-21 15:27   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 13/35] mtd: rawnand: marvell: " Miquel Raynal
2018-07-21 16:57   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 14/35] mtd: rawnand: mtk: " Miquel Raynal
2018-07-21 17:10   ` Boris Brezillon
2018-07-26  6:06     ` xiaolei li
2018-07-26  6:14       ` Boris Brezillon
2018-07-26  6:46         ` xiaolei li
2018-07-26  6:49           ` Miquel Raynal
2018-07-26  6:53             ` xiaolei li
2018-07-20 15:15 ` [PATCH v4 15/35] mtd: rawnand: mxc: " Miquel Raynal
2018-07-21 17:19   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 16/35] mtd: rawnand: nandsim: " Miquel Raynal
2018-07-21 17:21   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 17/35] mtd: rawnand: omap2: " Miquel Raynal
2018-07-21 17:34   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 18/35] mtd: rawnand: s3c2410: " Miquel Raynal
2018-07-21 17:38   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 19/35] mtd: rawnand: sh_flctl: move all NAND chip related setup in one function Miquel Raynal
2018-07-21 17:48   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 20/35] mtd: rawnand: sh_flctl: convert driver to nand_scan() Miquel Raynal
2018-07-21 17:49   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 21/35] mtd: rawnand: sunxi: " Miquel Raynal
2018-07-21 17:50   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 22/35] mtd: rawnand: tango: " Miquel Raynal
2018-07-21 17:52   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 23/35] mtd: rawnand: txx9ndfmc: rename nand controller internal structure Miquel Raynal
2018-07-21 17:53   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 24/35] mtd: rawnand: txx9ndfmc: convert driver to nand_scan() Miquel Raynal
2018-07-21 17:54   ` Boris Brezillon
2018-07-21 18:04   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 25/35] mtd: rawnand: vf610: " Miquel Raynal
2018-07-21 18:05   ` Boris Brezillon
2018-07-25  8:57   ` Stefan Agner
2018-07-20 15:15 ` [PATCH v4 26/35] mtd: rawnand: atmel: " Miquel Raynal
2018-07-22  6:40   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 27/35] mtd: rawnand: sm_common: convert driver to nand_scan_with_ids() Miquel Raynal
2018-07-22  6:44   ` Boris Brezillon
2018-07-26 19:06     ` Boris Brezillon
2018-07-26 23:13       ` Miquel Raynal
2018-07-20 15:15 ` [PATCH v4 28/35] mtd: rawnand: allow exiting immediately nand_scan_ident() Miquel Raynal
2018-07-22  8:49   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 29/35] mtd: rawnand: docg4: convert driver to nand_scan() Miquel Raynal
2018-07-22  8:52   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 30/35] mtd: rawnand: qcom: " Miquel Raynal
2018-07-22  8:59   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 31/35] mtd: rawnand: jz4740: " Miquel Raynal
2018-07-22  9:29   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 32/35] mtd: rawnand: tegra: " Miquel Raynal
2018-07-22  9:31   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 33/35] mtd: rawnand: do not export nand_scan_[ident|tail]() anymore Miquel Raynal
2018-07-22 10:30   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 34/35] mtd: rawnand: allocate model parameter dynamically Miquel Raynal
2018-07-22 10:32   ` Boris Brezillon
2018-07-20 15:15 ` [PATCH v4 35/35] mtd: rawnand: allocate dynamically ONFI parameters during detection Miquel Raynal
2018-07-22 10:35   ` Boris Brezillon
2018-07-26 23:34 ` [PATCH v4 00/35] Allow dynamic allocations during NAND chip identification phase Miquel Raynal

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