linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/36] Introduce the generic ECC engine abstraction
@ 2019-03-04 22:28 Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
                   ` (35 more replies)
  0 siblings, 36 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

As of today, only raw NAND controllers used to feature an integrated
ECC engine and so controller drivers always embedded some code to
enable/disable the correction.

This statement is no longer correct as SPI-NAND devices might not
embed an on-die ECC engine and must make use of an external ECC
engine. We figured there are three possible situations for (generic)
NAND device: either the engine is 'on-die' (most of the SPI-NANDs, a
few raw NANDs), or the engine is part of the host controller (most raw
NANDs), or the engine may be external (SPI controllers might feature
an ECC engine, or there are still the possibility to use software
correction).


To solve this situation, this is a proposal on how to make things
work. We want to create an ECC engine object which has simple
callbacks:
* init/cleanup its context
* prepare an I/O operation
* finish an I/O operation
Details about what is going to happen in these callbacks is described
in drivers/mtd/nand/ecc/engine.c.

The logic in this series is:
1/ Use the generic NAND core for all NAND devices (raw and SPI).
2/ Create the ECC engine interface in drivers/mtd/nand/ecc/
3/ Move code in driver/mtd/nand/ecc.
4/ Make both software engines (Hamming and BCH) generic, move them in
   the ecc/ directory, clean them a bit and instantiate ECC
   engines. Write raw NAND helpers to use these two new engines.
5/ Isolate SPI-NAND on-die ECC engine in its own driver.
6/ Make use from the SPI-NAND layer of all the ECC engines listed
   above (on user request, people can now make use of soft BCH if they
   don't have an ECC-engine).

This work is still WIP, I expect a few 0-day regressions, maybe the
naming is not perfect but it gives an idea of what I would like to
introduce. The next steps are:
1/ Migrate the raw NAND core to make a proper use of these ECC
   engines.
2/ Deprecate in the raw NAND subsystem the interfaces used until now
   (I expect we should get rid of a lot of boilerplate).
3/ Introduce an external hardware ECC engine driver.


Thanks,
Miquèl

Changes in v2
=============
* SPDX license identifiers for soft BCH and Hamming: the license macro
  was right, "GPL" means "GPLv2 or higher", so do not change this
  portion. Also update the commit messages to fit the actual change.
* Do not compile-in the NAND core by default, do it only for raw
  NAND. Remove the dependencies on CONFIG_MTD in a different
  patch. Also, keep an extra level of hierarchy in Kconfig for the
  NAND bits by adding a menu instead of a config.
* Moved the standard OOB layouts in the ecc/engine.c driver instead of
  in the NAND core.
* Used the nand_ecc_ prefix in most of the engines functions instead
  of just ecc_, which is now reserved for bare helpers. Get rid of the
  __ecc prefix.
* In the sunxi NAND controller driver: moved the ECC structure from
  sunxi_nfc to sunxi_nand_chip as the ECC engine is per-chip and not
  per controller.
* Software Hamming ECC engine is only enabled by default if raw NAND
  is also enabled. NDFC now selects the software Hamming ECC engine
  (instead of depending on it).
* Mention in software BCH and Hamming Kconfig entries that booting
  from NAND is very likely to fail if the user selects these symbols
  as modules.
* Added Boris Reviewed-by tag on the SPI-NAND typo fixing patch.
* Renamed the "mode" into a "provider" entry in the ECC configuration
  structures.
* Moved the "total" entry of the ECC configuration directly in the
  context structure (should probably not be public but let's keep it
  as is for now).
* Split the generic ECC engine introduction into smaller patches to do
  some renaming aside.
* Drop the "maximize" entry in the ECC engine configuration structure,
  keep using a flag like before.
* Canceled the move of the SPI-NAND specific ECC engine out of the
  core file.
* Amended the root ECC structures to have three nand_ecc_conf
  structures: one for the defaults, one for the chip requirements, one
  for the user desires.
* Created a *ondie_engine pointer in the nand_ecc structure to save
  the on-die ECC engine, if any. For instance, saving a reference to
  this engine is done by the SPI-NAND core.
* Dropped the SPI-NAND flag that was used to distinguish between NAND
  flavors from the NAND core, it should not be needed anymore.
* Added an helper in the NAND core to put a reference on an ECC
  engine. This will be used by the hardware engines only.
* Renamed the files ecc/sw-{bch,hamming}.c and their headers
  include/linux/mtd/nand-ecc-sw-{bch,hamming}-engine.h.
* Created a MTD_NAND_ECC invisible Kconfig symbol.
* Added plenty of missing EXPORT_SYMBOL{,_GPL}().
* Minor modifications so that everything still compiles even when
  modules and built-in drivers are mixed in Kconfig in the whole NAND
  directory.


Miquel Raynal (36):
  mtd: nand: Move nand_device forward declaration to the top
  mtd: nand: Add an extra level in the Kconfig hierarchy
  mtd: nand: Drop useless 'depends on' in Kconfig
  mtd: rawnand: Use the NAND core
  mtd: nand: Add a NAND page I/O request type
  mtd: nand: Rename a core structure
  mtd: rawnand: Avoid a typedef
  mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones
  mtd: rawnand: Clarify the values for invalid ECC mode/algo
  mtd: nand: Introduce the ECC engine abstraction
  mtd: Fix typo in mtd_ooblayout_set_databytes() description
  mtd: nand: Move standard OOB layouts to the generic ECC core
  mtd: nand: Move ECC specific functions to ecc/engine.c
  mtd: nand: ecc: Move BCH code into the ecc/ directory
  mtd: nand: ecc: Use SPDX license identifier for the software BCH code
  mtd: nand: ecc: Turn the software BCH implementation generic
  mtd: rawnand: Get rid of chip->ecc.priv
  mtd: nand: ecc: Move Hamming code into the ecc/ directory
  mtd: nand: ecc: Use SPDX license identifier for the software Hamming
    code
  mtd: nand: ecc: Clarify the software Hamming introductory line
  mtd: nand: ecc: Turn the software Hamming implementation generic
  mtd: nand: Remove useless include about software Hamming ECC
  mtd: nand: ecc: Let the software BCH ECC engine be a module
  mtd: nand: ecc: Let the software Hamming ECC engine be unselected
  mtd: nand: ecc: Create the software BCH engine instance
  mtd: nand: ecc: Create the software Hamming engine instance
  mtd: nand: Let software ECC engines be retrieved from the NAND core
  mtd: spinand: Fix typo in comment
  mtd: spinand: Move ECC related definitions earlier in the driver
  mtd: spinand: Instantiate a SPI-NAND on-die ECC engine
  mtd: nand: Let on-die ECC engines be retrieved from the NAND core
  mtd: rawnand: Fill a default ECC provider/algorithm
  mtd: spinand: Fill a default ECC provider/algorithm
  mtd: nand: Add helpers to manage ECC engines and configurations
  mtd: spinand: Use the external ECC engine logic
  mtd: spinand: Propagate ECC information to the MTD structure

 arch/arm/mach-s3c24xx/common-smdk.c           |   1 -
 arch/arm/mach-s3c24xx/mach-anubis.c           |   1 -
 arch/arm/mach-s3c24xx/mach-at2440evb.c        |   1 -
 arch/arm/mach-s3c24xx/mach-bast.c             |   1 -
 arch/arm/mach-s3c24xx/mach-gta02.c            |   1 -
 arch/arm/mach-s3c24xx/mach-jive.c             |   1 -
 arch/arm/mach-s3c24xx/mach-mini2440.c         |   1 -
 arch/arm/mach-s3c24xx/mach-osiris.c           |   1 -
 arch/arm/mach-s3c24xx/mach-qt2410.c           |   1 -
 arch/arm/mach-s3c24xx/mach-rx3715.c           |   1 -
 arch/arm/mach-s3c24xx/mach-vstms.c            |   1 -
 drivers/mtd/mtdcore.c                         |   2 +-
 drivers/mtd/nand/Kconfig                      |   5 +
 drivers/mtd/nand/Makefile                     |   1 +
 drivers/mtd/nand/core.c                       | 124 ++++
 drivers/mtd/nand/ecc/Kconfig                  |  41 ++
 drivers/mtd/nand/ecc/Makefile                 |   5 +
 drivers/mtd/nand/ecc/engine.c                 | 481 +++++++++++++++
 drivers/mtd/nand/ecc/sw-bch.c                 | 424 ++++++++++++++
 .../nand/{raw/nand_ecc.c => ecc/sw-hamming.c} | 347 ++++++++---
 drivers/mtd/nand/onenand/Kconfig              |   1 -
 drivers/mtd/nand/raw/Kconfig                  |  26 +-
 drivers/mtd/nand/raw/Makefile                 |   2 -
 drivers/mtd/nand/raw/atmel/nand-controller.c  |  12 +-
 drivers/mtd/nand/raw/cs553x_nand.c            |   3 +-
 drivers/mtd/nand/raw/denali.c                 |   3 +
 drivers/mtd/nand/raw/denali_pci.c             |   1 -
 drivers/mtd/nand/raw/fsl_elbc_nand.c          |   1 -
 drivers/mtd/nand/raw/fsl_ifc_nand.c           |   1 -
 drivers/mtd/nand/raw/fsl_upm.c                |   1 -
 drivers/mtd/nand/raw/fsmc_nand.c              |   3 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c    |  12 +-
 drivers/mtd/nand/raw/lpc32xx_mlc.c            |   1 -
 drivers/mtd/nand/raw/lpc32xx_slc.c            |   3 +-
 drivers/mtd/nand/raw/marvell_nand.c           |   7 +-
 drivers/mtd/nand/raw/mtk_nand.c               |   4 +-
 drivers/mtd/nand/raw/nand_base.c              | 551 ++++++------------
 drivers/mtd/nand/raw/nand_bch.c               | 232 --------
 drivers/mtd/nand/raw/nand_esmt.c              |  11 +-
 drivers/mtd/nand/raw/nand_hynix.c             |  41 +-
 drivers/mtd/nand/raw/nand_jedec.c             |   4 +-
 drivers/mtd/nand/raw/nand_micron.c            |  14 +-
 drivers/mtd/nand/raw/nand_onfi.c              |   8 +-
 drivers/mtd/nand/raw/nand_samsung.c           |  19 +-
 drivers/mtd/nand/raw/nand_toshiba.c           |  13 +-
 drivers/mtd/nand/raw/nandsim.c                |   3 +-
 drivers/mtd/nand/raw/ndfc.c                   |   3 +-
 drivers/mtd/nand/raw/omap2.c                  |  32 +-
 drivers/mtd/nand/raw/pasemi_nand.c            |   1 -
 drivers/mtd/nand/raw/s3c2410.c                |   1 -
 drivers/mtd/nand/raw/sharpsl.c                |   3 +-
 drivers/mtd/nand/raw/sunxi_nand.c             |  38 +-
 drivers/mtd/nand/raw/tegra_nand.c             |  12 +-
 drivers/mtd/nand/raw/tmio_nand.c              |   7 +-
 drivers/mtd/nand/raw/txx9ndfmc.c              |   5 +-
 drivers/mtd/nand/spi/Kconfig                  |   1 +
 drivers/mtd/nand/spi/core.c                   | 301 ++++++----
 drivers/mtd/nand/spi/macronix.c               |   6 +-
 drivers/mtd/nand/spi/on-die-ecc-engine.c      |   0
 drivers/mtd/nand/spi/toshiba.c                |   6 +-
 drivers/mtd/sm_ftl.c                          |  30 +-
 drivers/mtd/tests/mtd_nandecctest.c           |  31 +-
 include/linux/mtd/nand-ecc-sw-bch.h           |  80 +++
 include/linux/mtd/nand-ecc-sw-hamming.h       |  99 ++++
 include/linux/mtd/nand.h                      | 150 ++++-
 include/linux/mtd/nand_bch.h                  |  69 ---
 include/linux/mtd/nand_ecc.h                  |  42 --
 include/linux/mtd/rawnand.h                   |  42 +-
 include/linux/mtd/sharpsl.h                   |   1 -
 include/linux/mtd/spinand.h                   |  13 +-
 include/linux/platform_data/mtd-davinci.h     |   2 +-
 .../linux/platform_data/mtd-nand-s3c2410.h    |   2 +-
 72 files changed, 2240 insertions(+), 1155 deletions(-)
 create mode 100644 drivers/mtd/nand/ecc/Kconfig
 create mode 100644 drivers/mtd/nand/ecc/Makefile
 create mode 100644 drivers/mtd/nand/ecc/engine.c
 create mode 100644 drivers/mtd/nand/ecc/sw-bch.c
 rename drivers/mtd/nand/{raw/nand_ecc.c => ecc/sw-hamming.c} (59%)
 delete mode 100644 drivers/mtd/nand/raw/nand_bch.c
 create mode 100644 drivers/mtd/nand/spi/on-die-ecc-engine.c
 create mode 100644 include/linux/mtd/nand-ecc-sw-bch.h
 create mode 100644 include/linux/mtd/nand-ecc-sw-hamming.h
 delete mode 100644 include/linux/mtd/nand_bch.h
 delete mode 100644 include/linux/mtd/nand_ecc.h

-- 
2.19.1


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

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

* [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:12   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy Miquel Raynal
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

This structure might be used earlier in this file, let's move the
forward declaration at the top.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/mtd/nand.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index cebc38b6d6f5..30f0fb02abe2 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -12,6 +12,8 @@
 
 #include <linux/mtd/mtd.h>
 
+struct nand_device;
+
 /**
  * struct nand_memory_organization - Memory organization structure
  * @bits_per_cell: number of bits per NAND cell
@@ -133,8 +135,6 @@ struct nand_bbt {
 	unsigned long *cache;
 };
 
-struct nand_device;
-
 /**
  * struct nand_ops - NAND operations
  * @erase: erase a specific block. No need to check if the block is bad before
-- 
2.19.1


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

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

* [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:13   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig Miquel Raynal
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Use an extra level in Kconfig for all NAND related entries.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/Kconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 495751ed3fd7..d2ef8b89568e 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -1,6 +1,10 @@
+menu "NAND"
+
 config MTD_NAND_CORE
 	tristate
 
 source "drivers/mtd/nand/onenand/Kconfig"
 source "drivers/mtd/nand/raw/Kconfig"
 source "drivers/mtd/nand/spi/Kconfig"
+
+endmenu
-- 
2.19.1


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

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

* [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:15   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 04/36] mtd: rawnand: Use the NAND core Miquel Raynal
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Both oneNAND and raw NAND bits can be compiled if MTD is enabled
because of the if/endif logic in drivers/mtd/Kconfig. There is no need
for an extra "depends on MTD" in their respective Kconfig files.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/onenand/Kconfig | 1 -
 drivers/mtd/nand/raw/Kconfig     | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/mtd/nand/onenand/Kconfig b/drivers/mtd/nand/onenand/Kconfig
index 9dc15748947b..c168f3b4b296 100644
--- a/drivers/mtd/nand/onenand/Kconfig
+++ b/drivers/mtd/nand/onenand/Kconfig
@@ -1,6 +1,5 @@
 menuconfig MTD_ONENAND
 	tristate "OneNAND Device Support"
-	depends on MTD
 	depends on HAS_IOMEM
 	help
 	  This enables support for accessing all type of OneNAND flash
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 510a6b32820d..ebb8a3da9fa5 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -11,7 +11,6 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
 
 menuconfig MTD_RAW_NAND
 	tristate "Raw/Parallel NAND Device Support"
-	depends on MTD
 	select MTD_NAND_ECC_SW_HAMMING
 	help
 	  This enables support for accessing all type of raw/parallel
-- 
2.19.1


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

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

* [PATCH v2 04/36] mtd: rawnand: Use the NAND core
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (2 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:21   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type Miquel Raynal
                   ` (31 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Before introducing the generic ECC engine abstraction, we need to be
sure that raw NAND and SPI-NAND speak the same language: let's use the
generic NAND layer with the raw NAND part (the SPI-NAND one already
uses it).

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index ebb8a3da9fa5..952dc50a8634 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -11,6 +11,7 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
 
 menuconfig MTD_RAW_NAND
 	tristate "Raw/Parallel NAND Device Support"
+	select MTD_NAND_CORE
 	select MTD_NAND_ECC_SW_HAMMING
 	help
 	  This enables support for accessing all type of raw/parallel
-- 
2.19.1


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

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

* [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (3 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 04/36] mtd: rawnand: Use the NAND core Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:23   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 06/36] mtd: nand: Rename a core structure Miquel Raynal
                   ` (30 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Use an enum to differentiate the type of I/O (reading or writing a
page). Also update the request iterator.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/core.c |  4 ++--
 include/linux/mtd/nand.h    | 13 +++++++++++--
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index ed5e340dff51..9ee192585854 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -558,7 +558,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 
 	mutex_lock(&spinand->lock);
 
-	nanddev_io_for_each_page(nand, from, ops, &iter) {
+	nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) {
 		ret = spinand_select_target(spinand, iter.req.pos.target);
 		if (ret)
 			break;
@@ -606,7 +606,7 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to,
 
 	mutex_lock(&spinand->lock);
 
-	nanddev_io_for_each_page(nand, to, ops, &iter) {
+	nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, &iter) {
 		ret = spinand_select_target(spinand, iter.req.pos.target);
 		if (ret)
 			break;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 30f0fb02abe2..84ab76f34c74 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -82,8 +82,14 @@ struct nand_pos {
 	unsigned int page;
 };
 
+enum nand_page_io_req_type {
+	NAND_PAGE_READ = 0,
+	NAND_PAGE_WRITE,
+};
+
 /**
  * struct nand_page_io_req - NAND I/O request object
+ * @type: the type of page I/O: read or write
  * @pos: the position this I/O request is targeting
  * @dataoffs: the offset within the page
  * @datalen: number of data bytes to read from/write to this page
@@ -99,6 +105,7 @@ struct nand_pos {
  * specific commands/operations.
  */
 struct nand_page_io_req {
+	enum nand_page_io_req_type type;
 	struct nand_pos pos;
 	unsigned int dataoffs;
 	unsigned int datalen;
@@ -624,11 +631,13 @@ static inline void nanddev_pos_next_page(struct nand_device *nand,
  * layer.
  */
 static inline void nanddev_io_iter_init(struct nand_device *nand,
+					enum nand_page_io_req_type reqtype,
 					loff_t offs, struct mtd_oob_ops *req,
 					struct nand_io_iter *iter)
 {
 	struct mtd_info *mtd = nanddev_to_mtd(nand);
 
+	iter->req.type = reqtype;
 	iter->req.mode = req->mode;
 	iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
 	iter->req.ooboffs = req->ooboffs;
@@ -698,8 +707,8 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand,
  *
  * Should be used for iterate over pages that are contained in an MTD request.
  */
-#define nanddev_io_for_each_page(nand, start, req, iter)		\
-	for (nanddev_io_iter_init(nand, start, req, iter);		\
+#define nanddev_io_for_each_page(nand, type, start, req, iter)		\
+	for (nanddev_io_iter_init(nand, type, start, req, iter);	\
 	     !nanddev_io_iter_end(nand, iter);				\
 	     nanddev_io_iter_next_page(nand, iter))
 
-- 
2.19.1


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

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

* [PATCH v2 06/36] mtd: nand: Rename a core structure
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (4 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:30   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 07/36] mtd: rawnand: Avoid a typedef Miquel Raynal
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Prepare the migration to a generic ECC engine by renaming the
nand_ecc_req structure into nand_ecc_conf. This structure will be the
base of a wider 'nand_ecc' structure.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/mtd/nand.h    | 8 ++++----
 include/linux/mtd/spinand.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 84ab76f34c74..78cf905083c9 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -123,11 +123,11 @@ struct nand_page_io_req {
 };
 
 /**
- * struct nand_ecc_req - NAND ECC requirements
+ * struct nand_ecc_conf - NAND ECC configuration
  * @strength: ECC strength
- * @step_size: ECC step/block size
+ * @step_size: Number of bytes per step
  */
-struct nand_ecc_req {
+struct nand_ecc_conf {
 	unsigned int strength;
 	unsigned int step_size;
 };
@@ -186,7 +186,7 @@ struct nand_ops {
 struct nand_device {
 	struct mtd_info mtd;
 	struct nand_memory_organization memorg;
-	struct nand_ecc_req eccreq;
+	struct nand_ecc_conf eccreq;
 	struct nand_row_converter rowconv;
 	struct nand_bbt bbt;
 	const struct nand_ops *ops;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index b92e2aa955b6..3008de54f958 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -263,7 +263,7 @@ struct spinand_info {
 	u8 devid;
 	u32 flags;
 	struct nand_memory_organization memorg;
-	struct nand_ecc_req eccreq;
+	struct nand_ecc_conf eccreq;
 	struct spinand_ecc_info eccinfo;
 	struct {
 		const struct spinand_op_variants *read_cache;
-- 
2.19.1


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

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

* [PATCH v2 07/36] mtd: rawnand: Avoid a typedef
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (5 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 06/36] mtd: nand: Rename a core structure Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:55   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 08/36] mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones Miquel Raynal
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

In new code, the use of typedef is discouraged. Before moving this
section out of the raw NAND base, let's switch the nand_ecc_modes_t
type into a regular nand_ecc_mode enumeration.

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

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index e14f02a01efd..05174c6a3099 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4881,8 +4881,8 @@ static int of_get_nand_ecc_mode(struct device_node *np)
 
 	/*
 	 * For backward compatibility we support few obsoleted values that don't
-	 * have their mappings into nand_ecc_modes_t anymore (they were merged
-	 * with other enums).
+	 * have their mappings into the nand_ecc_mode enum anymore (they were
+	 * merged with other enums).
 	 */
 	if (!strcasecmp(pm, "soft_bch"))
 		return NAND_ECC_SOFT;
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 14748183508b..c5bf6bb49329 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -87,14 +87,14 @@ struct nand_chip;
 /*
  * Constants for ECC_MODES
  */
-typedef enum {
+enum nand_ecc_mode {
 	NAND_ECC_NONE,
 	NAND_ECC_SOFT,
 	NAND_ECC_HW,
 	NAND_ECC_HW_SYNDROME,
 	NAND_ECC_HW_OOB_FIRST,
 	NAND_ECC_ON_DIE,
-} nand_ecc_modes_t;
+};
 
 enum nand_ecc_algo {
 	NAND_ECC_UNKNOWN,
@@ -340,7 +340,7 @@ static const struct nand_ecc_caps __name = {			\
  * @write_oob:	function to write chip OOB data
  */
 struct nand_ecc_ctrl {
-	nand_ecc_modes_t mode;
+	enum nand_ecc_mode mode;
 	enum nand_ecc_algo algo;
 	int steps;
 	int size;
diff --git a/include/linux/platform_data/mtd-davinci.h b/include/linux/platform_data/mtd-davinci.h
index 1bbfa27cccb4..e7457be12b8f 100644
--- a/include/linux/platform_data/mtd-davinci.h
+++ b/include/linux/platform_data/mtd-davinci.h
@@ -81,7 +81,7 @@ struct davinci_nand_pdata {		/* platform_data */
 	 * Newer ones also support 4-bit ECC, but are awkward
 	 * using it with large page chips.
 	 */
-	nand_ecc_modes_t	ecc_mode;
+	enum nand_ecc_mode	ecc_mode;
 	u8			ecc_bits;
 
 	/* e.g. NAND_BUSWIDTH_16 */
diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
index f8c553f92655..ff6501c51244 100644
--- a/include/linux/platform_data/mtd-nand-s3c2410.h
+++ b/include/linux/platform_data/mtd-nand-s3c2410.h
@@ -52,7 +52,7 @@ struct s3c2410_platform_nand {
 
 	unsigned int	ignore_unset_ecc:1;
 
-	nand_ecc_modes_t	ecc_mode;
+	enum nand_ecc_mode	ecc_mode;
 
 	int			nr_sets;
 	struct s3c2410_nand_set *sets;
-- 
2.19.1


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

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

* [PATCH v2 08/36] mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (6 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 07/36] mtd: rawnand: Avoid a typedef Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo Miquel Raynal
                   ` (27 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

NAND ECC modes (or providers) have their own enumeration but, unlike
their algorithms counterpart, there is no invalid or uninitialized
value to discriminate between an error and having chosen a no-ECC
situation. Add an "invalid" entry for this purpose.

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

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 05174c6a3099..f4e85e56a041 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4875,7 +4875,7 @@ static int of_get_nand_ecc_mode(struct device_node *np)
 	if (err < 0)
 		return err;
 
-	for (i = 0; i < ARRAY_SIZE(nand_ecc_modes); i++)
+	for (i = NAND_ECC_NONE; i < ARRAY_SIZE(nand_ecc_modes); i++)
 		if (!strcasecmp(pm, nand_ecc_modes[i]))
 			return i;
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index c5bf6bb49329..d25e0c07b0ad 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -88,6 +88,7 @@ struct nand_chip;
  * Constants for ECC_MODES
  */
 enum nand_ecc_mode {
+	NAND_ECC_INVALID,
 	NAND_ECC_NONE,
 	NAND_ECC_SOFT,
 	NAND_ECC_HW,
-- 
2.19.1


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

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

* [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (7 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 08/36] mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:57   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction Miquel Raynal
                   ` (26 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

In the nand_ecc_{mode,algo} enumerations, clarify the fact that the
value 0 will be used for invalid/uninitialized data.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/mtd/rawnand.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index d25e0c07b0ad..95b0c7114701 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -88,7 +88,7 @@ struct nand_chip;
  * Constants for ECC_MODES
  */
 enum nand_ecc_mode {
-	NAND_ECC_INVALID,
+	NAND_ECC_INVALID = 0,
 	NAND_ECC_NONE,
 	NAND_ECC_SOFT,
 	NAND_ECC_HW,
@@ -98,7 +98,7 @@ enum nand_ecc_mode {
 };
 
 enum nand_ecc_algo {
-	NAND_ECC_UNKNOWN,
+	NAND_ECC_UNKNOWN = 0,
 	NAND_ECC_HAMMING,
 	NAND_ECC_BCH,
 	NAND_ECC_RS,
-- 
2.19.1


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

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

* [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (8 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 12:10   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description Miquel Raynal
                   ` (25 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Create a generic ECC engine object.

Later the ecc/engine.c file will receive more generic code coming from
the raw NAND specific part. This is a base to instantiate ECC engine
objects.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/Kconfig                     |   1 +
 drivers/mtd/nand/Makefile                    |   1 +
 drivers/mtd/nand/ecc/Kconfig                 |   6 +
 drivers/mtd/nand/ecc/Makefile                |   3 +
 drivers/mtd/nand/ecc/engine.c                | 138 +++++++++++++++++++
 drivers/mtd/nand/raw/atmel/nand-controller.c |   9 +-
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  12 +-
 drivers/mtd/nand/raw/marvell_nand.c          |   7 +-
 drivers/mtd/nand/raw/mtk_nand.c              |   4 +-
 drivers/mtd/nand/raw/nand_base.c             |  17 +--
 drivers/mtd/nand/raw/nand_esmt.c             |  11 +-
 drivers/mtd/nand/raw/nand_hynix.c            |  41 +++---
 drivers/mtd/nand/raw/nand_jedec.c            |   4 +-
 drivers/mtd/nand/raw/nand_micron.c           |  14 +-
 drivers/mtd/nand/raw/nand_onfi.c             |   8 +-
 drivers/mtd/nand/raw/nand_samsung.c          |  19 +--
 drivers/mtd/nand/raw/nand_toshiba.c          |  11 +-
 drivers/mtd/nand/raw/sunxi_nand.c            |   5 +-
 drivers/mtd/nand/raw/tegra_nand.c            |   9 +-
 drivers/mtd/nand/spi/core.c                  |   4 +-
 drivers/mtd/nand/spi/macronix.c              |   6 +-
 drivers/mtd/nand/spi/toshiba.c               |   6 +-
 include/linux/mtd/nand.h                     |  82 ++++++++++-
 include/linux/mtd/spinand.h                  |   2 +-
 24 files changed, 327 insertions(+), 93 deletions(-)
 create mode 100644 drivers/mtd/nand/ecc/Kconfig
 create mode 100644 drivers/mtd/nand/ecc/Makefile
 create mode 100644 drivers/mtd/nand/ecc/engine.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index d2ef8b89568e..75d0bd18b818 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -6,5 +6,6 @@ config MTD_NAND_CORE
 source "drivers/mtd/nand/onenand/Kconfig"
 source "drivers/mtd/nand/raw/Kconfig"
 source "drivers/mtd/nand/spi/Kconfig"
+source "drivers/mtd/nand/ecc/Kconfig"
 
 endmenu
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 7ecd80c0a66e..9772e781534d 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
 obj-y	+= onenand/
 obj-y	+= raw/
 obj-y	+= spi/
+obj-y	+= ecc/
diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
new file mode 100644
index 000000000000..01439f66ecbf
--- /dev/null
+++ b/drivers/mtd/nand/ecc/Kconfig
@@ -0,0 +1,6 @@
+menu "ECC engine support"
+
+config MTD_NAND_ECC
+	tristate
+
+endmenu
diff --git a/drivers/mtd/nand/ecc/Makefile b/drivers/mtd/nand/ecc/Makefile
new file mode 100644
index 000000000000..c7367f834d81
--- /dev/null
+++ b/drivers/mtd/nand/ecc/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_MTD_NAND_ECC)		+= engine.o
diff --git a/drivers/mtd/nand/ecc/engine.c b/drivers/mtd/nand/ecc/engine.c
new file mode 100644
index 000000000000..4c7943ddf2cc
--- /dev/null
+++ b/drivers/mtd/nand/ecc/engine.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Generic Error-Correcting Code (ECC) engine
+ *
+ * Copyright (C) 2019 Macronix
+ * Author:
+ *     Miquèl RAYNAL <miquel.raynal@bootlin.com>
+ *
+ *
+ * This file describes the abstraction of any NAND ECC engine. It has been
+ * designed to fit most cases, including parallel NANDs and SPI-NANDs.
+ *
+ * There are three main situations where instantiating this ECC engine makes
+ * sense:
+ *   - "external": The ECC engine is outside the NAND pipeline, typically this
+ *                 is a software ECC engine. One can also imagine a generic
+ *                 hardware ECC engine which would be an IP itself. Interacting
+ *                 with a SPI-NAND device without on-die ECC could be achieved
+ *                 thanks to the use of such external engine.
+ *   - "pipelined": The ECC engine is inside the NAND pipeline, ie. on the
+ *                  controller's side. This is the case of most of the raw NAND
+ *                  controllers. These controllers usually embed an hardware ECC
+ *                  engine which is managed thanks to the same register set as
+ *                  the controller's.
+ *   - "ondie": The ECC engine is inside the NAND pipeline, on the chip's side.
+ *              Some NAND chips can correct themselves the data. The on-die
+ *              correction can be enabled, disabled and the status of the
+ *              correction after a read may be retrieved with a NAND command
+ *              (may be vendor specific).
+ *
+ * Besides the initial setup and final cleanups, the interfaces are rather
+ * simple:
+ *   - "prepare": Prepare an I/O request, check the ECC engine is enabled or
+ *                disabled as requested before the I/O. In case of software
+ *                correction, this step may involve to derive the ECC bytes and
+ *                place them in the OOB area before a write.
+ *   - "finish": Finish an I/O request, check the status of the operation ie.
+ *               the data validity in case of a read (report to the upper layer
+ *               any bitflip/errors).
+ *
+ * Both prepare/finish callbacks are supposed to enclose I/O request and will
+ * behave differently depending on the desired correction:
+ *   - "raw": Correction disabled
+ *   - "ecc": Correction enabled
+ *
+ * The request direction is impacting the logic as well:
+ *   - "read": Load data from the NAND chip
+ *   - "write": Store data in the NAND chip
+ *
+ * Mixing all this combinations together gives the following behavior.
+ *
+ * ["external" ECC engine]
+ *   - external + prepare + raw + read: do nothing
+ *   - external + finish  + raw + read: do nothing
+ *   - external + prepare + raw + write: do nothing
+ *   - external + finish  + raw + write: do nothing
+ *   - external + prepare + ecc + read: do nothing
+ *   - external + finish  + ecc + read: calculate expected ECC bytes, extract
+ *                                      ECC bytes from OOB buffer, correct
+ *                                      and report any bitflip/error
+ *   - external + prepare + ecc + write: calculate ECC bytes and store them at
+ *                                       the right place in the OOB buffer based
+ *                                       on the OOB layout
+ *   - external + finish  + ecc + write: do nothing
+ *
+ * ["pipelined" ECC engine]
+ *   - pipelined + prepare + raw + read: disable the controller's ECC engine if
+ *                                       activated
+ *   - pipelined + finish  + raw + read: do nothing
+ *   - pipelined + prepare + raw + write: disable the controller's ECC engine if
+ *                                        activated
+ *   - pipelined + finish  + raw + write: do nothing
+ *   - pipelined + prepare + ecc + read: enable the controller's ECC engine if
+ *                                       deactivated
+ *   - pipelined + finish  + ecc + read: check the status, report any
+ *                                       error/bitflip
+ *   - pipelined + prepare + ecc + write: enable the controller's ECC engine if
+ *                                        deactivated
+ *   - pipelined + finish  + ecc + write: do nothing
+ *
+ * ["ondie" ECC engine]
+ *   - ondie + prepare + raw + read: send commands to disable the on-chip ECC
+ *                                   engine if activated
+ *   - ondie + finish  + raw + read: do nothing
+ *   - ondie + prepare + raw + write: send commands to disable the on-chip ECC
+ *                                    engine if activated
+ *   - ondie + finish  + raw + write: do nothing
+ *   - ondie + prepare + ecc + read: send commands to enable the on-chip ECC
+ *                                   engine if deactivated
+ *   - ondie + finish  + ecc + read: send commands to check the status, report
+ *                                   any error/bitflip
+ *   - ondie + prepare + ecc + write: send commands to enable the on-chip ECC
+ *                                    engine if deactivated
+ *   - ondie + finish  + ecc + write: do nothing
+ */
+
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+
+int nand_ecc_init_ctx(struct nand_device *nand)
+{
+	if (!nand->ecc.engine->ops->init_ctx)
+		return 0;
+
+	return nand->ecc.engine->ops->init_ctx(nand);
+}
+EXPORT_SYMBOL(nand_ecc_init_ctx);
+
+void nand_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	if (nand->ecc.engine->ops->cleanup_ctx)
+		nand->ecc.engine->ops->cleanup_ctx(nand);
+}
+EXPORT_SYMBOL(nand_ecc_cleanup_ctx);
+
+int nand_ecc_prepare_io_req(struct nand_device *nand,
+			    struct nand_page_io_req *req, void *oobbuf)
+{
+	if (!nand->ecc.engine->ops->prepare_io_req)
+		return 0;
+
+	return nand->ecc.engine->ops->prepare_io_req(nand, req, oobbuf);
+}
+EXPORT_SYMBOL(nand_ecc_prepare_io_req);
+
+int nand_ecc_finish_io_req(struct nand_device *nand,
+			   struct nand_page_io_req *req, void *oobbuf)
+{
+	if (!nand->ecc.engine->ops->finish_io_req)
+		return 0;
+
+	return nand->ecc.engine->ops->finish_io_req(nand, req, oobbuf);
+}
+EXPORT_SYMBOL(nand_ecc_finish_io_req);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
+MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index 9867e9115399..3dacaa352a58 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -1039,6 +1039,7 @@ static int atmel_hsmc_nand_pmecc_read_page_raw(struct nand_chip *chip,
 
 static int atmel_nand_pmecc_init(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
@@ -1068,15 +1069,15 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
 		req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
 	else if (chip->ecc.strength)
 		req.ecc.strength = chip->ecc.strength;
-	else if (chip->base.eccreq.strength)
-		req.ecc.strength = chip->base.eccreq.strength;
+	else if (requirements->strength)
+		req.ecc.strength = requirements->strength;
 	else
 		req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
 
 	if (chip->ecc.size)
 		req.ecc.sectorsize = chip->ecc.size;
-	else if (chip->base.eccreq.step_size)
-		req.ecc.sectorsize = chip->base.eccreq.step_size;
+	else if (requirements->step_size)
+		req.ecc.sectorsize = requirements->step_size;
 	else
 		req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO;
 
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index dbefb6bac5c9..1d0f556129de 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -204,8 +204,8 @@ static int set_geometry_by_ecc_info(struct gpmi_nand_data *this,
 	default:
 		dev_err(this->dev,
 			"unsupported nand chip. ecc bits : %d, ecc size : %d\n",
-			chip->base.eccreq.strength,
-			chip->base.eccreq.step_size);
+			chip->base.ecc.requirements.strength,
+			chip->base.ecc.requirements.step_size);
 		return -EINVAL;
 	}
 	geo->ecc_chunk_size = ecc_step;
@@ -418,13 +418,13 @@ int common_nfc_set_geometry(struct gpmi_nand_data *this)
 
 	if ((of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc"))
 				|| legacy_set_geometry(this)) {
-		if (!(chip->base.eccreq.strength > 0 &&
-		      chip->base.eccreq.step_size > 0))
+		if (!(chip->base.ecc.requirements.strength > 0 &&
+		      chip->base.ecc.requirements.step_size > 0))
 			return -EINVAL;
 
 		return set_geometry_by_ecc_info(this,
-						chip->base.eccreq.strength,
-						chip->base.eccreq.step_size);
+						chip->base.ecc.requirements.strength,
+						chip->base.ecc.requirements.step_size);
 	}
 
 	return 0;
diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c
index d21e808bb075..4d0d3c34ac12 100644
--- a/drivers/mtd/nand/raw/marvell_nand.c
+++ b/drivers/mtd/nand/raw/marvell_nand.c
@@ -2244,13 +2244,14 @@ static int marvell_nand_ecc_init(struct mtd_info *mtd,
 				 struct nand_ecc_ctrl *ecc)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct marvell_nfc *nfc = to_marvell_nfc(chip->controller);
 	int ret;
 
 	if (ecc->mode != NAND_ECC_NONE && (!ecc->size || !ecc->strength)) {
-		if (chip->base.eccreq.step_size && chip->base.eccreq.strength) {
-			ecc->size = chip->base.eccreq.step_size;
-			ecc->strength = chip->base.eccreq.strength;
+		if (requirements->step_size && requirements->strength) {
+			ecc->size = requirements->step_size;
+			ecc->strength = requirements->strength;
 		} else {
 			dev_info(nfc->dev,
 				 "No minimum ECC strength, using 1b/512B\n");
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index bfb89aca4155..b66eb96b7d49 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -1197,8 +1197,8 @@ static int mtk_nfc_ecc_init(struct device *dev, struct mtd_info *mtd)
 	/* if optional dt settings not present */
 	if (!nand->ecc.size || !nand->ecc.strength) {
 		/* use datasheet requirements */
-		nand->ecc.strength = nand->base.eccreq.strength;
-		nand->ecc.size = nand->base.eccreq.step_size;
+		nand->ecc.strength = nand->base.ecc.requirements.strength;
+		nand->ecc.size = nand->base.ecc.requirements.step_size;
 
 		/*
 		 * align eccstrength and eccsize
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index f4e85e56a041..b12ca291c7e3 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4592,8 +4592,8 @@ static bool find_full_id_nand(struct nand_chip *chip,
 					   memorg->pagesize *
 					   memorg->pages_per_eraseblock);
 		chip->options |= type->options;
-		chip->base.eccreq.strength = NAND_ECC_STRENGTH(type);
-		chip->base.eccreq.step_size = NAND_ECC_STEP(type);
+		chip->base.ecc.requirements.strength = NAND_ECC_STRENGTH(type);
+		chip->base.ecc.requirements.step_size = NAND_ECC_STEP(type);
 		chip->onfi_timing_mode_default =
 					type->onfi_timing_mode_default;
 
@@ -5266,8 +5266,8 @@ nand_match_ecc_req(struct nand_chip *chip,
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	const struct nand_ecc_step_info *stepinfo;
-	int req_step = chip->base.eccreq.step_size;
-	int req_strength = chip->base.eccreq.strength;
+	int req_step = chip->base.ecc.requirements.step_size;
+	int req_strength = chip->base.ecc.requirements.strength;
 	int req_corr, step_size, strength, nsteps, ecc_bytes, ecc_bytes_total;
 	int best_step, best_strength, best_ecc_bytes;
 	int best_ecc_bytes_total = INT_MAX;
@@ -5458,9 +5458,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	int corr, ds_corr;
 
-	if (ecc->size == 0 || chip->base.eccreq.step_size == 0)
+	if (ecc->size == 0 || requirements->step_size == 0)
 		/* Not enough information */
 		return true;
 
@@ -5469,10 +5470,10 @@ static bool nand_ecc_strength_good(struct nand_chip *chip)
 	 * the correction density.
 	 */
 	corr = (mtd->writesize * ecc->strength) / ecc->size;
-	ds_corr = (mtd->writesize * chip->base.eccreq.strength) /
-		  chip->base.eccreq.step_size;
+	ds_corr = (mtd->writesize * requirements->strength) /
+		  requirements->step_size;
 
-	return corr >= ds_corr && ecc->strength >= chip->base.eccreq.strength;
+	return corr >= ds_corr && ecc->strength >= requirements->strength;
 }
 
 static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos)
diff --git a/drivers/mtd/nand/raw/nand_esmt.c b/drivers/mtd/nand/raw/nand_esmt.c
index 3de5e89482f5..c3fc85f77ff8 100644
--- a/drivers/mtd/nand/raw/nand_esmt.c
+++ b/drivers/mtd/nand/raw/nand_esmt.c
@@ -10,24 +10,25 @@
 
 static void esmt_nand_decode_id(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	nand_decode_ext_id(chip);
 
 	/* Extract ECC requirements from 5th id byte. */
 	if (chip->id.len >= 5 && nand_is_slc(chip)) {
-		chip->base.eccreq.step_size = 512;
+		requirements->step_size = 512;
 		switch (chip->id.data[4] & 0x3) {
 		case 0x0:
-			chip->base.eccreq.strength = 4;
+			requirements->strength = 4;
 			break;
 		case 0x1:
-			chip->base.eccreq.strength = 2;
+			requirements->strength = 2;
 			break;
 		case 0x2:
-			chip->base.eccreq.strength = 1;
+			requirements->strength = 1;
 			break;
 		default:
 			WARN(1, "Could not get ECC info");
-			chip->base.eccreq.step_size = 0;
+			requirements->step_size = 0;
 			break;
 		}
 	}
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 821d221b83eb..3c05991e3445 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -504,34 +504,35 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip,
 static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
 						bool valid_jedecid)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	u8 ecc_level = (chip->id.data[4] >> 4) & 0x7;
 
 	if (valid_jedecid) {
 		/* Reference: H27UCG8T2E datasheet */
-		chip->base.eccreq.step_size = 1024;
+		requirements->step_size = 1024;
 
 		switch (ecc_level) {
 		case 0:
-			chip->base.eccreq.step_size = 0;
-			chip->base.eccreq.strength = 0;
+			requirements->step_size = 0;
+			requirements->strength = 0;
 			break;
 		case 1:
-			chip->base.eccreq.strength = 4;
+			requirements->strength = 4;
 			break;
 		case 2:
-			chip->base.eccreq.strength = 24;
+			requirements->strength = 24;
 			break;
 		case 3:
-			chip->base.eccreq.strength = 32;
+			requirements->strength = 32;
 			break;
 		case 4:
-			chip->base.eccreq.strength = 40;
+			requirements->strength = 40;
 			break;
 		case 5:
-			chip->base.eccreq.strength = 50;
+			requirements->strength = 50;
 			break;
 		case 6:
-			chip->base.eccreq.strength = 60;
+			requirements->strength = 60;
 			break;
 		default:
 			/*
@@ -552,14 +553,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
 		if (nand_tech < 3) {
 			/* > 26nm, reference: H27UBG8T2A datasheet */
 			if (ecc_level < 5) {
-				chip->base.eccreq.step_size = 512;
-				chip->base.eccreq.strength = 1 << ecc_level;
+				requirements->step_size = 512;
+				requirements->strength = 1 << ecc_level;
 			} else if (ecc_level < 7) {
 				if (ecc_level == 5)
-					chip->base.eccreq.step_size = 2048;
+					requirements->step_size = 2048;
 				else
-					chip->base.eccreq.step_size = 1024;
-				chip->base.eccreq.strength = 24;
+					requirements->step_size = 1024;
+				requirements->strength = 24;
 			} else {
 				/*
 				 * We should never reach this case, but if that
@@ -572,14 +573,14 @@ static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
 		} else {
 			/* <= 26nm, reference: H27UBG8T2B datasheet */
 			if (!ecc_level) {
-				chip->base.eccreq.step_size = 0;
-				chip->base.eccreq.strength = 0;
+				requirements->step_size = 0;
+				requirements->strength = 0;
 			} else if (ecc_level < 5) {
-				chip->base.eccreq.step_size = 512;
-				chip->base.eccreq.strength = 1 << (ecc_level - 1);
+				requirements->step_size = 512;
+				requirements->strength = 1 << (ecc_level - 1);
 			} else {
-				chip->base.eccreq.step_size = 1024;
-				chip->base.eccreq.strength = 24 +
+				requirements->step_size = 1024;
+				requirements->strength = 24 +
 							(8 * (ecc_level - 5));
 			}
 		}
diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c
index 9b540e76f84f..46afa25abc70 100644
--- a/drivers/mtd/nand/raw/nand_jedec.c
+++ b/drivers/mtd/nand/raw/nand_jedec.c
@@ -110,8 +110,8 @@ int nand_jedec_detect(struct nand_chip *chip)
 	ecc = &p->ecc_info[0];
 
 	if (ecc->codeword_size >= 9) {
-		chip->base.eccreq.strength = ecc->ecc_bits;
-		chip->base.eccreq.step_size = 1 << ecc->codeword_size;
+		chip->base.ecc.requirements.strength = ecc->ecc_bits;
+		chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size;
 	} else {
 		pr_warn("Invalid codeword size\n");
 	}
diff --git a/drivers/mtd/nand/raw/nand_micron.c b/drivers/mtd/nand/raw/nand_micron.c
index 7a2cef02eacd..dd2358a01f54 100644
--- a/drivers/mtd/nand/raw/nand_micron.c
+++ b/drivers/mtd/nand/raw/nand_micron.c
@@ -379,6 +379,7 @@ enum {
  */
 static int micron_supports_on_die_ecc(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	u8 id[5];
 	int ret;
 
@@ -391,7 +392,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 	/*
 	 * We only support on-die ECC of 4/512 or 8/512
 	 */
-	if  (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8)
+	if  (requirements->strength != 4 && requirements->strength != 8)
 		return MICRON_ON_DIE_UNSUPPORTED;
 
 	/* 0x2 means on-die ECC is available. */
@@ -424,7 +425,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 	/*
 	 * We only support on-die ECC of 4/512 or 8/512
 	 */
-	if  (chip->base.eccreq.strength != 4 && chip->base.eccreq.strength != 8)
+	if  (requirements->strength != 4 && requirements->strength != 8)
 		return MICRON_ON_DIE_UNSUPPORTED;
 
 	return MICRON_ON_DIE_SUPPORTED;
@@ -432,6 +433,7 @@ static int micron_supports_on_die_ecc(struct nand_chip *chip)
 
 static int micron_nand_init(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct micron_nand *micron;
 	int ondie;
@@ -479,7 +481,7 @@ static int micron_nand_init(struct nand_chip *chip)
 		 * That's not needed for 8-bit ECC, because the status expose
 		 * a better approximation of the number of bitflips in a page.
 		 */
-		if (chip->base.eccreq.strength == 4) {
+		if (requirements->strength == 4) {
 			micron->ecc.rawbuf = kmalloc(mtd->writesize +
 						     mtd->oobsize,
 						     GFP_KERNEL);
@@ -489,16 +491,16 @@ static int micron_nand_init(struct nand_chip *chip)
 			}
 		}
 
-		if (chip->base.eccreq.strength == 4)
+		if (requirements->strength == 4)
 			mtd_set_ooblayout(mtd,
 					  &micron_nand_on_die_4_ooblayout_ops);
 		else
 			mtd_set_ooblayout(mtd,
 					  &micron_nand_on_die_8_ooblayout_ops);
 
-		chip->ecc.bytes = chip->base.eccreq.strength * 2;
+		chip->ecc.bytes = requirements->strength * 2;
 		chip->ecc.size = 512;
-		chip->ecc.strength = chip->base.eccreq.strength;
+		chip->ecc.strength = requirements->strength;
 		chip->ecc.algo = NAND_ECC_BCH;
 		chip->ecc.read_page = micron_nand_read_page_on_die_ecc;
 		chip->ecc.write_page = micron_nand_write_page_on_die_ecc;
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
index 0b879bd0a68c..9d21b47ebef1 100644
--- a/drivers/mtd/nand/raw/nand_onfi.c
+++ b/drivers/mtd/nand/raw/nand_onfi.c
@@ -94,8 +94,8 @@ static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
 		goto ext_out;
 	}
 
-	chip->base.eccreq.strength = ecc->ecc_bits;
-	chip->base.eccreq.step_size = 1 << ecc->codeword_size;
+	chip->base.ecc.requirements.strength = ecc->ecc_bits;
+	chip->base.ecc.requirements.step_size = 1 << ecc->codeword_size;
 	ret = 0;
 
 ext_out:
@@ -252,8 +252,8 @@ int nand_onfi_detect(struct nand_chip *chip)
 		chip->options |= NAND_BUSWIDTH_16;
 
 	if (p->ecc_bits != 0xff) {
-		chip->base.eccreq.strength = p->ecc_bits;
-		chip->base.eccreq.step_size = 512;
+		chip->base.ecc.requirements.strength = p->ecc_bits;
+		chip->base.ecc.requirements.step_size = 512;
 	} else if (onfi_version >= 21 &&
 		(le16_to_cpu(p->features) & ONFI_FEATURE_EXT_PARAM_PAGE)) {
 
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index f7d7041b6213..4874ba33db15 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -19,6 +19,7 @@
 
 static void samsung_nand_decode_id(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_memory_organization *memorg;
 
@@ -80,23 +81,23 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
 		/* Extract ECC requirements from 5th id byte*/
 		extid = (chip->id.data[4] >> 4) & 0x07;
 		if (extid < 5) {
-			chip->base.eccreq.step_size = 512;
-			chip->base.eccreq.strength = 1 << extid;
+			requirements->step_size = 512;
+			requirements->strength = 1 << extid;
 		} else {
-			chip->base.eccreq.step_size = 1024;
+			requirements->step_size = 1024;
 			switch (extid) {
 			case 5:
-				chip->base.eccreq.strength = 24;
+				requirements->strength = 24;
 				break;
 			case 6:
-				chip->base.eccreq.strength = 40;
+				requirements->strength = 40;
 				break;
 			case 7:
-				chip->base.eccreq.strength = 60;
+				requirements->strength = 60;
 				break;
 			default:
 				WARN(1, "Could not decode ECC info");
-				chip->base.eccreq.step_size = 0;
+				requirements->step_size = 0;
 			}
 		}
 	} else {
@@ -106,8 +107,8 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
 			switch (chip->id.data[1]) {
 			/* K9F4G08U0D-S[I|C]B0(T00) */
 			case 0xDC:
-				chip->base.eccreq.step_size = 512;
-				chip->base.eccreq.strength = 1;
+				requirements->step_size = 512;
+				requirements->strength = 1;
 				break;
 
 			/* K9F1G08U0E 21nm chips do not support subpage write */
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index 13f9632f1cb4..f00d958d724f 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -100,6 +100,7 @@ static void toshiba_nand_benand_init(struct nand_chip *chip)
 
 static void toshiba_nand_decode_id(struct nand_chip *chip)
 {
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_memory_organization *memorg;
 
@@ -130,20 +131,20 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
 	 *  - 24nm: 8 bit ECC for each 512Byte is required.
 	 */
 	if (chip->id.len >= 6 && nand_is_slc(chip)) {
-		chip->base.eccreq.step_size = 512;
+		requirements->step_size = 512;
 		switch (chip->id.data[5] & 0x7) {
 		case 0x4:
-			chip->base.eccreq.strength = 1;
+			requirements->strength = 1;
 			break;
 		case 0x5:
-			chip->base.eccreq.strength = 4;
+			requirements->strength = 4;
 			break;
 		case 0x6:
-			chip->base.eccreq.strength = 8;
+			requirements->strength = 8;
 			break;
 		default:
 			WARN(1, "Could not get ECC info");
-			chip->base.eccreq.step_size = 0;
+			requirements->step_size = 0;
 			break;
 		}
 	}
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 69599854fdd6..43b22564da10 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1807,6 +1807,7 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
 
 static int sunxi_nand_attach_chip(struct nand_chip *nand)
 {
+	struct nand_ecc_conf *requirements = &nand->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(nand);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	struct device_node *np = nand_get_flash_node(nand);
@@ -1821,8 +1822,8 @@ static int sunxi_nand_attach_chip(struct nand_chip *nand)
 	nand->options |= NAND_SUBPAGE_READ;
 
 	if (!ecc->size) {
-		ecc->size = nand->base.eccreq.step_size;
-		ecc->strength = nand->base.eccreq.strength;
+		ecc->size = requirements->step_size;
+		ecc->strength = requirements->strength;
 	}
 
 	if (!ecc->size || !ecc->strength)
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index 3cc9a4c41443..31d547d96795 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -853,7 +853,7 @@ static int tegra_nand_get_strength(struct nand_chip *chip, const int *strength,
 		} else {
 			strength_sel = strength[i];
 
-			if (strength_sel < chip->base.eccreq.strength)
+			if (strength_sel < chip->base.ecc.requirements.strength)
 				continue;
 		}
 
@@ -906,6 +906,7 @@ static int tegra_nand_select_strength(struct nand_chip *chip, int oobsize)
 static int tegra_nand_attach_chip(struct nand_chip *chip)
 {
 	struct tegra_nand_controller *ctrl = to_tegra_ctrl(chip->controller);
+	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct tegra_nand_chip *nand = to_tegra_chip(chip);
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int bits_per_step;
@@ -917,9 +918,9 @@ static int tegra_nand_attach_chip(struct nand_chip *chip)
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = 512;
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
-	if (chip->base.eccreq.step_size != 512) {
+	if (requirements->step_size != 512) {
 		dev_err(ctrl->dev, "Unsupported step size %d\n",
-			chip->base.eccreq.step_size);
+			requirements->step_size);
 		return -EINVAL;
 	}
 
@@ -950,7 +951,7 @@ static int tegra_nand_attach_chip(struct nand_chip *chip)
 		if (ret < 0) {
 			dev_err(ctrl->dev,
 				"No valid strength found, minimum %d\n",
-				chip->base.eccreq.strength);
+				requirements->strength);
 			return ret;
 		}
 
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 9ee192585854..ab41b9434d87 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -480,7 +480,7 @@ static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
 		 * fixed, so let's return the maximum possible value so that
 		 * wear-leveling layers move the data immediately.
 		 */
-		return nand->eccreq.strength;
+		return nand->ecc.ctx.conf.strength;
 
 	case STATUS_ECC_UNCOR_ERROR:
 		return -EBADMSG;
@@ -869,7 +869,7 @@ int spinand_match_and_init(struct spinand_device *spinand,
 			continue;
 
 		nand->memorg = table[i].memorg;
-		nand->eccreq = table[i].eccreq;
+		nand->ecc.requirements = table[i].eccreq;
 		spinand->eccinfo = table[i].eccinfo;
 		spinand->flags = table[i].flags;
 		spinand->select_target = table[i].select_target;
diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index c6300d9d63f9..ef71312966a2 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -78,10 +78,10 @@ static int mx35lf1ge4ab_ecc_get_status(struct spinand_device *spinand,
 		 * data around if it's not necessary.
 		 */
 		if (mx35lf1ge4ab_get_eccsr(spinand, &eccsr))
-			return nand->eccreq.strength;
+			return nand->ecc.ctx.conf.strength;
 
-		if (WARN_ON(eccsr > nand->eccreq.strength || !eccsr))
-			return nand->eccreq.strength;
+		if (WARN_ON(eccsr > nand->ecc.ctx.conf.strength || !eccsr))
+			return nand->ecc.ctx.conf.strength;
 
 		return eccsr;
 
diff --git a/drivers/mtd/nand/spi/toshiba.c b/drivers/mtd/nand/spi/toshiba.c
index 00ddab08e6c6..4ac336d3a304 100644
--- a/drivers/mtd/nand/spi/toshiba.c
+++ b/drivers/mtd/nand/spi/toshiba.c
@@ -77,12 +77,12 @@ static int tc58cvg2s0h_ecc_get_status(struct spinand_device *spinand,
 		 * data around if it's not necessary.
 		 */
 		if (spi_mem_exec_op(spinand->spimem, &op))
-			return nand->eccreq.strength;
+			return nand->ecc.ctx.conf.strength;
 
 		mbf >>= 4;
 
-		if (WARN_ON(mbf > nand->eccreq.strength || !mbf))
-			return nand->eccreq.strength;
+		if (WARN_ON(mbf > nand->ecc.ctx.conf.strength || !mbf))
+			return nand->ecc.ctx.conf.strength;
 
 		return mbf;
 
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 78cf905083c9..45caaa489085 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -124,12 +124,18 @@ struct nand_page_io_req {
 
 /**
  * struct nand_ecc_conf - NAND ECC configuration
+ * @provider: ECC engine provider type
+ * @algo: ECC algorithm (if relevant)
  * @strength: ECC strength
  * @step_size: Number of bytes per step
+ * @flags: Misc properties
  */
 struct nand_ecc_conf {
+	unsigned int provider;
+	unsigned int algo;
 	unsigned int strength;
 	unsigned int step_size;
+	unsigned int flags;
 };
 
 #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) }
@@ -164,11 +170,79 @@ struct nand_ops {
 	bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos);
 };
 
+/**
+ * struct nand_ecc_context - Context for the ECC engine
+ * @conf: basic ECC engine parameters
+ * @total: Total number of bytes used for storing ECC codes, this is used by
+ *         generic OOB layouts
+ * @priv: ECC engine driver private data
+ */
+struct nand_ecc_context {
+	struct nand_ecc_conf conf;
+	unsigned int total;
+	void *priv;
+};
+
+/**
+ * struct nand_ecc_engine_ops - Generic ECC engine operations
+ * @init_ctx: given a desired user configuration for the pointed NAND device,
+ *            requests the ECC engine driver to setup a configuration with
+ *            values it supports.
+ * @cleanup_ctx: clean the context initialized by @init_ctx.
+ * @prepare_io_req: is called before reading/writing a page to prepare the I/O
+ *                  request to be performed with ECC correction.
+ * @finish_io_req: is called after reading/writing a page to terminate the I/O
+ *                 request and ensure proper ECC correction.
+ */
+struct nand_ecc_engine_ops {
+	int (*init_ctx)(struct nand_device *nand);
+	void (*cleanup_ctx)(struct nand_device *nand);
+	int (*prepare_io_req)(struct nand_device *nand,
+			      struct nand_page_io_req *req,
+			      void *oobbuf);
+	int (*finish_io_req)(struct nand_device *nand,
+			     struct nand_page_io_req *req,
+			     void *oobbuf);
+};
+
+/**
+ * struct nand_ecc_engine - Generic ECC engine abstraction for NAND devices
+ * @ops: ECC engine operations
+ */
+struct nand_ecc_engine {
+	struct nand_ecc_engine_ops *ops;
+};
+
+int nand_ecc_init_ctx(struct nand_device *nand);
+void nand_ecc_cleanup_ctx(struct nand_device *nand);
+int nand_ecc_prepare_io_req(struct nand_device *nand,
+			    struct nand_page_io_req *req, void *oobbuf);
+int nand_ecc_finish_io_req(struct nand_device *nand,
+			   struct nand_page_io_req *req, void *oobbuf);
+
+/**
+ * struct nand_ecc - High-level ECC object
+ * @defaults: Default values, depend on the underlying subsystem
+ * @requirements: ECC requirements from the NAND chip perspective
+ * @user_conf: User desires in terms of ECC parameters
+ * @ctx: ECC context for the ECC engine, derived from the device @requirements
+ *       the @user_conf and the @defaults
+ * @ondie_engine: On-die ECC engine reference, if any
+ * @engine: ECC engine actually bound
+ */
+struct nand_ecc {
+	struct nand_ecc_conf defaults;
+	struct nand_ecc_conf requirements;
+	struct nand_ecc_conf user_conf;
+	struct nand_ecc_context ctx;
+	struct nand_ecc_engine *ondie_engine;
+	struct nand_ecc_engine *engine;
+};
+
 /**
  * struct nand_device - NAND device
  * @mtd: MTD instance attached to the NAND device
  * @memorg: memory layout
- * @eccreq: ECC requirements
  * @rowconv: position to row address converter
  * @bbt: bad block table info
  * @ops: NAND operations attached to the NAND device
@@ -176,8 +250,8 @@ struct nand_ops {
  * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND)
  * should declare their own NAND object embedding a nand_device struct (that's
  * how inheritance is done).
- * struct_nand_device->memorg and struct_nand_device->eccreq should be filled
- * at device detection time to reflect the NAND device
+ * struct_nand_device->memorg and struct_nand_device->ecc.ctx.conf should
+ * be filled at device detection time to reflect the NAND device
  * capabilities/requirements. Once this is done nanddev_init() can be called.
  * It will take care of converting NAND information into MTD ones, which means
  * the specialized NAND layers should never manually tweak
@@ -186,7 +260,7 @@ struct nand_ops {
 struct nand_device {
 	struct mtd_info mtd;
 	struct nand_memory_organization memorg;
-	struct nand_ecc_conf eccreq;
+	struct nand_ecc ecc;
 	struct nand_row_converter rowconv;
 	struct nand_bbt bbt;
 	const struct nand_ops *ops;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 3008de54f958..75a28dc79a9c 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -168,7 +168,7 @@ struct spinand_id {
  *	    match, 0 if the manufacturer ID does not match and a negative
  *	    error code otherwise. When true is returned, the core assumes
  *	    that properties of the NAND chip (spinand->base.memorg and
- *	    spinand->base.eccreq) have been filled
+ *	    spinand->base.ecc.ctx.conf) have been filled
  * @init: initialize a SPI NAND device
  * @cleanup: cleanup a SPI NAND device
  *
-- 
2.19.1


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

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

* [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (9 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-31 11:32   ` Boris Brezillon
  2019-03-04 22:28 ` [PATCH v2 12/36] mtd: nand: Move standard OOB layouts to the generic ECC core Miquel Raynal
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Fix a probable copy/paste error: the function works like
mtd_ooblayout_set_bytes(), not the *_get_bytes() alternate.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/mtdcore.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 21e3cdc04036..6ed48018163c 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1592,7 +1592,7 @@ EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
  * @start: first ECC byte to set
  * @nbytes: number of ECC bytes to set
  *
- * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes.
+ * Works like mtd_ooblayout_set_bytes(), except it acts on free bytes.
  *
  * Returns zero on success, a negative error code otherwise.
  */
-- 
2.19.1


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

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

* [PATCH v2 12/36] mtd: nand: Move standard OOB layouts to the generic ECC core
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (10 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 13/36] mtd: nand: Move ECC specific functions to ecc/engine.c Miquel Raynal
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

These OOB layouts are generic to all NAND chips, the should not be
restricted to be used only by raw NAND controller drivers. They might
later be used by generic ECC engines and SPI-NAND devices as well.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/engine.c       | 161 +++++++++++++++++++++++++++
 drivers/mtd/nand/raw/Kconfig        |   1 +
 drivers/mtd/nand/raw/nand_base.c    | 162 +---------------------------
 drivers/mtd/nand/raw/nand_toshiba.c |   2 +
 include/linux/mtd/nand.h            |   4 +
 include/linux/mtd/rawnand.h         |   3 -
 6 files changed, 170 insertions(+), 163 deletions(-)

diff --git a/drivers/mtd/nand/ecc/engine.c b/drivers/mtd/nand/ecc/engine.c
index 4c7943ddf2cc..f52ffce8e684 100644
--- a/drivers/mtd/nand/ecc/engine.c
+++ b/drivers/mtd/nand/ecc/engine.c
@@ -133,6 +133,167 @@ int nand_ecc_finish_io_req(struct nand_device *nand,
 }
 EXPORT_SYMBOL(nand_ecc_finish_io_req);
 
+/* Define default oob placement schemes for large and small page devices */
+static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+
+	if (section > 1)
+		return -ERANGE;
+
+	if (!section) {
+		oobregion->offset = 0;
+		if (mtd->oobsize == 16)
+			oobregion->length = 4;
+		else
+			oobregion->length = 3;
+	} else {
+		if (mtd->oobsize == 8)
+			return -ERANGE;
+
+		oobregion->offset = 6;
+		oobregion->length = total_ecc_bytes - 4;
+	}
+
+	return 0;
+}
+
+static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	if (section > 1)
+		return -ERANGE;
+
+	if (mtd->oobsize == 16) {
+		if (section)
+			return -ERANGE;
+
+		oobregion->length = 8;
+		oobregion->offset = 8;
+	} else {
+		oobregion->length = 2;
+		if (!section)
+			oobregion->offset = 3;
+		else
+			oobregion->offset = 6;
+	}
+
+	return 0;
+}
+
+const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = {
+	.ecc = nand_ooblayout_ecc_sp,
+	.free = nand_ooblayout_free_sp,
+};
+EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops);
+
+static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+
+	if (section || !total_ecc_bytes)
+		return -ERANGE;
+
+	oobregion->length = total_ecc_bytes;
+	oobregion->offset = mtd->oobsize - oobregion->length;
+
+	return 0;
+}
+
+static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+
+	if (section)
+		return -ERANGE;
+
+	oobregion->length = mtd->oobsize - total_ecc_bytes - 2;
+	oobregion->offset = 2;
+
+	return 0;
+}
+
+const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
+	.ecc = nand_ooblayout_ecc_lp,
+	.free = nand_ooblayout_free_lp,
+};
+EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
+
+/*
+ * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
+ * are placed at a fixed offset.
+ */
+static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
+					 struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+
+	if (section)
+		return -ERANGE;
+
+	switch (mtd->oobsize) {
+	case 64:
+		oobregion->offset = 40;
+		break;
+	case 128:
+		oobregion->offset = 80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	oobregion->length = total_ecc_bytes;
+	if (oobregion->offset + oobregion->length > mtd->oobsize)
+		return -ERANGE;
+
+	return 0;
+}
+
+static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
+					  struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	unsigned int total_ecc_bytes = nand->ecc.ctx.total;
+	int ecc_offset = 0;
+
+	if (section < 0 || section > 1)
+		return -ERANGE;
+
+	switch (mtd->oobsize) {
+	case 64:
+		ecc_offset = 40;
+		break;
+	case 128:
+		ecc_offset = 80;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (section == 0) {
+		oobregion->offset = 2;
+		oobregion->length = ecc_offset - 2;
+	} else {
+		oobregion->offset = ecc_offset + total_ecc_bytes;
+		oobregion->length = mtd->oobsize - oobregion->offset;
+	}
+
+	return 0;
+}
+
+const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
+	.ecc = nand_ooblayout_ecc_lp_hamming,
+	.free = nand_ooblayout_free_lp_hamming,
+};
+EXPORT_SYMBOL_GPL(nand_ooblayout_lp_hamming_ops);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 952dc50a8634..621991a242c1 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -12,6 +12,7 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
 menuconfig MTD_RAW_NAND
 	tristate "Raw/Parallel NAND Device Support"
 	select MTD_NAND_CORE
+	select MTD_NAND_ECC
 	select MTD_NAND_ECC_SW_HAMMING
 	help
 	  This enables support for accessing all type of raw/parallel
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index b12ca291c7e3..187e6b1fd84d 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -38,6 +38,7 @@
 #include <linux/mm.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/nand_bch.h>
 #include <linux/interrupt.h>
@@ -49,166 +50,6 @@
 
 #include "internals.h"
 
-/* Define default oob placement schemes for large and small page devices */
-static int nand_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
-				 struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section > 1)
-		return -ERANGE;
-
-	if (!section) {
-		oobregion->offset = 0;
-		if (mtd->oobsize == 16)
-			oobregion->length = 4;
-		else
-			oobregion->length = 3;
-	} else {
-		if (mtd->oobsize == 8)
-			return -ERANGE;
-
-		oobregion->offset = 6;
-		oobregion->length = ecc->total - 4;
-	}
-
-	return 0;
-}
-
-static int nand_ooblayout_free_sp(struct mtd_info *mtd, int section,
-				  struct mtd_oob_region *oobregion)
-{
-	if (section > 1)
-		return -ERANGE;
-
-	if (mtd->oobsize == 16) {
-		if (section)
-			return -ERANGE;
-
-		oobregion->length = 8;
-		oobregion->offset = 8;
-	} else {
-		oobregion->length = 2;
-		if (!section)
-			oobregion->offset = 3;
-		else
-			oobregion->offset = 6;
-	}
-
-	return 0;
-}
-
-const struct mtd_ooblayout_ops nand_ooblayout_sp_ops = {
-	.ecc = nand_ooblayout_ecc_sp,
-	.free = nand_ooblayout_free_sp,
-};
-EXPORT_SYMBOL_GPL(nand_ooblayout_sp_ops);
-
-static int nand_ooblayout_ecc_lp(struct mtd_info *mtd, int section,
-				 struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section || !ecc->total)
-		return -ERANGE;
-
-	oobregion->length = ecc->total;
-	oobregion->offset = mtd->oobsize - oobregion->length;
-
-	return 0;
-}
-
-static int nand_ooblayout_free_lp(struct mtd_info *mtd, int section,
-				  struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section)
-		return -ERANGE;
-
-	oobregion->length = mtd->oobsize - ecc->total - 2;
-	oobregion->offset = 2;
-
-	return 0;
-}
-
-const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
-	.ecc = nand_ooblayout_ecc_lp,
-	.free = nand_ooblayout_free_lp,
-};
-EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
-
-/*
- * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
- * are placed at a fixed offset.
- */
-static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
-					 struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-
-	if (section)
-		return -ERANGE;
-
-	switch (mtd->oobsize) {
-	case 64:
-		oobregion->offset = 40;
-		break;
-	case 128:
-		oobregion->offset = 80;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	oobregion->length = ecc->total;
-	if (oobregion->offset + oobregion->length > mtd->oobsize)
-		return -ERANGE;
-
-	return 0;
-}
-
-static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
-					  struct mtd_oob_region *oobregion)
-{
-	struct nand_chip *chip = mtd_to_nand(mtd);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-	int ecc_offset = 0;
-
-	if (section < 0 || section > 1)
-		return -ERANGE;
-
-	switch (mtd->oobsize) {
-	case 64:
-		ecc_offset = 40;
-		break;
-	case 128:
-		ecc_offset = 80;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (section == 0) {
-		oobregion->offset = 2;
-		oobregion->length = ecc_offset - 2;
-	} else {
-		oobregion->offset = ecc_offset + ecc->total;
-		oobregion->length = mtd->oobsize - oobregion->offset;
-	}
-
-	return 0;
-}
-
-static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
-	.ecc = nand_ooblayout_ecc_lp_hamming,
-	.free = nand_ooblayout_free_lp_hamming,
-};
-
 static int check_offs_len(struct nand_chip *chip, loff_t ofs, uint64_t len)
 {
 	int ret = 0;
@@ -5735,6 +5576,7 @@ static int nand_scan_tail(struct nand_chip *chip)
 		goto err_nand_manuf_cleanup;
 	}
 	ecc->total = ecc->steps * ecc->bytes;
+	chip->base.ecc.ctx.total = ecc->total;
 	if (ecc->total > mtd->oobsize) {
 		WARN(1, "Total number of ECC bytes exceeded oobsize\n");
 		ret = -EINVAL;
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index f00d958d724f..566cc1a11679 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -15,6 +15,8 @@
  * GNU General Public License for more details.
  */
 
+#include <linux/mtd/nand.h>
+
 #include "internals.h"
 
 /* Bit for detecting BENAND */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 45caaa489085..277c0cf822b9 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -122,6 +122,10 @@ struct nand_page_io_req {
 	int mode;
 };
 
+extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
+extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops;
+extern const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops;
+
 /**
  * struct nand_ecc_conf - NAND ECC configuration
  * @provider: ECC engine provider type
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 95b0c7114701..0c2beb6fcf0b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1099,9 +1099,6 @@ struct nand_chip {
 	} manufacturer;
 };
 
-extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
-extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops;
-
 static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
 {
 	return container_of(mtd, struct nand_chip, base.mtd);
-- 
2.19.1


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

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

* [PATCH v2 13/36] mtd: nand: Move ECC specific functions to ecc/engine.c
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (11 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 12/36] mtd: nand: Move standard OOB layouts to the generic ECC core Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 14/36] mtd: nand: ecc: Move BCH code into the ecc/ directory Miquel Raynal
                   ` (22 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Move generic code that will benefit to be shared out of the raw NAND
subsystem.

While at it, remove the maximize option from the NAND chip structure
and move it into a user configuration flag.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/engine.c                | 156 ++++++++++++++++
 drivers/mtd/nand/raw/atmel/nand-controller.c |   3 +-
 drivers/mtd/nand/raw/denali.c                |   3 +
 drivers/mtd/nand/raw/denali_pci.c            |   1 -
 drivers/mtd/nand/raw/nand_base.c             | 176 +++----------------
 drivers/mtd/nand/raw/sunxi_nand.c            |   3 +-
 drivers/mtd/nand/raw/tegra_nand.c            |   3 +-
 include/linux/mtd/nand.h                     |  33 ++++
 include/linux/mtd/rawnand.h                  |  22 +--
 9 files changed, 226 insertions(+), 174 deletions(-)

diff --git a/drivers/mtd/nand/ecc/engine.c b/drivers/mtd/nand/ecc/engine.c
index f52ffce8e684..c6779acc936d 100644
--- a/drivers/mtd/nand/ecc/engine.c
+++ b/drivers/mtd/nand/ecc/engine.c
@@ -294,6 +294,162 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
 };
 EXPORT_SYMBOL_GPL(nand_ooblayout_lp_hamming_ops);
 
+static const char * const nand_ecc_modes[] = {
+	[NAND_ECC_NONE]		= "none",
+	[NAND_ECC_SOFT]		= "soft",
+	[NAND_ECC_HW]		= "hw",
+	[NAND_ECC_HW_SYNDROME]	= "hw_syndrome",
+	[NAND_ECC_HW_OOB_FIRST]	= "hw_oob_first",
+	[NAND_ECC_ON_DIE]	= "on-die",
+};
+
+static int of_get_nand_ecc_provider(struct device_node *np)
+{
+	const char *pm;
+	int err, i;
+
+	err = of_property_read_string(np, "nand-ecc-mode", &pm);
+	if (err < 0)
+		return err;
+
+	for (i = NAND_ECC_NONE; i < ARRAY_SIZE(nand_ecc_modes); i++)
+		if (!strcasecmp(pm, nand_ecc_modes[i]))
+			return i;
+
+	/*
+	 * For backward compatibility we support few obsoleted values that don't
+	 * have their mappings into the nand_ecc_modes enumeration anymore (they
+	 * were merged with other enums).
+	 */
+	if (!strcasecmp(pm, "soft_bch"))
+		return NAND_ECC_SOFT;
+
+	return -ENODEV;
+}
+
+static const char * const nand_ecc_algos[] = {
+	[NAND_ECC_HAMMING]	= "hamming",
+	[NAND_ECC_BCH]		= "bch",
+	[NAND_ECC_RS]		= "rs",
+};
+
+static int of_get_nand_ecc_algo(struct device_node *np)
+{
+	const char *pm;
+	int err, i;
+
+	err = of_property_read_string(np, "nand-ecc-algo", &pm);
+	if (!err) {
+		for (i = NAND_ECC_HAMMING; i < ARRAY_SIZE(nand_ecc_algos); i++)
+			if (!strcasecmp(pm, nand_ecc_algos[i]))
+				return i;
+		return -ENODEV;
+	}
+
+	/*
+	 * For backward compatibility we also read "nand-ecc-mode" checking
+	 * for some obsoleted values that were specifying ECC algorithm.
+	 */
+	err = of_property_read_string(np, "nand-ecc-mode", &pm);
+	if (err < 0)
+		return err;
+
+	if (!strcasecmp(pm, "soft"))
+		return NAND_ECC_HAMMING;
+	else if (!strcasecmp(pm, "soft_bch"))
+		return NAND_ECC_BCH;
+
+	return -ENODEV;
+}
+
+static int of_get_nand_ecc_step_size(struct device_node *np)
+{
+	int ret;
+	u32 val;
+
+	ret = of_property_read_u32(np, "nand-ecc-step-size", &val);
+	return ret ? ret : val;
+}
+
+static int of_get_nand_ecc_strength(struct device_node *np)
+{
+	int ret;
+	u32 val;
+
+	ret = of_property_read_u32(np, "nand-ecc-strength", &val);
+	return ret ? ret : val;
+}
+
+static inline bool of_get_nand_ecc_maximize(struct device_node *np)
+{
+	return of_property_read_bool(np, "nand-ecc-maximize");
+}
+
+void nand_ecc_read_user_conf(struct nand_device *nand)
+{
+	struct device_node *dn = nanddev_get_flash_node(nand);
+	int provider, algo, strength, size;
+
+	provider = of_get_nand_ecc_provider(dn);
+	if (provider >= 0)
+		nand->ecc.user_conf.provider = provider;
+
+	algo = of_get_nand_ecc_algo(dn);
+	if (algo >= 0)
+		nand->ecc.user_conf.algo = algo;
+
+	strength = of_get_nand_ecc_strength(dn);
+	if (strength >= 0)
+		nand->ecc.user_conf.strength = strength;
+
+	size = of_get_nand_ecc_step_size(dn);
+	if (size >= 0)
+		nand->ecc.user_conf.step_size = size;
+
+	if (of_get_nand_ecc_maximize(dn))
+		nand->ecc.user_conf.flags |= NAND_ECC_MAXIMIZE;
+}
+EXPORT_SYMBOL(nand_ecc_read_user_conf);
+
+/**
+ * nand_ecc_correction_is_enough - Check if the chip configuration meets the
+ *                                 datasheet requirements.
+ *
+ * @nand: Device to check
+ *
+ * If our configuration corrects A bits per B bytes and the minimum
+ * required correction level is X bits per Y bytes, then we must ensure
+ * both of the following are true:
+ *
+ * (1) A / B >= X / Y
+ * (2) A >= X
+ *
+ * Requirement (1) ensures we can correct for the required bitflip density.
+ * Requirement (2) ensures we can correct even when all bitflips are clumped
+ * in the same sector.
+ */
+bool nand_ecc_correction_is_enough(struct nand_device *nand)
+{
+	struct nand_ecc_conf *reqs = &nand->ecc.requirements;
+	struct nand_ecc_conf *conf = &nand->ecc.ctx.conf;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int corr, ds_corr;
+
+	if (conf->step_size == 0 || reqs->step_size == 0)
+		/* Not enough information */
+		return true;
+
+	/*
+	 * We get the number of corrected bits per page to compare
+	 * the correction density.
+	 */
+	corr = (mtd->writesize * conf->strength) / conf->step_size;
+	ds_corr = (mtd->writesize * reqs->strength) / reqs->step_size;
+
+	return corr >= ds_corr && conf->strength >= reqs->strength;
+}
+EXPORT_SYMBOL(nand_ecc_correction_is_enough);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
index 3dacaa352a58..9c14b4a01192 100644
--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
+++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
@@ -1041,6 +1041,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
 {
 	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	struct atmel_nand *nand = to_atmel_nand(chip);
 	struct atmel_nand_controller *nc;
 	struct atmel_pmecc_user_req req;
@@ -1065,7 +1066,7 @@ static int atmel_nand_pmecc_init(struct nand_chip *chip)
 			chip->ecc.size = val;
 	}
 
-	if (chip->ecc.options & NAND_ECC_MAXIMIZE)
+	if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE)
 		req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
 	else if (chip->ecc.strength)
 		req.ecc.strength = chip->ecc.strength;
diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index 3ec0242b0aa2..706bd73708e7 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -1284,6 +1284,7 @@ int denali_init(struct denali_nand_info *denali)
 {
 	struct nand_chip *chip = &denali->nand;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	u32 features = ioread32(denali->reg + FEATURES);
 	int ret;
 
@@ -1329,6 +1330,8 @@ int denali_init(struct denali_nand_info *denali)
 	if (denali->clk_rate && denali->clk_x_rate)
 		chip->options |= NAND_KEEP_TIMINGS;
 
+	nanddev->ecc.user_conf.flags |= NAND_ECC_MAXIMIZE;
+
 	chip->legacy.dummy_controller.ops = &denali_controller_ops;
 	ret = nand_scan(chip, denali->max_banks);
 	if (ret)
diff --git a/drivers/mtd/nand/raw/denali_pci.c b/drivers/mtd/nand/raw/denali_pci.c
index 48e9ac54ad53..bf3cb7c0480f 100644
--- a/drivers/mtd/nand/raw/denali_pci.c
+++ b/drivers/mtd/nand/raw/denali_pci.c
@@ -64,7 +64,6 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	denali->dev = &dev->dev;
 	denali->irq = dev->irq;
 	denali->ecc_caps = &denali_pci_ecc_caps;
-	denali->nand.ecc.options |= NAND_ECC_MAXIMIZE;
 	denali->clk_rate = 50000000;		/* 50 MHz */
 	denali->clk_x_rate = 200000000;		/* 200 MHz */
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 187e6b1fd84d..9efe3dd578b5 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4698,92 +4698,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 	return ret;
 }
 
-static const char * const nand_ecc_modes[] = {
-	[NAND_ECC_NONE]		= "none",
-	[NAND_ECC_SOFT]		= "soft",
-	[NAND_ECC_HW]		= "hw",
-	[NAND_ECC_HW_SYNDROME]	= "hw_syndrome",
-	[NAND_ECC_HW_OOB_FIRST]	= "hw_oob_first",
-	[NAND_ECC_ON_DIE]	= "on-die",
-};
-
-static int of_get_nand_ecc_mode(struct device_node *np)
-{
-	const char *pm;
-	int err, i;
-
-	err = of_property_read_string(np, "nand-ecc-mode", &pm);
-	if (err < 0)
-		return err;
-
-	for (i = NAND_ECC_NONE; i < ARRAY_SIZE(nand_ecc_modes); i++)
-		if (!strcasecmp(pm, nand_ecc_modes[i]))
-			return i;
-
-	/*
-	 * For backward compatibility we support few obsoleted values that don't
-	 * have their mappings into the nand_ecc_mode enum anymore (they were
-	 * merged with other enums).
-	 */
-	if (!strcasecmp(pm, "soft_bch"))
-		return NAND_ECC_SOFT;
-
-	return -ENODEV;
-}
-
-static const char * const nand_ecc_algos[] = {
-	[NAND_ECC_HAMMING]	= "hamming",
-	[NAND_ECC_BCH]		= "bch",
-	[NAND_ECC_RS]		= "rs",
-};
-
-static int of_get_nand_ecc_algo(struct device_node *np)
-{
-	const char *pm;
-	int err, i;
-
-	err = of_property_read_string(np, "nand-ecc-algo", &pm);
-	if (!err) {
-		for (i = NAND_ECC_HAMMING; i < ARRAY_SIZE(nand_ecc_algos); i++)
-			if (!strcasecmp(pm, nand_ecc_algos[i]))
-				return i;
-		return -ENODEV;
-	}
-
-	/*
-	 * For backward compatibility we also read "nand-ecc-mode" checking
-	 * for some obsoleted values that were specifying ECC algorithm.
-	 */
-	err = of_property_read_string(np, "nand-ecc-mode", &pm);
-	if (err < 0)
-		return err;
-
-	if (!strcasecmp(pm, "soft"))
-		return NAND_ECC_HAMMING;
-	else if (!strcasecmp(pm, "soft_bch"))
-		return NAND_ECC_BCH;
-
-	return -ENODEV;
-}
-
-static int of_get_nand_ecc_step_size(struct device_node *np)
-{
-	int ret;
-	u32 val;
-
-	ret = of_property_read_u32(np, "nand-ecc-step-size", &val);
-	return ret ? ret : val;
-}
-
-static int of_get_nand_ecc_strength(struct device_node *np)
-{
-	int ret;
-	u32 val;
-
-	ret = of_property_read_u32(np, "nand-ecc-strength", &val);
-	return ret ? ret : val;
-}
-
 static int of_get_nand_bus_width(struct device_node *np)
 {
 	u32 val;
@@ -4805,10 +4719,10 @@ static bool of_get_nand_on_flash_bbt(struct device_node *np)
 	return of_property_read_bool(np, "nand-on-flash-bbt");
 }
 
-static int nand_dt_init(struct nand_chip *chip)
+static int rawnand_dt_init(struct nand_chip *chip)
 {
 	struct device_node *dn = nand_get_flash_node(chip);
-	int ecc_mode, ecc_algo, ecc_strength, ecc_step;
+	struct nand_device *nand = mtd_to_nanddev(nand_to_mtd(chip));
 
 	if (!dn)
 		return 0;
@@ -4822,25 +4736,21 @@ static int nand_dt_init(struct nand_chip *chip)
 	if (of_get_nand_on_flash_bbt(dn))
 		chip->bbt_options |= NAND_BBT_USE_FLASH;
 
-	ecc_mode = of_get_nand_ecc_mode(dn);
-	ecc_algo = of_get_nand_ecc_algo(dn);
-	ecc_strength = of_get_nand_ecc_strength(dn);
-	ecc_step = of_get_nand_ecc_step_size(dn);
-
-	if (ecc_mode >= 0)
-		chip->ecc.mode = ecc_mode;
-
-	if (ecc_algo >= 0)
-		chip->ecc.algo = ecc_algo;
-
-	if (ecc_strength >= 0)
-		chip->ecc.strength = ecc_strength;
-
-	if (ecc_step > 0)
-		chip->ecc.size = ecc_step;
-
-	if (of_property_read_bool(dn, "nand-ecc-maximize"))
-		chip->ecc.options |= NAND_ECC_MAXIMIZE;
+	nand_ecc_read_user_conf(nand);
+
+	/*
+	 * Raw NAND default provider is "hardware" (can be changed by the
+	 * drivers in the ->attach() phase).
+	 */
+	nand->ecc.defaults.provider = NAND_ECC_HW;
+	if (!nand->ecc.user_conf.provider)
+		nand->ecc.user_conf.provider = nand->ecc.defaults.provider;
+
+	/* Legacy parameters */
+	chip->ecc.mode = nand->ecc.user_conf.provider;
+	chip->ecc.algo = nand->ecc.user_conf.algo;
+	chip->ecc.strength = nand->ecc.user_conf.strength;
+	chip->ecc.size = nand->ecc.user_conf.step_size;
 
 	return 0;
 }
@@ -4876,7 +4786,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 	/* Enforce the right timings for reset/detection */
 	onfi_fill_data_interface(chip, NAND_SDR_IFACE, 0);
 
-	ret = nand_dt_init(chip);
+	ret = rawnand_dt_init(chip);
 	if (ret)
 		return ret;
 
@@ -4940,6 +4850,7 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
 static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 
 	if (WARN_ON(ecc->mode != NAND_ECC_SOFT))
@@ -5011,7 +4922,7 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 		 * used.
 		 */
 		if (mtd->ooblayout == &nand_ooblayout_lp_ops &&
-		    ecc->options & NAND_ECC_MAXIMIZE) {
+		    nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE) {
 			int steps, bytes;
 
 			/* Always prefer 1k blocks over 512bytes ones */
@@ -5249,11 +5160,12 @@ nand_maximize_ecc(struct nand_chip *chip,
  * @caps: ECC engine caps info structure
  * @oobavail: OOB size that the ECC engine can use
  *
- * Choose the ECC configuration according to following logic
+ * Choose the ECC configuration according to following logic.
  *
  * 1. If both ECC step size and ECC strength are already set (usually by DT)
  *    then check if it is supported by this controller.
- * 2. If NAND_ECC_MAXIMIZE is set, then select maximum ECC strength.
+ * 2. If the user provided the nand-ecc-maximize property, then select maximum
+ *    ECC strength.
  * 3. Otherwise, try to match the ECC step size and ECC strength closest
  *    to the chip's requirement. If available OOB size can't fit the chip
  *    requirement then fallback to the maximum ECC step size and ECC strength.
@@ -5264,6 +5176,7 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
 			 const struct nand_ecc_caps *caps, int oobavail)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 
 	if (WARN_ON(oobavail < 0 || oobavail > mtd->oobsize))
 		return -EINVAL;
@@ -5271,7 +5184,7 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
 	if (chip->ecc.size && chip->ecc.strength)
 		return nand_check_ecc_caps(chip, caps, oobavail);
 
-	if (chip->ecc.options & NAND_ECC_MAXIMIZE)
+	if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE)
 		return nand_maximize_ecc(chip, caps, oobavail);
 
 	if (!nand_match_ecc_req(chip, caps, oobavail))
@@ -5281,42 +5194,6 @@ int nand_ecc_choose_conf(struct nand_chip *chip,
 }
 EXPORT_SYMBOL_GPL(nand_ecc_choose_conf);
 
-/*
- * Check if the chip configuration meet the datasheet requirements.
-
- * If our configuration corrects A bits per B bytes and the minimum
- * required correction level is X bits per Y bytes, then we must ensure
- * both of the following are true:
- *
- * (1) A / B >= X / Y
- * (2) A >= X
- *
- * Requirement (1) ensures we can correct for the required bitflip density.
- * Requirement (2) ensures we can correct even when all bitflips are clumped
- * in the same sector.
- */
-static bool nand_ecc_strength_good(struct nand_chip *chip)
-{
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	struct nand_ecc_ctrl *ecc = &chip->ecc;
-	struct nand_ecc_conf *requirements = &chip->base.ecc.requirements;
-	int corr, ds_corr;
-
-	if (ecc->size == 0 || requirements->step_size == 0)
-		/* Not enough information */
-		return true;
-
-	/*
-	 * We get the number of corrected bits per page to compare
-	 * the correction density.
-	 */
-	corr = (mtd->writesize * ecc->strength) / ecc->size;
-	ds_corr = (mtd->writesize * requirements->strength) /
-		  requirements->step_size;
-
-	return corr >= ds_corr && ecc->strength >= requirements->strength;
-}
-
 static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos)
 {
 	struct nand_chip *chip = container_of(nand, struct nand_chip,
@@ -5372,6 +5249,7 @@ static const struct nand_ops rawnand_ops = {
 static int nand_scan_tail(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
 	int ret, i;
 
@@ -5594,7 +5472,7 @@ static int nand_scan_tail(struct nand_chip *chip)
 	mtd->oobavail = ret;
 
 	/* ECC sanity check: warn if it's too weak */
-	if (!nand_ecc_strength_good(chip))
+	if (!nand_ecc_correction_is_enough(nanddev))
 		pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n",
 			mtd->name);
 
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 43b22564da10..bff30a42f270 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -1681,6 +1681,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 				       struct device_node *np)
 {
 	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
+	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	struct nand_chip *nand = mtd_to_nand(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
@@ -1689,7 +1690,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 	int ret;
 	int i;
 
-	if (ecc->options & NAND_ECC_MAXIMIZE) {
+	if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE) {
 		int bytes;
 
 		ecc->size = 1024;
diff --git a/drivers/mtd/nand/raw/tegra_nand.c b/drivers/mtd/nand/raw/tegra_nand.c
index 31d547d96795..d3a4dd5cc945 100644
--- a/drivers/mtd/nand/raw/tegra_nand.c
+++ b/drivers/mtd/nand/raw/tegra_nand.c
@@ -838,7 +838,8 @@ static int tegra_nand_get_strength(struct nand_chip *chip, const int *strength,
 				   int strength_len, int bits_per_step,
 				   int oobsize)
 {
-	bool maximize = chip->ecc.options & NAND_ECC_MAXIMIZE;
+	struct nand_device *nanddev = mtd_to_nanddev(nand_to_mtd(chip));
+	bool maximize = nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE;
 	int i;
 
 	/*
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 277c0cf822b9..5db24fa073f2 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -126,6 +126,23 @@ extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
 extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops;
 extern const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops;
 
+enum nand_ecc_mode {
+	NAND_ECC_INVALID = 0,
+	NAND_ECC_NONE,
+	NAND_ECC_SOFT,
+	NAND_ECC_HW,
+	NAND_ECC_HW_SYNDROME,
+	NAND_ECC_HW_OOB_FIRST,
+	NAND_ECC_ON_DIE,
+};
+
+enum nand_ecc_algo {
+	NAND_ECC_UNKNOWN = 0,
+	NAND_ECC_HAMMING,
+	NAND_ECC_BCH,
+	NAND_ECC_RS,
+};
+
 /**
  * struct nand_ecc_conf - NAND ECC configuration
  * @provider: ECC engine provider type
@@ -144,6 +161,9 @@ struct nand_ecc_conf {
 
 #define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) }
 
+/* NAND ECC misc flags */
+#define NAND_ECC_MAXIMIZE BIT(0)
+
 /**
  * struct nand_bbt - bad block table object
  * @cache: in memory BBT cache
@@ -217,12 +237,14 @@ struct nand_ecc_engine {
 	struct nand_ecc_engine_ops *ops;
 };
 
+void nand_ecc_read_user_conf(struct nand_device *nand);
 int nand_ecc_init_ctx(struct nand_device *nand);
 void nand_ecc_cleanup_ctx(struct nand_device *nand);
 int nand_ecc_prepare_io_req(struct nand_device *nand,
 			    struct nand_page_io_req *req, void *oobbuf);
 int nand_ecc_finish_io_req(struct nand_device *nand,
 			   struct nand_page_io_req *req, void *oobbuf);
+bool nand_ecc_correction_is_enough(struct nand_device *nand);
 
 /**
  * struct nand_ecc - High-level ECC object
@@ -310,6 +332,17 @@ static inline struct mtd_info *nanddev_to_mtd(struct nand_device *nand)
 	return &nand->mtd;
 }
 
+/**
+ * nanddev_get_flash_node() - Get the device node attached to a NAND device
+ * @nand: NAND device
+ *
+ * Return: the device node linked to @nand.
+ */
+static inline struct device_node *nanddev_get_flash_node(struct nand_device *nand)
+{
+	return mtd_get_of_node(nanddev_to_mtd(nand));
+}
+
 /*
  * nanddev_bits_per_cell() - Get the number of bits per cell
  * @nand: NAND device
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 0c2beb6fcf0b..c5fdab30cf96 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -19,6 +19,7 @@
 #include <linux/wait.h>
 #include <linux/spinlock.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/flashchip.h>
 #include <linux/mtd/bbm.h>
 #include <linux/mtd/jedec.h>
@@ -84,26 +85,6 @@ struct nand_chip;
 
 #define NAND_DATA_IFACE_CHECK_ONLY	-1
 
-/*
- * Constants for ECC_MODES
- */
-enum nand_ecc_mode {
-	NAND_ECC_INVALID = 0,
-	NAND_ECC_NONE,
-	NAND_ECC_SOFT,
-	NAND_ECC_HW,
-	NAND_ECC_HW_SYNDROME,
-	NAND_ECC_HW_OOB_FIRST,
-	NAND_ECC_ON_DIE,
-};
-
-enum nand_ecc_algo {
-	NAND_ECC_UNKNOWN = 0,
-	NAND_ECC_HAMMING,
-	NAND_ECC_BCH,
-	NAND_ECC_RS,
-};
-
 /*
  * Constants for Hardware ECC
  */
@@ -121,7 +102,6 @@ enum nand_ecc_algo {
  * pages and you want to rely on the default implementation.
  */
 #define NAND_ECC_GENERIC_ERASED_CHECK	BIT(0)
-#define NAND_ECC_MAXIMIZE		BIT(1)
 
 /*
  * When using software implementation of Hamming, we can specify which byte
-- 
2.19.1


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

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

* [PATCH v2 14/36] mtd: nand: ecc: Move BCH code into the ecc/ directory
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (12 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 13/36] mtd: nand: Move ECC specific functions to ecc/engine.c Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 15/36] mtd: nand: ecc: Use SPDX license identifier for the software BCH code Miquel Raynal
                   ` (21 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Move generic ECC code in the ecc/ sub-directory for later re-use by
the SPI NAND layer.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/Kconfig                        | 11 +++++++++++
 drivers/mtd/nand/ecc/Makefile                       |  1 +
 drivers/mtd/nand/{raw/nand_bch.c => ecc/sw-bch.c}   |  2 +-
 drivers/mtd/nand/raw/Kconfig                        | 10 ----------
 drivers/mtd/nand/raw/Makefile                       |  1 -
 drivers/mtd/nand/raw/nand_base.c                    |  2 +-
 drivers/mtd/nand/raw/nandsim.c                      |  2 +-
 drivers/mtd/nand/raw/omap2.c                        |  2 +-
 include/linux/mtd/{nand_bch.h => nand-ecc-sw-bch.h} |  6 +++---
 9 files changed, 19 insertions(+), 18 deletions(-)
 rename drivers/mtd/nand/{raw/nand_bch.c => ecc/sw-bch.c} (99%)
 rename include/linux/mtd/{nand_bch.h => nand-ecc-sw-bch.h} (93%)

diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
index 01439f66ecbf..75a37f48e126 100644
--- a/drivers/mtd/nand/ecc/Kconfig
+++ b/drivers/mtd/nand/ecc/Kconfig
@@ -3,4 +3,15 @@ menu "ECC engine support"
 config MTD_NAND_ECC
 	tristate
 
+config MTD_NAND_ECC_SW_BCH
+	bool "Software BCH ECC engine"
+	select BCH
+	select MTD_NAND_ECC
+	default n
+	help
+	  This enables support for software BCH error correction. Binary BCH
+	  codes are more powerful and cpu intensive than traditional Hamming
+	  ECC codes. They are used with NAND devices requiring more than 1 bit
+	  of error correction.
+
 endmenu
diff --git a/drivers/mtd/nand/ecc/Makefile b/drivers/mtd/nand/ecc/Makefile
index c7367f834d81..36b6ee57ad61 100644
--- a/drivers/mtd/nand/ecc/Makefile
+++ b/drivers/mtd/nand/ecc/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_MTD_NAND_ECC)		+= engine.o
+obj-$(CONFIG_MTD_NAND_ECC_SW_BCH)	+= sw-bch.o
diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/ecc/sw-bch.c
similarity index 99%
rename from drivers/mtd/nand/raw/nand_bch.c
rename to drivers/mtd/nand/ecc/sw-bch.c
index 574c0ca16160..b640d5771382 100644
--- a/drivers/mtd/nand/raw/nand_bch.c
+++ b/drivers/mtd/nand/ecc/sw-bch.c
@@ -26,7 +26,7 @@
 #include <linux/bitops.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_bch.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/bch.h>
 
 /**
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 621991a242c1..44dcac13fc0b 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -21,16 +21,6 @@ menuconfig MTD_RAW_NAND
 
 if MTD_RAW_NAND
 
-config MTD_NAND_ECC_SW_BCH
-	bool "Support software BCH ECC"
-	select BCH
-	default n
-	help
-	  This enables support for software BCH error correction. Binary BCH
-	  codes are more powerful and cpu intensive than traditional Hamming
-	  ECC codes. They are used with NAND devices requiring more than 1 bit
-	  of error correction.
-
 comment "Raw/parallel NAND flash controllers"
 
 config MTD_NAND_DENALI
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index ffe95b157131..18ae42077b05 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -2,7 +2,6 @@
 
 obj-$(CONFIG_MTD_RAW_NAND)		+= nand.o
 obj-$(CONFIG_MTD_NAND_ECC_SW_HAMMING)	+= nand_ecc.o
-obj-$(CONFIG_MTD_NAND_ECC_SW_BCH)	+= nand_bch.o
 obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
 
 obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 9efe3dd578b5..8047e4f44601 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -40,7 +40,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
-#include <linux/mtd/nand_bch.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 670abe8d59ca..ae913f65be45 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -36,7 +36,7 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_bch.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/list.h>
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index eaf14813a3ab..3b77c36e43ee 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -26,7 +26,7 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <linux/mtd/nand_bch.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/platform_data/elm.h>
 
 #include <linux/omap-gpmc.h>
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
similarity index 93%
rename from include/linux/mtd/nand_bch.h
rename to include/linux/mtd/nand-ecc-sw-bch.h
index 06ce2b655c13..a682a15fa165 100644
--- a/include/linux/mtd/nand_bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -8,8 +8,8 @@
  * This file is the header for the NAND BCH ECC implementation.
  */
 
-#ifndef __MTD_NAND_BCH_H__
-#define __MTD_NAND_BCH_H__
+#ifndef __MTD_NAND_ECC_SW_BCH_H__
+#define __MTD_NAND_ECC_SW_BCH_H__
 
 struct mtd_info;
 struct nand_chip;
@@ -66,4 +66,4 @@ static inline void nand_bch_free(struct nand_bch_control *nbc) {}
 
 #endif /* CONFIG_MTD_NAND_ECC_SW_BCH */
 
-#endif /* __MTD_NAND_BCH_H__ */
+#endif /* __MTD_NAND_ECC_SW_BCH_H__ */
-- 
2.19.1


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

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

* [PATCH v2 15/36] mtd: nand: ecc: Use SPDX license identifier for the software BCH code
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (13 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 14/36] mtd: nand: ecc: Move BCH code into the ecc/ directory Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 16/36] mtd: nand: ecc: Turn the software BCH implementation generic Miquel Raynal
                   ` (20 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Remove the legacy license text and replace it with the new standard:
an SPDX license identifier.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-bch.c       | 15 +--------------
 include/linux/mtd/nand-ecc-sw-bch.h |  5 +----
 2 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-bch.c b/drivers/mtd/nand/ecc/sw-bch.c
index b640d5771382..2f8f3883c8a3 100644
--- a/drivers/mtd/nand/ecc/sw-bch.c
+++ b/drivers/mtd/nand/ecc/sw-bch.c
@@ -1,22 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * This file provides ECC correction for more than 1 bit per block of data,
  * using binary BCH codes. It relies on the generic BCH library lib/bch.c.
  *
  * Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.com>
- *
- * This file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 or (at your option) any
- * later version.
- *
- * This file is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this file; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
 #include <linux/types.h>
diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
index a682a15fa165..12107aa7c371 100644
--- a/include/linux/mtd/nand-ecc-sw-bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.com>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * This file is the header for the NAND BCH ECC implementation.
  */
 
-- 
2.19.1


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

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

* [PATCH v2 16/36] mtd: nand: ecc: Turn the software BCH implementation generic
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (14 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 15/36] mtd: nand: ecc: Use SPDX license identifier for the software BCH code Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 17/36] mtd: rawnand: Get rid of chip->ecc.priv Miquel Raynal
                   ` (19 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Add helpers in the raw NAND core to call the generic functions that
will be re-used by the SPI-NAND layer.

While at it, do some cleanup in the file and its header.

The only reason why rawnand_bch helpers are exported is that the OMAP2
driver uses them. This is something that should be fixed and these
helpers turned static.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-bch.c       | 192 ++++++++++++----------------
 drivers/mtd/nand/raw/nand_base.c    |  88 +++++++++++--
 drivers/mtd/nand/raw/nandsim.c      |   3 +-
 drivers/mtd/nand/raw/omap2.c        |  32 ++---
 include/linux/mtd/nand-ecc-sw-bch.h |  77 +++++------
 include/linux/mtd/rawnand.h         |   5 +
 6 files changed, 223 insertions(+), 174 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-bch.c b/drivers/mtd/nand/ecc/sw-bch.c
index 2f8f3883c8a3..aba78f5b1964 100644
--- a/drivers/mtd/nand/ecc/sw-bch.c
+++ b/drivers/mtd/nand/ecc/sw-bch.c
@@ -11,133 +11,132 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/nand-ecc-sw-bch.h>
-#include <linux/bch.h>
 
 /**
- * struct nand_bch_control - private NAND BCH control structure
- * @bch:       BCH control structure
- * @errloc:    error location array
- * @eccmask:   XOR ecc mask, allows erased pages to be decoded as valid
+ * nand_ecc_sw_bch_calculate - Calculate the ECC corresponding to a data block
+ *
+ * @nand: NAND device
+ * @buf: Input buffer with raw data
+ * @code: Output buffer with ECC
  */
-struct nand_bch_control {
-	struct bch_control   *bch;
-	unsigned int         *errloc;
-	unsigned char        *eccmask;
-};
-
-/**
- * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block
- * @chip:	NAND chip object
- * @buf:	input buffer with raw data
- * @code:	output buffer with ECC
- */
-int nand_bch_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
-			   unsigned char *code)
+int nand_ecc_sw_bch_calculate(struct nand_device *nand,
+			      const unsigned char *buf, unsigned char *code)
 {
-	struct nand_bch_control *nbc = chip->ecc.priv;
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
 	unsigned int i;
 
-	memset(code, 0, chip->ecc.bytes);
-	encode_bch(nbc->bch, buf, chip->ecc.size, code);
+	memset(code, 0, engine_conf->code_size);
+	encode_bch(engine_conf->bch, buf, nand->ecc.ctx.conf.step_size, code);
 
 	/* apply mask so that an erased page is a valid codeword */
-	for (i = 0; i < chip->ecc.bytes; i++)
-		code[i] ^= nbc->eccmask[i];
+	for (i = 0; i < engine_conf->code_size; i++)
+		code[i] ^= engine_conf->eccmask[i];
 
 	return 0;
 }
-EXPORT_SYMBOL(nand_bch_calculate_ecc);
+EXPORT_SYMBOL(nand_ecc_sw_bch_calculate);
 
 /**
- * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
- * @chip:	NAND chip object
- * @buf:	raw data read from the chip
- * @read_ecc:	ECC from the chip
- * @calc_ecc:	the ECC calculated from raw data
+ * nand_ecc_sw_bch_correct - Detect, correct and report bit error(s)
  *
- * Detect and correct bit errors for a data byte block
+ * @nand: NAND device
+ * @buf: Raw data read from the chip
+ * @read_ecc: ECC bytes from the chip
+ * @calc_ecc: ECC calculated from the raw data
+ *
+ * Detect and correct bit errors for a data block.
  */
-int nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
-			  unsigned char *read_ecc, unsigned char *calc_ecc)
+int nand_ecc_sw_bch_correct(struct nand_device *nand, unsigned char *buf,
+			    unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-	struct nand_bch_control *nbc = chip->ecc.priv;
-	unsigned int *errloc = nbc->errloc;
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
+	unsigned int step_size = nand->ecc.ctx.conf.step_size;
+	unsigned int *errloc = engine_conf->errloc;
 	int i, count;
 
-	count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
-			   NULL, errloc);
+	count = decode_bch(engine_conf->bch, NULL, step_size, read_ecc,
+			   calc_ecc, NULL, errloc);
 	if (count > 0) {
 		for (i = 0; i < count; i++) {
-			if (errloc[i] < (chip->ecc.size*8))
-				/* error is located in data, correct it */
+			if (errloc[i] < (step_size * 8))
+				/* The error is in the data: correct it */
 				buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
-			/* else error in ecc, no action needed */
 
+			/* Otherwise the error is in the ECC: nothing to do */
 			pr_debug("%s: corrected bitflip %u\n", __func__,
-					errloc[i]);
+				 errloc[i]);
 		}
 	} else if (count < 0) {
-		pr_err("ecc unrecoverable error\n");
+		pr_err("ECC unrecoverable error\n");
 		count = -EBADMSG;
 	}
+
 	return count;
 }
-EXPORT_SYMBOL(nand_bch_correct_data);
+EXPORT_SYMBOL(nand_ecc_sw_bch_correct);
 
 /**
- * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
- * @mtd:	MTD block structure
+ * nand_ecc_sw_bch_cleanup - Cleanup software BCH ECC resources
+ * @nand: NAND device
+ */
+void nand_ecc_sw_bch_cleanup(struct nand_device *nand)
+{
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
+
+	free_bch(engine_conf->bch);
+	kfree(engine_conf->errloc);
+	kfree(engine_conf->eccmask);
+}
+EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup);
+
+/**
+ * nand_ecc_sw_bch_init - Initialize software BCH ECC engine
+ * @nand: NAND device
  *
- * Returns:
- *  a pointer to a new NAND BCH control structure, or NULL upon failure
+ * Returns: a pointer to a new NAND BCH control structure, or NULL upon failure
  *
- * Initialize NAND BCH error correction. Parameters @eccsize and @eccbytes
- * are used to compute BCH parameters m (Galois field order) and t (error
- * correction capability). @eccbytes should be equal to the number of bytes
- * required to store m*t bits, where m is such that 2^m-1 > @eccsize*8.
+ * Initialize NAND BCH error correction. @nand.ecc parameters 'step_size' and
+ * 'bytes' are used to compute BCH parameters m (Galois field order) and t
+ * (error correction capability). 'bytes' should be equal to the number of bytes
+ * required to store m*t bits, where m is such that 2^m-1 > step_size*8.
  *
  * Example: to configure 4 bit correction per 512 bytes, you should pass
- * @eccsize = 512  (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
- * @eccbytes = 7   (7 bytes are required to store m*t = 13*4 = 52 bits)
+ * step_size = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
+ * bytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits)
  */
-struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
+int nand_ecc_sw_bch_init(struct nand_device *nand)
 {
-	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
 	unsigned int m, t, eccsteps, i;
-	struct nand_bch_control *nbc = NULL;
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
 	unsigned char *erased_page;
-	unsigned int eccsize = nand->ecc.size;
-	unsigned int eccbytes = nand->ecc.bytes;
-	unsigned int eccstrength = nand->ecc.strength;
+	unsigned int eccsize = nand->ecc.ctx.conf.step_size;
+	unsigned int eccbytes = engine_conf->code_size;
+	unsigned int eccstrength = nand->ecc.ctx.conf.strength;
 
 	if (!eccbytes && eccstrength) {
 		eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
-		nand->ecc.bytes = eccbytes;
+		engine_conf->code_size = eccbytes;
 	}
 
 	if (!eccsize || !eccbytes) {
 		pr_warn("ecc parameters not supplied\n");
-		goto fail;
+		return -EINVAL;
 	}
 
 	m = fls(1+8*eccsize);
 	t = (eccbytes*8)/m;
 
-	nbc = kzalloc(sizeof(*nbc), GFP_KERNEL);
-	if (!nbc)
-		goto fail;
-
-	nbc->bch = init_bch(m, t, 0);
-	if (!nbc->bch)
-		goto fail;
+	engine_conf->bch = init_bch(m, t, 0);
+	if (!engine_conf->bch)
+		return -EINVAL;
 
 	/* verify that eccbytes has the expected value */
-	if (nbc->bch->ecc_bytes != eccbytes) {
+	if (engine_conf->bch->ecc_bytes != eccbytes) {
 		pr_warn("invalid eccbytes %u, should be %u\n",
-			eccbytes, nbc->bch->ecc_bytes);
+			eccbytes, engine_conf->bch->ecc_bytes);
 		goto fail;
 	}
 
@@ -155,24 +154,15 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 		goto fail;
 	}
 
-	/*
-	 * ecc->steps and ecc->total might be used by mtd->ooblayout->ecc(),
-	 * which is called by mtd_ooblayout_count_eccbytes().
-	 * Make sure they are properly initialized before calling
-	 * mtd_ooblayout_count_eccbytes().
-	 * FIXME: we should probably rework the sequencing in nand_scan_tail()
-	 * to avoid setting those fields twice.
-	 */
-	nand->ecc.steps = eccsteps;
-	nand->ecc.total = eccsteps * eccbytes;
 	if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) {
 		pr_warn("invalid ecc layout\n");
 		goto fail;
 	}
 
-	nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
-	nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL);
-	if (!nbc->eccmask || !nbc->errloc)
+	engine_conf->eccmask = kmalloc(eccbytes, GFP_KERNEL);
+	engine_conf->errloc = kmalloc_array(t, sizeof(*engine_conf->errloc),
+					    GFP_KERNEL);
+	if (!engine_conf->eccmask || !engine_conf->errloc)
 		goto fail;
 	/*
 	 * compute and store the inverted ecc of an erased ecc block
@@ -182,37 +172,25 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
 		goto fail;
 
 	memset(erased_page, 0xff, eccsize);
-	memset(nbc->eccmask, 0, eccbytes);
-	encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
+	memset(engine_conf->eccmask, 0, eccbytes);
+	encode_bch(engine_conf->bch, erased_page, eccsize,
+		   engine_conf->eccmask);
 	kfree(erased_page);
 
 	for (i = 0; i < eccbytes; i++)
-		nbc->eccmask[i] ^= 0xff;
+		engine_conf->eccmask[i] ^= 0xff;
 
 	if (!eccstrength)
-		nand->ecc.strength = (eccbytes * 8) / fls(8 * eccsize);
+		nand->ecc.ctx.conf.strength = (eccbytes * 8) / fls(8 * eccsize);
+
+	return 0;
 
-	return nbc;
 fail:
-	nand_bch_free(nbc);
-	return NULL;
-}
-EXPORT_SYMBOL(nand_bch_init);
+	nand_ecc_sw_bch_cleanup(nand);
 
-/**
- * nand_bch_free - [NAND Interface] Release NAND BCH ECC resources
- * @nbc:	NAND BCH control structure
- */
-void nand_bch_free(struct nand_bch_control *nbc)
-{
-	if (nbc) {
-		free_bch(nbc->bch);
-		kfree(nbc->errloc);
-		kfree(nbc->eccmask);
-		kfree(nbc);
-	}
+	return -EINVAL;
 }
-EXPORT_SYMBOL(nand_bch_free);
+EXPORT_SYMBOL(nand_ecc_sw_bch_init);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8047e4f44601..d6dd0ef42585 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4847,11 +4847,73 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
 	kfree(chip->parameters.onfi);
 }
 
+int rawnand_sw_bch_init(struct nand_chip *chip)
+{
+	struct nand_device *base = &chip->base;
+	struct nand_ecc_sw_bch_conf *engine_conf;
+	int ret;
+
+	base->ecc.user_conf.provider = NAND_ECC_SOFT;
+	base->ecc.user_conf.algo = NAND_ECC_BCH;
+	base->ecc.user_conf.step_size = chip->ecc.size;
+	base->ecc.user_conf.strength = chip->ecc.strength;
+
+	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
+	if (!engine_conf)
+		return -ENOMEM;
+
+	engine_conf->code_size = chip->ecc.bytes;
+
+	base->ecc.ctx.priv = engine_conf;
+
+	ret = nand_ecc_sw_bch_init(base);
+	if (ret)
+		kfree(base->ecc.ctx.priv);
+
+	chip->ecc.size = base->ecc.ctx.conf.step_size;
+	chip->ecc.strength = base->ecc.ctx.conf.strength;
+	chip->ecc.total = base->ecc.ctx.total;
+	chip->ecc.steps = engine_conf->nsteps;
+	chip->ecc.bytes = engine_conf->code_size;
+
+	return ret;
+}
+EXPORT_SYMBOL(rawnand_sw_bch_init);
+
+static int rawnand_sw_bch_calculate(struct nand_chip *chip,
+				    const unsigned char *buf,
+				    unsigned char *code)
+{
+	struct nand_device *base = &chip->base;
+
+	return nand_ecc_sw_bch_calculate(base, buf, code);
+}
+
+int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
+			   unsigned char *read_ecc, unsigned char *calc_ecc)
+{
+	struct nand_device *base = &chip->base;
+
+	return nand_ecc_sw_bch_correct(base, buf, read_ecc, calc_ecc);
+}
+EXPORT_SYMBOL(rawnand_sw_bch_correct);
+
+void rawnand_sw_bch_cleanup(struct nand_chip *chip)
+{
+	struct nand_device *base = &chip->base;
+
+	nand_ecc_sw_bch_cleanup(base);
+
+	kfree(base->ecc.ctx.priv);
+}
+EXPORT_SYMBOL(rawnand_sw_bch_cleanup);
+
 static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	struct nand_ecc_ctrl *ecc = &chip->ecc;
+	int ret;
 
 	if (WARN_ON(ecc->mode != NAND_ECC_SOFT))
 		return -EINVAL;
@@ -4877,12 +4939,12 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 
 		return 0;
 	case NAND_ECC_BCH:
-		if (!mtd_nand_has_bch()) {
+		if (!IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)) {
 			WARN(1, "CONFIG_MTD_NAND_ECC_SW_BCH not enabled\n");
 			return -EINVAL;
 		}
-		ecc->calculate = nand_bch_calculate_ecc;
-		ecc->correct = nand_bch_correct_data;
+		ecc->calculate = rawnand_sw_bch_calculate;
+		ecc->correct = rawnand_sw_bch_correct;
 		ecc->read_page = nand_read_page_swecc;
 		ecc->read_subpage = nand_read_subpage;
 		ecc->write_page = nand_write_page_swecc;
@@ -4934,13 +4996,14 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 			ecc->strength = bytes * 8 / fls(8 * ecc->size);
 		}
 
