From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Boris Brezillon <boris.brezillon@collabora.com>
Cc: Richard Weinberger <richard@nod.at>,
Vignesh Raghavendra <vigneshr@ti.com>,
Tudor Ambarus <Tudor.Ambarus@microchip.com>,
<linux-mtd@lists.infradead.org>, Rob Herring <robh+dt@kernel.org>,
Mark Rutland <mark.rutland@arm.com>, <devicetree@vger.kernel.org>,
Julien Su <juliensu@mxic.com.tw>,
Weijie Gao <weijie.gao@mediatek.com>,
Paul Cercueil <paul@crapouillou.net>,
Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
Mason Yang <masonccyang@mxic.com.tw>,
Chuanhong Guo <gch981213@gmail.com>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH v6 15/18] mtd: nand: Introduce the ECC engine abstraction
Date: Fri, 29 May 2020 01:46:13 +0200 [thread overview]
Message-ID: <20200529014613.6e64f95f@xps13> (raw)
In-Reply-To: <20200528205251.5e8abdd1@collabora.com>
Hi Boris,
Boris Brezillon <boris.brezillon@collabora.com> wrote on Thu, 28 May
2020 20:52:51 +0200:
> On Thu, 28 May 2020 13:31:10 +0200
> Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> > Create a generic ECC engine object.
> >
> > Later the ecc.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 | 7 ++
> > drivers/mtd/nand/Makefile | 2 +
> > drivers/mtd/nand/ecc.c | 138 ++++++++++++++++++++++++++++++++++++++
> > include/linux/mtd/nand.h | 67 ++++++++++++++++++
> > 4 files changed, 214 insertions(+)
> > create mode 100644 drivers/mtd/nand/ecc.c
> >
> > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
> > index c1a45b071165..a4478ffa279d 100644
> > --- a/drivers/mtd/nand/Kconfig
> > +++ b/drivers/mtd/nand/Kconfig
> > @@ -9,4 +9,11 @@ source "drivers/mtd/nand/onenand/Kconfig"
> > source "drivers/mtd/nand/raw/Kconfig"
> > source "drivers/mtd/nand/spi/Kconfig"
> >
> > +menu "ECC engine support"
> > +
> > +config MTD_NAND_ECC
> > + bool
> > +
> > +endmenu
> > +
> > endmenu
> > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
> > index 7ecd80c0a66e..981372953b56 100644
> > --- a/drivers/mtd/nand/Makefile
> > +++ b/drivers/mtd/nand/Makefile
> > @@ -6,3 +6,5 @@ obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o
> > obj-y += onenand/
> > obj-y += raw/
> > obj-y += spi/
> > +
> > +nandcore-$(CONFIG_MTD_NAND_ECC) += ecc.o
> > diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
> > new file mode 100644
> > index 000000000000..e4f2b6fcbb12
> > --- /dev/null
> > +++ b/drivers/mtd/nand/ecc.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
>
> I'm not sure why you put quotes around those names.
>
> > + * is a software ECC engine. One can also imagine a generic
>
> ^ or an hardware
> engine that's outside the NAND controller pipeline.
>
> You can the drop the "One can also imagine ..." since it's more than a
> theoretical use case, we already have a few engines that fall in this
> category.
>
> > + * hardware ECC engine which would be an IP itself. Interacting
> > + * with a SPI-NAND device without on-die ECC could be achieved
>
> ^can
>
> > + * thanks to the use of such external engine.
>
> But I think I would simply drop this last sentence.
>
> > + * - "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.
>
> Again, I would drop the last sentence here. I think saying the ECC
> bytes are generated/data corrected on the fly when a page is
> written/read would be more useful.
>
> > + * - "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).
>
> "The on-die correction can be enabled, disabled" -> this is true for
> any kind of ECC engine :P.
>
> > + *
> > + * 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
>
> ^if/whether
>
> > + * disabled as requested before the I/O. In case of software
>
> How about "Enable/disable the ECC engine based on the I/O request type."
>
> > + * correction, this step may involve to derive the ECC bytes and
> > + * place them in the OOB area before a write.
>
> This is also true for external hardware ECC engines.
>
> > + * - "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).
>
> It's all about correcting/reporting errors, right. Let's try to put
> that into simple words: "Correct the data in case of a read request and
> report the number of corrected bits/uncorrectable errors. Most likely
> empty for write operations, unless you have hardware specific stuff to
> do, like shutting down the engine to save some power"
>
> > + *
> > + * Both prepare/finish callbacks are supposed to enclose I/O request and will
>
> "The I/O request should be enclosed in a prepare()/finish() pair of
> calls" or "The prepare/finish call should surround the I/O request".
>
> > + * behave differently depending on the desired correction:
>
> ^requested I/O type
>
> > + * - "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.
>
> Mention that those are just examples, and drivers are free to add
> custom steps in their prepare/finish hooks.
>
> > + *
> > + * ["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>
> > +
>
> Shouldn't we have kernel-docs for those functions?
>
> > +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)
> > +{
> > + if (!nand->ecc.engine->ops->prepare_io_req)
> > + return 0;
> > +
> > + return nand->ecc.engine->ops->prepare_io_req(nand, req);
> > +}
> > +EXPORT_SYMBOL(nand_ecc_prepare_io_req);
> > +
> > +int nand_ecc_finish_io_req(struct nand_device *nand,
> > + struct nand_page_io_req *req)
> > +{
> > + if (!nand->ecc.engine->ops->finish_io_req)
> > + return 0;
> > +
> > + return nand->ecc.engine->ops->finish_io_req(nand, req);
> > +}
> > +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/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
> > index 2e9af24936cd..0be260fd2f86 100644
> > --- a/include/linux/mtd/nand.h
> > +++ b/include/linux/mtd/nand.h
> > @@ -221,6 +221,73 @@ 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
>
> Sometimes you start your description with an uppercase, sometimes not.
>
> > + * generic OOB layouts
> > + * @priv: ECC engine driver private data
> > + */
> > +struct nand_ecc_context {
> > + struct nand_ecc_props conf;
> > + unsigned int total;
> > + void *priv;
> > +};
> > +
> > +/**
> > + * struct nand_ecc_engine_ops - Generic ECC engine operations
>
> ^s/Generic//
>
> > + * @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);
> > + int (*finish_io_req)(struct nand_device *nand,
> > + struct nand_page_io_req *req);
> > +};
> > +
> > +/**
> > + * struct nand_ecc_engine - Generic ECC engine abstraction for NAND devices
>
> ^s/Generic//
>
> > + * @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);
> > +int nand_ecc_finish_io_req(struct nand_device *nand,
> > + struct nand_page_io_req *req);
> > +
> > +/**
> > + * struct nand_ecc - High-level ECC object
>
> I think you can drop the "High-level" and just say "Information
> relative to the ECC"
>
> > + * @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_props defaults;
> > + struct nand_ecc_props requirements;
> > + struct nand_ecc_props 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
>
All comments applied.
Thanks,
Miquèl
next prev parent reply other threads:[~2020-05-28 23:46 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-28 11:30 [PATCH v6 00/18] Introduce the generic ECC engine abstraction Miquel Raynal
2020-05-28 11:30 ` [PATCH v6 01/18] dt-bindings: mtd: Document nand-ecc-placement Miquel Raynal
2020-05-28 12:02 ` Boris Brezillon
2020-05-28 11:30 ` [PATCH v6 02/18] mtd: rawnand: Create a new enumeration to describe OOB placement Miquel Raynal
2020-05-28 12:08 ` Boris Brezillon
2020-05-28 14:10 ` Miquel Raynal
2020-05-28 11:30 ` [PATCH v6 03/18] mtd: rawnand: Separate the ECC engine type and the " Miquel Raynal
2020-05-28 14:14 ` Boris Brezillon
2020-05-28 11:30 ` [PATCH v6 04/18] mtd: rawnand: Create a helper to retrieve the ECC placement Miquel Raynal
2020-05-28 14:22 ` Boris Brezillon
2020-05-28 11:31 ` [PATCH v6 05/18] mtd: rawnand: Add a kernel doc to the ECC algorithm enumeration Miquel Raynal
2020-05-28 14:26 ` Boris Brezillon
2020-05-28 11:31 ` [PATCH v6 06/18] mtd: rawnand: Rename the ECC algorithm enumeration items Miquel Raynal
2020-05-28 14:26 ` Boris Brezillon
2020-05-28 11:31 ` [PATCH v6 07/18] mtd: rawnand: Create a new enumeration to describe properly ECC types Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 08/18] mtd: rawnand: Use the new ECC engine type enumeration Miquel Raynal
2020-05-28 14:31 ` Boris Brezillon
2020-05-28 14:45 ` Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 09/18] mtd: nand: Move nand_device forward declaration to the top Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 10/18] mtd: nand: Add an extra level in the Kconfig hierarchy Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 11/18] mtd: nand: Drop useless 'depends on' in Kconfig Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 12/18] mtd: nand: Add a NAND page I/O request type Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 13/18] mtd: nand: Rename a core structure Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 14/18] mtd: nand: Add more parameters to the nand_ecc_props structure Miquel Raynal
2020-05-28 14:34 ` Boris Brezillon
2020-05-28 14:57 ` Miquel Raynal
2020-05-28 15:00 ` Boris Brezillon
2020-05-28 15:02 ` Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 15/18] mtd: nand: Introduce the ECC engine abstraction Miquel Raynal
2020-05-28 18:52 ` Boris Brezillon
2020-05-28 23:46 ` Miquel Raynal [this message]
2020-05-28 11:31 ` [PATCH v6 16/18] mtd: nand: Convert generic NAND bits to use the ECC framework Miquel Raynal
2020-05-28 14:39 ` Boris Brezillon
2020-05-28 14:49 ` Miquel Raynal
2020-05-28 14:52 ` Boris Brezillon
2020-05-28 15:04 ` Miquel Raynal
2020-05-28 16:00 ` Boris Brezillon
2020-05-28 23:48 ` Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 17/18] mtd: rawnand: Write a compatibility layer Miquel Raynal
2020-05-28 14:42 ` Boris Brezillon
2020-05-28 14:53 ` Miquel Raynal
2020-05-28 11:31 ` [PATCH v6 18/18] mtd: rawnand: Move generic bits to the ECC framework Miquel Raynal
2020-05-28 14:45 ` Boris Brezillon
2020-05-28 15:55 ` Boris Brezillon
2020-05-28 15:56 ` Boris Brezillon
2020-05-28 23:55 ` Miquel Raynal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200529014613.6e64f95f@xps13 \
--to=miquel.raynal@bootlin.com \
--cc=Tudor.Ambarus@microchip.com \
--cc=boris.brezillon@collabora.com \
--cc=devicetree@vger.kernel.org \
--cc=gch981213@gmail.com \
--cc=juliensu@mxic.com.tw \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-mtd@lists.infradead.org \
--cc=mark.rutland@arm.com \
--cc=masonccyang@mxic.com.tw \
--cc=paul@crapouillou.net \
--cc=richard@nod.at \
--cc=robh+dt@kernel.org \
--cc=thomas.petazzoni@bootlin.com \
--cc=vigneshr@ti.com \
--cc=weijie.gao@mediatek.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).