-		/* See nand_bch_init() for details. */
+		/* See ecc_sw_bch_init() for details. */
 		ecc->bytes = 0;
-		ecc->priv = nand_bch_init(mtd);
-		if (!ecc->priv) {
+		ret = rawnand_sw_bch_init(chip);
+		if (ret) {
 			WARN(1, "BCH ECC initialization failed!\n");
-			return -EINVAL;
+			return ret;
 		}
+
 		return 0;
 	default:
 		WARN(1, "Unsupported ECC algorithm!\n");
@@ -5447,14 +5510,17 @@ static int nand_scan_tail(struct nand_chip *chip)
 	 * Set the number of read / write steps for one page depending on ECC
 	 * mode.
 	 */
-	ecc->steps = mtd->writesize / ecc->size;
+	if (!ecc->steps)
+		ecc->steps = mtd->writesize / ecc->size;
 	if (ecc->steps * ecc->size != mtd->writesize) {
 		WARN(1, "Invalid ECC parameters\n");
 		ret = -EINVAL;
 		goto err_nand_manuf_cleanup;
 	}
-	ecc->total = ecc->steps * ecc->bytes;
-	chip->base.ecc.ctx.total = ecc->total;
+
+	if (!ecc->total)
+		ecc->total = ecc->steps * ecc->bytes;
+
 	if (ecc->total > mtd->oobsize) {
 		WARN(1, "Total number of ECC bytes exceeded oobsize\n");
 		ret = -EINVAL;
@@ -5643,7 +5709,7 @@ void nand_cleanup(struct nand_chip *chip)
 {
 	if (chip->ecc.mode == NAND_ECC_SOFT &&
 	    chip->ecc.algo == NAND_ECC_BCH)
-		nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
+		rawnand_sw_bch_cleanup(chip);
 
 	/* Free bad block table memory */
 	kfree(chip->bbt);
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index ae913f65be45..a60b972dd211 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -36,7 +36,6 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/list.h>
@@ -2175,7 +2174,7 @@ static int ns_attach_chip(struct nand_chip *chip)
 	if (!bch)
 		return 0;
 
-	if (!mtd_nand_has_bch()) {
+	if (!IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)) {
 		NS_ERR("BCH ECC support is disabled\n");
 		return -EINVAL;
 	}
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index 3b77c36e43ee..5e526499824e 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -26,7 +26,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-#include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/platform_data/elm.h>
 
 #include <linux/omap-gpmc.h>
@@ -2051,16 +2050,16 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
 		chip->ecc.bytes		= 7;
 		chip->ecc.strength	= 4;
 		chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		chip->ecc.correct	= nand_bch_correct_data;
+		chip->ecc.correct	= rawnand_sw_bch_correct;
 		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) {
+		err = rawnand_sw_bch_init(chip);
+		if (err) {
 			dev_err(dev, "Unable to use BCH library\n");
-			return -EINVAL;
+			return err;
 		}
 		break;
 
@@ -2093,16 +2092,16 @@ static int omap_nand_attach_chip(struct nand_chip *chip)
 		chip->ecc.bytes		= 13;
 		chip->ecc.strength	= 8;
 		chip->ecc.hwctl		= omap_enable_hwecc_bch;
-		chip->ecc.correct	= nand_bch_correct_data;
+		chip->ecc.correct	= rawnand_sw_bch_correct;
 		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) {
+		err = rawnand_sw_bch_init(chip);
+		if (err) {
 			dev_err(dev, "unable to use BCH library\n");
-			return -EINVAL;
+			return err;
 		}
 		break;
 
@@ -2208,7 +2207,6 @@ static int omap_nand_probe(struct platform_device *pdev)
 	nand_chip		= &info->nand;
 	mtd			= nand_to_mtd(nand_chip);
 	mtd->dev.parent		= &pdev->dev;
-	nand_chip->ecc.priv	= NULL;
 	nand_set_flash_node(nand_chip, dev->of_node);
 
 	if (!mtd->name) {
@@ -2278,10 +2276,9 @@ static int omap_nand_probe(struct platform_device *pdev)
 return_error:
 	if (!IS_ERR_OR_NULL(info->dma))
 		dma_release_channel(info->dma);
-	if (nand_chip->ecc.priv) {
-		nand_bch_free(nand_chip->ecc.priv);
-		nand_chip->ecc.priv = NULL;
-	}
+
+	rawnand_sw_bch_cleanup(nand_chip);
+
 	return err;
 }
 
@@ -2290,10 +2287,9 @@ static int omap_nand_remove(struct platform_device *pdev)
 	struct mtd_info *mtd = platform_get_drvdata(pdev);
 	struct nand_chip *nand_chip = mtd_to_nand(mtd);
 	struct omap_nand_info *info = mtd_to_omap(mtd);
-	if (nand_chip->ecc.priv) {
-		nand_bch_free(nand_chip->ecc.priv);
-		nand_chip->ecc.priv = NULL;
-	}
+
+	rawnand_sw_bch_cleanup(nand_chip);
+
 	if (info->dma)
 		dma_release_channel(info->dma);
 	nand_release(nand_chip);
diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
index 12107aa7c371..509723870fc8 100644
--- a/include/linux/mtd/nand-ecc-sw-bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -8,58 +8,63 @@
 #ifndef __MTD_NAND_ECC_SW_BCH_H__
 #define __MTD_NAND_ECC_SW_BCH_H__
 
-struct mtd_info;
-struct nand_chip;
-struct nand_bch_control;
+#include <linux/mtd/nand.h>
+#include <linux/bch.h>
+
+/**
+ * struct nand_ecc_sw_bch_conf - private software BCH ECC engine structure
+ * @reqooblen: Save the actual user OOB length requested before overwriting it
+ * @code_size: Number of bytes needed to store a code (one code per step)
+ * @nsteps: Number of steps
+ * @calc_buf: Buffer to use when calculating ECC bytes
+ * @code_buf: Buffer to use when reading (raw) ECC bytes from the chip
+ * @bch: BCH control structure
+ * @errloc: error location array
+ * @eccmask: XOR ecc mask, allows erased pages to be decoded as valid
+ */
+struct nand_ecc_sw_bch_conf {
+	unsigned int reqooblen;
+	unsigned int code_size;
+	unsigned int nsteps;
+	u8 *calc_buf;
+	u8 *code_buf;
+	struct bch_control *bch;
+	unsigned int *errloc;
+	unsigned char *eccmask;
+};
 
 #if defined(CONFIG_MTD_NAND_ECC_SW_BCH)
 
-static inline int mtd_nand_has_bch(void) { return 1; }
-
-/*
- * Calculate BCH ecc code
- */
-int nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
-			   u_char *ecc_code);
-
-/*
- * Detect and correct bit errors
- */
-int nand_bch_correct_data(struct nand_chip *chip, u_char *dat,
-			  u_char *read_ecc, u_char *calc_ecc);
-/*
- * Initialize BCH encoder/decoder
- */
-struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
-/*
- * Release BCH encoder/decoder resources
- */
-void nand_bch_free(struct nand_bch_control *nbc);
+int nand_ecc_sw_bch_calculate(struct nand_device *nand,
+			      const unsigned char *buf, unsigned char *code);
+int nand_ecc_sw_bch_correct(struct nand_device *nand, unsigned char *buf,
+			    unsigned char *read_ecc, unsigned char *calc_ecc);
+int nand_ecc_sw_bch_init(struct nand_device *nand);
+void nand_ecc_sw_bch_cleanup(struct nand_device *nand);
 
 #else /* !CONFIG_MTD_NAND_ECC_SW_BCH */
 
-static inline int mtd_nand_has_bch(void) { return 0; }
-
-static inline int
-nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
-		       u_char *ecc_code)
+static inline int nand_ecc_sw_bch_calculate(struct nand_device *nand,
+					    const unsigned char *buf,
+					    unsigned char *code)
 {
-	return -1;
+	return -ENOTSUPP;
 }
 
-static inline int
-nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
-		      unsigned char *read_ecc, unsigned char *calc_ecc)
+static inline int nand_ecc_sw_bch_correct(struct nand_device *nand,
+					  unsigned char *buf,
+					  unsigned char *read_ecc,
+					  unsigned char *calc_ecc)
 {
 	return -ENOTSUPP;
 }
 
-static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
+static inline int nand_ecc_sw_bch_init(struct nand_device *nand)
 {
-	return NULL;
+	return -EINVAL;
 }
 
-static inline void nand_bch_free(struct nand_bch_control *nbc) {}
+static inline void nand_ecc_sw_bch_cleanup(struct nand_device *nand) {}
 
 #endif /* CONFIG_MTD_NAND_ECC_SW_BCH */
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index c5fdab30cf96..72d4672b424b 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1232,6 +1232,11 @@ static inline int nand_opcode_8bits(unsigned int command)
 	return 0;
 }
 
+int rawnand_sw_bch_init(struct nand_chip *chip);
+int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
+			   unsigned char *read_ecc, unsigned char *calc_ecc);
+void rawnand_sw_bch_cleanup(struct nand_chip *chip);
+
 int nand_check_erased_ecc_chunk(void *data, int datalen,
 				void *ecc, int ecclen,
 				void *extraoob, int extraooblen,
-- 
2.19.1


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

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

* [PATCH v2 17/36] mtd: rawnand: Get rid of chip->ecc.priv
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (15 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 16/36] mtd: nand: ecc: Turn the software BCH implementation generic Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 18/36] mtd: nand: ecc: Move Hamming code into the ecc/ directory Miquel Raynal
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

nand_ecc_ctrl embeds a private pointer which had only a meaning in the
sunxi driver. This structure will soon be deprecated, but as this
field is actually not needed, let's just drop it.

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

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index bff30a42f270..b30f5a31e8a0 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -199,6 +199,7 @@ struct sunxi_nand_hw_ecc {
 struct sunxi_nand_chip {
 	struct list_head node;
 	struct nand_chip nand;
+	struct sunxi_nand_hw_ecc *ecc;
 	unsigned long clk_rate;
 	u32 timing_cfg;
 	u32 timing_ctl;
@@ -230,6 +231,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  *			this NAND controller
  * @complete:		a completion object used to wait for NAND
  *			controller events
+ * @ecc:		ECC controller structure
  */
 struct sunxi_nfc {
 	struct nand_controller controller;
@@ -773,15 +775,15 @@ static void sunxi_nfc_randomizer_read_buf(struct mtd_info *mtd, uint8_t *buf,
 static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
 {
 	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
-	struct sunxi_nand_hw_ecc *data = nand->ecc.priv;
 	u32 ecc_ctl;
 
 	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
 	ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
 		     NFC_ECC_BLOCK_SIZE_MSK);
-	ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION |
-		   NFC_ECC_PIPELINE;
+	ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(sunxi_nand->ecc->mode) |
+		   NFC_ECC_EXCEPTION | NFC_ECC_PIPELINE;
 
 	if (nand->ecc.size == 512)
 		ecc_ctl |= NFC_ECC_BLOCK_512;
@@ -1671,9 +1673,9 @@ static const struct mtd_ooblayout_ops sunxi_nand_ooblayout_ops = {
 	.free = sunxi_nand_ooblayout_free,
 };
 
-static void sunxi_nand_hw_ecc_ctrl_cleanup(struct nand_ecc_ctrl *ecc)
+static void sunxi_nand_hw_ecc_ctrl_cleanup(struct sunxi_nand_chip *sunxi_nand)
 {
-	kfree(ecc->priv);
+	kfree(sunxi_nand->ecc);
 }
 
 static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
@@ -1685,7 +1687,6 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 	struct nand_chip *nand = mtd_to_nand(mtd);
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
-	struct sunxi_nand_hw_ecc *data;
 	int nsectors;
 	int ret;
 	int i;
@@ -1722,8 +1723,8 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 	if (ecc->size != 512 && ecc->size != 1024)
 		return -EINVAL;
 
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data)
+	sunxi_nand->ecc = kzalloc(sizeof(*sunxi_nand->ecc), GFP_KERNEL);
+	if (!sunxi_nand->ecc)
 		return -ENOMEM;
 
 	/* Prefer 1k ECC chunk over 512 ones */
@@ -1750,7 +1751,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 		goto err;
 	}
 
-	data->mode = i;
+	sunxi_nand->ecc->mode = i;
 
 	/* HW ECC always request ECC bytes for 1024 bytes blocks */
 	ecc->bytes = DIV_ROUND_UP(ecc->strength * fls(8 * 1024), 8);
@@ -1768,7 +1769,6 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 	ecc->read_oob = sunxi_nfc_hw_ecc_read_oob;
 	ecc->write_oob = sunxi_nfc_hw_ecc_write_oob;
 	mtd_set_ooblayout(mtd, &sunxi_nand_ooblayout_ops);
-	ecc->priv = data;
 
 	if (nfc->dmac) {
 		ecc->read_page = sunxi_nfc_hw_ecc_read_page_dma;
@@ -1789,16 +1789,16 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct mtd_info *mtd,
 	return 0;
 
 err:
-	kfree(data);
+	kfree(sunxi_nand->ecc);
 
 	return ret;
 }
 
-static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
+static void sunxi_nand_ecc_cleanup(struct sunxi_nand_chip *sunxi_nand)
 {
-	switch (ecc->mode) {
+	switch (sunxi_nand->ecc->mode) {
 	case NAND_ECC_HW:
-		sunxi_nand_hw_ecc_ctrl_cleanup(ecc);
+		sunxi_nand_hw_ecc_ctrl_cleanup(sunxi_nand);
 		break;
 	case NAND_ECC_NONE:
 	default:
@@ -1980,7 +1980,7 @@ static void sunxi_nand_chips_cleanup(struct sunxi_nfc *nfc)
 		chip = list_first_entry(&nfc->chips, struct sunxi_nand_chip,
 					node);
 		nand_release(&chip->nand);
-		sunxi_nand_ecc_cleanup(&chip->nand.ecc);
+		sunxi_nand_ecc_cleanup(chip);
 		list_del(&chip->node);
 	}
 }
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index 72d4672b424b..b0c6e1ac3989 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -279,7 +279,6 @@ static const struct nand_ecc_caps __name = {			\
  * @prepad:	padding information for syndrome based ECC generators
  * @postpad:	padding information for syndrome based ECC generators
  * @options:	ECC specific options (see NAND_ECC_XXX flags defined above)
- * @priv:	pointer to private ECC control data
  * @calc_buf:	buffer for calculated ECC, size is oobsize.
  * @code_buf:	buffer for ECC read from flash, size is oobsize.
  * @hwctl:	function to control hardware ECC generator. Must only
@@ -331,7 +330,6 @@ struct nand_ecc_ctrl {
 	int prepad;
 	int postpad;
 	unsigned int options;
-	void *priv;
 	u8 *calc_buf;
 	u8 *code_buf;
 	void (*hwctl)(struct nand_chip *chip, int mode);
-- 
2.19.1


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

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

* [PATCH v2 18/36] mtd: nand: ecc: Move Hamming code into the ecc/ directory
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (16 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 17/36] mtd: rawnand: Get rid of chip->ecc.priv Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 19/36] mtd: nand: ecc: Use SPDX license identifier for the software Hamming code Miquel Raynal
                   ` (17 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Move software Hamming ECC code in the ecc/ sub-directory for later
re-use by the SPI NAND layer.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 arch/arm/mach-s3c24xx/common-smdk.c                   |  2 +-
 arch/arm/mach-s3c24xx/mach-anubis.c                   |  2 +-
 arch/arm/mach-s3c24xx/mach-at2440evb.c                |  2 +-
 arch/arm/mach-s3c24xx/mach-bast.c                     |  2 +-
 arch/arm/mach-s3c24xx/mach-gta02.c                    |  2 +-
 arch/arm/mach-s3c24xx/mach-jive.c                     |  2 +-
 arch/arm/mach-s3c24xx/mach-mini2440.c                 |  2 +-
 arch/arm/mach-s3c24xx/mach-osiris.c                   |  2 +-
 arch/arm/mach-s3c24xx/mach-qt2410.c                   |  2 +-
 arch/arm/mach-s3c24xx/mach-rx3715.c                   |  2 +-
 arch/arm/mach-s3c24xx/mach-vstms.c                    |  2 +-
 drivers/mtd/nand/ecc/Kconfig                          | 11 +++++++++++
 drivers/mtd/nand/ecc/Makefile                         |  1 +
 drivers/mtd/nand/{raw/nand_ecc.c => ecc/sw-hamming.c} |  2 +-
 drivers/mtd/nand/raw/Kconfig                          | 11 -----------
 drivers/mtd/nand/raw/Makefile                         |  1 -
 drivers/mtd/nand/raw/cs553x_nand.c                    |  2 +-
 drivers/mtd/nand/raw/fsl_elbc_nand.c                  |  2 +-
 drivers/mtd/nand/raw/fsl_ifc_nand.c                   |  2 +-
 drivers/mtd/nand/raw/fsl_upm.c                        |  2 +-
 drivers/mtd/nand/raw/fsmc_nand.c                      |  2 +-
 drivers/mtd/nand/raw/lpc32xx_mlc.c                    |  2 +-
 drivers/mtd/nand/raw/lpc32xx_slc.c                    |  2 +-
 drivers/mtd/nand/raw/nand_base.c                      |  2 +-
 drivers/mtd/nand/raw/ndfc.c                           |  2 +-
 drivers/mtd/nand/raw/pasemi_nand.c                    |  2 +-
 drivers/mtd/nand/raw/s3c2410.c                        |  2 +-
 drivers/mtd/nand/raw/sharpsl.c                        |  2 +-
 drivers/mtd/nand/raw/tmio_nand.c                      |  2 +-
 drivers/mtd/nand/raw/txx9ndfmc.c                      |  2 +-
 drivers/mtd/sm_ftl.c                                  |  2 +-
 drivers/mtd/tests/mtd_nandecctest.c                   |  2 +-
 .../linux/mtd/{nand_ecc.h => nand-ecc-sw-hamming.h}   |  6 +++---
 include/linux/mtd/sharpsl.h                           |  2 +-
 34 files changed, 44 insertions(+), 44 deletions(-)
 rename drivers/mtd/nand/{raw/nand_ecc.c => ecc/sw-hamming.c} (99%)
 rename include/linux/mtd/{nand_ecc.h => nand-ecc-sw-hamming.h} (90%)

diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index 58e30cad386c..ffe34a5a3174 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -19,7 +19,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 072966dcad78..83472294191b 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -36,7 +36,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <net/ax88796.h>
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 58c5ef3cf1d7..c841b90695b9 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -37,7 +37,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index a7c3955ae8f6..4f3d3e819a2a 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -24,7 +24,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/platform_data/asoc-s3c24xx_simtec.h>
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 594901f3b8e5..1c6f11216c0c 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -36,7 +36,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index 885e8f12e4b9..b2afb4099ab4 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -40,7 +40,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 9035f868fb34..8c173a6f1bdc 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -46,7 +46,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index ee3630cb236a..0dd72072aa3d 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -33,7 +33,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 5d48e5b6e738..19f2e12130ec 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -21,7 +21,7 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index 529c6faf862f..05aac6499d82 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -22,7 +22,7 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index d76b28b65e65..e0218ae0040e 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -16,7 +16,7 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/memblock.h>
 
diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
index 75a37f48e126..7be48a7efda0 100644
--- a/drivers/mtd/nand/ecc/Kconfig
+++ b/drivers/mtd/nand/ecc/Kconfig
@@ -3,6 +3,17 @@ menu "ECC engine support"
 config MTD_NAND_ECC
 	tristate
 
+config MTD_NAND_ECC_SW_HAMMING
+	tristate
+
+config MTD_NAND_ECC_SW_HAMMING_SMC
+	bool "NAND ECC Smart Media byte order"
+	depends on MTD_NAND_ECC_SW_HAMMING
+	default n
+	help
+	  Software ECC according to the Smart Media Specification.
+	  The original Linux implementation had byte 0 and 1 swapped.
+
 config MTD_NAND_ECC_SW_BCH
 	bool "Software BCH ECC engine"
 	select BCH
diff --git a/drivers/mtd/nand/ecc/Makefile b/drivers/mtd/nand/ecc/Makefile
index 36b6ee57ad61..353277fecb38 100644
--- a/drivers/mtd/nand/ecc/Makefile
+++ b/drivers/mtd/nand/ecc/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_MTD_NAND_ECC)		+= engine.o
+obj-$(CONFIG_MTD_NAND_ECC_SW_HAMMING)	+= sw-hamming.o
 obj-$(CONFIG_MTD_NAND_ECC_SW_BCH)	+= sw-bch.o
diff --git a/drivers/mtd/nand/raw/nand_ecc.c b/drivers/mtd/nand/ecc/sw-hamming.c
similarity index 99%
rename from drivers/mtd/nand/raw/nand_ecc.c
rename to drivers/mtd/nand/ecc/sw-hamming.c
index 4f4347533058..b6931cd9f401 100644
--- a/drivers/mtd/nand/raw/nand_ecc.c
+++ b/drivers/mtd/nand/ecc/sw-hamming.c
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <asm/byteorder.h>
 
 /*
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 44dcac13fc0b..770c73c1bb7d 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -1,14 +1,3 @@
-config MTD_NAND_ECC_SW_HAMMING
-	tristate
-
-config MTD_NAND_ECC_SW_HAMMING_SMC
-	bool "NAND ECC Smart Media byte order"
-	depends on MTD_NAND_ECC_SW_HAMMING
-	default n
-	help
-	  Software ECC according to the Smart Media Specification.
-	  The original Linux implementation had byte 0 and 1 swapped.
-
 menuconfig MTD_RAW_NAND
 	tristate "Raw/Parallel NAND Device Support"
 	select MTD_NAND_CORE
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 18ae42077b05..a5ce9cec8dd3 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_MTD_RAW_NAND)		+= nand.o
-obj-$(CONFIG_MTD_NAND_ECC_SW_HAMMING)	+= nand_ecc.o
 obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
 
 obj-$(CONFIG_MTD_NAND_CAFE)		+= cafe_nand.o
diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
index c6f578aff5d9..98cc55df27b1 100644
--- a/drivers/mtd/nand/raw/cs553x_nand.c
+++ b/drivers/mtd/nand/raw/cs553x_nand.c
@@ -23,7 +23,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/msr.h>
diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index 293a5b71833a..a43f9373ce22 100644
--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
@@ -35,7 +35,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/io.h>
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index 04a3dcd675bf..7f7e1ecf612c 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -28,7 +28,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/fsl_ifc.h>
 #include <linux/iopoll.h>
 
diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index 5ccc28ec0985..80dc210f05cf 100644
--- a/drivers/mtd/nand/raw/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
@@ -15,7 +15,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
 #include <linux/of_address.h>
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 325b4414dccc..e1bd8b7a0bf5 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -26,7 +26,7 @@
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 086964f8d424..0ae7ab7dbc68 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -41,7 +41,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 
 #define DRV_NAME "lpc32xx_mlc"
 
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index a2c5fdc875bd..eabd1fd9d2de 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -32,7 +32,7 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index d6dd0ef42585..4d7877408b82 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -39,7 +39,7 @@
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/nand-ecc-sw-bch.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
index 9857e0e5acd4..0d79bbe89a4f 100644
--- a/drivers/mtd/nand/raw/ndfc.c
+++ b/drivers/mtd/nand/raw/ndfc.c
@@ -23,7 +23,7 @@
  */
 #include <linux/module.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/ndfc.h>
 #include <linux/slab.h>
diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
index 643cd22af009..49c503a1d8ec 100644
--- a/drivers/mtd/nand/raw/pasemi_nand.c
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index adc7a196e383..7f40cc85782d 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -43,7 +43,7 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/platform_data/mtd-nand-s3c2410.h>
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index c82f26c8b58c..c352fd040ead 100644
--- a/drivers/mtd/nand/raw/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index f3b59e649b7d..7422fea7777c 100644
--- a/drivers/mtd/nand/raw/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
@@ -35,7 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 
diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index ddf0420c0997..d264b3588ac4 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -17,7 +17,7 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/platform_data/txx9/ndfmc.h>
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index e0955a98a0f4..e48114739668 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -16,7 +16,7 @@
 #include <linux/sysfs.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include "nand/raw/sm_common.h"
 #include "sm_ftl.h"
 
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
index 73b06304c975..49824d2ae11a 100644
--- a/drivers/mtd/tests/mtd_nandecctest.c
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -7,7 +7,7 @@
 #include <linux/string.h>
 #include <linux/bitops.h>
 #include <linux/slab.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 
 #include "mtd_test.h"
 
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand-ecc-sw-hamming.h
similarity index 90%
rename from include/linux/mtd/nand_ecc.h
rename to include/linux/mtd/nand-ecc-sw-hamming.h
index 0b3bb156c344..c0f015b1a077 100644
--- a/include/linux/mtd/nand_ecc.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -10,8 +10,8 @@
  * This file is the header for the ECC algorithm.
  */
 
-#ifndef __MTD_NAND_ECC_H__
-#define __MTD_NAND_ECC_H__
+#ifndef __MTD_NAND_ECC_SW_HAMMING_H__
+#define __MTD_NAND_ECC_SW_HAMMING_H__
 
 struct nand_chip;
 
@@ -39,4 +39,4 @@ int __nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc,
 int nand_correct_data(struct nand_chip *chip, u_char *dat, u_char *read_ecc,
 		      u_char *calc_ecc);
 
-#endif /* __MTD_NAND_ECC_H__ */
+#endif /* __MTD_NAND_ECC_SW_HAMMING_H__ */
diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h
index e1845fc4afbd..ccd952f27e00 100644
--- a/include/linux/mtd/sharpsl.h
+++ b/include/linux/mtd/sharpsl.h
@@ -9,7 +9,7 @@
  */
 
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 struct sharpsl_nand_platform_data {
-- 
2.19.1


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

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

* [PATCH v2 19/36] mtd: nand: ecc: Use SPDX license identifier for the software Hamming code
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (17 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 18/36] mtd: nand: ecc: Move Hamming code into the ecc/ directory Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 20/36] mtd: nand: ecc: Clarify the software Hamming introductory line Miquel Raynal
                   ` (16 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Remove the legacy license text and replace it with the new standard:
an SPDX license identifier.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-hamming.c       | 16 +---------------
 include/linux/mtd/nand-ecc-sw-hamming.h |  5 +----
 2 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-hamming.c b/drivers/mtd/nand/ecc/sw-hamming.c
index b6931cd9f401..ba84f5ebbc37 100644
--- a/drivers/mtd/nand/ecc/sw-hamming.c
+++ b/drivers/mtd/nand/ecc/sw-hamming.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * This file contains an ECC algorithm that detects and corrects 1 bit
  * errors in a 256 byte block of data.
@@ -11,21 +12,6 @@
  *
  * Information on how this algorithm works and how it was developed
  * can be found in Documentation/mtd/nand_ecc.txt
- *
- * This file is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 or (at your option) any
- * later version.
- *
- * This file is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this file; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
  */
 
 #include <linux/types.h>
diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index c0f015b1a077..1bd7493c682b 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -1,12 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  *  Copyright (C) 2000-2010 Steven J. Hill <sjhill@realitydiluted.com>
  *			    David Woodhouse <dwmw2@infradead.org>
  *			    Thomas Gleixner <tglx@linutronix.de>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * This file is the header for the ECC algorithm.
  */
 
-- 
2.19.1


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

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

* [PATCH v2 20/36] mtd: nand: ecc: Clarify the software Hamming introductory line
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (18 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 19/36] mtd: nand: ecc: Use SPDX license identifier for the software Hamming code Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 21/36] mtd: nand: ecc: Turn the software Hamming implementation generic Miquel Raynal
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

The include file pretends being the header for "ECC algorithm", while
it is just the header for the Hamming implementation. Make this clear
by rewording the sentence.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/mtd/nand-ecc-sw-hamming.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index 1bd7493c682b..4ce99fa574e3 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -4,7 +4,7 @@
  *			    David Woodhouse <dwmw2@infradead.org>
  *			    Thomas Gleixner <tglx@linutronix.de>
  *
- * This file is the header for the ECC algorithm.
+ * This file is the header for the NAND Hamming ECC implementation.
  */
 
 #ifndef __MTD_NAND_ECC_SW_HAMMING_H__
-- 
2.19.1


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

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

* [PATCH v2 21/36] mtd: nand: ecc: Turn the software Hamming implementation generic
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (19 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 20/36] mtd: nand: ecc: Clarify the software Hamming introductory line Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 22/36] mtd: nand: Remove useless include about software Hamming ECC Miquel Raynal
                   ` (14 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Add helpers in the raw NAND core to call the generic functions that
will be re-used by the SPI-NAND layer.

While at it, do some cleanup in the file and its header.

There are two drivers (not even raw NAND controller drivers) using the
bare helpers ecc_sw_hamming_calculate/correct():
mtd_nandecctest.c and sm_ftl.c. It would be nice to find another way
to call these functions and finish to clean the driver.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-hamming.c       | 121 +++++++++++-------------
 drivers/mtd/nand/raw/cs553x_nand.c      |   3 +-
 drivers/mtd/nand/raw/fsmc_nand.c        |   2 +-
 drivers/mtd/nand/raw/lpc32xx_slc.c      |   2 +-
 drivers/mtd/nand/raw/nand_base.c        |  88 ++++++++++++++++-
 drivers/mtd/nand/raw/ndfc.c             |   3 +-
 drivers/mtd/nand/raw/sharpsl.c          |   2 +-
 drivers/mtd/nand/raw/tmio_nand.c        |   6 +-
 drivers/mtd/nand/raw/txx9ndfmc.c        |   4 +-
 drivers/mtd/sm_ftl.c                    |  28 +++---
 drivers/mtd/tests/mtd_nandecctest.c     |  29 +++---
 include/linux/mtd/nand-ecc-sw-hamming.h |  50 +++++-----
 include/linux/mtd/rawnand.h             |   9 ++
 13 files changed, 211 insertions(+), 136 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-hamming.c b/drivers/mtd/nand/ecc/sw-hamming.c
index ba84f5ebbc37..816e5ea816c2 100644
--- a/drivers/mtd/nand/ecc/sw-hamming.c
+++ b/drivers/mtd/nand/ecc/sw-hamming.c
@@ -17,8 +17,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/rawnand.h>
 #include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <asm/byteorder.h>
 
@@ -75,7 +73,7 @@ static const char bitsperbyte[256] = {
  * addressbits is a lookup table to filter out the bits from the xor-ed
  * ECC data that identify the faulty location.
  * this is only used for repairing parity
- * see the comments in nand_correct_data for more details
+ * see the comments in nand_ecc_sw_hamming_correct for more details
  */
 static const char addressbits[256] = {
 	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
@@ -112,30 +110,23 @@ static const char addressbits[256] = {
 	0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f
 };
 
-/**
- * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
- *			 block
- * @buf:	input buffer with raw data
- * @eccsize:	data bytes per ECC step (256 or 512)
- * @code:	output buffer with ECC
- * @sm_order:	Smart Media byte ordering
- */
-void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
-			  unsigned char *code, bool sm_order)
+int ecc_sw_hamming_calculate(const unsigned char *buf, unsigned int step_size,
+			     unsigned char *code, bool sm_order)
 {
-	int i;
-	const uint32_t *bp = (uint32_t *)buf;
-	/* 256 or 512 bytes/ecc  */
-	const uint32_t eccsize_mult = eccsize >> 8;
-	uint32_t cur;		/* current value in buffer */
+	const u32 *bp = (uint32_t *)buf;
+	const u32 eccsize_mult = step_size >> 8;
+	/* current value in buffer */
+	u32 cur;
 	/* rp0..rp15..rp17 are the various accumulated parities (per byte) */
-	uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
-	uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
-	uint32_t uninitialized_var(rp17);	/* to make compiler happy */
-	uint32_t par;		/* the cumulative parity for all data */
-	uint32_t tmppar;	/* the cumulative parity for this iteration;
-				   for rp12, rp14 and rp16 at the end of the
-				   loop */
+	u32 rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
+	u32 rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
+	/* Make the compiler happy */
+	u32 uninitialized_var(rp17);
+	/* Cumulative parity for all data */
+	u32 par;
+	/* Cumulative parity at the end of the loop (rp12, rp14, rp16) */
+	u32 tmppar;
+	int i;
 
 	par = 0;
 	rp4 = 0;
@@ -356,45 +347,36 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
 		    (invparity[par & 0x55] << 2) |
 		    (invparity[rp17] << 1) |
 		    (invparity[rp16] << 0);
-}
-EXPORT_SYMBOL(__nand_calculate_ecc);
-
-/**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
- *			 block
- * @chip:	NAND chip object
- * @buf:	input buffer with raw data
- * @code:	output buffer with ECC
- */
-int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
-		       unsigned char *code)
-{
-	bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
-
-	__nand_calculate_ecc(buf, chip->ecc.size, code, sm_order);
 
 	return 0;
 }
-EXPORT_SYMBOL(nand_calculate_ecc);
+EXPORT_SYMBOL(ecc_sw_hamming_calculate);
 
 /**
- * __nand_correct_data - [NAND Interface] Detect and correct bit error(s)
- * @buf:	raw data read from the chip
- * @read_ecc:	ECC from the chip
- * @calc_ecc:	the ECC calculated from raw data
- * @eccsize:	data bytes per ECC step (256 or 512)
- * @sm_order:	Smart Media byte order
+ * nand_ecc_sw_hamming_calculate - Calculate 3-byte ECC for 256/512-byte block
  *
- * Detect and correct a 1 bit error for eccsize byte block
+ * @nand: NAND device
+ * @buf: Input buffer with raw data
+ * @code: Output buffer with ECC
  */
-int __nand_correct_data(unsigned char *buf,
-			unsigned char *read_ecc, unsigned char *calc_ecc,
-			unsigned int eccsize, bool sm_order)
+int nand_ecc_sw_hamming_calculate(struct nand_device *nand,
+				  const unsigned char *buf, unsigned char *code)
 {
+	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
+	unsigned int step_size = nand->ecc.ctx.conf.step_size;
+
+	return ecc_sw_hamming_calculate(buf, step_size, code,
+					engine_conf->sm_order);
+}
+EXPORT_SYMBOL(nand_ecc_sw_hamming_calculate);
+
+int ecc_sw_hamming_correct(unsigned char *buf, unsigned char *read_ecc,
+			   unsigned char *calc_ecc, unsigned int step_size,
+			   bool sm_order)
+{
+	const u32 eccsize_mult = step_size >> 8;
 	unsigned char b0, b1, b2, bit_addr;
 	unsigned int byte_addr;
-	/* 256 or 512 bytes/ecc  */
-	const uint32_t eccsize_mult = eccsize >> 8;
 
 	/*
 	 * b0 to b2 indicate which bit is faulty (if any)
@@ -458,27 +440,30 @@ int __nand_correct_data(unsigned char *buf,
 	pr_err("%s: uncorrectable ECC error\n", __func__);
 	return -EBADMSG;
 }
-EXPORT_SYMBOL(__nand_correct_data);
+EXPORT_SYMBOL(ecc_sw_hamming_correct);
 
 /**
- * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
- * @chip:	NAND chip object
- * @buf:	raw data read from the chip
- * @read_ecc:	ECC from the chip
- * @calc_ecc:	the ECC calculated from raw data
+ * nand_ecc_sw_hamming_correct - Detect and correct bit error(s)
  *
- * Detect and correct a 1 bit error for 256/512 byte block
+ * @nand: NAND device
+ * @buf: Raw data read from the chip
+ * @read_ecc: ECC bytes read from the chip
+ * @calc_ecc: ECC calculated from the raw data
+ *
+ * Detect and correct up to 1 bit error per 256/512-byte block.
  */
-int nand_correct_data(struct nand_chip *chip, unsigned char *buf,
-		      unsigned char *read_ecc, unsigned char *calc_ecc)
+int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf,
+				unsigned char *read_ecc,
+				unsigned char *calc_ecc)
 {
-	bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
+	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
+	unsigned int step_size = nand->ecc.ctx.conf.step_size;
 
-	return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size,
-				   sm_order);
+	return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc, step_size,
+				      engine_conf->sm_order);
 }
-EXPORT_SYMBOL(nand_correct_data);
+EXPORT_SYMBOL(nand_ecc_sw_hamming_correct);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
-MODULE_DESCRIPTION("Generic NAND ECC support");
+MODULE_DESCRIPTION("NAND software Hamming ECC support");
diff --git a/drivers/mtd/nand/raw/cs553x_nand.c b/drivers/mtd/nand/raw/cs553x_nand.c
index 98cc55df27b1..3fbff2a5dab1 100644
--- a/drivers/mtd/nand/raw/cs553x_nand.c
+++ b/drivers/mtd/nand/raw/cs553x_nand.c
@@ -23,7 +23,6 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/msr.h>
@@ -219,7 +218,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr)
 	this->ecc.bytes = 3;
 	this->ecc.hwctl  = cs_enable_hwecc;
 	this->ecc.calculate = cs_calculate_ecc;
-	this->ecc.correct  = nand_correct_data;
+	this->ecc.correct  = rawnand_sw_hamming_correct;
 	this->ecc.strength = 1;
 
 	/* Enable the following for a flash based bad block table */
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index e1bd8b7a0bf5..0e0585bec837 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -936,7 +936,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
 	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.correct = rawnand_sw_hamming_correct;
 		nand->ecc.bytes = 3;
 		nand->ecc.strength = 1;
 		nand->ecc.options |= NAND_ECC_SOFT_HAMMING_SM_ORDER;
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index eabd1fd9d2de..8b000c783ba6 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -901,7 +901,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
 	chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
 	chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
 	chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
-	chip->ecc.correct = nand_correct_data;
+	chip->ecc.correct = rawnand_sw_hamming_correct;
 	chip->ecc.strength = 1;
 	chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 4d7877408b82..6b0050b907ba 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4847,6 +4847,75 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
 	kfree(chip->parameters.onfi);
 }
 
+int rawnand_sw_hamming_init(struct nand_chip *chip)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_ecc_sw_hamming_conf *engine_conf;
+	struct nand_device *base = &chip->base;
+
+	base->ecc.user_conf.provider = NAND_ECC_SOFT;
+	base->ecc.user_conf.algo = NAND_ECC_HAMMING;
+	base->ecc.user_conf.strength = chip->ecc.strength;
+	base->ecc.user_conf.step_size = chip->ecc.size;
+
+	if (base->ecc.user_conf.strength != 1 ||
+	    (base->ecc.user_conf.step_size != 256 &&
+	     base->ecc.user_conf.step_size != 512)) {
+		pr_err("%s: unsupported strength or step size\n", __func__);
+		return -EINVAL;
+	}
+
+	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
+	if (!engine_conf)
+		return -ENOMEM;
+
+	engine_conf->code_size = 3;
+	engine_conf->nsteps = mtd->writesize / base->ecc.user_conf.step_size;
+
+	if (chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER)
+		engine_conf->sm_order = true;
+
+	base->ecc.ctx.priv = engine_conf;
+
+	chip->ecc.size = base->ecc.ctx.conf.step_size;
+	chip->ecc.strength = base->ecc.ctx.conf.strength;
+	chip->ecc.total = base->ecc.ctx.total;
+	chip->ecc.steps = engine_conf->nsteps;
+	chip->ecc.bytes = engine_conf->code_size;
+
+	return 0;
+}
+EXPORT_SYMBOL(rawnand_sw_hamming_init);
+
+int rawnand_sw_hamming_calculate(struct nand_chip *chip,
+				 const unsigned char *buf,
+				 unsigned char *code)
+{
+	struct nand_device *base = &chip->base;
+
+	return nand_ecc_sw_hamming_calculate(base, buf, code);
+}
+EXPORT_SYMBOL(rawnand_sw_hamming_calculate);
+
+int rawnand_sw_hamming_correct(struct nand_chip *chip,
+			       unsigned char *buf,
+			       unsigned char *read_ecc,
+			       unsigned char *calc_ecc)
+{
+	struct nand_device *base = &chip->base;
+
+	return nand_ecc_sw_hamming_correct(base, buf, read_ecc, calc_ecc);
+}
+EXPORT_SYMBOL(rawnand_sw_hamming_correct);
+
+void rawnand_sw_hamming_cleanup(struct nand_chip *chip)
+{
+	struct nand_device *base = &chip->base;
+
+	kfree(base->ecc.ctx.priv);
+}
+EXPORT_SYMBOL(rawnand_sw_hamming_cleanup);
+
 int rawnand_sw_bch_init(struct nand_chip *chip)
 {
 	struct nand_device *base = &chip->base;
@@ -4920,8 +4989,8 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 
 	switch (ecc->algo) {
 	case NAND_ECC_HAMMING:
-		ecc->calculate = nand_calculate_ecc;
-		ecc->correct = nand_correct_data;
+		ecc->calculate = rawnand_sw_hamming_calculate;
+		ecc->correct = rawnand_sw_hamming_correct;
 		ecc->read_page = nand_read_page_swecc;
 		ecc->read_subpage = nand_read_subpage;
 		ecc->write_page = nand_write_page_swecc;
@@ -4937,6 +5006,12 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 		if (IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC))
 			ecc->options |= NAND_ECC_SOFT_HAMMING_SM_ORDER;
 
+		ret = rawnand_sw_hamming_init(chip);
+		if (ret) {
+			WARN(1, "Hamming ECC initialization failed!\n");
+			return ret;
+		}
+
 		return 0;
 	case NAND_ECC_BCH:
 		if (!IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)) {
@@ -5707,9 +5782,12 @@ EXPORT_SYMBOL(nand_scan_with_ids);
  */
 void nand_cleanup(struct nand_chip *chip)
 {
-	if (chip->ecc.mode == NAND_ECC_SOFT &&
-	    chip->ecc.algo == NAND_ECC_BCH)
-		rawnand_sw_bch_cleanup(chip);
+	if (chip->ecc.mode == NAND_ECC_SOFT) {
+		if (chip->ecc.algo == NAND_ECC_HAMMING)
+			rawnand_sw_hamming_cleanup(chip);
+		else if (chip->ecc.algo == NAND_ECC_BCH)
+			rawnand_sw_bch_cleanup(chip);
+	}
 
 	/* Free bad block table memory */
 	kfree(chip->bbt);
diff --git a/drivers/mtd/nand/raw/ndfc.c b/drivers/mtd/nand/raw/ndfc.c
index 0d79bbe89a4f..e92079dc1a47 100644
--- a/drivers/mtd/nand/raw/ndfc.c
+++ b/drivers/mtd/nand/raw/ndfc.c
@@ -23,7 +23,6 @@
  */
 #include <linux/module.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/ndfc.h>
 #include <linux/slab.h>
@@ -151,7 +150,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	chip->controller = &ndfc->ndfc_control;
 	chip->legacy.read_buf = ndfc_read_buf;
 	chip->legacy.write_buf = ndfc_write_buf;
-	chip->ecc.correct = nand_correct_data;
+	chip->ecc.correct = ecc_sw_hamming_correct;
 	chip->ecc.hwctl = ndfc_enable_hwecc;
 	chip->ecc.calculate = ndfc_calculate_ecc;
 	chip->ecc.mode = NAND_ECC_HW;
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index c352fd040ead..31786044ba3c 100644
--- a/drivers/mtd/nand/raw/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -168,7 +168,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev)
 	this->badblock_pattern = data->badblock_pattern;
 	this->ecc.hwctl = sharpsl_nand_enable_hwecc;
 	this->ecc.calculate = sharpsl_nand_calculate_ecc;
-	this->ecc.correct = nand_correct_data;
+	this->ecc.correct = rawnand_sw_hamming_correct;
 
 	/* Scan to find existence of the device */
 	err = nand_scan(this, 1);
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index 7422fea7777c..efee3c3acd12 100644
--- a/drivers/mtd/nand/raw/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
@@ -295,11 +295,11 @@ static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf,
 	int r0, r1;
 
 	/* assume ecc.size = 512 and ecc.bytes = 6 */
-	r0 = __nand_correct_data(buf, read_ecc, calc_ecc, 256, false);
+	r0 = rawnand_sw_hamming_correct(chip, buf, read_ecc, calc_ecc);
 	if (r0 < 0)
 		return r0;
-	r1 = __nand_correct_data(buf + 256, read_ecc + 3, calc_ecc + 3, 256,
-				 false);
+	r1 = rawnand_sw_hamming_correct(chip, buf + 256, read_ecc + 3,
+					calc_ecc + 3);
 	if (r1 < 0)
 		return r1;
 	return r0 + r1;
diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index d264b3588ac4..4174d0012f0f 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -198,8 +198,8 @@ static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf,
 	int stat;
 
 	for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) {
-		stat = __nand_correct_data(buf, read_ecc, calc_ecc, 256,
-					   false);
+		stat = rawnand_sw_hamming_correct(chip, buf, read_ecc,
+						  calc_ecc);
 		if (stat < 0)
 			return stat;
 		corrected += stat;
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index e48114739668..1fbe4823071b 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -219,20 +219,19 @@ static void sm_break_offset(struct sm_ftl *ftl, loff_t loffset,
 
 static int sm_correct_sector(uint8_t *buffer, struct sm_oob *oob)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	uint8_t ecc[3];
 
-	__nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-	if (__nand_correct_data(buffer, ecc, oob->ecc1, SM_SMALL_PAGE,
-				IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)) < 0)
+	ecc_sw_hamming_calculate(buffer, SM_SMALL_PAGE, ecc, sm_order);
+	if (ecc_sw_hamming_correct(buffer, ecc, oob->ecc1, SM_SMALL_PAGE,
+				   sm_order) < 0)
 		return -EIO;
 
 	buffer += SM_SMALL_PAGE;
 
-	__nand_calculate_ecc(buffer, SM_SMALL_PAGE, ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-	if (__nand_correct_data(buffer, ecc, oob->ecc2, SM_SMALL_PAGE,
-				IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC)) < 0)
+	ecc_sw_hamming_calculate(buffer, SM_SMALL_PAGE, ecc, sm_order);
+	if (ecc_sw_hamming_correct(buffer, ecc, oob->ecc2, SM_SMALL_PAGE,
+				   sm_order) < 0)
 		return -EIO;
 	return 0;
 }
@@ -371,6 +370,7 @@ static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf,
 			  int zone, int block, int lba,
 			  unsigned long invalid_bitmap)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	struct sm_oob oob;
 	int boffset;
 	int retry = 0;
@@ -397,13 +397,13 @@ static int sm_write_block(struct sm_ftl *ftl, uint8_t *buf,
 		}
 
 		if (ftl->smallpagenand) {
-			__nand_calculate_ecc(buf + boffset, SM_SMALL_PAGE,
-					oob.ecc1,
-					IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
+			ecc_sw_hamming_calculate(buf + boffset,
+						 SM_SMALL_PAGE, oob.ecc1,
+						 sm_order);
 
-			__nand_calculate_ecc(buf + boffset + SM_SMALL_PAGE,
-					SM_SMALL_PAGE, oob.ecc2,
-					IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
+			ecc_sw_hamming_calculate(buf + boffset + SM_SMALL_PAGE,
+						 SM_SMALL_PAGE, oob.ecc2,
+						 sm_order);
 		}
 		if (!sm_write_sector(ftl, zone, block, boffset,
 							buf + boffset, &oob))
diff --git a/drivers/mtd/tests/mtd_nandecctest.c b/drivers/mtd/tests/mtd_nandecctest.c
index 49824d2ae11a..755a5f2bdb11 100644
--- a/drivers/mtd/tests/mtd_nandecctest.c
+++ b/drivers/mtd/tests/mtd_nandecctest.c
@@ -118,13 +118,13 @@ static void no_bit_error(void *error_data, void *error_ecc,
 static int no_bit_error_verify(void *error_data, void *error_ecc,
 				void *correct_data, const size_t size)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	unsigned char calc_ecc[3];
 	int ret;
 
-	__nand_calculate_ecc(error_data, size, calc_ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-	ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size,
-				  IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
+	ecc_sw_hamming_calculate(error_data, size, calc_ecc, sm_order);
+	ret = ecc_sw_hamming_correct(error_data, error_ecc, calc_ecc, size,
+				     sm_order);
 	if (ret == 0 && !memcmp(correct_data, error_data, size))
 		return 0;
 
@@ -148,13 +148,13 @@ static void single_bit_error_in_ecc(void *error_data, void *error_ecc,
 static int single_bit_error_correct(void *error_data, void *error_ecc,
 				void *correct_data, const size_t size)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	unsigned char calc_ecc[3];
 	int ret;
 
-	__nand_calculate_ecc(error_data, size, calc_ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-	ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size,
-				  IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
+	ecc_sw_hamming_calculate(error_data, size, calc_ecc, sm_order);
+	ret = ecc_sw_hamming_correct(error_data, error_ecc, calc_ecc, size,
+				     sm_order);
 	if (ret == 1 && !memcmp(correct_data, error_data, size))
 		return 0;
 
@@ -185,13 +185,13 @@ static void double_bit_error_in_ecc(void *error_data, void *error_ecc,
 static int double_bit_error_detect(void *error_data, void *error_ecc,
 				void *correct_data, const size_t size)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	unsigned char calc_ecc[3];
 	int ret;
 
-	__nand_calculate_ecc(error_data, size, calc_ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-	ret = __nand_correct_data(error_data, error_ecc, calc_ecc, size,
-				  IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
+	ecc_sw_hamming_calculate(error_data, size, calc_ecc, sm_order);
+	ret = ecc_sw_hamming_correct(error_data, error_ecc, calc_ecc, size,
+				     sm_order);
 
 	return (ret == -EBADMSG) ? 0 : -EINVAL;
 }
@@ -247,6 +247,7 @@ static void dump_data_ecc(void *error_data, void *error_ecc, void *correct_data,
 
 static int nand_ecc_test_run(const size_t size)
 {
+	bool sm_order = IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC);
 	int i;
 	int err = 0;
 	void *error_data;
@@ -265,9 +266,7 @@ static int nand_ecc_test_run(const size_t size)
 	}
 
 	prandom_bytes(correct_data, size);
-	__nand_calculate_ecc(correct_data, size, correct_ecc,
-			     IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC));
-
+	ecc_sw_hamming_calculate(correct_data, size, correct_ecc, sm_order);
 	for (i = 0; i < ARRAY_SIZE(nand_ecc_test); i++) {
 		nand_ecc_test[i].prepare(error_data, error_ecc,
 				correct_data, correct_ecc, size);
diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index 4ce99fa574e3..f2d28e5d1888 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -10,30 +10,36 @@
 #ifndef __MTD_NAND_ECC_SW_HAMMING_H__
 #define __MTD_NAND_ECC_SW_HAMMING_H__
 
-struct nand_chip;
+#include <linux/mtd/nand.h>
 
-/*
- * Calculate 3 byte ECC code for eccsize byte block
+/**
+ * struct nand_ecc_sw_hamming_conf - private software Hamming ECC engine structure
+ * @reqooblen: Save the actual user OOB length requested before overwriting it
+ * @code_size: Number of bytes needed to store a code (one code per step)
+ * @nsteps: Number of steps
+ * @calc_buf: Buffer to use when calculating ECC bytes
+ * @code_buf: Buffer to use when reading (raw) ECC bytes from the chip
+ * @sm_order: Smart Media special ordering
  */
-void __nand_calculate_ecc(const u_char *dat, unsigned int eccsize,
-			  u_char *ecc_code, bool sm_order);
+struct nand_ecc_sw_hamming_conf {
+	unsigned int reqooblen;
+	unsigned int code_size;
+	unsigned int nsteps;
+	u8 *calc_buf;
+	u8 *code_buf;
+	unsigned int sm_order;
+};
 
-/*
- * Calculate 3 byte ECC code for 256/512 byte block
- */
-int nand_calculate_ecc(struct nand_chip *chip, const u_char *dat,
-		       u_char *ecc_code);
-
-/*
- * Detect and correct a 1 bit error for eccsize byte block
- */
-int __nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc,
-			unsigned int eccsize, bool sm_order);
-
-/*
- * Detect and correct a 1 bit error for 256/512 byte block
- */
-int nand_correct_data(struct nand_chip *chip, u_char *dat, u_char *read_ecc,
-		      u_char *calc_ecc);
+int ecc_sw_hamming_calculate(const unsigned char *buf, unsigned int step_size,
+			     unsigned char *code, bool sm_order);
+int nand_ecc_sw_hamming_calculate(struct nand_device *nand,
+				  const unsigned char *buf,
+				  unsigned char *code);
+int ecc_sw_hamming_correct(unsigned char *buf, unsigned char *read_ecc,
+			   unsigned char *calc_ecc, unsigned int step_size,
+			   bool sm_order);
+int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf,
+				unsigned char *read_ecc,
+				unsigned char *calc_ecc);
 
 #endif /* __MTD_NAND_ECC_SW_HAMMING_H__ */
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b0c6e1ac3989..1999f8ffb24f 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1230,6 +1230,15 @@ static inline int nand_opcode_8bits(unsigned int command)
 	return 0;
 }
 
+int rawnand_sw_hamming_init(struct nand_chip *chip);
+int rawnand_sw_hamming_calculate(struct nand_chip *chip,
+				 const unsigned char *buf,
+				 unsigned char *code);
+int rawnand_sw_hamming_correct(struct nand_chip *chip,
+			       unsigned char *buf,
+			       unsigned char *read_ecc,
+			       unsigned char *calc_ecc);
+void rawnand_sw_hamming_cleanup(struct nand_chip *chip);
 int rawnand_sw_bch_init(struct nand_chip *chip);
 int rawnand_sw_bch_correct(struct nand_chip *chip, unsigned char *buf,
 			   unsigned char *read_ecc, unsigned char *calc_ecc);
-- 
2.19.1


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

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

* [PATCH v2 22/36] mtd: nand: Remove useless include about software Hamming ECC
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (20 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 21/36] mtd: nand: ecc: Turn the software Hamming implementation generic Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 23/36] mtd: nand: ecc: Let the software BCH ECC engine be a module Miquel Raynal
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Most of the includes are simply useless, drop them.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 arch/arm/mach-s3c24xx/common-smdk.c    | 1 -
 arch/arm/mach-s3c24xx/mach-anubis.c    | 1 -
 arch/arm/mach-s3c24xx/mach-at2440evb.c | 1 -
 arch/arm/mach-s3c24xx/mach-bast.c      | 1 -
 arch/arm/mach-s3c24xx/mach-gta02.c     | 1 -
 arch/arm/mach-s3c24xx/mach-jive.c      | 1 -
 arch/arm/mach-s3c24xx/mach-mini2440.c  | 1 -
 arch/arm/mach-s3c24xx/mach-osiris.c    | 1 -
 arch/arm/mach-s3c24xx/mach-qt2410.c    | 1 -
 arch/arm/mach-s3c24xx/mach-rx3715.c    | 1 -
 arch/arm/mach-s3c24xx/mach-vstms.c     | 1 -
 drivers/mtd/nand/raw/fsl_elbc_nand.c   | 1 -
 drivers/mtd/nand/raw/fsl_ifc_nand.c    | 1 -
 drivers/mtd/nand/raw/fsl_upm.c         | 1 -
 drivers/mtd/nand/raw/fsmc_nand.c       | 1 -
 drivers/mtd/nand/raw/lpc32xx_mlc.c     | 1 -
 drivers/mtd/nand/raw/lpc32xx_slc.c     | 1 -
 drivers/mtd/nand/raw/pasemi_nand.c     | 1 -
 drivers/mtd/nand/raw/s3c2410.c         | 1 -
 drivers/mtd/nand/raw/sharpsl.c         | 1 -
 drivers/mtd/nand/raw/tmio_nand.c       | 1 -
 drivers/mtd/nand/raw/txx9ndfmc.c       | 1 -
 include/linux/mtd/sharpsl.h            | 1 -
 23 files changed, 23 deletions(-)

diff --git a/arch/arm/mach-s3c24xx/common-smdk.c b/arch/arm/mach-s3c24xx/common-smdk.c
index ffe34a5a3174..7cab64bea951 100644
--- a/arch/arm/mach-s3c24xx/common-smdk.c
+++ b/arch/arm/mach-s3c24xx/common-smdk.c
@@ -19,7 +19,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 83472294191b..8e4410d1bfa1 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -36,7 +36,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <net/ax88796.h>
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index c841b90695b9..35dc86805dce 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -37,7 +37,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/devs.h>
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 4f3d3e819a2a..3f8e2e7a2dff 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -24,7 +24,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/platform_data/asoc-s3c24xx_simtec.h>
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 1c6f11216c0c..b63f5c2aeac7 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -36,7 +36,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index b2afb4099ab4..d9b920ad444e 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -40,7 +40,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 8c173a6f1bdc..cdc305bbb74f 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -46,7 +46,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/gpio-cfg.h>
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index 0dd72072aa3d..025a7678b5cc 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -33,7 +33,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <plat/cpu.h>
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 19f2e12130ec..a1835139a6a6 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index 05aac6499d82..13c73f6063bb 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/mach/arch.h>
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index e0218ae0040e..c1db572d2513 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -16,7 +16,6 @@
 #include <linux/io.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/memblock.h>
 
diff --git a/drivers/mtd/nand/raw/fsl_elbc_nand.c b/drivers/mtd/nand/raw/fsl_elbc_nand.c
index a43f9373ce22..ed84b25e8e6e 100644
--- a/drivers/mtd/nand/raw/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_elbc_nand.c
@@ -35,7 +35,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <asm/io.h>
diff --git a/drivers/mtd/nand/raw/fsl_ifc_nand.c b/drivers/mtd/nand/raw/fsl_ifc_nand.c
index 7f7e1ecf612c..ac85e9dd1318 100644
--- a/drivers/mtd/nand/raw/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/raw/fsl_ifc_nand.c
@@ -28,7 +28,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/fsl_ifc.h>
 #include <linux/iopoll.h>
 
diff --git a/drivers/mtd/nand/raw/fsl_upm.c b/drivers/mtd/nand/raw/fsl_upm.c
index 80dc210f05cf..224ba9449fc2 100644
--- a/drivers/mtd/nand/raw/fsl_upm.c
+++ b/drivers/mtd/nand/raw/fsl_upm.c
@@ -15,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/mtd.h>
 #include <linux/of_address.h>
diff --git a/drivers/mtd/nand/raw/fsmc_nand.c b/drivers/mtd/nand/raw/fsmc_nand.c
index 0e0585bec837..797028037f78 100644
--- a/drivers/mtd/nand/raw/fsmc_nand.c
+++ b/drivers/mtd/nand/raw/fsmc_nand.c
@@ -26,7 +26,6 @@
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/mtd/partitions.h>
diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
index 0ae7ab7dbc68..af75eabddc6f 100644
--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
@@ -41,7 +41,6 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 
 #define DRV_NAME "lpc32xx_mlc"
 
diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c
index 8b000c783ba6..5629ef7750aa 100644
--- a/drivers/mtd/nand/raw/lpc32xx_slc.c
+++ b/drivers/mtd/nand/raw/lpc32xx_slc.c
@@ -32,7 +32,6 @@
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
diff --git a/drivers/mtd/nand/raw/pasemi_nand.c b/drivers/mtd/nand/raw/pasemi_nand.c
index 49c503a1d8ec..3b6f51a31e7d 100644
--- a/drivers/mtd/nand/raw/pasemi_nand.c
+++ b/drivers/mtd/nand/raw/pasemi_nand.c
@@ -26,7 +26,6 @@
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index 7f40cc85782d..b8462b9b4276 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -43,7 +43,6 @@
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 #include <linux/platform_data/mtd-nand-s3c2410.h>
diff --git a/drivers/mtd/nand/raw/sharpsl.c b/drivers/mtd/nand/raw/sharpsl.c
index 31786044ba3c..df542d77b1db 100644
--- a/drivers/mtd/nand/raw/sharpsl.c
+++ b/drivers/mtd/nand/raw/sharpsl.c
@@ -16,7 +16,6 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/sharpsl.h>
 #include <linux/interrupt.h>
diff --git a/drivers/mtd/nand/raw/tmio_nand.c b/drivers/mtd/nand/raw/tmio_nand.c
index efee3c3acd12..6fac98df3a92 100644
--- a/drivers/mtd/nand/raw/tmio_nand.c
+++ b/drivers/mtd/nand/raw/tmio_nand.c
@@ -35,7 +35,6 @@
 #include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
 
diff --git a/drivers/mtd/nand/raw/txx9ndfmc.c b/drivers/mtd/nand/raw/txx9ndfmc.c
index 4174d0012f0f..afdb947253bf 100644
--- a/drivers/mtd/nand/raw/txx9ndfmc.c
+++ b/drivers/mtd/nand/raw/txx9ndfmc.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
 #include <linux/platform_data/txx9/ndfmc.h>
diff --git a/include/linux/mtd/sharpsl.h b/include/linux/mtd/sharpsl.h
index ccd952f27e00..3375a9958cfe 100644
--- a/include/linux/mtd/sharpsl.h
+++ b/include/linux/mtd/sharpsl.h
@@ -9,7 +9,6 @@
  */
 
 #include <linux/mtd/rawnand.h>
-#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/partitions.h>
 
 struct sharpsl_nand_platform_data {
-- 
2.19.1


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

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

* [PATCH v2 23/36] mtd: nand: ecc: Let the software BCH ECC engine be a module
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (21 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 22/36] mtd: nand: Remove useless include about software Hamming ECC Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 24/36] mtd: nand: ecc: Let the software Hamming ECC engine be unselected Miquel Raynal
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

There is no reason to prevent the software BCH ECC engine
implementation to be compiled as a module, so change the 'bool' into a
'tristate'.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/Kconfig        | 6 +++++-
 include/linux/mtd/nand-ecc-sw-bch.h | 2 +-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
index 7be48a7efda0..a9ab9bab252c 100644
--- a/drivers/mtd/nand/ecc/Kconfig
+++ b/drivers/mtd/nand/ecc/Kconfig
@@ -15,7 +15,7 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
 	  The original Linux implementation had byte 0 and 1 swapped.
 
 config MTD_NAND_ECC_SW_BCH
-	bool "Software BCH ECC engine"
+	tristate "Software BCH ECC engine"
 	select BCH
 	select MTD_NAND_ECC
 	default n
@@ -25,4 +25,8 @@ config MTD_NAND_ECC_SW_BCH
 	  ECC codes. They are used with NAND devices requiring more than 1 bit
 	  of error correction.
 
+	  If you are booting from NAND and need the BCH engine in order to mount
+	  your filesystem, then do not select =m for this option unless you have
+	  an initramfs.
+
 endmenu
diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
index 509723870fc8..e72f781829c8 100644
--- a/include/linux/mtd/nand-ecc-sw-bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -33,7 +33,7 @@ struct nand_ecc_sw_bch_conf {
 	unsigned char *eccmask;
 };
 
-#if defined(CONFIG_MTD_NAND_ECC_SW_BCH)
+#if IS_REACHABLE(CONFIG_MTD_NAND_ECC_SW_BCH)
 
 int nand_ecc_sw_bch_calculate(struct nand_device *nand,
 			      const unsigned char *buf, unsigned char *code);
-- 
2.19.1


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

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

* [PATCH v2 24/36] mtd: nand: ecc: Let the software Hamming ECC engine be unselected
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (22 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 23/36] mtd: nand: ecc: Let the software BCH ECC engine be a module Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 25/36] mtd: nand: ecc: Create the software BCH engine instance Miquel Raynal
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

There is no reason to always embed the software Hamming ECC engine
implementation. By default it is (with raw NAND), but we can let the
user decide.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/Kconfig            | 11 +++++++-
 drivers/mtd/nand/raw/Kconfig            |  2 +-
 include/linux/mtd/nand-ecc-sw-hamming.h | 36 +++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
index a9ab9bab252c..a2593faf46f3 100644
--- a/drivers/mtd/nand/ecc/Kconfig
+++ b/drivers/mtd/nand/ecc/Kconfig
@@ -4,7 +4,16 @@ config MTD_NAND_ECC
 	tristate
 
 config MTD_NAND_ECC_SW_HAMMING
-	tristate
+	tristate "Software Hamming ECC engine"
+	default y if MTD_RAW_NAND
+	select MTD_NAND_ECC
+	help
+	  This enables support for software Hamming error
+	  correction. This correction can correct up to 1 bit error
+	  per chunk and detect up to 2 bit errors. While it used to be
+	  widely used with old parts, newer NAND chips usually require
+	  more strength correction and in this case BCH or RS will be
+	  preferred.
 
 config MTD_NAND_ECC_SW_HAMMING_SMC
 	bool "NAND ECC Smart Media byte order"
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 770c73c1bb7d..390cba259167 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -2,7 +2,6 @@ menuconfig MTD_RAW_NAND
 	tristate "Raw/Parallel NAND Device Support"
 	select MTD_NAND_CORE
 	select MTD_NAND_ECC
-	select MTD_NAND_ECC_SW_HAMMING
 	help
 	  This enables support for accessing all type of raw/parallel
 	  NAND flash devices. For further information see
@@ -71,6 +70,7 @@ config MTD_NAND_AU1550
 config MTD_NAND_NDFC
 	tristate "IBM/MCC 4xx NAND controller"
 	depends on 4xx
+	select MTD_NAND_ECC_SW_HAMMING
 	select MTD_NAND_ECC_SW_HAMMING_SMC
 	help
 	  NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index f2d28e5d1888..4d41d6ec9fe7 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -30,6 +30,8 @@ struct nand_ecc_sw_hamming_conf {
 	unsigned int sm_order;
 };
 
+#if IS_REACHABLE(CONFIG_MTD_NAND_ECC_SW_HAMMING)
+
 int ecc_sw_hamming_calculate(const unsigned char *buf, unsigned int step_size,
 			     unsigned char *code, bool sm_order);
 int nand_ecc_sw_hamming_calculate(struct nand_device *nand,
@@ -42,4 +44,38 @@ int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf,
 				unsigned char *read_ecc,
 				unsigned char *calc_ecc);
 
+#else /* !CONFIG_MTD_NAND_ECC_SW_HAMMING */
+
+static inline int ecc_sw_hamming_calculate(const unsigned char *buf,
+					   unsigned int step_size,
+					   unsigned char *code, bool sm_order)
+{
+	return -ENOTSUPP;
+}
+
+static inline int nand_ecc_sw_hamming_calculate(struct nand_device *nand,
+						const unsigned char *buf,
+						unsigned char *code)
+{
+	return -ENOTSUPP;
+}
+
+static inline int ecc_sw_hamming_correct(unsigned char *buf,
+					 unsigned char *read_ecc,
+					 unsigned char *calc_ecc,
+					 unsigned int step_size, bool sm_order)
+{
+	return -ENOTSUPP;
+}
+
+static inline int nand_ecc_sw_hamming_correct(struct nand_device *nand,
+					      unsigned char *buf,
+					      unsigned char *read_ecc,
+					      unsigned char *calc_ecc)
+{
+	return -ENOTSUPP;
+}
+
+#endif /* CONFIG_MTD_NAND_ECC_SW_HAMMING */
+
 #endif /* __MTD_NAND_ECC_SW_HAMMING_H__ */
-- 
2.19.1


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

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

* [PATCH v2 25/36] mtd: nand: ecc: Create the software BCH engine instance
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (23 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 24/36] mtd: nand: ecc: Let the software Hamming ECC engine be unselected Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 26/36] mtd: nand: ecc: Create the software Hamming " Miquel Raynal
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Let's continue introducing the generic ECC engine abstraction in the
NAND subsystem by instantiating a first ECC engine: the software
BCH one.

While at it, make a very tidy ecc_sw_bch_init() function and move all
the sanity checks and user input management in
nand_ecc_sw_bch_init_ctx(). This second helper will be called from the
raw RAND core.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-bch.c       | 341 +++++++++++++++++++++++-----
 drivers/mtd/nand/raw/nand_base.c    |  62 +----
 include/linux/mtd/nand-ecc-sw-bch.h |  14 +-
 3 files changed, 303 insertions(+), 114 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-bch.c b/drivers/mtd/nand/ecc/sw-bch.c
index aba78f5b1964..4fbcae28b29c 100644
--- a/drivers/mtd/nand/ecc/sw-bch.c
+++ b/drivers/mtd/nand/ecc/sw-bch.c
@@ -81,7 +81,7 @@ EXPORT_SYMBOL(nand_ecc_sw_bch_correct);
  * nand_ecc_sw_bch_cleanup - Cleanup software BCH ECC resources
  * @nand: NAND device
  */
-void nand_ecc_sw_bch_cleanup(struct nand_device *nand)
+static void nand_ecc_sw_bch_cleanup(struct nand_device *nand)
 {
 	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
 
@@ -89,7 +89,6 @@ void nand_ecc_sw_bch_cleanup(struct nand_device *nand)
 	kfree(engine_conf->errloc);
 	kfree(engine_conf->eccmask);
 }
-EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup);
 
 /**
  * nand_ecc_sw_bch_init - Initialize software BCH ECC engine
@@ -106,70 +105,36 @@ EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup);
  * step_size = 512 (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
  * bytes = 7 (7 bytes are required to store m*t = 13*4 = 52 bits)
  */
-int nand_ecc_sw_bch_init(struct nand_device *nand)
+static int nand_ecc_sw_bch_init(struct nand_device *nand)
 {
-	struct mtd_info *mtd = nanddev_to_mtd(nand);
-	unsigned int m, t, eccsteps, i;
 	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
-	unsigned char *erased_page;
 	unsigned int eccsize = nand->ecc.ctx.conf.step_size;
 	unsigned int eccbytes = engine_conf->code_size;
-	unsigned int eccstrength = nand->ecc.ctx.conf.strength;
+	unsigned int m, t, i;
+	unsigned char *erased_page;
+	int ret;
 
-	if (!eccbytes && eccstrength) {
-		eccbytes = DIV_ROUND_UP(eccstrength * fls(8 * eccsize), 8);
-		engine_conf->code_size = eccbytes;
-	}
-
-	if (!eccsize || !eccbytes) {
-		pr_warn("ecc parameters not supplied\n");
-		return -EINVAL;
-	}
-
-	m = fls(1+8*eccsize);
-	t = (eccbytes*8)/m;
+	m = fls(1 + (8 * eccsize));
+	t = (eccbytes * 8) / m;
 
 	engine_conf->bch = init_bch(m, t, 0);
 	if (!engine_conf->bch)
 		return -EINVAL;
 
-	/* verify that eccbytes has the expected value */
-	if (engine_conf->bch->ecc_bytes != eccbytes) {
-		pr_warn("invalid eccbytes %u, should be %u\n",
-			eccbytes, engine_conf->bch->ecc_bytes);
-		goto fail;
-	}
-
-	eccsteps = mtd->writesize/eccsize;
-
-	/* Check that we have an oob layout description. */
-	if (!mtd->ooblayout) {
-		pr_warn("missing oob scheme");
-		goto fail;
-	}
-
-	/* sanity checks */
-	if (8*(eccsize+eccbytes) >= (1 << m)) {
-		pr_warn("eccsize %u is too large\n", eccsize);
-		goto fail;
-	}
-
-	if (mtd_ooblayout_count_eccbytes(mtd) != (eccsteps*eccbytes)) {
-		pr_warn("invalid ecc layout\n");
-		goto fail;
-	}
-
 	engine_conf->eccmask = kmalloc(eccbytes, GFP_KERNEL);
 	engine_conf->errloc = kmalloc_array(t, sizeof(*engine_conf->errloc),
 					    GFP_KERNEL);
-	if (!engine_conf->eccmask || !engine_conf->errloc)
-		goto fail;
-	/*
-	 * compute and store the inverted ecc of an erased ecc block
-	 */
+	if (!engine_conf->eccmask || !engine_conf->errloc) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
+
+	/* Compute and store the inverted ECC of an erased step */
 	erased_page = kmalloc(eccsize, GFP_KERNEL);
-	if (!erased_page)
-		goto fail;
+	if (!erased_page) {
+		ret = -ENOMEM;
+		goto cleanup;
+	}
 
 	memset(erased_page, 0xff, eccsize);
 	memset(engine_conf->eccmask, 0, eccbytes);
@@ -180,17 +145,279 @@ int nand_ecc_sw_bch_init(struct nand_device *nand)
 	for (i = 0; i < eccbytes; i++)
 		engine_conf->eccmask[i] ^= 0xff;
 
-	if (!eccstrength)
-		nand->ecc.ctx.conf.strength = (eccbytes * 8) / fls(8 * eccsize);
+	/* Verify that the number of code bytes has the expected value */
+	if (engine_conf->bch->ecc_bytes != eccbytes) {
+		pr_err("Invalid number of ECC bytes: %u, expected: %u\n",
+		       eccbytes, engine_conf->bch->ecc_bytes);
+		ret = -EINVAL;
+		goto cleanup;
+	}
+
+	/* Sanity checks */
+	if (8 * (eccsize + eccbytes) >= (1 << m)) {
+		pr_err("ECC step size is too large (%u)\n", eccsize);
+		ret = -EINVAL;
+		goto cleanup;
+	}
 
 	return 0;
 
-fail:
+cleanup:
 	nand_ecc_sw_bch_cleanup(nand);
 
-	return -EINVAL;
+	return ret;
 }
-EXPORT_SYMBOL(nand_ecc_sw_bch_init);
+
+int nand_ecc_sw_bch_init_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_conf *conf = &nand->ecc.ctx.conf;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct nand_ecc_sw_bch_conf *engine_conf;
+	unsigned int code_size = 0, nsteps;
+	int ret;
+
+	/* Only large page NAND chips may use BCH */
+	if (mtd->oobsize < 64) {
+		pr_err("BCH cannot be used with small page NAND chips\n");
+		return -EINVAL;
+	}
+
+	if (!mtd->ooblayout)
+		mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+
+	conf->provider = NAND_ECC_SOFT;
+	conf->algo = NAND_ECC_BCH;
+	conf->step_size = nand->ecc.user_conf.step_size;
+	conf->strength = nand->ecc.user_conf.strength;
+
+	/*
+	 * Board driver should supply ECC size and ECC strength
+	 * values to select how many bits are correctable.
+	 * Otherwise, default to 512 bytes for large page devices and 256 for
+	 * small page devices.
+	 */
+	if (!conf->step_size) {
+		if (mtd->oobsize >= 64)
+			conf->step_size = 512;
+		else
+			conf->step_size = 256;
+
+		conf->strength = 4;
+	}
+
+	nsteps = mtd->writesize / conf->step_size;
+
+	/* Maximize */
+	if (nand->ecc.user_conf.flags & NAND_ECC_MAXIMIZE) {
+		conf->step_size = 1024;
+		nsteps = mtd->writesize / conf->step_size;
+		/* Reserve 2 bytes for the BBM */
+		code_size = (mtd->oobsize - 2) / nsteps;
+		conf->strength = code_size * 8 / fls(8 * conf->step_size);
+	}
+
+	if (!code_size)
+		code_size = DIV_ROUND_UP(conf->strength *
+					 fls(8 * conf->step_size), 8);
+
+	if (!conf->strength)
+		conf->strength = (code_size * 8) / fls(8 * conf->step_size);
+
+	if (!code_size && !conf->strength) {
+		pr_err("Missing ECC parameters\n");
+		return -EINVAL;
+	}
+
+	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
+	if (!engine_conf)
+		return -ENOMEM;
+
+	engine_conf->code_size = code_size;
+	engine_conf->nsteps = nsteps;
+	engine_conf->calc_buf = kzalloc(sizeof(mtd->oobsize), GFP_KERNEL);
+	engine_conf->code_buf = kzalloc(sizeof(mtd->oobsize), GFP_KERNEL);
+	if (!engine_conf->calc_buf || !engine_conf->code_buf) {
+		kfree(engine_conf);
+		return -ENOMEM;
+	}
+
+	nand->ecc.ctx.priv = engine_conf;
+	nand->ecc.ctx.total = nsteps * code_size;
+
+	ret = nand_ecc_sw_bch_init(nand);
+	if (ret) {
+		kfree(engine_conf->calc_buf);
+		kfree(engine_conf->code_buf);
+		kfree(engine_conf);
+		return -ENOMEM;
+	}
+
+	/* Verify the layout validity */
+	if (mtd_ooblayout_count_eccbytes(mtd) !=
+	    engine_conf->nsteps * engine_conf->code_size) {
+		pr_err("Invalid ECC layout\n");
+		nand_ecc_sw_bch_cleanup(nand);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_sw_bch_init_ctx);
+
+void nand_ecc_sw_bch_cleanup_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
+
+	if (engine_conf) {
+		nand_ecc_sw_bch_cleanup(nand);
+		kfree(engine_conf->calc_buf);
+		kfree(engine_conf->code_buf);
+		kfree(engine_conf);
+	}
+}
+EXPORT_SYMBOL(nand_ecc_sw_bch_cleanup_ctx);
+
+static int nand_ecc_sw_bch_prepare_io_req(struct nand_device *nand,
+					  struct nand_page_io_req *req,
+					  void *oobbuf)
+{
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int eccsize = nand->ecc.ctx.conf.step_size;
+	int eccbytes = engine_conf->code_size;
+	int eccsteps = engine_conf->nsteps;
+	int total = nand->ecc.ctx.total;
+	u8 *ecccalc = engine_conf->calc_buf;
+	const u8 *data = req->databuf.out;
+	int i, ret;
+
+	/* Ensure the OOB buffer is empty before using it */
+	if (req->oobbuf.in)
+		memset(req->oobbuf.in, 0xff, nanddev_per_page_oobsize(nand));
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	/* This engine does not provide BBM/free OOB bytes protection */
+	if (!req->datalen)
+		return 0;
+
+	/*
+	 * Ensure OOB area is fully read/written otherwise the software
+	 * correction cannot not apply.
+	 */
+	engine_conf->reqooblen = req->ooblen;
+	req->ooblen = nanddev_per_page_oobsize(nand);
+
+	/* No more preparation for page read */
+	if (req->type == NAND_PAGE_READ)
+		return 0;
+
+	/* Preparation for page write: derive the ECC bytes and place them */
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, data += eccsize)
+		nand_ecc_sw_bch_calculate(nand, data, &ecccalc[i]);
+
+	ret = mtd_ooblayout_set_eccbytes(mtd, ecccalc, oobbuf, 0, total);
+
+	/* Also place user data OOB bytes in the free area, if any */
+	if (engine_conf->reqooblen) {
+		if (req->mode == MTD_OPS_AUTO_OOB)
+			mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
+						    oobbuf,
+						    req->ooboffs,
+						    req->ooblen);
+		else
+			memcpy(oobbuf + req->ooboffs, req->oobbuf.out,
+			       req->ooblen);
+	}
+
+	return ret;
+}
+
+static int nand_ecc_sw_bch_finish_io_req(struct nand_device *nand,
+					 struct nand_page_io_req *req,
+					 void *oobbuf)
+{
+	struct nand_ecc_sw_bch_conf *engine_conf = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int eccsize = nand->ecc.ctx.conf.step_size;
+	int total = nand->ecc.ctx.total;
+	int eccbytes = engine_conf->code_size;
+	int eccsteps = engine_conf->nsteps;
+	u8 *ecccalc = engine_conf->calc_buf;
+	u8 *ecccode = engine_conf->code_buf;
+	unsigned int max_bitflips = 0;
+	u8 *data = req->databuf.in;
+	int i, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	/* This engine does not provide BBM/free OOB bytes protection */
+	if (!req->datalen)
+		return 0;
+
+	/* Don't mess up with the upper layer: restore the request OOB length */
+	req->ooblen = engine_conf->reqooblen;
+
+	/* Nothing more to do for page write */
+	if (req->type == NAND_PAGE_WRITE)
+		return 0;
+
+	/* Finish a page read: retrieve the (raw) ECC bytes*/
+	ret = mtd_ooblayout_get_eccbytes(mtd, ecccode, oobbuf, 0, total);
+	if (ret)
+		return ret;
+
+	/* Calculate the ECC bytes */
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, data += eccsize)
+		nand_ecc_sw_bch_calculate(nand, data, &ecccalc[i]);
+
+	/* Finish a page read: compare and correct */
+	for (eccsteps = engine_conf->nsteps, i = 0, data = req->databuf.in;
+	     eccsteps;
+	     eccsteps--, i += eccbytes, data += eccsize) {
+		int stat =  nand_ecc_sw_bch_correct(nand, data,
+						    &ecccode[i],
+						    &ecccalc[i]);
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+
+	/* Format the OOB buffer that will be returned to the user */
+	if (req->ooblen) {
+		if (req->mode == MTD_OPS_AUTO_OOB)
+			mtd_ooblayout_get_databytes(mtd, oobbuf,
+						    req->oobbuf.in,
+						    req->ooboffs, req->ooblen);
+		else
+			memcpy(req->oobbuf.in, oobbuf + req->ooboffs,
+			       req->ooblen);
+	}
+
+	return max_bitflips;
+}
+
+static struct nand_ecc_engine_ops nand_ecc_sw_bch_engine_ops = {
+	.init_ctx = nand_ecc_sw_bch_init_ctx,
+	.cleanup_ctx = nand_ecc_sw_bch_cleanup_ctx,
+	.prepare_io_req = nand_ecc_sw_bch_prepare_io_req,
+	.finish_io_req = nand_ecc_sw_bch_finish_io_req,
+};
+
+static struct nand_ecc_engine nand_ecc_sw_bch_engine = {
+	.ops = &nand_ecc_sw_bch_engine_ops,
+};
+
+struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void)
+{
+	return &nand_ecc_sw_bch_engine;
+}
+EXPORT_SYMBOL(nand_ecc_sw_bch_get_engine);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 6b0050b907ba..8b910c818755 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4927,17 +4927,11 @@ int rawnand_sw_bch_init(struct nand_chip *chip)
 	base->ecc.user_conf.step_size = chip->ecc.size;
 	base->ecc.user_conf.strength = chip->ecc.strength;
 
-	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
-	if (!engine_conf)
-		return -ENOMEM;
-
-	engine_conf->code_size = chip->ecc.bytes;
-
-	base->ecc.ctx.priv = engine_conf;
-
-	ret = nand_ecc_sw_bch_init(base);
+	ret = nand_ecc_sw_bch_init_ctx(base);
 	if (ret)
-		kfree(base->ecc.ctx.priv);
+		return ret;
+
+	engine_conf = base->ecc.ctx.priv;
 
 	chip->ecc.size = base->ecc.ctx.conf.step_size;
 	chip->ecc.strength = base->ecc.ctx.conf.strength;
@@ -4945,7 +4939,7 @@ int rawnand_sw_bch_init(struct nand_chip *chip)
 	chip->ecc.steps = engine_conf->nsteps;
 	chip->ecc.bytes = engine_conf->code_size;
 
-	return ret;
+	return 0;
 }
 EXPORT_SYMBOL(rawnand_sw_bch_init);
 
@@ -4971,9 +4965,7 @@ void rawnand_sw_bch_cleanup(struct nand_chip *chip)
 {
 	struct nand_device *base = &chip->base;
 
-	nand_ecc_sw_bch_cleanup(base);
-
-	kfree(base->ecc.ctx.priv);
+	nand_ecc_sw_bch_cleanup_ctx(base);
 }
 EXPORT_SYMBOL(rawnand_sw_bch_cleanup);
 
@@ -5028,51 +5020,15 @@ static int nand_set_ecc_soft_ops(struct nand_chip *chip)
 		ecc->read_oob = nand_read_oob_std;
 		ecc->write_oob = nand_write_oob_std;
 
-		/*
-		* Board driver should supply ecc.size and ecc.strength
-		* values to select how many bits are correctable.
-		* Otherwise, default to 4 bits for large page devices.
-		*/
-		if (!ecc->size && (mtd->oobsize >= 64)) {
-			ecc->size = 512;
-			ecc->strength = 4;
-		}
-
-		/*
-		 * if no ecc placement scheme was provided pickup the default
-		 * large page one.
-		 */
-		if (!mtd->ooblayout) {
-			/* handle large page devices only */
-			if (mtd->oobsize < 64) {
-				WARN(1, "OOB layout is required when using software BCH on small pages\n");
-				return -EINVAL;
-			}
-
-			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-
-		}
-
 		/*
 		 * We can only maximize ECC config when the default layout is
 		 * used, otherwise we don't know how many bytes can really be
 		 * used.
 		 */
-		if (mtd->ooblayout == &nand_ooblayout_lp_ops &&
-		    nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE) {
-			int steps, bytes;
+		if (nanddev->ecc.user_conf.flags & NAND_ECC_MAXIMIZE &&
+		    mtd->ooblayout != &nand_ooblayout_lp_ops)
+			nanddev->ecc.user_conf.flags &= ~NAND_ECC_MAXIMIZE;
 
-			/* Always prefer 1k blocks over 512bytes ones */
-			ecc->size = 1024;
-			steps = mtd->writesize / ecc->size;
-
-			/* Reserve 2 bytes for the BBM */
-			bytes = (mtd->oobsize - 2) / steps;
-			ecc->strength = bytes * 8 / fls(8 * ecc->size);
-		}
-
-		/* See ecc_sw_bch_init() for details. */
-		ecc->bytes = 0;
 		ret = rawnand_sw_bch_init(chip);
 		if (ret) {
 			WARN(1, "BCH ECC initialization failed!\n");
diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
index e72f781829c8..cd9044d293f8 100644
--- a/include/linux/mtd/nand-ecc-sw-bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -39,8 +39,9 @@ int nand_ecc_sw_bch_calculate(struct nand_device *nand,
 			      const unsigned char *buf, unsigned char *code);
 int nand_ecc_sw_bch_correct(struct nand_device *nand, unsigned char *buf,
 			    unsigned char *read_ecc, unsigned char *calc_ecc);
-int nand_ecc_sw_bch_init(struct nand_device *nand);
-void nand_ecc_sw_bch_cleanup(struct nand_device *nand);
+int nand_ecc_sw_bch_init_ctx(struct nand_device *nand);
+void nand_ecc_sw_bch_cleanup_ctx(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void);
 
 #else /* !CONFIG_MTD_NAND_ECC_SW_BCH */
 
@@ -59,12 +60,17 @@ static inline int nand_ecc_sw_bch_correct(struct nand_device *nand,
 	return -ENOTSUPP;
 }
 
-static inline int nand_ecc_sw_bch_init(struct nand_device *nand)
+static inline int nand_ecc_sw_bch_init_ctx(struct nand_device *nand)
 {
 	return -EINVAL;
 }
 
-static inline void nand_ecc_sw_bch_cleanup(struct nand_device *nand) {}
+static inline void nand_ecc_sw_bch_cleanup_ctx(struct nand_device *nand) {}
+
+static inline struct nand_ecc_engine *nand_ecc_sw_bch_get_engine(void)
+{
+	return NULL;
+}
 
 #endif /* CONFIG_MTD_NAND_ECC_SW_BCH */
 
-- 
2.19.1


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

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

* [PATCH v2 26/36] mtd: nand: ecc: Create the software Hamming engine instance
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (24 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 25/36] mtd: nand: ecc: Create the software BCH engine instance Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 27/36] mtd: nand: Let software ECC engines be retrieved from the NAND core Miquel Raynal
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Let's continue introducing the generic ECC engine abstraction in the
NAND subsystem by instantiating a second ECC engine: the software
Hamming one.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/sw-hamming.c       | 208 ++++++++++++++++++++++++
 drivers/mtd/nand/raw/nand_base.c        |  25 +--
 include/linux/mtd/nand-ecc-sw-hamming.h |  15 ++
 3 files changed, 231 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/ecc/sw-hamming.c b/drivers/mtd/nand/ecc/sw-hamming.c
index 816e5ea816c2..c58dfddc0ff3 100644
--- a/drivers/mtd/nand/ecc/sw-hamming.c
+++ b/drivers/mtd/nand/ecc/sw-hamming.c
@@ -17,6 +17,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <asm/byteorder.h>
 
@@ -464,6 +465,213 @@ int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf,
 }
 EXPORT_SYMBOL(nand_ecc_sw_hamming_correct);
 
+int nand_ecc_sw_hamming_init_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_conf *conf = &nand->ecc.ctx.conf;
+	struct nand_ecc_sw_hamming_conf *engine_conf;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+
+	if (!mtd->ooblayout) {
+		switch (mtd->oobsize) {
+		case 8:
+		case 16:
+			mtd_set_ooblayout(mtd, &nand_ooblayout_sp_ops);
+			break;
+		case 64:
+		case 128:
+			mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	conf->provider = NAND_ECC_SOFT;
+	conf->algo = NAND_ECC_HAMMING;
+	conf->step_size = nand->ecc.user_conf.step_size;
+	conf->strength = 1;
+
+	/* Use the strongest configuration by default */
+	if (conf->step_size != 256 && conf->step_size != 512)
+		conf->step_size = 256;
+
+	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
+	if (!engine_conf)
+		return -ENOMEM;
+
+	engine_conf->code_size = 3;
+	engine_conf->nsteps = mtd->writesize / conf->step_size;
+	engine_conf->calc_buf = kzalloc(sizeof(mtd->oobsize), GFP_KERNEL);
+	engine_conf->code_buf = kzalloc(sizeof(mtd->oobsize), GFP_KERNEL);
+	if (!engine_conf->calc_buf || !engine_conf->code_buf) {
+		kfree(engine_conf);
+		return -ENOMEM;
+	}
+
+	nand->ecc.ctx.priv = engine_conf;
+	nand->ecc.ctx.total = engine_conf->nsteps * engine_conf->code_size;
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_sw_hamming_init_ctx);
+
+void nand_ecc_sw_hamming_cleanup_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
+
+	if (engine_conf) {
+		kfree(engine_conf->calc_buf);
+		kfree(engine_conf->code_buf);
+	}
+
+	kfree(engine_conf);
+}
+EXPORT_SYMBOL(nand_ecc_sw_hamming_cleanup_ctx);
+
+static int nand_ecc_sw_hamming_prepare_io_req(struct nand_device *nand,
+					      struct nand_page_io_req *req,
+					      void *oobbuf)
+{
+	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int eccsize = nand->ecc.ctx.conf.step_size;
+	int eccbytes = engine_conf->code_size;
+	int eccsteps = engine_conf->nsteps;
+	int total = nand->ecc.ctx.total;
+	u8 *ecccalc = engine_conf->calc_buf;
+	const u8 *data = req->databuf.out;
+	int i, ret;
+
+	/* Ensure the OOB buffer is empty before using it */
+	if (req->oobbuf.in)
+		memset(req->oobbuf.in, 0xff, nanddev_per_page_oobsize(nand));
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	/* This engine does not provide BBM/free OOB bytes protection */
+	if (!req->datalen)
+		return 0;
+
+	/*
+	 * Ensure OOB area is fully read/written otherwise the software
+	 * correction cannot not apply.
+	 */
+	engine_conf->reqooblen = req->ooblen;
+	req->ooblen = nanddev_per_page_oobsize(nand);
+
+	/* No preparation for page read */
+	if (req->type == NAND_PAGE_READ)
+		return 0;
+
+	/* Preparation for page write: derive the ECC bytes and place them */
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, data += eccsize)
+		nand_ecc_sw_hamming_calculate(nand, data, &ecccalc[i]);
+
+	ret = mtd_ooblayout_set_eccbytes(mtd, ecccalc, oobbuf, 0, total);
+
+	/* Also place user data OOB bytes in the free area, if any */
+	if (engine_conf->reqooblen) {
+		if (req->mode == MTD_OPS_AUTO_OOB)
+			mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
+						    oobbuf,
+						    req->ooboffs,
+						    req->ooblen);
+		else
+			memcpy(oobbuf + req->ooboffs, req->oobbuf.out,
+			       req->ooblen);
+	}
+
+	return ret;
+}
+
+static int nand_ecc_sw_hamming_finish_io_req(struct nand_device *nand,
+					     struct nand_page_io_req *req,
+					     void *oobbuf)
+{
+	struct nand_ecc_sw_hamming_conf *engine_conf = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int eccsize = nand->ecc.ctx.conf.step_size;
+	int total = nand->ecc.ctx.total;
+	int eccbytes = engine_conf->code_size;
+	int eccsteps = engine_conf->nsteps;
+	u8 *ecccalc = engine_conf->calc_buf;
+	u8 *ecccode = engine_conf->code_buf;
+	unsigned int max_bitflips = 0;
+	u8 *data = req->databuf.in;
+	int i, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	/* This engine does not provide BBM/free OOB bytes protection */
+	if (!req->datalen)
+		return 0;
+
+	/* Don't mess up with the upper layer: restore the request OOB length */
+	req->ooblen = engine_conf->reqooblen;
+
+	/* Nothing more to do for page write */
+	if (req->type == NAND_PAGE_WRITE)
+		return 0;
+
+	/* Finish a page read: retrieve the (raw) ECC bytes*/
+	ret = mtd_ooblayout_get_eccbytes(mtd, ecccode, oobbuf, 0, total);
+	if (ret)
+		return ret;
+
+	/* Calculate the ECC bytes */
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, data += eccsize)
+		nand_ecc_sw_hamming_calculate(nand, data, &ecccalc[i]);
+
+	eccsteps = engine_conf->nsteps;
+
+	/* Finish a page read: compare and correct */
+	for (eccsteps = engine_conf->nsteps, i = 0, data = req->databuf.in;
+	     eccsteps;
+	     eccsteps--, i += eccbytes, data += eccsize) {
+		int stat =  nand_ecc_sw_hamming_correct(nand, data,
+							&ecccode[i],
+							&ecccalc[i]);
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+
+	/* Format the OOB buffer that will be returned to the user */
+	if (req->ooblen) {
+		if (req->mode == MTD_OPS_AUTO_OOB)
+			mtd_ooblayout_get_databytes(mtd, oobbuf,
+						    req->oobbuf.in,
+						    req->ooboffs, req->ooblen);
+		else
+			memcpy(req->oobbuf.in, oobbuf + req->ooboffs,
+			       req->ooblen);
+	}
+
+	return max_bitflips;
+}
+
+static struct nand_ecc_engine_ops nand_ecc_sw_hamming_engine_ops = {
+	.init_ctx = nand_ecc_sw_hamming_init_ctx,
+	.cleanup_ctx = nand_ecc_sw_hamming_cleanup_ctx,
+	.prepare_io_req = nand_ecc_sw_hamming_prepare_io_req,
+	.finish_io_req = nand_ecc_sw_hamming_finish_io_req,
+};
+
+static struct nand_ecc_engine nand_ecc_sw_hamming_engine = {
+	.ops = &nand_ecc_sw_hamming_engine_ops,
+};
+
+struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void)
+{
+	return &nand_ecc_sw_hamming_engine;
+}
+EXPORT_SYMBOL(nand_ecc_sw_hamming_get_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
 MODULE_DESCRIPTION("NAND software Hamming ECC support");
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 8b910c818755..3149af72f519 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4849,34 +4849,24 @@ static void nand_scan_ident_cleanup(struct nand_chip *chip)
 
 int rawnand_sw_hamming_init(struct nand_chip *chip)
 {
-	struct mtd_info *mtd = nand_to_mtd(chip);
 	struct nand_ecc_sw_hamming_conf *engine_conf;
 	struct nand_device *base = &chip->base;
+	int ret;
 
 	base->ecc.user_conf.provider = NAND_ECC_SOFT;
 	base->ecc.user_conf.algo = NAND_ECC_HAMMING;
 	base->ecc.user_conf.strength = chip->ecc.strength;
 	base->ecc.user_conf.step_size = chip->ecc.size;
 
-	if (base->ecc.user_conf.strength != 1 ||
-	    (base->ecc.user_conf.step_size != 256 &&
-	     base->ecc.user_conf.step_size != 512)) {
-		pr_err("%s: unsupported strength or step size\n", __func__);
-		return -EINVAL;
-	}
+	ret = nand_ecc_sw_hamming_init_ctx(base);
+	if (ret)
+		return ret;
 
-	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
-	if (!engine_conf)
-		return -ENOMEM;
-
-	engine_conf->code_size = 3;
-	engine_conf->nsteps = mtd->writesize / base->ecc.user_conf.step_size;
+	engine_conf = base->ecc.ctx.priv;
 
 	if (chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER)
 		engine_conf->sm_order = true;
 
-	base->ecc.ctx.priv = engine_conf;
-
 	chip->ecc.size = base->ecc.ctx.conf.step_size;
 	chip->ecc.strength = base->ecc.ctx.conf.strength;
 	chip->ecc.total = base->ecc.ctx.total;
@@ -4912,7 +4902,7 @@ void rawnand_sw_hamming_cleanup(struct nand_chip *chip)
 {
 	struct nand_device *base = &chip->base;
 
-	kfree(base->ecc.ctx.priv);
+	nand_ecc_sw_hamming_cleanup_ctx(base);
 }
 EXPORT_SYMBOL(rawnand_sw_hamming_cleanup);
 
@@ -5376,7 +5366,8 @@ static int nand_scan_tail(struct nand_chip *chip)
 	 * If no default placement scheme is given, select an appropriate one.
 	 */
 	if (!mtd->ooblayout &&
-	    !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH)) {
+	    !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH) &&
+	    !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_HAMMING)) {
 		switch (mtd->oobsize) {
 		case 8:
 		case 16:
diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index 4d41d6ec9fe7..9ea096aaf230 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -32,6 +32,8 @@ struct nand_ecc_sw_hamming_conf {
 
 #if IS_REACHABLE(CONFIG_MTD_NAND_ECC_SW_HAMMING)
 
+int nand_ecc_sw_hamming_init_ctx(struct nand_device *nand);
+void nand_ecc_sw_hamming_cleanup_ctx(struct nand_device *nand);
 int ecc_sw_hamming_calculate(const unsigned char *buf, unsigned int step_size,
 			     unsigned char *code, bool sm_order);
 int nand_ecc_sw_hamming_calculate(struct nand_device *nand,
@@ -43,9 +45,17 @@ int ecc_sw_hamming_correct(unsigned char *buf, unsigned char *read_ecc,
 int nand_ecc_sw_hamming_correct(struct nand_device *nand, unsigned char *buf,
 				unsigned char *read_ecc,
 				unsigned char *calc_ecc);
+struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
 
 #else /* !CONFIG_MTD_NAND_ECC_SW_HAMMING */
 
+static inline int nand_ecc_sw_hamming_init_ctx(struct nand_device *nand)
+{
+	return -ENOTSUPP;
+}
+
+static inline void nand_ecc_sw_hamming_cleanup_ctx(struct nand_device *nand) {}
+
 static inline int ecc_sw_hamming_calculate(const unsigned char *buf,
 					   unsigned int step_size,
 					   unsigned char *code, bool sm_order)
@@ -76,6 +86,11 @@ static inline int nand_ecc_sw_hamming_correct(struct nand_device *nand,
 	return -ENOTSUPP;
 }
 
+static inline struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void)
+{
+	return NULL;
+}
+
 #endif /* CONFIG_MTD_NAND_ECC_SW_HAMMING */
 
 #endif /* __MTD_NAND_ECC_SW_HAMMING_H__ */
-- 
2.19.1


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

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

* [PATCH v2 27/36] mtd: nand: Let software ECC engines be retrieved from the NAND core
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (25 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 26/36] mtd: nand: ecc: Create the software Hamming " Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 28/36] mtd: spinand: Fix typo in comment Miquel Raynal
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Before making use of the ECC engines, we must retrieve them. Add the
boilerplate for the ones already available: software engines (Hamming
and BCH).

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/engine.c           | 20 ++++++++++++++++++++
 include/linux/mtd/nand-ecc-sw-bch.h     |  3 +++
 include/linux/mtd/nand-ecc-sw-hamming.h |  3 +++
 include/linux/mtd/nand.h                |  3 +++
 4 files changed, 29 insertions(+)

diff --git a/drivers/mtd/nand/ecc/engine.c b/drivers/mtd/nand/ecc/engine.c
index c6779acc936d..4345124e01bf 100644
--- a/drivers/mtd/nand/ecc/engine.c
+++ b/drivers/mtd/nand/ecc/engine.c
@@ -450,6 +450,26 @@ bool nand_ecc_correction_is_enough(struct nand_device *nand)
 }
 EXPORT_SYMBOL(nand_ecc_correction_is_enough);
 
+struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand)
+{
+	unsigned int algo = nand->ecc.user_conf.algo;
+
+	if (algo == NAND_ECC_UNKNOWN)
+		algo = nand->ecc.defaults.algo;
+
+	switch (algo) {
+	case NAND_ECC_HAMMING:
+		return nand_ecc_sw_hamming_get_engine();
+	case NAND_ECC_BCH:
+		return nand_ecc_sw_bch_get_engine();
+	default:
+		break;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(nand_ecc_get_sw_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/include/linux/mtd/nand-ecc-sw-bch.h b/include/linux/mtd/nand-ecc-sw-bch.h
index cd9044d293f8..e4f9b4aee3cd 100644
--- a/include/linux/mtd/nand-ecc-sw-bch.h
+++ b/include/linux/mtd/nand-ecc-sw-bch.h
@@ -11,6 +11,9 @@
 #include <linux/mtd/nand.h>
 #include <linux/bch.h>
 
+/* Needed for cross inclusion with nand.h */
+struct nand_device;
+
 /**
  * struct nand_ecc_sw_bch_conf - private software BCH ECC engine structure
  * @reqooblen: Save the actual user OOB length requested before overwriting it
diff --git a/include/linux/mtd/nand-ecc-sw-hamming.h b/include/linux/mtd/nand-ecc-sw-hamming.h
index 9ea096aaf230..75bf80529fe9 100644
--- a/include/linux/mtd/nand-ecc-sw-hamming.h
+++ b/include/linux/mtd/nand-ecc-sw-hamming.h
@@ -12,6 +12,9 @@
 
 #include <linux/mtd/nand.h>
 
+/* Needed for cross inclusion with nand.h */
+struct nand_device;
+
 /**
  * struct nand_ecc_sw_hamming_conf - private software Hamming ECC engine structure
  * @reqooblen: Save the actual user OOB length requested before overwriting it
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 5db24fa073f2..c68060cebc86 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -11,6 +11,8 @@
 #define __LINUX_MTD_NAND_H
 
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
+#include <linux/mtd/nand-ecc-sw-bch.h>
 
 struct nand_device;
 
@@ -245,6 +247,7 @@ int nand_ecc_prepare_io_req(struct nand_device *nand,
 int nand_ecc_finish_io_req(struct nand_device *nand,
 			   struct nand_page_io_req *req, void *oobbuf);
 bool nand_ecc_correction_is_enough(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
 
 /**
  * struct nand_ecc - High-level ECC object
-- 
2.19.1


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

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

* [PATCH v2 28/36] mtd: spinand: Fix typo in comment
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (26 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 27/36] mtd: nand: Let software ECC engines be retrieved from the NAND core Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 29/36] mtd: spinand: Move ECC related definitions earlier in the driver Miquel Raynal
                   ` (7 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

One comment in the SPI-NAND core is not very clear, fix it to ease the
understanding of what the block does.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 drivers/mtd/nand/spi/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index ab41b9434d87..9c8a5ee626cd 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1032,7 +1032,7 @@ static int spinand_init(struct spinand_device *spinand)
 
 	/*
 	 * Right now, we don't support ECC, so let the whole oob
-	 * area is available for user.
+	 * area available for the user.
 	 */
 	mtd->_read_oob = spinand_mtd_read;
 	mtd->_write_oob = spinand_mtd_write;
-- 
2.19.1


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

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

* [PATCH v2 29/36] mtd: spinand: Move ECC related definitions earlier in the driver
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (27 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 28/36] mtd: spinand: Fix typo in comment Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 30/36] mtd: spinand: Instantiate a SPI-NAND on-die ECC engine Miquel Raynal
                   ` (6 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Prepare the creation of a SPI-NAND chips on-die ECC engine by
gathering the ECC-related code earlier enough in the core to avoid the
need for forward declarations.

The next step is to actually create that engine by implementing the
generic ECC interface.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/core.c              | 106 +++++++++++------------
 drivers/mtd/nand/spi/on-die-ecc-engine.c |   0
 2 files changed, 53 insertions(+), 53 deletions(-)
 create mode 100644 drivers/mtd/nand/spi/on-die-ecc-engine.c

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 9c8a5ee626cd..43f0e97c1808 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -207,6 +207,59 @@ static int spinand_ecc_enable(struct spinand_device *spinand,
 			       enable ? CFG_ECC_ENABLE : 0);
 }
 
+static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
+{
+	struct nand_device *nand = spinand_to_nand(spinand);
+
+	if (spinand->eccinfo.get_status)
+		return spinand->eccinfo.get_status(spinand, status);
+
+	switch (status & STATUS_ECC_MASK) {
+	case STATUS_ECC_NO_BITFLIPS:
+		return 0;
+
+	case STATUS_ECC_HAS_BITFLIPS:
+		/*
+		 * We have no way to know exactly how many bitflips have been
+		 * fixed, so let's return the maximum possible value so that
+		 * wear-leveling layers move the data immediately.
+		 */
+		return nand->ecc.ctx.conf.strength;
+
+	case STATUS_ECC_UNCOR_ERROR:
+		return -EBADMSG;
+
+	default:
+		break;
+	}
+
+	return -EINVAL;
+}
+
+static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section,
+				       struct mtd_oob_region *region)
+{
+	return -ERANGE;
+}
+
+static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section,
+					struct mtd_oob_region *region)
+{
+	if (section)
+		return -ERANGE;
+
+	/* Reserve 2 bytes for the BBM. */
+	region->offset = 2;
+	region->length = 62;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
+	.ecc = spinand_noecc_ooblayout_ecc,
+	.free = spinand_noecc_ooblayout_free,
+};
+
 static int spinand_write_enable_op(struct spinand_device *spinand)
 {
 	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
@@ -463,35 +516,6 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
 	return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
 }
 
-static int spinand_check_ecc_status(struct spinand_device *spinand, u8 status)
-{
-	struct nand_device *nand = spinand_to_nand(spinand);
-
-	if (spinand->eccinfo.get_status)
-		return spinand->eccinfo.get_status(spinand, status);
-
-	switch (status & STATUS_ECC_MASK) {
-	case STATUS_ECC_NO_BITFLIPS:
-		return 0;
-
-	case STATUS_ECC_HAS_BITFLIPS:
-		/*
-		 * We have no way to know exactly how many bitflips have been
-		 * fixed, so let's return the maximum possible value so that
-		 * wear-leveling layers move the data immediately.
-		 */
-		return nand->ecc.ctx.conf.strength;
-
-	case STATUS_ECC_UNCOR_ERROR:
-		return -EBADMSG;
-
-	default:
-		break;
-	}
-
-	return -EINVAL;
-}
-
 static int spinand_read_page(struct spinand_device *spinand,
 			     const struct nand_page_io_req *req,
 			     bool ecc_enabled)
@@ -937,30 +961,6 @@ static int spinand_detect(struct spinand_device *spinand)
 	return 0;
 }
 
-static int spinand_noecc_ooblayout_ecc(struct mtd_info *mtd, int section,
-				       struct mtd_oob_region *region)
-{
-	return -ERANGE;
-}
-
-static int spinand_noecc_ooblayout_free(struct mtd_info *mtd, int section,
-					struct mtd_oob_region *region)
-{
-	if (section)
-		return -ERANGE;
-
-	/* Reserve 2 bytes for the BBM. */
-	region->offset = 2;
-	region->length = 62;
-
-	return 0;
-}
-
-static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
-	.ecc = spinand_noecc_ooblayout_ecc,
-	.free = spinand_noecc_ooblayout_free,
-};
-
 static int spinand_init(struct spinand_device *spinand)
 {
 	struct device *dev = &spinand->spimem->spi->dev;
diff --git a/drivers/mtd/nand/spi/on-die-ecc-engine.c b/drivers/mtd/nand/spi/on-die-ecc-engine.c
new file mode 100644
index 000000000000..e69de29bb2d1
-- 
2.19.1


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

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

* [PATCH v2 30/36] mtd: spinand: Instantiate a SPI-NAND on-die ECC engine
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (28 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 29/36] mtd: spinand: Move ECC related definitions earlier in the driver Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 31/36] mtd: nand: Let on-die ECC engines be retrieved from the NAND core Miquel Raynal
                   ` (5 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Make use of the existing functions taken from the SPI-NAND core to
instantiate an on-die ECC engine specific to the SPI-NAND core. The
next step will be to tweak the core to use this object instead of
calling the helpers directly.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/core.c | 69 +++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h |  9 +++++
 2 files changed, 78 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 43f0e97c1808..90f62ea4111c 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -260,6 +260,75 @@ static const struct mtd_ooblayout_ops spinand_noecc_ooblayout = {
 	.free = spinand_noecc_ooblayout_free,
 };
 
+static int spinand_ondie_ecc_init_ctx(struct nand_device *nand)
+{
+	struct spinand_device *spinand = nand_to_spinand(nand);
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct spinand_ondie_ecc_conf *engine_conf;
+
+	nand->ecc.ctx.conf.provider = NAND_ECC_ON_DIE;
+	nand->ecc.ctx.conf.step_size = nand->ecc.requirements.step_size;
+	nand->ecc.ctx.conf.strength = nand->ecc.requirements.strength;
+
+	engine_conf = kzalloc(sizeof(*engine_conf), GFP_KERNEL);
+	if (!engine_conf)
+		return -ENOMEM;
+
+	nand->ecc.ctx.priv = engine_conf;
+
+	if (spinand->eccinfo.ooblayout)
+		mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout);
+	else
+		mtd_set_ooblayout(mtd, &spinand_noecc_ooblayout);
+
+	return 0;
+}
+
+static void spinand_ondie_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	kfree(nand->ecc.ctx.priv);
+}
+
+static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand,
+					    struct nand_page_io_req *req,
+					    void *oobbuf)
+{
+	struct spinand_device *spinand = nand_to_spinand(nand);
+	bool enable = (req->mode != MTD_OPS_RAW);
+
+	/* Only enable or disable the engine */
+	return spinand_ecc_enable(spinand, enable);
+}
+
+static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
+					   struct nand_page_io_req *req,
+					   void *oobbuf)
+{
+	struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv;
+	struct spinand_device *spinand = nand_to_spinand(nand);
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	/* Nothing to do when finishing a page write */
+	if (req->type == NAND_PAGE_WRITE)
+		return 0;
+
+	/* Finish a page write: check the status, report errors/bitflips */
+	return spinand_check_ecc_status(spinand, engine_conf->status);
+}
+
+static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
+	.init_ctx = spinand_ondie_ecc_init_ctx,
+	.cleanup_ctx = spinand_ondie_ecc_cleanup_ctx,
+	.prepare_io_req = spinand_ondie_ecc_prepare_io_req,
+	.finish_io_req = spinand_ondie_ecc_finish_io_req,
+};
+
+static __maybe_unused struct nand_ecc_engine spinand_ondie_ecc_engine = {
+	.ops = &spinand_ondie_ecc_engine_ops,
+};
+
 static int spinand_write_enable_op(struct spinand_device *spinand)
 {
 	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 75a28dc79a9c..d093d237fba8 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -240,6 +240,15 @@ struct spinand_ecc_info {
 
 #define SPINAND_HAS_QE_BIT		BIT(0)
 
+/**
+ * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
+ * @status: status of the last wait operation that will be used in case
+ *          ->get_status() is not populated by the spinand device.
+ */
+struct spinand_ondie_ecc_conf {
+	u8 status;
+};
+
 /**
  * struct spinand_info - Structure used to describe SPI NAND chips
  * @model: model name
-- 
2.19.1


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

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

* [PATCH v2 31/36] mtd: nand: Let on-die ECC engines be retrieved from the NAND core
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (29 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 30/36] mtd: spinand: Instantiate a SPI-NAND on-die ECC engine Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 32/36] mtd: rawnand: Fill a default ECC provider/algorithm Miquel Raynal
                   ` (4 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Before making use of the ECC engines, we must retrieve them. Add the
boilerplate for the on-die ones.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/ecc/engine.c | 6 ++++++
 include/linux/mtd/nand.h      | 1 +
 2 files changed, 7 insertions(+)

diff --git a/drivers/mtd/nand/ecc/engine.c b/drivers/mtd/nand/ecc/engine.c
index 4345124e01bf..2464b7dea062 100644
--- a/drivers/mtd/nand/ecc/engine.c
+++ b/drivers/mtd/nand/ecc/engine.c
@@ -470,6 +470,12 @@ struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand)
 }
 EXPORT_SYMBOL(nand_ecc_get_sw_engine);
 
+struct nand_ecc_engine *nand_ecc_get_ondie_engine(struct nand_device *nand)
+{
+	return nand->ecc.ondie_engine;
+}
+EXPORT_SYMBOL(nand_ecc_get_ondie_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c68060cebc86..3498d22fe893 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -248,6 +248,7 @@ int nand_ecc_finish_io_req(struct nand_device *nand,
 			   struct nand_page_io_req *req, void *oobbuf);
 bool nand_ecc_correction_is_enough(struct nand_device *nand);
 struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_get_ondie_engine(struct nand_device *nand);
 
 /**
  * struct nand_ecc - High-level ECC object
-- 
2.19.1


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

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

* [PATCH v2 32/36] mtd: rawnand: Fill a default ECC provider/algorithm
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (30 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 31/36] mtd: nand: Let on-die ECC engines be retrieved from the NAND core Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 33/36] mtd: spinand: " Miquel Raynal
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

The raw NAND layer may want to use one or another ECC provider if the
user did not explicitly broadcasted his choice through the DT. Raw
NAND controllers can also want to force these values. In any case, the
NAND core must be able to know their preference and this works by
letting subsystems/drivers filling/changing the "defaults" ECC
structure.

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

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3149af72f519..f4b9374a8729 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -5596,6 +5596,13 @@ static int nand_scan_tail(struct nand_chip *chip)
 		break;
 	}
 
+	/*
+	 * If there is no specific user request for the ECC engine provider, use
+	 * the one chosen by the driver being instantiated.
+	 */
+	chip->base.ecc.defaults.provider = ecc->mode;
+	chip->base.ecc.defaults.algo = ecc->algo;
+
 	ret = nanddev_init(&chip->base, &rawnand_ops, mtd->owner);
 	if (ret)
 		goto err_nand_manuf_cleanup;
-- 
2.19.1


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

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

* [PATCH v2 33/36] mtd: spinand: Fill a default ECC provider/algorithm
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (31 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 32/36] mtd: rawnand: Fill a default ECC provider/algorithm Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 34/36] mtd: nand: Add helpers to manage ECC engines and configurations Miquel Raynal
                   ` (2 subsequent siblings)
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

The SPI-NAND layer default is on-die ECC because until now it was the
only one supported. New SPI-NAND chip flavors might use something else
as ECC engine provider but this will always be the default if the user
does not choose explicitly something else.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/core.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 90f62ea4111c..7ff957c2e9f0 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -325,7 +325,7 @@ static struct nand_ecc_engine_ops spinand_ondie_ecc_engine_ops = {
 	.finish_io_req = spinand_ondie_ecc_finish_io_req,
 };
 
-static __maybe_unused struct nand_ecc_engine spinand_ondie_ecc_engine = {
+static struct nand_ecc_engine spinand_ondie_ecc_engine = {
 	.ops = &spinand_ondie_ecc_engine_ops,
 };
 
@@ -1099,6 +1099,10 @@ static int spinand_init(struct spinand_device *spinand)
 	if (ret)
 		goto err_manuf_cleanup;
 
+	/* SPI-NAND default ECC engine is on-die */
+	nand->ecc.defaults.provider = NAND_ECC_ON_DIE;
+	nand->ecc.ondie_engine = &spinand_ondie_ecc_engine;
+
 	/*
 	 * Right now, we don't support ECC, so let the whole oob
 	 * area available for the user.
-- 
2.19.1


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

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

* [PATCH v2 34/36] mtd: nand: Add helpers to manage ECC engines and configurations
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (32 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 33/36] mtd: spinand: " Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 35/36] mtd: spinand: Use the external ECC engine logic Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 36/36] mtd: spinand: Propagate ECC information to the MTD structure Miquel Raynal
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Add the logic in the NAND core to find the right ECC engine depending
on the NAND chip requirements and the user desires. Right now, the
choice may be made between (more will come):
* software Hamming
* software BCH
* on-die (SPI-NAND devices only)

Once the ECC engine has been found, the ECC engine must be
configured.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/core.c  | 124 +++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h |   4 ++
 2 files changed, 128 insertions(+)

diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 0a2be5e6d669..bed8977d94da 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -207,6 +207,130 @@ int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len)
 }
 EXPORT_SYMBOL_GPL(nanddev_mtd_max_bad_blocks);
 
+/**
+ * nanddev_get_ecc_engine() - Find and get a suitable ECC engine
+ * @nand: NAND device
+ */
+static int nanddev_get_ecc_engine(struct nand_device *nand)
+{
+	int provider;
+
+	/* Read the user desires in terms of ECC engine/configuration */
+	nand_ecc_read_user_conf(nand);
+
+	provider = nand->ecc.user_conf.provider;
+	if (provider == NAND_ECC_INVALID)
+		provider = nand->ecc.defaults.provider;
+
+	switch (provider) {
+	case NAND_ECC_NONE:
+		return 0;
+	case NAND_ECC_SOFT:
+		nand->ecc.engine = nand_ecc_get_sw_engine(nand);
+		break;
+	case NAND_ECC_ON_DIE:
+		nand->ecc.engine = nand_ecc_get_ondie_engine(nand);
+		break;
+	case NAND_ECC_HW:
+		pr_err("Hardware ECC engines not supported yet\n");
+		break;
+	default:
+		pr_err("Missing ECC engine provider\n");
+	}
+
+	if (!nand->ecc.engine)
+		return  -EINVAL;
+
+	return 0;
+}
+
+/**
+ * nanddev_put_ecc_engine() - Dettach and put the in-use ECC engine
+ * @nand: NAND device
+ */
+static int nanddev_put_ecc_engine(struct nand_device *nand)
+{
+	switch (nand->ecc.ctx.conf.provider) {
+	case NAND_ECC_HW:
+		pr_err("Hardware ECC engines not supported yet\n");
+		break;
+	case NAND_ECC_NONE:
+	case NAND_ECC_SOFT:
+	case NAND_ECC_ON_DIE:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/**
+ * nanddev_find_ecc_configuration() - Find a suitable ECC configuration
+ * @nand: NAND device
+ */
+static int nanddev_find_ecc_configuration(struct nand_device *nand)
+{
+	int ret;
+
+	if (!nand->ecc.engine)
+		return -ENOTSUPP;
+
+	ret = nand_ecc_init_ctx(nand);
+	if (ret)
+		return ret;
+
+	if (!nand_ecc_correction_is_enough(nand))
+		pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n",
+			nand->mtd.name);
+
+	return 0;
+}
+
+/**
+ * nanddev_ecc_engine_init() - Initialize an ECC engine for the chip
+ * @nand: NAND device
+ */
+int nanddev_ecc_engine_init(struct nand_device *nand)
+{
+	int ret;
+
+	/* Look for the ECC engine to use */
+	ret = nanddev_get_ecc_engine(nand);
+	if (ret) {
+		pr_err("No ECC engine found\n");
+		return ret;
+	}
+
+	/* No ECC engine requested */
+	if (!nand->ecc.engine)
+		return 0;
+
+	/* Configure the engine: balance user input and chip requirements */
+	ret = nanddev_find_ecc_configuration(nand);
+	if (ret) {
+		pr_err("No suitable ECC configuration\n");
+		nanddev_put_ecc_engine(nand);
+
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nanddev_ecc_engine_init);
+
+/**
+ * nanddev_ecc_engine_cleanup() - Cleanup ECC engine initializations
+ * @nand: NAND device
+ */
+void nanddev_ecc_engine_cleanup(struct nand_device *nand)
+{
+	if (nand->ecc.engine)
+		nand_ecc_cleanup_ctx(nand);
+
+	nanddev_put_ecc_engine(nand);
+}
+EXPORT_SYMBOL_GPL(nanddev_ecc_engine_cleanup);
+
 /**
  * nanddev_init() - Initialize a NAND device
  * @nand: NAND device
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 3498d22fe893..b3a5506a891b 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -832,6 +832,10 @@ bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
 int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
 int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
 
+/* ECC related functions */
+int nanddev_ecc_engine_init(struct nand_device *nand);
+void nanddev_ecc_engine_cleanup(struct nand_device *nand);
+
 /* BBT related functions */
 enum nand_bbt_block_status {
 	NAND_BBT_BLOCK_STATUS_UNKNOWN,
-- 
2.19.1


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

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

* [PATCH v2 35/36] mtd: spinand: Use the external ECC engine logic
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (33 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 34/36] mtd: nand: Add helpers to manage ECC engines and configurations Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  2019-03-04 22:28 ` [PATCH v2 36/36] mtd: spinand: Propagate ECC information to the MTD structure Miquel Raynal
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

Now that all the logic is available in the NAND core, let's use it
from the SPI-NAND core. Right now there is no functional change as the
default ECC engine for SPI-NANDs is set to 'on-die', but user can now
use software correction if they want to by just setting the right
properties in the DT.

Also note that the OOB layout handling is removed from the SPI-NAND
core as each ECC engine is supposed to handle it by it's own; users
should not be aware of that.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/Kconfig |   1 +
 drivers/mtd/nand/spi/core.c  | 110 ++++++++++++++++++-----------------
 2 files changed, 57 insertions(+), 54 deletions(-)

diff --git a/drivers/mtd/nand/spi/Kconfig b/drivers/mtd/nand/spi/Kconfig
index 7c37d2929b68..3e8433fbe54f 100644
--- a/drivers/mtd/nand/spi/Kconfig
+++ b/drivers/mtd/nand/spi/Kconfig
@@ -1,6 +1,7 @@
 menuconfig MTD_SPI_NAND
 	tristate "SPI NAND device Support"
 	select MTD_NAND_CORE
+	select MTD_NAND_ECC
 	depends on SPI_MASTER
 	select SPI_MEM
 	help
diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 7ff957c2e9f0..3ffd50530c19 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -329,6 +329,14 @@ static struct nand_ecc_engine spinand_ondie_ecc_engine = {
 	.ops = &spinand_ondie_ecc_engine_ops,
 };
 
+static void spinand_ondie_ecc_save_status(struct nand_device *nand, u8 status)
+{
+	struct spinand_ondie_ecc_conf *engine_conf = nand->ecc.ctx.priv;
+
+	if (nand->ecc.ctx.conf.provider == NAND_ECC_ON_DIE && engine_conf)
+		engine_conf->status = status;
+}
+
 static int spinand_write_enable_op(struct spinand_device *spinand)
 {
 	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
@@ -351,7 +359,6 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
 {
 	struct spi_mem_op op = *spinand->op_templates.read_cache;
 	struct nand_device *nand = spinand_to_nand(spinand);
-	struct mtd_info *mtd = nanddev_to_mtd(nand);
 	struct nand_page_io_req adjreq = *req;
 	unsigned int nbytes = 0;
 	void *buf = NULL;
@@ -405,17 +412,6 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
 		memcpy(req->databuf.in, spinand->databuf + req->dataoffs,
 		       req->datalen);
 
-	if (req->ooblen) {
-		if (req->mode == MTD_OPS_AUTO_OOB)
-			mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
-						    spinand->oobbuf,
-						    req->ooboffs,
-						    req->ooblen);
-		else
-			memcpy(req->oobbuf.in, spinand->oobbuf + req->ooboffs,
-			       req->ooblen);
-	}
-
 	return 0;
 }
 
@@ -424,16 +420,18 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 {
 	struct spi_mem_op op = *spinand->op_templates.write_cache;
 	struct nand_device *nand = spinand_to_nand(spinand);
-	struct mtd_info *mtd = nanddev_to_mtd(nand);
 	struct nand_page_io_req adjreq = *req;
 	unsigned int nbytes = 0;
 	void *buf = NULL;
 	u16 column = 0;
 	int ret;
 
+	/*
+	 * Only reset the data buffer, the OOB buffer is prepared by ECC engines
+	 *->prepare/finish_io_req() callbacks.
+	 */
 	memset(spinand->databuf, 0xff,
-	       nanddev_page_size(nand) +
-	       nanddev_per_page_oobsize(nand));
+	       nanddev_page_size(nand));
 
 	if (req->datalen) {
 		memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
@@ -446,15 +444,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 	}
 
 	if (req->ooblen) {
-		if (req->mode == MTD_OPS_AUTO_OOB)
-			mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
-						    spinand->oobbuf,
-						    req->ooboffs,
-						    req->ooblen);
-		else
-			memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
-			       req->ooblen);
-
 		adjreq.ooblen = nanddev_per_page_oobsize(nand);
 		adjreq.ooboffs = 0;
 		nbytes += nanddev_per_page_oobsize(nand);
@@ -586,12 +575,17 @@ static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
 }
 
 static int spinand_read_page(struct spinand_device *spinand,
-			     const struct nand_page_io_req *req,
-			     bool ecc_enabled)
+			     const struct nand_page_io_req *req)
 {
+	struct nand_device *nand = spinand_to_nand(spinand);
 	u8 status;
 	int ret;
 
+	ret = nand_ecc_prepare_io_req(nand, (struct nand_page_io_req *)req,
+				      spinand->oobbuf);
+	if (ret)
+		return ret;
+
 	ret = spinand_load_page_op(spinand, req);
 	if (ret)
 		return ret;
@@ -600,22 +594,28 @@ static int spinand_read_page(struct spinand_device *spinand,
 	if (ret < 0)
 		return ret;
 
+	spinand_ondie_ecc_save_status(nand, status);
+
 	ret = spinand_read_from_cache_op(spinand, req);
 	if (ret)
 		return ret;
 
-	if (!ecc_enabled)
-		return 0;
-
-	return spinand_check_ecc_status(spinand, status);
+	return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req,
+				      spinand->oobbuf);
 }
 
 static int spinand_write_page(struct spinand_device *spinand,
 			      const struct nand_page_io_req *req)
 {
+	struct nand_device *nand = spinand_to_nand(spinand);
 	u8 status;
 	int ret;
 
+	ret = nand_ecc_prepare_io_req(nand, (struct nand_page_io_req *)req,
+				      spinand->oobbuf);
+	if (ret)
+		return ret;
+
 	ret = spinand_write_enable_op(spinand);
 	if (ret)
 		return ret;
@@ -630,9 +630,10 @@ static int spinand_write_page(struct spinand_device *spinand,
 
 	ret = spinand_wait(spinand, &status);
 	if (!ret && (status & STATUS_PROG_FAILED))
-		ret = -EIO;
+		return -EIO;
 
-	return ret;
+	return nand_ecc_finish_io_req(nand, (struct nand_page_io_req *)req,
+				      spinand->oobbuf);
 }
 
 static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
@@ -642,25 +643,24 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 	struct nand_device *nand = mtd_to_nanddev(mtd);
 	unsigned int max_bitflips = 0;
 	struct nand_io_iter iter;
-	bool enable_ecc = false;
+	bool disable_ecc = false;
 	bool ecc_failed = false;
 	int ret = 0;
 
-	if (ops->mode != MTD_OPS_RAW && spinand->eccinfo.ooblayout)
-		enable_ecc = true;
+	if (ops->mode == MTD_OPS_RAW || !spinand->eccinfo.ooblayout)
+		disable_ecc = true;
 
 	mutex_lock(&spinand->lock);
 
 	nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) {
+		if (disable_ecc)
+			iter.req.mode = MTD_OPS_RAW;
+
 		ret = spinand_select_target(spinand, iter.req.pos.target);
 		if (ret)
 			break;
 
-		ret = spinand_ecc_enable(spinand, enable_ecc);
-		if (ret)
-			break;
-
-		ret = spinand_read_page(spinand, &iter.req, enable_ecc);
+		ret = spinand_read_page(spinand, &iter.req);
 		if (ret < 0 && ret != -EBADMSG)
 			break;
 
@@ -691,20 +691,19 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to,
 	struct spinand_device *spinand = mtd_to_spinand(mtd);
 	struct nand_device *nand = mtd_to_nanddev(mtd);
 	struct nand_io_iter iter;
-	bool enable_ecc = false;
+	bool disable_ecc = false;
 	int ret = 0;
 
-	if (ops->mode != MTD_OPS_RAW && mtd->ooblayout)
-		enable_ecc = true;
+	if (ops->mode == MTD_OPS_RAW || !mtd->ooblayout)
+		disable_ecc = true;
 
 	mutex_lock(&spinand->lock);
 
 	nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, &iter) {
-		ret = spinand_select_target(spinand, iter.req.pos.target);
-		if (ret)
-			break;
+		if (disable_ecc)
+			iter.req.mode = MTD_OPS_RAW;
 
-		ret = spinand_ecc_enable(spinand, enable_ecc);
+		ret = spinand_select_target(spinand, iter.req.pos.target);
 		if (ret)
 			break;
 
@@ -734,7 +733,7 @@ static bool spinand_isbad(struct nand_device *nand, const struct nand_pos *pos)
 
 	memset(spinand->oobbuf, 0, 2);
 	spinand_select_target(spinand, pos->target);
-	spinand_read_page(spinand, &req, false);
+	spinand_read_page(spinand, &req);
 	if (spinand->oobbuf[0] != 0xff || spinand->oobbuf[1] != 0xff)
 		printk("would be bad, but fuck it\n");
 //		return true;
@@ -1103,6 +1102,11 @@ static int spinand_init(struct spinand_device *spinand)
 	nand->ecc.defaults.provider = NAND_ECC_ON_DIE;
 	nand->ecc.ondie_engine = &spinand_ondie_ecc_engine;
 
+	spinand_ecc_enable(spinand, false);
+	ret = nanddev_ecc_engine_init(nand);
+	if (ret)
+		goto err_cleanup_nanddev;
+
 	/*
 	 * Right now, we don't support ECC, so let the whole oob
 	 * area available for the user.
@@ -1115,19 +1119,17 @@ static int spinand_init(struct spinand_device *spinand)
 	mtd->_erase = spinand_mtd_erase;
 	mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
 
-	if (spinand->eccinfo.ooblayout)
-		mtd_set_ooblayout(mtd, spinand->eccinfo.ooblayout);
-	else
-		mtd_set_ooblayout(mtd, &spinand_noecc_ooblayout);
-
 	ret = mtd_ooblayout_count_freebytes(mtd);
 	if (ret < 0)
-		goto err_cleanup_nanddev;
+		goto err_cleanup_ecc_engine;
 
 	mtd->oobavail = ret;
 
 	return 0;
 
+err_cleanup_ecc_engine:
+	nanddev_ecc_engine_cleanup(nand);
+
 err_cleanup_nanddev:
 	nanddev_cleanup(nand);
 
-- 
2.19.1


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

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

* [PATCH v2 36/36] mtd: spinand: Propagate ECC information to the MTD structure
  2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
                   ` (34 preceding siblings ...)
  2019-03-04 22:28 ` [PATCH v2 35/36] mtd: spinand: Use the external ECC engine logic Miquel Raynal
@ 2019-03-04 22:28 ` Miquel Raynal
  35 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-03-04 22:28 UTC (permalink / raw)
  To: Boris Brezillon, Richard Weinberger, David Woodhouse,
	Brian Norris, Marek Vasut, Tudor Ambarus
  Cc: Vignesh R, Tudor Ambarus, Julien Su, Schrempf Frieder,
	Paul Cercueil, linux-mtd, Thomas Petazzoni, Miquel Raynal,
	Mason Yang, linux-arm-kernel

This is done by default in the raw NAND core (nand_base.c) but was
missing in the SPI-NAND core. Without these two lines the ecc_strength
and ecc_step_size values are not exported to the user through sysfs.

This fix depends on recent changes and should not be backported as-is.

Fixes: 7529df465248 ("mtd: nand: Add core infrastructure to support SPI NANDs")
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/spi/core.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 3ffd50530c19..98f399253921 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1125,6 +1125,10 @@ static int spinand_init(struct spinand_device *spinand)
 
 	mtd->oobavail = ret;
 
+	/* Propagate ECC information to mtd_info */
+	mtd->ecc_strength = nand->ecc.ctx.conf.strength;
+	mtd->ecc_step_size = nand->ecc.ctx.conf.step_size;
+
 	return 0;
 
 err_cleanup_ecc_engine:
-- 
2.19.1


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

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

* Re: [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top
  2019-03-04 22:28 ` [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
@ 2019-03-31 11:12   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:12 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:06 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> This structure might be used earlier in this file, let's move the
> forward declaration at the top.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

> ---
>  include/linux/mtd/nand.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index cebc38b6d6f5..30f0fb02abe2 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -12,6 +12,8 @@
>  
>  #include <linux/mtd/mtd.h>
>  
> +struct nand_device;
> +
>  /**
>   * struct nand_memory_organization - Memory organization structure
>   * @bits_per_cell: number of bits per NAND cell
> @@ -133,8 +135,6 @@ struct nand_bbt {
>  	unsigned long *cache;
>  };
>  
> -struct nand_device;
> -
>  /**
>   * struct nand_ops - NAND operations
>   * @erase: erase a specific block. No need to check if the block is bad before


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

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

* Re: [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy
  2019-03-04 22:28 ` [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy Miquel Raynal
@ 2019-03-31 11:13   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:13 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:07 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Use an extra level in Kconfig for all NAND related entries.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

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

> ---
>  drivers/mtd/nand/Kconfig | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index 495751ed3fd7..d2ef8b89568e 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -1,6 +1,10 @@
> +menu "NAND"
> +
>  config MTD_NAND_CORE
>  	tristate
>  
>  source "drivers/mtd/nand/onenand/Kconfig"
>  source "drivers/mtd/nand/raw/Kconfig"
>  source "drivers/mtd/nand/spi/Kconfig"
> +
> +endmenu


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

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

* Re: [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig
  2019-03-04 22:28 ` [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig Miquel Raynal
@ 2019-03-31 11:15   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:15 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:08 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Both oneNAND and raw NAND bits can be compiled if MTD is enabled

	^ OneNAND		  ^ can't		   ^ disabled

> because of the if/endif logic in drivers/mtd/Kconfig. There is no need
> for an extra "depends on MTD" in their respective Kconfig files.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

With this addressed

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

> ---
>  drivers/mtd/nand/onenand/Kconfig | 1 -
>  drivers/mtd/nand/raw/Kconfig     | 1 -
>  2 files changed, 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/onenand/Kconfig b/drivers/mtd/nand/onenand/Kconfig
> index 9dc15748947b..c168f3b4b296 100644
> --- a/drivers/mtd/nand/onenand/Kconfig
> +++ b/drivers/mtd/nand/onenand/Kconfig
> @@ -1,6 +1,5 @@
>  menuconfig MTD_ONENAND
>  	tristate "OneNAND Device Support"
> -	depends on MTD
>  	depends on HAS_IOMEM
>  	help
>  	  This enables support for accessing all type of OneNAND flash
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index 510a6b32820d..ebb8a3da9fa5 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -11,7 +11,6 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
>  
>  menuconfig MTD_RAW_NAND
>  	tristate "Raw/Parallel NAND Device Support"
> -	depends on MTD
>  	select MTD_NAND_ECC_SW_HAMMING
>  	help
>  	  This enables support for accessing all type of raw/parallel


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

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

* Re: [PATCH v2 04/36] mtd: rawnand: Use the NAND core
  2019-03-04 22:28 ` [PATCH v2 04/36] mtd: rawnand: Use the NAND core Miquel Raynal
@ 2019-03-31 11:21   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:21 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:09 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Before introducing the generic ECC engine abstraction, we need to be
> sure that raw NAND and SPI-NAND speak the same language: let's use the
> generic NAND layer with the raw NAND part (the SPI-NAND one already
> uses it).

Nit: I'm not sure it's useful to compile/depends on the generic NAND
layer until you actually start using it. I would have selected
MTD_NAND_CORE in the patch that starts using some of the functions
exposed there, but that's just a tiny detail.

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

> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/Kconfig | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index ebb8a3da9fa5..952dc50a8634 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -11,6 +11,7 @@ config MTD_NAND_ECC_SW_HAMMING_SMC
>  
>  menuconfig MTD_RAW_NAND
>  	tristate "Raw/Parallel NAND Device Support"
> +	select MTD_NAND_CORE
>  	select MTD_NAND_ECC_SW_HAMMING
>  	help
>  	  This enables support for accessing all type of raw/parallel


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

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

* Re: [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type
  2019-03-04 22:28 ` [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type Miquel Raynal
@ 2019-03-31 11:23   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:23 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:10 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Use an enum to differentiate the type of I/O (reading or writing a
> page). Also update the request iterator.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/spi/core.c |  4 ++--
>  include/linux/mtd/nand.h    | 13 +++++++++++--
>  2 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index ed5e340dff51..9ee192585854 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -558,7 +558,7 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
>  
>  	mutex_lock(&spinand->lock);
>  
> -	nanddev_io_for_each_page(nand, from, ops, &iter) {
> +	nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) {
>  		ret = spinand_select_target(spinand, iter.req.pos.target);
>  		if (ret)
>  			break;
> @@ -606,7 +606,7 @@ static int spinand_mtd_write(struct mtd_info *mtd, loff_t to,
>  
>  	mutex_lock(&spinand->lock);
>  
> -	nanddev_io_for_each_page(nand, to, ops, &iter) {
> +	nanddev_io_for_each_page(nand, NAND_PAGE_WRITE, to, ops, &iter) {
>  		ret = spinand_select_target(spinand, iter.req.pos.target);
>  		if (ret)
>  			break;
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 30f0fb02abe2..84ab76f34c74 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -82,8 +82,14 @@ struct nand_pos {
>  	unsigned int page;
>  };
>  
> +enum nand_page_io_req_type {
> +	NAND_PAGE_READ = 0,
> +	NAND_PAGE_WRITE,
> +};

Please add a kernel doc header. Once done you can add

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

> +
>  /**
>   * struct nand_page_io_req - NAND I/O request object
> + * @type: the type of page I/O: read or write
>   * @pos: the position this I/O request is targeting
>   * @dataoffs: the offset within the page
>   * @datalen: number of data bytes to read from/write to this page
> @@ -99,6 +105,7 @@ struct nand_pos {
>   * specific commands/operations.
>   */
>  struct nand_page_io_req {
> +	enum nand_page_io_req_type type;
>  	struct nand_pos pos;
>  	unsigned int dataoffs;
>  	unsigned int datalen;
> @@ -624,11 +631,13 @@ static inline void nanddev_pos_next_page(struct nand_device *nand,
>   * layer.
>   */
>  static inline void nanddev_io_iter_init(struct nand_device *nand,
> +					enum nand_page_io_req_type reqtype,
>  					loff_t offs, struct mtd_oob_ops *req,
>  					struct nand_io_iter *iter)
>  {
>  	struct mtd_info *mtd = nanddev_to_mtd(nand);
>  
> +	iter->req.type = reqtype;
>  	iter->req.mode = req->mode;
>  	iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
>  	iter->req.ooboffs = req->ooboffs;
> @@ -698,8 +707,8 @@ static inline bool nanddev_io_iter_end(struct nand_device *nand,
>   *
>   * Should be used for iterate over pages that are contained in an MTD request.
>   */
> -#define nanddev_io_for_each_page(nand, start, req, iter)		\
> -	for (nanddev_io_iter_init(nand, start, req, iter);		\
> +#define nanddev_io_for_each_page(nand, type, start, req, iter)		\
> +	for (nanddev_io_iter_init(nand, type, start, req, iter);	\
>  	     !nanddev_io_iter_end(nand, iter);				\
>  	     nanddev_io_iter_next_page(nand, iter))
>  


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

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

* Re: [PATCH v2 06/36] mtd: nand: Rename a core structure
  2019-03-04 22:28 ` [PATCH v2 06/36] mtd: nand: Rename a core structure Miquel Raynal
@ 2019-03-31 11:30   ` Boris Brezillon
  2019-05-03  8:26     ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:30 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:11 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Prepare the migration to a generic ECC engine by renaming the
> nand_ecc_req structure into nand_ecc_conf. This structure will be the
> base of a wider 'nand_ecc' structure.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  include/linux/mtd/nand.h    | 8 ++++----
>  include/linux/mtd/spinand.h | 2 +-
>  2 files changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> index 84ab76f34c74..78cf905083c9 100644
> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -123,11 +123,11 @@ struct nand_page_io_req {
>  };
>  
>  /**
> - * struct nand_ecc_req - NAND ECC requirements
> + * struct nand_ecc_conf - NAND ECC configuration

Maybe nand_ecc_info, nand_ecc_caps or nand_ecc_props would be more
appropriate as _conf seems to imply you can change it, which is not
the case when you use this struct to express chip requirements or when
you use an on-die ECC which is not configurable.

>   * @strength: ECC strength
> - * @step_size: ECC step/block size
> + * @step_size: Number of bytes per step
>   */
> -struct nand_ecc_req {
> +struct nand_ecc_conf {
>  	unsigned int strength;
>  	unsigned int step_size;
>  };
> @@ -186,7 +186,7 @@ struct nand_ops {
>  struct nand_device {
>  	struct mtd_info mtd;
>  	struct nand_memory_organization memorg;
> -	struct nand_ecc_req eccreq;
> +	struct nand_ecc_conf eccreq;
>  	struct nand_row_converter rowconv;
>  	struct nand_bbt bbt;
>  	const struct nand_ops *ops;
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index b92e2aa955b6..3008de54f958 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -263,7 +263,7 @@ struct spinand_info {
>  	u8 devid;
>  	u32 flags;
>  	struct nand_memory_organization memorg;
> -	struct nand_ecc_req eccreq;
> +	struct nand_ecc_conf eccreq;
>  	struct spinand_ecc_info eccinfo;
>  	struct {
>  		const struct spinand_op_variants *read_cache;


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

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

* Re: [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description
  2019-03-04 22:28 ` [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description Miquel Raynal
@ 2019-03-31 11:32   ` Boris Brezillon
  2019-05-03  8:18     ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:32 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:16 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Fix a probable copy/paste error: the function works like
> mtd_ooblayout_set_bytes(), not the *_get_bytes() alternate.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/mtdcore.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 21e3cdc04036..6ed48018163c 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -1592,7 +1592,7 @@ EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
>   * @start: first ECC byte to set
>   * @nbytes: number of ECC bytes to set

Looks like the parameter descriptions are wrong too.

>   *
> - * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes.
> + * Works like mtd_ooblayout_set_bytes(), except it acts on free bytes.
>   *
>   * Returns zero on success, a negative error code otherwise.
>   */


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

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

* Re: [PATCH v2 07/36] mtd: rawnand: Avoid a typedef
  2019-03-04 22:28 ` [PATCH v2 07/36] mtd: rawnand: Avoid a typedef Miquel Raynal
@ 2019-03-31 11:55   ` Boris Brezillon
  2019-05-03 12:40     ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:55 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:12 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> In new code, the use of typedef is discouraged. Before moving this
> section out of the raw NAND base, let's switch the nand_ecc_modes_t
> type into a regular nand_ecc_mode enumeration.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c               | 4 ++--
>  include/linux/mtd/rawnand.h                    | 6 +++---
>  include/linux/platform_data/mtd-davinci.h      | 2 +-
>  include/linux/platform_data/mtd-nand-s3c2410.h | 2 +-
>  4 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index e14f02a01efd..05174c6a3099 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -4881,8 +4881,8 @@ static int of_get_nand_ecc_mode(struct device_node *np)
>  
>  	/*
>  	 * For backward compatibility we support few obsoleted values that don't
> -	 * have their mappings into nand_ecc_modes_t anymore (they were merged
> -	 * with other enums).
> +	 * have their mappings into the nand_ecc_mode enum anymore (they were
> +	 * merged with other enums).
>  	 */
>  	if (!strcasecmp(pm, "soft_bch"))
>  		return NAND_ECC_SOFT;
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index 14748183508b..c5bf6bb49329 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -87,14 +87,14 @@ struct nand_chip;
>  /*
>   * Constants for ECC_MODES
>   */
> -typedef enum {
> +enum nand_ecc_mode {
>  	NAND_ECC_NONE,
>  	NAND_ECC_SOFT,
>  	NAND_ECC_HW,
>  	NAND_ECC_HW_SYNDROME,
>  	NAND_ECC_HW_OOB_FIRST,
>  	NAND_ECC_ON_DIE,
> -} nand_ecc_modes_t;
> +};

Hm, I'm really not a big fan of this enum because it's mixing 2
different concepts: the type of ECC engine to use (on-die,
hw-controller-side, software, no-ECC) and the layout of
ECC/FREE bytes (_SYNDROME, _OOB_FIRST).

I'd recommend creating a nand_ecc_engine_type enum:

enum nand_ecc_engine_type {
	NAND_NO_ECC_ENGINE,
	NAND_SOFT_ECC_ENGINE,
	NAND_HW_ECC_ENGINE,
	NAND_ON_DIE_ECC_ENGINE,
};

and then convert the raw NAND layer to this enum when the time comes.

>  
>  enum nand_ecc_algo {
>  	NAND_ECC_UNKNOWN,
> @@ -340,7 +340,7 @@ static const struct nand_ecc_caps __name = {			\
>   * @write_oob:	function to write chip OOB data
>   */
>  struct nand_ecc_ctrl {
> -	nand_ecc_modes_t mode;
> +	enum nand_ecc_mode mode;
>  	enum nand_ecc_algo algo;
>  	int steps;
>  	int size;
> diff --git a/include/linux/platform_data/mtd-davinci.h b/include/linux/platform_data/mtd-davinci.h
> index 1bbfa27cccb4..e7457be12b8f 100644
> --- a/include/linux/platform_data/mtd-davinci.h
> +++ b/include/linux/platform_data/mtd-davinci.h
> @@ -81,7 +81,7 @@ struct davinci_nand_pdata {		/* platform_data */
>  	 * Newer ones also support 4-bit ECC, but are awkward
>  	 * using it with large page chips.
>  	 */
> -	nand_ecc_modes_t	ecc_mode;
> +	enum nand_ecc_mode	ecc_mode;
>  	u8			ecc_bits;
>  
>  	/* e.g. NAND_BUSWIDTH_16 */
> diff --git a/include/linux/platform_data/mtd-nand-s3c2410.h b/include/linux/platform_data/mtd-nand-s3c2410.h
> index f8c553f92655..ff6501c51244 100644
> --- a/include/linux/platform_data/mtd-nand-s3c2410.h
> +++ b/include/linux/platform_data/mtd-nand-s3c2410.h
> @@ -52,7 +52,7 @@ struct s3c2410_platform_nand {
>  
>  	unsigned int	ignore_unset_ecc:1;
>  
> -	nand_ecc_modes_t	ecc_mode;
> +	enum nand_ecc_mode	ecc_mode;
>  
>  	int			nr_sets;
>  	struct s3c2410_nand_set *sets;


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

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

* Re: [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo
  2019-03-04 22:28 ` [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo Miquel Raynal
@ 2019-03-31 11:57   ` Boris Brezillon
  0 siblings, 0 replies; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 11:57 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:14 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> In the nand_ecc_{mode,algo} enumerations, clarify the fact that the
> value 0 will be used for invalid/uninitialized data.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  include/linux/mtd/rawnand.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index d25e0c07b0ad..95b0c7114701 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -88,7 +88,7 @@ struct nand_chip;
>   * Constants for ECC_MODES
>   */
>  enum nand_ecc_mode {
> -	NAND_ECC_INVALID,
> +	NAND_ECC_INVALID = 0,
>  	NAND_ECC_NONE,
>  	NAND_ECC_SOFT,
>  	NAND_ECC_HW,
> @@ -98,7 +98,7 @@ enum nand_ecc_mode {
>  };
>  
>  enum nand_ecc_algo {
> -	NAND_ECC_UNKNOWN,
> +	NAND_ECC_UNKNOWN = 0,
>  	NAND_ECC_HAMMING,
>  	NAND_ECC_BCH,
>  	NAND_ECC_RS,

Do we really need to do that? I think it's pretty common to leave the
first entry unassigned when we want things to start at 0...

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

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

* Re: [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction
  2019-03-04 22:28 ` [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction Miquel Raynal
@ 2019-03-31 12:10   ` Boris Brezillon
  2019-05-03 14:34     ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-03-31 12:10 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Mon,  4 Mar 2019 23:28:15 +0100
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Create a generic ECC engine object.
> 
> Later the ecc/engine.c file will receive more generic code coming from
> the raw NAND specific part. This is a base to instantiate ECC engine
> objects.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/mtd/nand/Kconfig                     |   1 +
>  drivers/mtd/nand/Makefile                    |   1 +
>  drivers/mtd/nand/ecc/Kconfig                 |   6 +
>  drivers/mtd/nand/ecc/Makefile                |   3 +
>  drivers/mtd/nand/ecc/engine.c                | 138 +++++++++++++++++++
>  drivers/mtd/nand/raw/atmel/nand-controller.c |   9 +-
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  12 +-
>  drivers/mtd/nand/raw/marvell_nand.c          |   7 +-
>  drivers/mtd/nand/raw/mtk_nand.c              |   4 +-
>  drivers/mtd/nand/raw/nand_base.c             |  17 +--
>  drivers/mtd/nand/raw/nand_esmt.c             |  11 +-
>  drivers/mtd/nand/raw/nand_hynix.c            |  41 +++---
>  drivers/mtd/nand/raw/nand_jedec.c            |   4 +-
>  drivers/mtd/nand/raw/nand_micron.c           |  14 +-
>  drivers/mtd/nand/raw/nand_onfi.c             |   8 +-
>  drivers/mtd/nand/raw/nand_samsung.c          |  19 +--
>  drivers/mtd/nand/raw/nand_toshiba.c          |  11 +-
>  drivers/mtd/nand/raw/sunxi_nand.c            |   5 +-
>  drivers/mtd/nand/raw/tegra_nand.c            |   9 +-
>  drivers/mtd/nand/spi/core.c                  |   4 +-
>  drivers/mtd/nand/spi/macronix.c              |   6 +-
>  drivers/mtd/nand/spi/toshiba.c               |   6 +-

Can we please split that in 3 patches:

1/ introduce the ECC framework
2/ convert spi nand
3/ convert raw nand

>  include/linux/mtd/nand.h                     |  82 ++++++++++-
>  include/linux/mtd/spinand.h                  |   2 +-
>  24 files changed, 327 insertions(+), 93 deletions(-)
>  create mode 100644 drivers/mtd/nand/ecc/Kconfig
>  create mode 100644 drivers/mtd/nand/ecc/Makefile
>  create mode 100644 drivers/mtd/nand/ecc/engine.c
> 
> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> index d2ef8b89568e..75d0bd18b818 100644
> --- a/drivers/mtd/nand/Kconfig
> +++ b/drivers/mtd/nand/Kconfig
> @@ -6,5 +6,6 @@ config MTD_NAND_CORE
>  source "drivers/mtd/nand/onenand/Kconfig"
>  source "drivers/mtd/nand/raw/Kconfig"
>  source "drivers/mtd/nand/spi/Kconfig"
> +source "drivers/mtd/nand/ecc/Kconfig"
>  
>  endmenu
> diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> index 7ecd80c0a66e..9772e781534d 100644
> --- a/drivers/mtd/nand/Makefile
> +++ b/drivers/mtd/nand/Makefile
> @@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
>  obj-y	+= onenand/
>  obj-y	+= raw/
>  obj-y	+= spi/
> +obj-y	+= ecc/
> diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
> new file mode 100644
> index 000000000000..01439f66ecbf
> --- /dev/null
> +++ b/drivers/mtd/nand/ecc/Kconfig
> @@ -0,0 +1,6 @@
> +menu "ECC engine support"
> +
> +config MTD_NAND_ECC
> +	tristate
> +

There's already an MTD_NAND_ECC symbol defined in
drivers/mtd/nand/raw/Kconfig, plus I don't think we want ecc/engine.c
to be compiled as a module, but instead be embedded in nand-core.ko.
Not to mention that the name, engine.ko, is probably too generic.

> +endmenu
> diff --git a/drivers/mtd/nand/ecc/Makefile b/drivers/mtd/nand/ecc/Makefile
> new file mode 100644
> index 000000000000..c7367f834d81
> --- /dev/null
> +++ b/drivers/mtd/nand/ecc/Makefile
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_MTD_NAND_ECC)		+= engine.o


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

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

* Re: [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description
  2019-03-31 11:32   ` Boris Brezillon
@ 2019-05-03  8:18     ` Miquel Raynal
  0 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-05-03  8:18 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
2019 13:32:46 +0200:

> On Mon,  4 Mar 2019 23:28:16 +0100
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Fix a probable copy/paste error: the function works like
> > mtd_ooblayout_set_bytes(), not the *_get_bytes() alternate.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/mtdcore.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > index 21e3cdc04036..6ed48018163c 100644
> > --- a/drivers/mtd/mtdcore.c
> > +++ b/drivers/mtd/mtdcore.c
> > @@ -1592,7 +1592,7 @@ EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
> >   * @start: first ECC byte to set
> >   * @nbytes: number of ECC bytes to set  
> 
> Looks like the parameter descriptions are wrong too.

Are you sure? I don't see where.

> 
> >   *
> > - * Works like mtd_ooblayout_get_bytes(), except it acts on free bytes.
> > + * Works like mtd_ooblayout_set_bytes(), except it acts on free bytes.
> >   *
> >   * Returns zero on success, a negative error code otherwise.
> >   */  
> 

Thanks,
Miquèl

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

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

* Re: [PATCH v2 06/36] mtd: nand: Rename a core structure
  2019-03-31 11:30   ` Boris Brezillon
@ 2019-05-03  8:26     ` Miquel Raynal
  0 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-05-03  8:26 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
2019 13:30:01 +0200:

> On Mon,  4 Mar 2019 23:28:11 +0100
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Prepare the migration to a generic ECC engine by renaming the
> > nand_ecc_req structure into nand_ecc_conf. This structure will be the
> > base of a wider 'nand_ecc' structure.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  include/linux/mtd/nand.h    | 8 ++++----
> >  include/linux/mtd/spinand.h | 2 +-
> >  2 files changed, 5 insertions(+), 5 deletions(-)
> > 
> > diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> > index 84ab76f34c74..78cf905083c9 100644
> > --- a/include/linux/mtd/nand.h
> > +++ b/include/linux/mtd/nand.h
> > @@ -123,11 +123,11 @@ struct nand_page_io_req {
> >  };
> >  
> >  /**
> > - * struct nand_ecc_req - NAND ECC requirements
> > + * struct nand_ecc_conf - NAND ECC configuration  
> 
> Maybe nand_ecc_info, nand_ecc_caps or nand_ecc_props would be more
> appropriate as _conf seems to imply you can change it, which is not
> the case when you use this struct to express chip requirements or when
> you use an on-die ECC which is not configurable.

nand_ecc_props sounds good to me!

Thanks,
Miquèl

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

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

* Re: [PATCH v2 07/36] mtd: rawnand: Avoid a typedef
  2019-03-31 11:55   ` Boris Brezillon
@ 2019-05-03 12:40     ` Miquel Raynal
  2019-05-03 12:50       ` Boris Brezillon
  0 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-05-03 12:40 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
2019 13:55:13 +0200:

> On Mon,  4 Mar 2019 23:28:12 +0100
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > In new code, the use of typedef is discouraged. Before moving this
> > section out of the raw NAND base, let's switch the nand_ecc_modes_t
> > type into a regular nand_ecc_mode enumeration.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/raw/nand_base.c               | 4 ++--
> >  include/linux/mtd/rawnand.h                    | 6 +++---
> >  include/linux/platform_data/mtd-davinci.h      | 2 +-
> >  include/linux/platform_data/mtd-nand-s3c2410.h | 2 +-
> >  4 files changed, 7 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index e14f02a01efd..05174c6a3099 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -4881,8 +4881,8 @@ static int of_get_nand_ecc_mode(struct device_node *np)
> >  
> >  	/*
> >  	 * For backward compatibility we support few obsoleted values that don't
> > -	 * have their mappings into nand_ecc_modes_t anymore (they were merged
> > -	 * with other enums).
> > +	 * have their mappings into the nand_ecc_mode enum anymore (they were
> > +	 * merged with other enums).
> >  	 */
> >  	if (!strcasecmp(pm, "soft_bch"))
> >  		return NAND_ECC_SOFT;
> > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > index 14748183508b..c5bf6bb49329 100644
> > --- a/include/linux/mtd/rawnand.h
> > +++ b/include/linux/mtd/rawnand.h
> > @@ -87,14 +87,14 @@ struct nand_chip;
> >  /*
> >   * Constants for ECC_MODES
> >   */
> > -typedef enum {
> > +enum nand_ecc_mode {
> >  	NAND_ECC_NONE,
> >  	NAND_ECC_SOFT,
> >  	NAND_ECC_HW,
> >  	NAND_ECC_HW_SYNDROME,
> >  	NAND_ECC_HW_OOB_FIRST,
> >  	NAND_ECC_ON_DIE,
> > -} nand_ecc_modes_t;
> > +};  
> 
> Hm, I'm really not a big fan of this enum because it's mixing 2
> different concepts: the type of ECC engine to use (on-die,
> hw-controller-side, software, no-ECC) and the layout of
> ECC/FREE bytes (_SYNDROME, _OOB_FIRST).
> 
> I'd recommend creating a nand_ecc_engine_type enum:
> 
> enum nand_ecc_engine_type {
> 	NAND_NO_ECC_ENGINE,
> 	NAND_SOFT_ECC_ENGINE,
> 	NAND_HW_ECC_ENGINE,
> 	NAND_ON_DIE_ECC_ENGINE,
> };
> 
> and then convert the raw NAND layer to this enum when the time comes.

I started something but this goes way too far from what I want to
achieve. I know it would be nice to have it but it has an
increasingly number of side effects which scared me. The way the
series is organized does not allow to easily ignore the raw NAND layer
first and then convert it. I am giving up on this one for now, sorry.

Thanks,
Miquèl

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

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

* Re: [PATCH v2 07/36] mtd: rawnand: Avoid a typedef
  2019-05-03 12:40     ` Miquel Raynal
@ 2019-05-03 12:50       ` Boris Brezillon
  2019-05-06 15:13         ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-05-03 12:50 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Fri, 3 May 2019 14:40:30 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Hi Boris,
> 
> Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
> 2019 13:55:13 +0200:
> 
> > On Mon,  4 Mar 2019 23:28:12 +0100
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > In new code, the use of typedef is discouraged. Before moving this
> > > section out of the raw NAND base, let's switch the nand_ecc_modes_t
> > > type into a regular nand_ecc_mode enumeration.
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/mtd/nand/raw/nand_base.c               | 4 ++--
> > >  include/linux/mtd/rawnand.h                    | 6 +++---
> > >  include/linux/platform_data/mtd-davinci.h      | 2 +-
> > >  include/linux/platform_data/mtd-nand-s3c2410.h | 2 +-
> > >  4 files changed, 7 insertions(+), 7 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > index e14f02a01efd..05174c6a3099 100644
> > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > @@ -4881,8 +4881,8 @@ static int of_get_nand_ecc_mode(struct device_node *np)
> > >  
> > >  	/*
> > >  	 * For backward compatibility we support few obsoleted values that don't
> > > -	 * have their mappings into nand_ecc_modes_t anymore (they were merged
> > > -	 * with other enums).
> > > +	 * have their mappings into the nand_ecc_mode enum anymore (they were
> > > +	 * merged with other enums).
> > >  	 */
> > >  	if (!strcasecmp(pm, "soft_bch"))
> > >  		return NAND_ECC_SOFT;
> > > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > > index 14748183508b..c5bf6bb49329 100644
> > > --- a/include/linux/mtd/rawnand.h
> > > +++ b/include/linux/mtd/rawnand.h
> > > @@ -87,14 +87,14 @@ struct nand_chip;
> > >  /*
> > >   * Constants for ECC_MODES
> > >   */
> > > -typedef enum {
> > > +enum nand_ecc_mode {
> > >  	NAND_ECC_NONE,
> > >  	NAND_ECC_SOFT,
> > >  	NAND_ECC_HW,
> > >  	NAND_ECC_HW_SYNDROME,
> > >  	NAND_ECC_HW_OOB_FIRST,
> > >  	NAND_ECC_ON_DIE,
> > > -} nand_ecc_modes_t;
> > > +};    
> > 
> > Hm, I'm really not a big fan of this enum because it's mixing 2
> > different concepts: the type of ECC engine to use (on-die,
> > hw-controller-side, software, no-ECC) and the layout of
> > ECC/FREE bytes (_SYNDROME, _OOB_FIRST).
> > 
> > I'd recommend creating a nand_ecc_engine_type enum:
> > 
> > enum nand_ecc_engine_type {
> > 	NAND_NO_ECC_ENGINE,
> > 	NAND_SOFT_ECC_ENGINE,
> > 	NAND_HW_ECC_ENGINE,
> > 	NAND_ON_DIE_ECC_ENGINE,
> > };
> > 
> > and then convert the raw NAND layer to this enum when the time comes.  
> 
> I started something but this goes way too far from what I want to
> achieve. I know it would be nice to have it but it has an
> increasingly number of side effects which scared me. The way the
> series is organized does not allow to easily ignore the raw NAND layer
> first and then convert it. I am giving up on this one for now, sorry.

I don't think that's a wise choice. Why not focusing on
nand_device/spinand with a clean implementation that does not try to
convert the rawnand layer to this approach? The reason I initially
started over with a new generic NAND layer instead of copying things
from nand_base is that I wanted to avoid having to deal with stuff that
were not so great in there, and clearly nand_ecc_mode is one of them.

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

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

* Re: [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction
  2019-03-31 12:10   ` Boris Brezillon
@ 2019-05-03 14:34     ` Miquel Raynal
  2019-05-03 15:54       ` Boris Brezillon
  0 siblings, 1 reply; 55+ messages in thread
From: Miquel Raynal @ 2019-05-03 14:34 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
2019 14:10:25 +0200:

> On Mon,  4 Mar 2019 23:28:15 +0100
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Create a generic ECC engine object.
> > 
> > Later the ecc/engine.c file will receive more generic code coming from
> > the raw NAND specific part. This is a base to instantiate ECC engine
> > objects.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> >  drivers/mtd/nand/Kconfig                     |   1 +
> >  drivers/mtd/nand/Makefile                    |   1 +
> >  drivers/mtd/nand/ecc/Kconfig                 |   6 +
> >  drivers/mtd/nand/ecc/Makefile                |   3 +
> >  drivers/mtd/nand/ecc/engine.c                | 138 +++++++++++++++++++
> >  drivers/mtd/nand/raw/atmel/nand-controller.c |   9 +-
> >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  12 +-
> >  drivers/mtd/nand/raw/marvell_nand.c          |   7 +-
> >  drivers/mtd/nand/raw/mtk_nand.c              |   4 +-
> >  drivers/mtd/nand/raw/nand_base.c             |  17 +--
> >  drivers/mtd/nand/raw/nand_esmt.c             |  11 +-
> >  drivers/mtd/nand/raw/nand_hynix.c            |  41 +++---
> >  drivers/mtd/nand/raw/nand_jedec.c            |   4 +-
> >  drivers/mtd/nand/raw/nand_micron.c           |  14 +-
> >  drivers/mtd/nand/raw/nand_onfi.c             |   8 +-
> >  drivers/mtd/nand/raw/nand_samsung.c          |  19 +--
> >  drivers/mtd/nand/raw/nand_toshiba.c          |  11 +-
> >  drivers/mtd/nand/raw/sunxi_nand.c            |   5 +-
> >  drivers/mtd/nand/raw/tegra_nand.c            |   9 +-
> >  drivers/mtd/nand/spi/core.c                  |   4 +-
> >  drivers/mtd/nand/spi/macronix.c              |   6 +-
> >  drivers/mtd/nand/spi/toshiba.c               |   6 +-  
> 
> Can we please split that in 3 patches:
> 
> 1/ introduce the ECC framework
> 2/ convert spi nand
> 3/ convert raw nand

Split in 2 patches:
1/ Introduce the ECC framework
2/ Change the eccreq parameter of the nand_device structure which
impacts both raw and SPI NAND frameworks.

> 
> >  include/linux/mtd/nand.h                     |  82 ++++++++++-
> >  include/linux/mtd/spinand.h                  |   2 +-
> >  24 files changed, 327 insertions(+), 93 deletions(-)
> >  create mode 100644 drivers/mtd/nand/ecc/Kconfig
> >  create mode 100644 drivers/mtd/nand/ecc/Makefile
> >  create mode 100644 drivers/mtd/nand/ecc/engine.c
> > 
> > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> > index d2ef8b89568e..75d0bd18b818 100644
> > --- a/drivers/mtd/nand/Kconfig
> > +++ b/drivers/mtd/nand/Kconfig
> > @@ -6,5 +6,6 @@ config MTD_NAND_CORE
> >  source "drivers/mtd/nand/onenand/Kconfig"
> >  source "drivers/mtd/nand/raw/Kconfig"
> >  source "drivers/mtd/nand/spi/Kconfig"
> > +source "drivers/mtd/nand/ecc/Kconfig"
> >  
> >  endmenu
> > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> > index 7ecd80c0a66e..9772e781534d 100644
> > --- a/drivers/mtd/nand/Makefile
> > +++ b/drivers/mtd/nand/Makefile
> > @@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
> >  obj-y	+= onenand/
> >  obj-y	+= raw/
> >  obj-y	+= spi/
> > +obj-y	+= ecc/
> > diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
> > new file mode 100644
> > index 000000000000..01439f66ecbf
> > --- /dev/null
> > +++ b/drivers/mtd/nand/ecc/Kconfig
> > @@ -0,0 +1,6 @@
> > +menu "ECC engine support"
> > +
> > +config MTD_NAND_ECC
> > +	tristate
> > +  
> 
> There's already an MTD_NAND_ECC symbol defined in
> drivers/mtd/nand/raw/Kconfig,

Didn't find any?

> plus I don't think we want ecc/engine.c
> to be compiled as a module, but instead be embedded in nand-core.ko.

How would you do that? I don't find the right way to embed
nand_ecc_engine.o directly in nandcore.o. The only solution I found was
to add nandcore-$(<cond>) += ecc/thing.o directly in
drivers/mtd/nand/Makefile but I don't think it is acceptable?

> Not to mention that the name, engine.ko, is probably too generic.

Renamed it nand_ecc_engine.ko for now.

Thanks,
Miquèl

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

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

* Re: [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction
  2019-05-03 14:34     ` Miquel Raynal
@ 2019-05-03 15:54       ` Boris Brezillon
  2019-05-06 15:49         ` Miquel Raynal
  0 siblings, 1 reply; 55+ messages in thread
From: Boris Brezillon @ 2019-05-03 15:54 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

On Fri, 3 May 2019 16:34:00 +0200
Miquel Raynal <miquel.raynal@bootlin.com> wrote:

> Hi Boris,
> 
> Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
> 2019 14:10:25 +0200:
> 
> > On Mon,  4 Mar 2019 23:28:15 +0100
> > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >   
> > > Create a generic ECC engine object.
> > > 
> > > Later the ecc/engine.c file will receive more generic code coming from
> > > the raw NAND specific part. This is a base to instantiate ECC engine
> > > objects.
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > >  drivers/mtd/nand/Kconfig                     |   1 +
> > >  drivers/mtd/nand/Makefile                    |   1 +
> > >  drivers/mtd/nand/ecc/Kconfig                 |   6 +
> > >  drivers/mtd/nand/ecc/Makefile                |   3 +
> > >  drivers/mtd/nand/ecc/engine.c                | 138 +++++++++++++++++++
> > >  drivers/mtd/nand/raw/atmel/nand-controller.c |   9 +-
> > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  12 +-
> > >  drivers/mtd/nand/raw/marvell_nand.c          |   7 +-
> > >  drivers/mtd/nand/raw/mtk_nand.c              |   4 +-
> > >  drivers/mtd/nand/raw/nand_base.c             |  17 +--
> > >  drivers/mtd/nand/raw/nand_esmt.c             |  11 +-
> > >  drivers/mtd/nand/raw/nand_hynix.c            |  41 +++---
> > >  drivers/mtd/nand/raw/nand_jedec.c            |   4 +-
> > >  drivers/mtd/nand/raw/nand_micron.c           |  14 +-
> > >  drivers/mtd/nand/raw/nand_onfi.c             |   8 +-
> > >  drivers/mtd/nand/raw/nand_samsung.c          |  19 +--
> > >  drivers/mtd/nand/raw/nand_toshiba.c          |  11 +-
> > >  drivers/mtd/nand/raw/sunxi_nand.c            |   5 +-
> > >  drivers/mtd/nand/raw/tegra_nand.c            |   9 +-
> > >  drivers/mtd/nand/spi/core.c                  |   4 +-
> > >  drivers/mtd/nand/spi/macronix.c              |   6 +-
> > >  drivers/mtd/nand/spi/toshiba.c               |   6 +-    
> > 
> > Can we please split that in 3 patches:
> > 
> > 1/ introduce the ECC framework
> > 2/ convert spi nand
> > 3/ convert raw nand  
> 
> Split in 2 patches:
> 1/ Introduce the ECC framework
> 2/ Change the eccreq parameter of the nand_device structure which
> impacts both raw and SPI NAND frameworks.
> 
> >   
> > >  include/linux/mtd/nand.h                     |  82 ++++++++++-
> > >  include/linux/mtd/spinand.h                  |   2 +-
> > >  24 files changed, 327 insertions(+), 93 deletions(-)
> > >  create mode 100644 drivers/mtd/nand/ecc/Kconfig
> > >  create mode 100644 drivers/mtd/nand/ecc/Makefile
> > >  create mode 100644 drivers/mtd/nand/ecc/engine.c
> > > 
> > > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> > > index d2ef8b89568e..75d0bd18b818 100644
> > > --- a/drivers/mtd/nand/Kconfig
> > > +++ b/drivers/mtd/nand/Kconfig
> > > @@ -6,5 +6,6 @@ config MTD_NAND_CORE
> > >  source "drivers/mtd/nand/onenand/Kconfig"
> > >  source "drivers/mtd/nand/raw/Kconfig"
> > >  source "drivers/mtd/nand/spi/Kconfig"
> > > +source "drivers/mtd/nand/ecc/Kconfig"
> > >  
> > >  endmenu
> > > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> > > index 7ecd80c0a66e..9772e781534d 100644
> > > --- a/drivers/mtd/nand/Makefile
> > > +++ b/drivers/mtd/nand/Makefile
> > > @@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
> > >  obj-y	+= onenand/
> > >  obj-y	+= raw/
> > >  obj-y	+= spi/
> > > +obj-y	+= ecc/
> > > diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
> > > new file mode 100644
> > > index 000000000000..01439f66ecbf
> > > --- /dev/null
> > > +++ b/drivers/mtd/nand/ecc/Kconfig
> > > @@ -0,0 +1,6 @@
> > > +menu "ECC engine support"
> > > +
> > > +config MTD_NAND_ECC
> > > +	tristate
> > > +    
> > 
> > There's already an MTD_NAND_ECC symbol defined in
> > drivers/mtd/nand/raw/Kconfig,  
> 
> Didn't find any?

There was one in drivers/mtd/nand/raw/Kconfig [1], but maybe it's gone
now.

> 
> > plus I don't think we want ecc/engine.c
> > to be compiled as a module, but instead be embedded in nand-core.ko.  
> 
> How would you do that? I don't find the right way to embed
> nand_ecc_engine.o directly in nandcore.o. The only solution I found was
> to add nandcore-$(<cond>) += ecc/thing.o directly in
> drivers/mtd/nand/Makefile but I don't think it is acceptable?

Or just move the core logic into drivers/mtd/nand/ecc.c and add

nandcore-$(<cond>) += ecc.o

to the Makefile.


> 
> > Not to mention that the name, engine.ko, is probably too generic.  
> 
> Renamed it nand_ecc_engine.ko for now.

Still think it's better to have the code embedded in nandcore.ko.

[1]https://elixir.bootlin.com/linux/v5.1-rc7/source/drivers/mtd/nand/raw/Kconfig#L1

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

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

* Re: [PATCH v2 07/36] mtd: rawnand: Avoid a typedef
  2019-05-03 12:50       ` Boris Brezillon
@ 2019-05-06 15:13         ` Miquel Raynal
  0 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-05-06 15:13 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 3 May
2019 14:50:06 +0200:

> On Fri, 3 May 2019 14:40:30 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Hi Boris,
> > 
> > Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
> > 2019 13:55:13 +0200:
> >   
> > > On Mon,  4 Mar 2019 23:28:12 +0100
> > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >     
> > > > In new code, the use of typedef is discouraged. Before moving this
> > > > section out of the raw NAND base, let's switch the nand_ecc_modes_t
> > > > type into a regular nand_ecc_mode enumeration.
> > > > 
> > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > ---
> > > >  drivers/mtd/nand/raw/nand_base.c               | 4 ++--
> > > >  include/linux/mtd/rawnand.h                    | 6 +++---
> > > >  include/linux/platform_data/mtd-davinci.h      | 2 +-
> > > >  include/linux/platform_data/mtd-nand-s3c2410.h | 2 +-
> > > >  4 files changed, 7 insertions(+), 7 deletions(-)
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > > index e14f02a01efd..05174c6a3099 100644
> > > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > > @@ -4881,8 +4881,8 @@ static int of_get_nand_ecc_mode(struct device_node *np)
> > > >  
> > > >  	/*
> > > >  	 * For backward compatibility we support few obsoleted values that don't
> > > > -	 * have their mappings into nand_ecc_modes_t anymore (they were merged
> > > > -	 * with other enums).
> > > > +	 * have their mappings into the nand_ecc_mode enum anymore (they were
> > > > +	 * merged with other enums).
> > > >  	 */
> > > >  	if (!strcasecmp(pm, "soft_bch"))
> > > >  		return NAND_ECC_SOFT;
> > > > diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> > > > index 14748183508b..c5bf6bb49329 100644
> > > > --- a/include/linux/mtd/rawnand.h
> > > > +++ b/include/linux/mtd/rawnand.h
> > > > @@ -87,14 +87,14 @@ struct nand_chip;
> > > >  /*
> > > >   * Constants for ECC_MODES
> > > >   */
> > > > -typedef enum {
> > > > +enum nand_ecc_mode {
> > > >  	NAND_ECC_NONE,
> > > >  	NAND_ECC_SOFT,
> > > >  	NAND_ECC_HW,
> > > >  	NAND_ECC_HW_SYNDROME,
> > > >  	NAND_ECC_HW_OOB_FIRST,
> > > >  	NAND_ECC_ON_DIE,
> > > > -} nand_ecc_modes_t;
> > > > +};      
> > > 
> > > Hm, I'm really not a big fan of this enum because it's mixing 2
> > > different concepts: the type of ECC engine to use (on-die,
> > > hw-controller-side, software, no-ECC) and the layout of
> > > ECC/FREE bytes (_SYNDROME, _OOB_FIRST).
> > > 
> > > I'd recommend creating a nand_ecc_engine_type enum:
> > > 
> > > enum nand_ecc_engine_type {
> > > 	NAND_NO_ECC_ENGINE,
> > > 	NAND_SOFT_ECC_ENGINE,
> > > 	NAND_HW_ECC_ENGINE,
> > > 	NAND_ON_DIE_ECC_ENGINE,
> > > };
> > > 
> > > and then convert the raw NAND layer to this enum when the time comes.    
> > 
> > I started something but this goes way too far from what I want to
> > achieve. I know it would be nice to have it but it has an
> > increasingly number of side effects which scared me. The way the
> > series is organized does not allow to easily ignore the raw NAND layer
> > first and then convert it. I am giving up on this one for now, sorry.  
> 
> I don't think that's a wise choice. Why not focusing on
> nand_device/spinand with a clean implementation that does not try to
> convert the rawnand layer to this approach?

I know, and that was probably the best thing to do, unfortunately I
started bigger because there was so much things to change, I got a bit
lost at the beginning. I know this is not a valid reason but in
practice I could not come with something lighter, ie. focused on
SPI-NAND only.

> The reason I initially
> started over with a new generic NAND layer instead of copying things
> from nand_base is that I wanted to avoid having to deal with stuff that
> were not so great in there, and clearly nand_ecc_mode is one of them.

I understand that so I think I managed to clean the situation with a
preliminary series which I will send soon.

Thanks,
Miquèl

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

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

* Re: [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction
  2019-05-03 15:54       ` Boris Brezillon
@ 2019-05-06 15:49         ` Miquel Raynal
  0 siblings, 0 replies; 55+ messages in thread
From: Miquel Raynal @ 2019-05-06 15:49 UTC (permalink / raw)
  To: Boris Brezillon
  Cc: Mason Yang, Vignesh R, Tudor Ambarus, Julien Su,
	Richard Weinberger, Boris Brezillon, Schrempf Frieder,
	Paul Cercueil, Marek Vasut, linux-mtd, Thomas Petazzoni,
	Brian Norris, David Woodhouse, linux-arm-kernel

Hi Boris,

Boris Brezillon <boris.brezillon@collabora.com> wrote on Fri, 3 May
2019 17:54:46 +0200:

> On Fri, 3 May 2019 16:34:00 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> 
> > Hi Boris,
> > 
> > Boris Brezillon <boris.brezillon@collabora.com> wrote on Sun, 31 Mar
> > 2019 14:10:25 +0200:
> >   
> > > On Mon,  4 Mar 2019 23:28:15 +0100
> > > Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> > >     
> > > > Create a generic ECC engine object.
> > > > 
> > > > Later the ecc/engine.c file will receive more generic code coming from
> > > > the raw NAND specific part. This is a base to instantiate ECC engine
> > > > objects.
> > > > 
> > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > ---
> > > >  drivers/mtd/nand/Kconfig                     |   1 +
> > > >  drivers/mtd/nand/Makefile                    |   1 +
> > > >  drivers/mtd/nand/ecc/Kconfig                 |   6 +
> > > >  drivers/mtd/nand/ecc/Makefile                |   3 +
> > > >  drivers/mtd/nand/ecc/engine.c                | 138 +++++++++++++++++++
> > > >  drivers/mtd/nand/raw/atmel/nand-controller.c |   9 +-
> > > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c   |  12 +-
> > > >  drivers/mtd/nand/raw/marvell_nand.c          |   7 +-
> > > >  drivers/mtd/nand/raw/mtk_nand.c              |   4 +-
> > > >  drivers/mtd/nand/raw/nand_base.c             |  17 +--
> > > >  drivers/mtd/nand/raw/nand_esmt.c             |  11 +-
> > > >  drivers/mtd/nand/raw/nand_hynix.c            |  41 +++---
> > > >  drivers/mtd/nand/raw/nand_jedec.c            |   4 +-
> > > >  drivers/mtd/nand/raw/nand_micron.c           |  14 +-
> > > >  drivers/mtd/nand/raw/nand_onfi.c             |   8 +-
> > > >  drivers/mtd/nand/raw/nand_samsung.c          |  19 +--
> > > >  drivers/mtd/nand/raw/nand_toshiba.c          |  11 +-
> > > >  drivers/mtd/nand/raw/sunxi_nand.c            |   5 +-
> > > >  drivers/mtd/nand/raw/tegra_nand.c            |   9 +-
> > > >  drivers/mtd/nand/spi/core.c                  |   4 +-
> > > >  drivers/mtd/nand/spi/macronix.c              |   6 +-
> > > >  drivers/mtd/nand/spi/toshiba.c               |   6 +-      
> > > 
> > > Can we please split that in 3 patches:
> > > 
> > > 1/ introduce the ECC framework
> > > 2/ convert spi nand
> > > 3/ convert raw nand    
> > 
> > Split in 2 patches:
> > 1/ Introduce the ECC framework
> > 2/ Change the eccreq parameter of the nand_device structure which
> > impacts both raw and SPI NAND frameworks.
> >   
> > >     
> > > >  include/linux/mtd/nand.h                     |  82 ++++++++++-
> > > >  include/linux/mtd/spinand.h                  |   2 +-
> > > >  24 files changed, 327 insertions(+), 93 deletions(-)
> > > >  create mode 100644 drivers/mtd/nand/ecc/Kconfig
> > > >  create mode 100644 drivers/mtd/nand/ecc/Makefile
> > > >  create mode 100644 drivers/mtd/nand/ecc/engine.c
> > > > 
> > > > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> > > > index d2ef8b89568e..75d0bd18b818 100644
> > > > --- a/drivers/mtd/nand/Kconfig
> > > > +++ b/drivers/mtd/nand/Kconfig
> > > > @@ -6,5 +6,6 @@ config MTD_NAND_CORE
> > > >  source "drivers/mtd/nand/onenand/Kconfig"
> > > >  source "drivers/mtd/nand/raw/Kconfig"
> > > >  source "drivers/mtd/nand/spi/Kconfig"
> > > > +source "drivers/mtd/nand/ecc/Kconfig"
> > > >  
> > > >  endmenu
> > > > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> > > > index 7ecd80c0a66e..9772e781534d 100644
> > > > --- a/drivers/mtd/nand/Makefile
> > > > +++ b/drivers/mtd/nand/Makefile
> > > > @@ -6,3 +6,4 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
> > > >  obj-y	+= onenand/
> > > >  obj-y	+= raw/
> > > >  obj-y	+= spi/
> > > > +obj-y	+= ecc/
> > > > diff --git a/drivers/mtd/nand/ecc/Kconfig b/drivers/mtd/nand/ecc/Kconfig
> > > > new file mode 100644
> > > > index 000000000000..01439f66ecbf
> > > > --- /dev/null
> > > > +++ b/drivers/mtd/nand/ecc/Kconfig
> > > > @@ -0,0 +1,6 @@
> > > > +menu "ECC engine support"
> > > > +
> > > > +config MTD_NAND_ECC
> > > > +	tristate
> > > > +      
> > > 
> > > There's already an MTD_NAND_ECC symbol defined in
> > > drivers/mtd/nand/raw/Kconfig,    
> > 
> > Didn't find any?  
> 
> There was one in drivers/mtd/nand/raw/Kconfig [1], but maybe it's gone
> now.
> 
> >   
> > > plus I don't think we want ecc/engine.c
> > > to be compiled as a module, but instead be embedded in nand-core.ko.    
> > 
> > How would you do that? I don't find the right way to embed
> > nand_ecc_engine.o directly in nandcore.o. The only solution I found was
> > to add nandcore-$(<cond>) += ecc/thing.o directly in
> > drivers/mtd/nand/Makefile but I don't think it is acceptable?  
> 
> Or just move the core logic into drivers/mtd/nand/ecc.c and add
> 
> nandcore-$(<cond>) += ecc.o
> 
> to the Makefile.
> 
> 
> >   
> > > Not to mention that the name, engine.ko, is probably too generic.    
> > 
> > Renamed it nand_ecc_engine.ko for now.  
> 
> Still think it's better to have the code embedded in nandcore.ko.
> 
> [1]https://elixir.bootlin.com/linux/v5.1-rc7/source/drivers/mtd/nand/raw/Kconfig#L1

What is there currently was not what I was looking for.

But nevermind, I moved all code to the nand/ directory, dropping the
ecc/ subdir. Now ECC code is called ecc-engine.o and is embedded in
nandcore.ko.


Thanks,
Miquèl

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

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

end of thread, other threads:[~2019-05-06 15:50 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-04 22:28 [PATCH v2 00/36] Introduce the generic ECC engine abstraction Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 01/36] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
2019-03-31 11:12   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 02/36] mtd: nand: Add an extra level in the Kconfig hierarchy Miquel Raynal
2019-03-31 11:13   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 03/36] mtd: nand: Drop useless 'depends on' in Kconfig Miquel Raynal
2019-03-31 11:15   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 04/36] mtd: rawnand: Use the NAND core Miquel Raynal
2019-03-31 11:21   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 05/36] mtd: nand: Add a NAND page I/O request type Miquel Raynal
2019-03-31 11:23   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 06/36] mtd: nand: Rename a core structure Miquel Raynal
2019-03-31 11:30   ` Boris Brezillon
2019-05-03  8:26     ` Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 07/36] mtd: rawnand: Avoid a typedef Miquel Raynal
2019-03-31 11:55   ` Boris Brezillon
2019-05-03 12:40     ` Miquel Raynal
2019-05-03 12:50       ` Boris Brezillon
2019-05-06 15:13         ` Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 08/36] mtd: rawnand: Add an invalid ECC mode to discriminate with valid ones Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 09/36] mtd: rawnand: Clarify the values for invalid ECC mode/algo Miquel Raynal
2019-03-31 11:57   ` Boris Brezillon
2019-03-04 22:28 ` [PATCH v2 10/36] mtd: nand: Introduce the ECC engine abstraction Miquel Raynal
2019-03-31 12:10   ` Boris Brezillon
2019-05-03 14:34     ` Miquel Raynal
2019-05-03 15:54       ` Boris Brezillon
2019-05-06 15:49         ` Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 11/36] mtd: Fix typo in mtd_ooblayout_set_databytes() description Miquel Raynal
2019-03-31 11:32   ` Boris Brezillon
2019-05-03  8:18     ` Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 12/36] mtd: nand: Move standard OOB layouts to the generic ECC core Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 13/36] mtd: nand: Move ECC specific functions to ecc/engine.c Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 14/36] mtd: nand: ecc: Move BCH code into the ecc/ directory Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 15/36] mtd: nand: ecc: Use SPDX license identifier for the software BCH code Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 16/36] mtd: nand: ecc: Turn the software BCH implementation generic Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 17/36] mtd: rawnand: Get rid of chip->ecc.priv Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 18/36] mtd: nand: ecc: Move Hamming code into the ecc/ directory Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 19/36] mtd: nand: ecc: Use SPDX license identifier for the software Hamming code Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 20/36] mtd: nand: ecc: Clarify the software Hamming introductory line Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 21/36] mtd: nand: ecc: Turn the software Hamming implementation generic Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 22/36] mtd: nand: Remove useless include about software Hamming ECC Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 23/36] mtd: nand: ecc: Let the software BCH ECC engine be a module Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 24/36] mtd: nand: ecc: Let the software Hamming ECC engine be unselected Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 25/36] mtd: nand: ecc: Create the software BCH engine instance Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 26/36] mtd: nand: ecc: Create the software Hamming " Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 27/36] mtd: nand: Let software ECC engines be retrieved from the NAND core Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 28/36] mtd: spinand: Fix typo in comment Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 29/36] mtd: spinand: Move ECC related definitions earlier in the driver Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 30/36] mtd: spinand: Instantiate a SPI-NAND on-die ECC engine Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 31/36] mtd: nand: Let on-die ECC engines be retrieved from the NAND core Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 32/36] mtd: rawnand: Fill a default ECC provider/algorithm Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 33/36] mtd: spinand: " Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 34/36] mtd: nand: Add helpers to manage ECC engines and configurations Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 35/36] mtd: spinand: Use the external ECC engine logic Miquel Raynal
2019-03-04 22:28 ` [PATCH v2 36/36] mtd: spinand: Propagate ECC information to the MTD structure 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).