From prabhakar.csengg at gmail.com  Fri Oct  1 01:02:06 2021
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Fri, 1 Oct 2021 09:02:06 +0100
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <YVXMc1A4D/y4kjim@shikoro>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXMc1A4D/y4kjim@shikoro>
Message-ID: <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>

Hi Wolfram,

Thank you for the review.

On Thu, Sep 30, 2021 at 3:40 PM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
>
> Hi,
>
> >  #define RPCIF_CMNCR_IO3FV(val)       (((val) & 0x3) << 14) /* undocumented */
> >  #define RPCIF_CMNCR_IO2FV(val)       (((val) & 0x3) << 12) /* undocumented */
> >  #define RPCIF_CMNCR_IO0FV(val)       (((val) & 0x3) << 8)
> > -#define RPCIF_CMNCR_IOFV_HIZ (RPCIF_CMNCR_IO0FV(3) | RPCIF_CMNCR_IO2FV(3) | \
> > -                              RPCIF_CMNCR_IO3FV(3))
> > +#define RPCIF_CMNCR_IOFV_HIZ(val) (RPCIF_CMNCR_IO0FV(val) | RPCIF_CMNCR_IO2FV(val) | \
> > +                              RPCIF_CMNCR_IO3FV(val))
>
> Is RPCIF_CMNCR_IO3FV and RPCIF_CMNCR_IO2FV actually documented in your
> datasheets? I am asking because I have a patch pending to remove writing
> to undocumented locations. So, I was aboout to remove the IO3FV and
> IO2FV macros.
>
Yes they are documented, you should be able to download the HW manual from [1]

> > +#define RPCIF_PHYADJ1                0x0070  /* R/W */
> > +#define RPCIF_PHYADJ2                0x0074  /* R/W */
>
> Those are named 'PHYADD' and 'PHYWR' in the Gen3 documentation. They are
> only available on a few of the Gen3 SoCs. I think the Gen3 namings make
> more sense because then it becomes easily understandable that the
> registers are used to write something to the PHY.
>
Agreed, will re-name it as per Gen3.

> > +#define RPCIF_PHYCNT_CKSEL(v)        (((v) & 0x3) << 16)
>
> We should add a comment here that these bits are only valid for G2L...
>
Will do.

> >  #define RPCIF_PHYCNT_STRTIM(v)       (((v) & 0x7) << 15)
>
> and these only for Gen3.
>
ditto.

>
> > +static void rpcif_timing_adjust_sdr(struct rpcif *rpc)
> > +{
> > +     u32 data;
> > +
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ2, 0xA5390000);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ1, 0x80000000);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ2, 0x00008080);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ1, 0x80000022);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ2, 0x00008080);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADJ1, 0x80000024);
>
> Can't we have defines for these magic values? At least in my latest Gen3
> documentation, these values are explained.
>
RZ/G2L manual doesn't explain these bits. Let me refer to R-Car Gen3
and define them as macros.

> > +
> > +     regmap_read(rpc->regmap, RPCIF_PHYCNT, &data);
> > +     regmap_write(rpc->regmap, RPCIF_PHYCNT, data | RPCIF_PHYCNT_CKSEL(3));
>
> regmap_update_bits?
>
will do.

> > +     if (rpc->type == RPCIF_RCAR_GEN3) {
> > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> > +                          RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> > +     } else {
> > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
>
> regmap_update_bits?
>
Im a bit hesitant to use regmap_update_bits() here as some of the bits
are not documented.

[1] https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rz-arm-based-high-end-32-64-bit-mpus/rzg2l-general-purpose-microprocessors-dual-core-arm-cortex-a55-12-ghz-cpus-3d-graphics-and-video-codec

Cheers,
Prabhakar

> Rest looks good.
>
> Thanks and happy hacking!
>
>    Wolfram
>


From prabhakar.csengg at gmail.com  Fri Oct  1 01:03:35 2021
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Fri, 1 Oct 2021 09:03:35 +0100
Subject: [PATCH 0/6] Add SPI Multi I/O Bus Controller support for RZ/G2L
In-Reply-To: <YVXRZNxrgmfROlJy@shikoro>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXRZNxrgmfROlJy@shikoro>
Message-ID: <CA+V-a8vKogydunptYaWVBq_UUQ98UUTp-n2-T+WH8thTRL8M4Q@mail.gmail.com>

Hi Wolfram,

On Thu, Sep 30, 2021 at 4:01 PM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
>
>
> > This patch series adds a couple of fixes for rpc-if driver and
> > adds support for RZ/G2L SoC, where the SPI Multi I/O Bus Controller
> > is identical to the RPC-IF block found on R-Car Gen3 SoC's.
>
> I did some basic testing on the Falcon board with a Renesas R-Car V3U
> SoC and did not find a regression, so:
>
> Tested-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
>
Thank you for testing this, I will include the Tested-by tag along
with the RB tags.

Cheers,
Prabhakar


From Tudor.Ambarus at microchip.com  Fri Oct  1 01:41:41 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 08:41:41 +0000
Subject: [PATCH v2 03/35] mtd: spi-nor: macronix: Handle ID collision b/w
 MX25L3233F and MX25L3205D
In-Reply-To: <e41e5aa88846c87d041e3c3ea7845202@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-4-tudor.ambarus@microchip.com>
 <e41e5aa88846c87d041e3c3ea7845202@walle.cc>
Message-ID: <970e427a-953d-cd3e-da80-84082a03333a@microchip.com>

On 8/24/21 1:42 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-07-27 06:51, schrieb Tudor Ambarus:
>> Macronix has a bad habbit of reusing flash IDs. While MX25L3233F
>> supports
>> RDSFDP opcode, MX25L3205D does not support it and does not recommend
>> issuing opcodes that are not supported ("It is not recommended to adopt
>> any other code not in the command definition table, which will
>> potentially
>> enter the hidden mode.").
>>
>> We tested the RDSFDP on the MX25L3205D and the conclusion is that the
>> flash didn't reply anything. Given that it is unlikely that RDSFDP will
>> cause any problems for the old MX25L3205D, differentiate between the
>> two
>> flashes by parsing SFDP.
>>
>> Tested MX25L3233F. Generated a 256 Kbyte random data and did an erase,
>> write, read back and compare test. The flash uses for reads
>> SPINOR_OP_READ_1_4_4 0xeb, for erases SPINOR_OP_BE_4K 0x20, and for
>> writes
>> SPINOR_OP_PP 0x02.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> Acked-by: Pratyush Yadav <p.yadav at ti.com>
>> ---
>> root at sama5d2-xplained:~# find / -iname spi-nor
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor
>> /sys/devices/platform/ahb/ahb:apb/f8000000.spi/spi_master/spi0/spi0.0/spi-nor
>> /sys/bus/spi/drivers/spi-nor
>> root at sama5d2-xplained:~# ls -al
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor
>> total 0
>> drwxr-xr-x 2 root root??? 0 Mar? 9 14:51 .
>> drwxr-xr-x 6 root root??? 0 Mar? 9 14:50 ..
>> -r--r--r-- 1 root root 4096 Mar? 9 14:51 jedec_id
>> -r--r--r-- 1 root root 4096 Mar? 9 14:51 manufacturer
>> -r--r--r-- 1 root root 4096 Mar? 9 14:51 partname
>> -r--r--r-- 1 root root??? 0 Mar? 9 14:51 sfdp
>> root at sama5d2-xplained:~# cat
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
>> c22016
>> root at sama5d2-xplained:~# cat
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
>> macronix
>> root at sama5d2-xplained:~# cat
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname
>> mx25l3233f
>> root at sama5d2-xplained:~# cat
>> /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp
>> > mx25l3233f-sfdp
>> root at sama5d2-xplained:~# hexdump mx25l3233f-sfdp
> 
> use xxd if possible and the sha1sum/md5sum is missing.

ok, will update.

> 
>> 0000000 4653 5044 0100 ff01 0000 0901 0030 ff00
>> 0000010 00c2 0401 0060 ff00 ffff ffff ffff ffff
>> 0000020 ffff ffff ffff ffff ffff ffff ffff ffff
>> 0000030 20e5 fff1 ffff 01ff eb44 6b08 3b08 bb04
>> 0000040 ffee ffff ffff ff00 ffff ff00 200c 520f
>> 0000050 d810 ff00 ffff ffff ffff ffff ffff ffff
>> 0000060 3600 2650 f99c 6477 cffe ffff ffff ffff
>> 0000070
>>
>> ?drivers/mtd/spi-nor/macronix.c | 23 ++++++++++++++++++++++-
>> ?1 file changed, 22 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mtd/spi-nor/macronix.c
>> b/drivers/mtd/spi-nor/macronix.c
>> index 27498ed0cc0d..68f6ac060bc6 100644
>> --- a/drivers/mtd/spi-nor/macronix.c
>> +++ b/drivers/mtd/spi-nor/macronix.c
>> @@ -8,6 +8,24 @@
>>
>> ?#include "core.h"
>>
>> +static int mx25l3233f_post_bfpt_fixups(struct spi_nor *nor,
>> +???????????????????????????? const struct sfdp_parameter_header *bfpt_header,
>> +???????????????????????????? const struct sfdp_bfpt *bfpt)
>> +{
>> +???? /*
>> +????? * Macronix has a bad habit of reusing flash IDs: MX25L3233F collides
>> +????? * with MX25L3205D. MX25L3233F defines SFDP tables, while the older
>> +????? * variant does not.
>> +????? */
>> +???? nor->name = "mx25l3233f";
>> +
>> +???? return 0;
>> +}
>> +
>> +static struct spi_nor_fixups mx25l3233f_fixups = {
>> +???? .post_bfpt = mx25l3233f_post_bfpt_fixups,
>> +};
>> +
>> ?static int
>> ?mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
>> ????????????????????????? const struct sfdp_parameter_header *bfpt_header,
>> @@ -39,7 +57,10 @@ static const struct flash_info macronix_parts[] = {
>> ????? { "mx25l4005a",? INFO(0xc22013, 0, 64 * 1024,?? 8, SECT_4K) },
>> ????? { "mx25l8005",?? INFO(0xc22014, 0, 64 * 1024,? 16, 0) },
>> ????? { "mx25l1606e",? INFO(0xc22015, 0, 64 * 1024,? 32, SECT_4K) },
>> -???? { "mx25l3205d",? INFO(0xc22016, 0, 64 * 1024,? 64, SECT_4K) },
>> +???? { "mx25l3205d",? INFO(0xc22016, 0, 64 * 1024,? 64, SPI_NOR_PARSE_SFDP
>> |
>> +?????????????????????????? SECT_4K)
>> +???????????? /* ID collision with mx25l3233f. */
>> +???????????? .fixups = &mx25l3233f_fixups },
> 
> Shouldn't we use mx25l3205d_fixups as name here? What if there are more
> flashes with the same id. Using the name of the colliding flash here
> doesn't really scale.

I agree, will change.

Cheers,
ta
> 
> -michael
> 
>> ????? { "mx25l3255e",? INFO(0xc29e16, 0, 64 * 1024,? 64, SECT_4K) },
>> ????? { "mx25l6405d",? INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
>> ????? { "mx25u2033e",? INFO(0xc22532, 0, 64 * 1024,?? 4, SECT_4K) },


From wsa+renesas at sang-engineering.com  Fri Oct  1 01:54:55 2021
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 1 Oct 2021 10:54:55 +0200
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXMc1A4D/y4kjim@shikoro>
 <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>
Message-ID: <YVbM3z7x+D0MCkTF@ninjato>

Hi Prabhakar,

> > Is RPCIF_CMNCR_IO3FV and RPCIF_CMNCR_IO2FV actually documented in your
> > datasheets? I am asking because I have a patch pending to remove writing
> > to undocumented locations. So, I was aboout to remove the IO3FV and
> > IO2FV macros.
> >
> Yes they are documented, you should be able to download the HW manual from [1]

Great, then I will keep them!

> > > +     regmap_write(rpc->regmap, RPCIF_PHYADJ2, 0x00008080);
> > > +     regmap_write(rpc->regmap, RPCIF_PHYADJ1, 0x80000024);
> >
> > Can't we have defines for these magic values? At least in my latest Gen3
> > documentation, these values are explained.
> >
> RZ/G2L manual doesn't explain these bits. Let me refer to R-Car Gen3
> and define them as macros.

Seems like we have the best of both worlds then with the documentation
;)

> > > +     if (rpc->type == RPCIF_RCAR_GEN3) {
> > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> > > +                          RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> > > +     } else {
> > > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> >
> > regmap_update_bits?
> >
> Im a bit hesitant to use regmap_update_bits() here as some of the bits
> are not documented.

Hmm, maybe I should then update the patch avoiding undocumented register
access beforehand? I will download your docs and see what remains and
send that out for you to check. Somewhen later today.

Sounds good?

Happy hacking,

   Wolfram

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211001/df372c9c/attachment.sig>

From prabhakar.csengg at gmail.com  Fri Oct  1 02:06:06 2021
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Fri, 1 Oct 2021 10:06:06 +0100
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <YVbM3z7x+D0MCkTF@ninjato>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXMc1A4D/y4kjim@shikoro>
 <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>
 <YVbM3z7x+D0MCkTF@ninjato>
Message-ID: <CA+V-a8uyQmW3+4hAt4534spKeQHDoeZzuJJE4RY70KLZfYOXoA@mail.gmail.com>

Hi Wolfram,

On Fri, Oct 1, 2021 at 9:55 AM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
>
> Hi Prabhakar,
>
> > > Is RPCIF_CMNCR_IO3FV and RPCIF_CMNCR_IO2FV actually documented in your
> > > datasheets? I am asking because I have a patch pending to remove writing
> > > to undocumented locations. So, I was aboout to remove the IO3FV and
> > > IO2FV macros.
> > >
> > Yes they are documented, you should be able to download the HW manual from [1]
>
> Great, then I will keep them!
>
> > > > +     regmap_write(rpc->regmap, RPCIF_PHYADJ2, 0x00008080);
> > > > +     regmap_write(rpc->regmap, RPCIF_PHYADJ1, 0x80000024);
> > >
> > > Can't we have defines for these magic values? At least in my latest Gen3
> > > documentation, these values are explained.
> > >
> > RZ/G2L manual doesn't explain these bits. Let me refer to R-Car Gen3
> > and define them as macros.
>
> Seems like we have the best of both worlds then with the documentation
> ;)
>
Indeed :)

> > > > +     if (rpc->type == RPCIF_RCAR_GEN3) {
> > > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> > > > +                          RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> > > > +     } else {
> > > > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > > > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > > > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> > >
> > > regmap_update_bits?
> > >
> > Im a bit hesitant to use regmap_update_bits() here as some of the bits
> > are not documented.
>
> Hmm, maybe I should then update the patch avoiding undocumented register
> access beforehand? I will download your docs and see what remains and
> send that out for you to check. Somewhen later today.
>
> Sounds good?
>
Fine with me.

Cheers,
Prabhakar

> Happy hacking,
>
>    Wolfram
>


From Tudor.Ambarus at microchip.com  Fri Oct  1 02:16:59 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 09:16:59 +0000
Subject: [PATCH v2 05/35] mtd: spi-nor: Introduce Manufacturer ID
 collisions driver
In-Reply-To: <fb581e64c1af72f30fdd10157e7275d4@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-6-tudor.ambarus@microchip.com>
 <fb581e64c1af72f30fdd10157e7275d4@walle.cc>
Message-ID: <022113f6-7cbf-8ddf-63ad-71f51ce3c0ef@microchip.com>

On 8/24/21 1:47 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-07-27 06:51, schrieb Tudor Ambarus:
>> Some manufacturers completely ignore the manufacturer's identification
>> code
>> standard (JEP106) and do not define the manufacturer ID continuation
>> scheme. This will result in manufacturer ID collisions.
>>
>> An an example, JEP106BA requires Boya that it's manufacturer ID to be
>> preceded by 8 continuation codes. Boya's identification code must be:
>> 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x68. But Boya ignores
>> the
>> continuation scheme and its ID collides with the manufacturer defined
>> in
>> bank one: Convex Computer.
>>
>> Introduce the manuf-id-collisions driver in order to address ID
>> collisions
>> between manufacturers. flash_info entries will be added in a first
>> come,
>> first served manner. Differentiation between flashes will be done at
>> runtime if possible. Where runtime differentiation is not possible, new
>> compatibles will be introduced, but this will be done as a last resort.
>> Every new flash addition that define the SFDP tables, should dump its
>> SFDP
>> tables in the patch's comment section below the --- line, so that we
>> can
>> reference it in case of collisions.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>> ?drivers/mtd/spi-nor/Makefile????????????? |? 1 +
>> ?drivers/mtd/spi-nor/core.c??????????????? |? 1 +
>> ?drivers/mtd/spi-nor/core.h??????????????? |? 1 +
>> ?drivers/mtd/spi-nor/manuf-id-collisions.c | 22 ++++++++++++++++++++++
>> ?4 files changed, 25 insertions(+)
>> ?create mode 100644 drivers/mtd/spi-nor/manuf-id-collisions.c
>>
>> diff --git a/drivers/mtd/spi-nor/Makefile
>> b/drivers/mtd/spi-nor/Makefile
>> index 6b904e439372..48763d10daad 100644
>> --- a/drivers/mtd/spi-nor/Makefile
>> +++ b/drivers/mtd/spi-nor/Makefile
>> @@ -1,6 +1,7 @@
>> ?# SPDX-License-Identifier: GPL-2.0
>>
>> ?spi-nor-objs???????????????? := core.o sfdp.o swp.o otp.o sysfs.o
>> +spi-nor-objs???????????????? += manuf-id-collisions.o
>> ?spi-nor-objs???????????????? += atmel.o
>> ?spi-nor-objs???????????????? += catalyst.o
>> ?spi-nor-objs???????????????? += eon.o
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 1a278d33b02d..d30c8f350dc1 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -1829,6 +1829,7 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor
>> *nor)
>> ?}
>>
>> ?static const struct spi_nor_manufacturer *manufacturers[] = {
>> +???? &spi_nor_manuf_id_collisions,
> 
> Intentionally at the beginning of all the flashes? So these

yes

> might take precedence over "normal" ones? Shouldn't it be

yes

> the other way around?

It doesn't really matter, either way we should correctly identify the flash.
I thought of putting the collisions driver first for better test coverage.
In case we miss a collision between a (future) entry from the manufacturer
collisions driver and one from a dedicated manufacturer driver, to hit the
flash entry from the collisions driver, which will report a wrong name for
the flash in the dedicated manufacturer driver. People will report that
something's wrong and we can fix the things sooner.

> 
>> ????? &spi_nor_atmel,
>> ????? &spi_nor_catalyst,
>> ????? &spi_nor_eon,
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index 55fceb0ec894..e9896cd60695 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -476,6 +476,7 @@ struct sfdp {
>> ?};
>>
>> ?/* Manufacturer drivers. */
>> +extern const struct spi_nor_manufacturer spi_nor_manuf_id_collisions;
>> ?extern const struct spi_nor_manufacturer spi_nor_atmel;
>> ?extern const struct spi_nor_manufacturer spi_nor_catalyst;
>> ?extern const struct spi_nor_manufacturer spi_nor_eon;
>> diff --git a/drivers/mtd/spi-nor/manuf-id-collisions.c
>> b/drivers/mtd/spi-nor/manuf-id-collisions.c
>> new file mode 100644
>> index 000000000000..bf7dba34f018
>> --- /dev/null
>> +++ b/drivers/mtd/spi-nor/manuf-id-collisions.c
>> @@ -0,0 +1,22 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Used to handle collisions between manufacturers, where
>> manufacturers are
>> + * ignorant enough to not implement the ID continuation scheme
>> described in the
>> + * JEP106 JEDEC standard.
>> + */
>> +
>> +#include <linux/mtd/spi-nor.h>
>> +#include "core.h"
>> +
>> +static const struct flash_info id_collision_parts[] = {
>> +???? /* Boya */
>> +???? { "by25q128as", INFO(0x684018, 0, 64 * 1024, 256, SPI_NOR_SKIP_SFDP |
>> +????????????????????????? SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> +????????????????????????? SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
>> +};
>> +
>> +const struct spi_nor_manufacturer spi_nor_manuf_id_collisions = {
>> +???? .name = "manufacturer ID collisions",
> 
> mhh, so we loose the manufacturer name. Doh. Can we do better?

yes, we can introduce a const char *manufacturer_name in struct spi_nor and
update it with the correct manufacturer name. Will do.

cheers,
ta

> 
> -michael
> 
>> +???? .parts = id_collision_parts,
>> +???? .nparts = ARRAY_SIZE(id_collision_parts),
>> +};


From Tudor.Ambarus at microchip.com  Fri Oct  1 02:26:18 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 09:26:18 +0000
Subject: [PATCH v2 06/35] mtd: spi-nor: manuf-id-collisions: Add support
 for xt25f128b
In-Reply-To: <20210816184348.sabnihh7b2sf34s4@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-7-tudor.ambarus@microchip.com>
 <20210816184348.sabnihh7b2sf34s4@ti.com>
Message-ID: <ce7410d4-1f2d-58ba-4c6a-a35aeb92bcf6@microchip.com>

On 8/16/21 9:43 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>> Flash does not support continuation codes and may collide with a flash
>> of other manufacturer, Intersil being an example .
> Nitpick:                                          ^ drop the extra space

thanks

> 
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>> 0000000 4653 5044 0100 ff01 0000 0901 0030 ff00
>> 0000010 000b 0301 0060 ff00 ffff ffff ffff ffff
>> 0000020 ffff ffff ffff ffff ffff ffff ffff ffff
>> 0000030 20e5 fff1 ffff 07ff eb44 6b08 3b08 bb42
>> 0000040 ffee ffff ffff ff00 ffff ff00 200c 520f
>> 0000050 d810 ff00 ffff ffff ffff ffff ffff ffff
>> 0000060 3600 2700 f99f 6477 e8d9 ffff
> 
> I think you should list all the other sysfs parameters as well. See
> Michael's comments on patch 35.

ok

> 
>>
>>  drivers/mtd/spi-nor/manuf-id-collisions.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/mtd/spi-nor/manuf-id-collisions.c b/drivers/mtd/spi-nor/manuf-id-collisions.c
>> index bf7dba34f018..db31470ebf6a 100644
>> --- a/drivers/mtd/spi-nor/manuf-id-collisions.c
>> +++ b/drivers/mtd/spi-nor/manuf-id-collisions.c
>> @@ -13,6 +13,10 @@ static const struct flash_info id_collision_parts[] = {
>>       { "by25q128as", INFO(0x684018, 0, 64 * 1024, 256, SPI_NOR_SKIP_SFDP |
>>                            SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>>                            SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
>> +
>> +     /* XTX (XTX Technology Limited) */
>> +     { "xt25f128b", INFO(0x0b4018, 0, 64 * 1024, 256, SPI_NOR_PARSE_SFDP |
>> +                         SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
> 
> I have not went and checked, but I assume these two flags can't be
> discovered via SFDP?

Locking is not covered by SFDP yet. The non SFDP discoverable flags will be parsed in a
spi_nor_nonsfdp_flags_init() method. I saw you've spotted a bug there, will handle it.

Cheers,
ta
> 
>>  };
>>
>>  const struct spi_nor_manufacturer spi_nor_manuf_id_collisions = {
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Fri Oct  1 02:38:25 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 09:38:25 +0000
Subject: [PATCH v2 08/35] mtd: spi-nor: core: Introduce the ate_init() hook
In-Reply-To: <20210816185446.topxrgwmvpt6n4ct@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-9-tudor.ambarus@microchip.com>
 <20210816185446.topxrgwmvpt6n4ct@ti.com>
Message-ID: <a8690ed4-589a-1c45-2ba7-84b2e4fdd83f@microchip.com>

On 8/16/21 9:54 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hi Tudor,
> 
>> Subject: [PATCH v2 08/35] mtd: spi-nor: core: Introduce the ate_init() hook
>                                                               ^^^^^^^^
> You ate the 'l' ;-)

right, thanks!

> 
> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>> The goal is to get rid of the spaghetti way of initializing the flash
>> parameters and settings. late_init() hook will be used to tweak various
>> parameters that are not defined by the SFDP standard. Can be used by
>> non SFDP compliant flashes in order to tweak flash parameters that
>> are not/shouldn't be handled by the flash_info flags. Will replace the
>> default_init() hook.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c | 15 +++++++++++----
>>  drivers/mtd/spi-nor/core.h |  8 ++++++++
>>  2 files changed, 19 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index d30c8f350dc1..15ccc9994215 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -2667,11 +2667,18 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
>>   * spi_nor_late_init_params() - Late initialization of default flash parameters.
>>   * @nor:     pointer to a 'struct spi_nor'
>>   *
>> - * Used to set default flash parameters and settings when the ->default_init()
>> - * hook or the SFDP parser let voids.
>> + * Used to tweak various flash parameters that are not defined by the SFDP
>> + * standard. Can be used by non SFDP compliant flashes in order to tweek flash
>> + * parameters that are not handled by the flash_info flags.
> 
> What about flashes that do have the SFDP table, but not all of them? For
> example, the Micron MT35XU512ABA flash currently uses the post_sfdp()
> hook to populate 8D-8D-8D fast read settings, command extension type,
> etc. These are supposed to be obtained from the xSPI Profile 1.0 table
> (like we do for Spansion/Cypress S28HS512T). But the flash does not
> populate this table. Should these go into the late_init() hook or the
> post_sfdp() hook?
> 
> FWIW, I think it should go into late_init(). post_sfdp() should only be
> used for correcting info obtained from the SFDP table. For populating
> the info not present in SFDP at all, late_init() should be used.

That's correct. Missing parameter tables are more suited for late_init(),
whereas post_sfdp is to tweak parameters that are wrongly defined in the tables.
spi_nor_post_sfdp_fixups() will be called only when SFDP tables are populated:
patch 15/35

Cheers,
ta
> 
> Thoughts?
> 
>>   */
>>  static void spi_nor_late_init_params(struct spi_nor *nor)
>>  {
>> +     if (nor->manufacturer && nor->manufacturer->late_init)
>> +             nor->manufacturer->late_init(nor);
>> +
>> +     if (nor->info->late_init)
>> +             nor->info->late_init(nor);
> 
> Manufacturer late_init goes before flash late_init. Makes sense.
> 
>> +
>>       /*
>>        * NOR protection support. When locking_ops are not provided, we pick
>>        * the default ones.
>> @@ -2713,8 +2720,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
>>   *    wrong).
>>   *           spi_nor_post_sfdp_fixups()
>>   *
>> - * 5/ Late default flash parameters initialization, used when the
>> - * ->default_init() hook or the SFDP parser do not set specific params.
>> + * 5/ Late flash parameters initialization, used to initialize flash
>> + * parameters that are not declared in the JESD216 SFDP standard.
>>   *           spi_nor_late_init_params()
>>   */
>>  static int spi_nor_init_params(struct spi_nor *nor)
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index e9896cd60695..13d5c5edfd27 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -391,6 +391,11 @@ struct flash_info {
>>
>>       /* Part specific fixup hooks. */
>>       const struct spi_nor_fixups *fixups;
>> +     /*
>> +      * Init flash parameters that are not declared in the JESD216 SFDP
>> +      * standard.
>> +      */
>> +     void (* const late_init)(struct spi_nor *nor);
>>  };
>>
>>  /* Used when the "_ext_id" is two bytes at most */
>> @@ -457,12 +462,15 @@ struct flash_info {
>>   * @parts: array of parts supported by this manufacturer
>>   * @nparts: number of entries in the parts array
>>   * @fixups: hooks called at various points in time during spi_nor_scan()
>> + * @late_init: used to init flash parameters that are not declared in the
>> + *             JESD216 SFDP standard.
>>   */
>>  struct spi_nor_manufacturer {
>>       const char *name;
>>       const struct flash_info *parts;
>>       unsigned int nparts;
>>       const struct spi_nor_fixups *fixups;
>> +     void (* const late_init)(struct spi_nor *nor);
> 
> The patch looks good to me other than the comments above.
> 
>>  };
>>
>>  /**
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Fri Oct  1 02:44:43 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 09:44:43 +0000
Subject: [PATCH v2 08/35] mtd: spi-nor: core: Introduce the ate_init() hook
In-Reply-To: <1176aa457faf4ef5b60558a70c9b70b5@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-9-tudor.ambarus@microchip.com>
 <20210816185446.topxrgwmvpt6n4ct@ti.com>
 <1176aa457faf4ef5b60558a70c9b70b5@walle.cc>
Message-ID: <a462e2aa-6998-afe3-bdf0-2f3bde8fdb5a@microchip.com>

On 9/10/21 12:40 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-08-16 20:54, schrieb Pratyush Yadav:
>> Hi Tudor,
>>
>>> Subject: [PATCH v2 08/35] mtd: spi-nor: core: Introduce the ate_init()
>>> hook
>> ????????????????????????????????????????????????????????????? ^^^^^^^^
>> You ate the 'l' ;-)
>>
>> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>>> The goal is to get rid of the spaghetti way of initializing the flash
>>> parameters and settings. late_init() hook will be used to tweak
>>> various
>>> parameters that are not defined by the SFDP standard. Can be used by
>>> non SFDP compliant flashes in order to tweak flash parameters that
>>> are not/shouldn't be handled by the flash_info flags. Will replace the
>>> default_init() hook.
>>>
>>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>>> ---
>>> ?drivers/mtd/spi-nor/core.c | 15 +++++++++++----
>>> ?drivers/mtd/spi-nor/core.h |? 8 ++++++++
>>> ?2 files changed, 19 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> index d30c8f350dc1..15ccc9994215 100644
>>> --- a/drivers/mtd/spi-nor/core.c
>>> +++ b/drivers/mtd/spi-nor/core.c
>>> @@ -2667,11 +2667,18 @@ static void spi_nor_post_sfdp_fixups(struct
>>> spi_nor *nor)
>>> ? * spi_nor_late_init_params() - Late initialization of default flash
>>> parameters.
>>> ? * @nor:??? pointer to a 'struct spi_nor'
>>> ? *
>>> - * Used to set default flash parameters and settings when the
>>> ->default_init()
>>> - * hook or the SFDP parser let voids.
>>> + * Used to tweak various flash parameters that are not defined by the
>>> SFDP
>>> + * standard. Can be used by non SFDP compliant flashes in order to
>>> tweek flash
>>> + * parameters that are not handled by the flash_info flags.
>>
>> What about flashes that do have the SFDP table, but not all of them?
>> For
>> example, the Micron MT35XU512ABA flash currently uses the post_sfdp()
>> hook to populate 8D-8D-8D fast read settings, command extension type,
>> etc. These are supposed to be obtained from the xSPI Profile 1.0 table
>> (like we do for Spansion/Cypress S28HS512T). But the flash does not
>> populate this table. Should these go into the late_init() hook or the
>> post_sfdp() hook?
>>
>> FWIW, I think it should go into late_init(). post_sfdp() should only be
>> used for correcting info obtained from the SFDP table. For populating
>> the info not present in SFDP at all, late_init() should be used.
>>
>> Thoughts?
> 
> Is there any difference between these? According to the description
> in spi_nor_init_params() your case should go into post_sfdp(). Mh

I thought I made it clearer in 15/35. I will revisit the documentation
updates and try to be more precise. Maybe it is worth to reorder the patches
to, I'll do it if there will not be huge conflicts.

Cheers,
ta

From Tudor.Ambarus at microchip.com  Fri Oct  1 04:40:57 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 11:40:57 +0000
Subject: [PATCH v2 09/35] mtd: spi-nor: atmel: Use flash late_init() for
 locking
In-Reply-To: <a9d41aa96a8749b599d4479f18479c5d@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-10-tudor.ambarus@microchip.com>
 <20210816190629.3kg4cbf5d7h7gyk5@ti.com>
 <a9d41aa96a8749b599d4479f18479c5d@walle.cc>
Message-ID: <88abe817-9d2f-35f6-746c-1640b166aab8@microchip.com>

On 9/10/21 12:44 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-08-16 21:06, schrieb Pratyush Yadav:
>> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>>> Locking is not described in JESD216 SFDP standard, place the locking
>>> init in late_init().
> 
> Btw, we should differentiate between the block protection
> bits and individual block locking. At least the latter is described
> in the SFDP (I've seen it in the XTX SFDP, haven't checked the
> standard yet).

that's probably a vendor specific table, not something standardized by SFDP.

> 
>> You are chaning the order of setting the locking ops here. Earlier,
>> they
>> were set before we parsed SFDP. Now they are set after we parse SFDP.
>> Though I don't see it making much of a difference.

Right, as the locking is not covered by SFDP, we should place it after
parsing SFDP.

>>
>>>
>>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>>> ---
>>> ?drivers/mtd/spi-nor/atmel.c | 30 +++++++++++-------------------
>>> ?1 file changed, 11 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
>>> index 1fea5cab492c..b937ef734e55 100644
>>> --- a/drivers/mtd/spi-nor/atmel.c
>>> +++ b/drivers/mtd/spi-nor/atmel.c
>>> @@ -48,15 +48,11 @@ static const struct spi_nor_locking_ops
>>> atmel_at25fs_locking_ops = {
>>> ???? .is_locked = atmel_at25fs_is_locked,
>>> ?};
>>>
>>> -static void atmel_at25fs_default_init(struct spi_nor *nor)
>>> +static void atmel_at25fs_late_init(struct spi_nor *nor)
>>> ?{
>>> ???? nor->params->locking_ops = &atmel_at25fs_locking_ops;
>>> ?}
>>>
>>> -static const struct spi_nor_fixups atmel_at25fs_fixups = {
>>> -??? .default_init = atmel_at25fs_default_init,
>>> -};
>>> -
>>> ?/**
>>> ? * atmel_set_global_protection - Do a Global Protect or Unprotect
>>> command
>>> ? * @nor:??? pointer to 'struct spi_nor'
>>> @@ -146,34 +142,30 @@ static const struct spi_nor_locking_ops
>>> atmel_global_protection_ops = {
>>> ???? .is_locked = atmel_is_global_protected,
>>> ?};
>>>
>>> -static void atmel_global_protection_default_init(struct spi_nor *nor)
>>> +static void atmel_global_protection_late_init(struct spi_nor *nor)
>>> ?{
>>> ???? nor->params->locking_ops = &atmel_global_protection_ops;
>>> ?}
>>>
>>> -static const struct spi_nor_fixups atmel_global_protection_fixups = {
>>> -??? .default_init = atmel_global_protection_default_init,
>>> -};
>>> -
>>> ?static const struct flash_info atmel_parts[] = {
>>> ???? /* Atmel -- some are (confusingly) marketed as "DataFlash" */
>>> ???? { "at25fs010",? INFO(0x1f6601, 0, 32 * 1024,?? 4, SECT_4K |
>>> SPI_NOR_HAS_LOCK)
>>> -??????????? .fixups = &atmel_at25fs_fixups },
>>> +??????????? .late_init = atmel_at25fs_late_init },
>>> ???? { "at25fs040",? INFO(0x1f6604, 0, 64 * 1024,?? 8, SECT_4K |
>>> SPI_NOR_HAS_LOCK)
>>> -??????????? .fixups = &atmel_at25fs_fixups },
>>> +??????????? .late_init = atmel_at25fs_late_init },
>>>
>>> ???? { "at25df041a", INFO(0x1f4401, 0, 64 * 1024,?? 8,
>>> ????????????????????????? SECT_4K | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
>>> -??????????????????? .fixups = &atmel_global_protection_fixups },
>>> +??????????? .late_init = atmel_global_protection_late_init },
>>
>> Won't you be better off setting this in the manufacturer late_init()?
>> It
>> seems common for most atmel flashes.
>>
>> Of course, this would cause a problem for atmel flashes that don't have
>> this at all, since we would set locking for those as well. But I think
>> we can avoid that by checking for SNOR_F_HAS_LOCK in
>> spi_nor_register_locking_ops().
> 
> +1
> 

we also have the atmel_at25fs_late_init() method. setting it per manufacturer will result
in setting the manufacturer locking ops for at25fs as well, which will be overwritten by the
at25fs locking ops. For those that don't support locking at all, we should clear the locking
ops as you said. This will make the code a little difficult to follow and we return a bit
to spaghetti. defining late_init() takes only a line anyway. I would keep the code as it is
if you don't mind. We can ask ourselves about scalability when we have lots of entries,
we can reevaluate this in the future. Tell me if you have strong opinions on this.

Cheers,
ta



From Tudor.Ambarus at microchip.com  Fri Oct  1 04:43:16 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 11:43:16 +0000
Subject: [PATCH v2 10/35] mtd: spi-nor: sst: Use flash late_init() for
 locking
In-Reply-To: <20210816190928.kvzex5r6ml77uigs@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-11-tudor.ambarus@microchip.com>
 <20210816190928.kvzex5r6ml77uigs@ti.com>
Message-ID: <3bd6b85b-ddd9-327d-7236-cbc982f7e00c@microchip.com>

On 8/16/21 10:09 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>> Locking ops are not discoverable via SFDP, use late_init() call.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> 
> Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
> 
> One question though. Have you tested these flashes (this one and the
> ones in the previous patch) to make sure you are not causing any
> regressions? While I don't see anything wrong with the patches, it would
> be good to have some test reports.

sst26vf064b was tested, I thought I specified it in the cover letter.
I haven't tested locking, but will do. It's not a tragedy if we slip few
bugs anyway, we're here to squash them.
> 
>> ---
>>  drivers/mtd/spi-nor/sst.c | 8 ++------
>>  1 file changed, 2 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
>> index 980f4c09c91d..29d100febdbf 100644
>> --- a/drivers/mtd/spi-nor/sst.c
>> +++ b/drivers/mtd/spi-nor/sst.c
>> @@ -46,15 +46,11 @@ static const struct spi_nor_locking_ops sst26vf_locking_ops = {
>>       .is_locked = sst26vf_is_locked,
>>  };
>>
>> -static void sst26vf_default_init(struct spi_nor *nor)
>> +static void sst26vf_late_init(struct spi_nor *nor)
>>  {
>>       nor->params->locking_ops = &sst26vf_locking_ops;
>>  }
>>
>> -static const struct spi_nor_fixups sst26vf_fixups = {
>> -     .default_init = sst26vf_default_init,
>> -};
>> -
>>  static const struct flash_info sst_parts[] = {
>>       /* SST -- large erase sizes are "overlays", "sectors" are 4K */
>>       { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8,
>> @@ -88,7 +84,7 @@ static const struct flash_info sst_parts[] = {
>>       { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
>>                             SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>>                             SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
>> -             .fixups = &sst26vf_fixups },
>> +             .late_init = sst26vf_late_init},
>>  };
>>
>>  static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Fri Oct  1 04:54:50 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 11:54:50 +0000
Subject: [PATCH v2 11/35] mtd: spi-nor: winbond: Use manufacturer
 late_init() for OTP ops
In-Reply-To: <20210816191744.k6ufbgrrwh6whhnc@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-12-tudor.ambarus@microchip.com>
 <20210816191744.k6ufbgrrwh6whhnc@ti.com>
Message-ID: <aaab30e5-9ea0-c103-0791-e565470ebbc0@microchip.com>

On 8/16/21 10:17 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>> OTP info is not yet discoverable via SFDP, use late_init() to init
>> the OTP ops.
> 
> What do you mean by the "yet"? Does it mean that OTP info is planned to
> be added to the next SFDP version? Or does it mean that it is possible
> to discover it via SFDP but we just don't support it yet?
> 
> If it is neither and it just means "SFDP does not mention OTP at all",
> like it is for locking, then you should just drop the "yet". I know this
> is very nitpicky but it just caught my eye.

I will update according to your suggestion.

> 
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/winbond.c | 9 +++++++--
>>  1 file changed, 7 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
>> index 96573f61caf5..6be45d2291c6 100644
>> --- a/drivers/mtd/spi-nor/winbond.c
>> +++ b/drivers/mtd/spi-nor/winbond.c
>> @@ -147,17 +147,22 @@ static const struct spi_nor_otp_ops winbond_otp_ops = {
>>  static void winbond_default_init(struct spi_nor *nor)
>>  {
>>       nor->params->set_4byte_addr_mode = winbond_set_4byte_addr_mode;
> 
> Why not move this to late_init() as well?

4byte mode is SFDP discoverable. Ideally we would get rid of the default_init()
hook. Flashes that define SFDP will get the 4byte mode from SFDP, the others
by explicitly setting the late_init() hook. All these should be done at flash
level, not manufacturer level, otherwise it will be hard to guess who sets what,
and we can end up with fixups for fixups.

I'll parse the 4byte mode from SFDP soon, I think I have some patches somewhere.
But the series is getting big, so maybe I'll keep it after this patch set.

> 
>> -     if (nor->params->otp.org->n_regions)
>> -             nor->params->otp.ops = &winbond_otp_ops;
>>  }
>>
>>  static const struct spi_nor_fixups winbond_fixups = {
>>       .default_init = winbond_default_init,
>>  };
>>
>> +static void winbond_late_init(struct spi_nor *nor)
>> +{
>> +     if (nor->params->otp.org->n_regions)
>> +             nor->params->otp.ops = &winbond_otp_ops;
>> +}
>> +
>>  const struct spi_nor_manufacturer spi_nor_winbond = {
>>       .name = "winbond",
>>       .parts = winbond_parts,
>>       .nparts = ARRAY_SIZE(winbond_parts),
>>       .fixups = &winbond_fixups,
>> +     .late_init = winbond_late_init,
>>  };
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Fri Oct  1 04:58:06 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 11:58:06 +0000
Subject: [PATCH v2 11/35] mtd: spi-nor: winbond: Use manufacturer
 late_init() for OTP ops
In-Reply-To: <a8e4b2d96b13c862e242e8009c7c6861@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-12-tudor.ambarus@microchip.com>
 <20210816191744.k6ufbgrrwh6whhnc@ti.com>
 <a8e4b2d96b13c862e242e8009c7c6861@walle.cc>
Message-ID: <88963f61-060f-9f74-9b4f-48d2754d24bc@microchip.com>

On 9/10/21 12:50 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-08-16 21:17, schrieb Pratyush Yadav:
>> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>>> OTP info is not yet discoverable via SFDP, use late_init() to init
>>> the OTP ops.
>>
>> What do you mean by the "yet"? Does it mean that OTP info is planned to
>> be added to the next SFDP version? Or does it mean that it is possible
>> to discover it via SFDP but we just don't support it yet?
> 
> I've seen a bit (again in the XTX SFDP) which indicates it supports
> OTP. But thats all. It doesn't mention _how_ you can actually use it.
> And there are at least two different variants.
> 

I've checked JEDEC Standard No. 216D.01, there are some OTP bits, but no
OTP memory as we handle in SPI NOR.

https://datasheet.lcsc.com/szlcsc/2005251034_XTX-XT25F128BSSIGT_C558844.pdf, Table 5, pg. 60
mentions something about Secured OTP, but that is a vendor table, we're good
for now.

cheers,
ta

From wsa+renesas at sang-engineering.com  Fri Oct  1 05:04:21 2021
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 1 Oct 2021 14:04:21 +0200
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <CA+V-a8uyQmW3+4hAt4534spKeQHDoeZzuJJE4RY70KLZfYOXoA@mail.gmail.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXMc1A4D/y4kjim@shikoro>
 <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>
 <YVbM3z7x+D0MCkTF@ninjato>
 <CA+V-a8uyQmW3+4hAt4534spKeQHDoeZzuJJE4RY70KLZfYOXoA@mail.gmail.com>
Message-ID: <YVb5RXvh9agIS7MG@ninjato>

Hi Prabhakar,

I checked the G2L datasheet and reconsidered. It is better if your patch
goes in first. That means...

> > > > Is RPCIF_CMNCR_IO3FV and RPCIF_CMNCR_IO2FV actually documented in your
> > > > datasheets? I am asking because I have a patch pending to remove writing
> > > > to undocumented locations. So, I was aboout to remove the IO3FV and
> > > > IO2FV macros.
> > > >
> > > Yes they are documented, you should be able to download the HW manual from [1]
> >
> > Great, then I will keep them!

... that you could change the comments here from "undocumented" to
"documened for G2L" or similar.

> > > > > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > > > > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > > > > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > > > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> > > >
> > > > regmap_update_bits?
> > > >
> > > Im a bit hesitant to use regmap_update_bits() here as some of the bits
> > > are not documented.

Here you can keep your code as is. I will change it afterwards if needed
once I clarified all undocumented locations.

Thanks and have a nice weekend,

   Wolfram

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211001/2bf8d4cf/attachment.sig>

From Tudor.Ambarus at microchip.com  Fri Oct  1 05:14:32 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 12:14:32 +0000
Subject: [PATCH v2 14/35] mtd: spi-nor: spansion: Use manufacturer
 late_init()
In-Reply-To: <ebfc420928ef28bb508148b41f55b0e6@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-15-tudor.ambarus@microchip.com>
 <ebfc420928ef28bb508148b41f55b0e6@walle.cc>
Message-ID: <d5f6181f-850c-122f-ebd3-57ac6c3eb1c6@microchip.com>

On 9/10/21 1:02 AM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>> spansion_post_sfdp_fixups() was called regardless if the flash defined
>> SFDP tables or not. A better place for this kind of parameters init is
>> in manufacturer's late_init() hook. post_sfdp() should be called only
>> when SFDP is defined. No functional change in this patch.
>>
>> Instead of doing the 4b opcodes settings at manufacturer level, thus
>> also for every flash that will be introduced, this should be done
>> just where it is needed, per flash. I'll let this for other patch.
> 
> Mh, then why does some flashes define SPI_NOR_4B_OPCODES. It's
> unclear to me when you would use SPI_NOR_4B_OPCODES and when

check patch 18/35, I dropped the SPI_NOR_4B_OPCODES flash_info entry flag.

4b-opcodes support is SFDP discoverable. Where flashes define the 4bait table,
they will fill the support by setting SPI NOR SNOR_F_4B_OPCODES flag. Where the
4bait table is not defined, SNOR_F_4B_OPCODES should be set in a late_init() hook.

> this individual fixup. Also right now, these SPI_NOR_4B_OPCODES
> flags for the spansion flashes are superfluous, no?
> 

there's no spansion flash_info entry that explicitly declare SPI_NOR_4B_OPCODES,
if that's what you meant.

Cheers,
ta



From p.yadav at ti.com  Fri Oct  1 05:19:55 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 1 Oct 2021 17:49:55 +0530
Subject: [PATCH v2 10/35] mtd: spi-nor: sst: Use flash late_init() for
 locking
In-Reply-To: <3bd6b85b-ddd9-327d-7236-cbc982f7e00c@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-11-tudor.ambarus@microchip.com>
 <20210816190928.kvzex5r6ml77uigs@ti.com>
 <3bd6b85b-ddd9-327d-7236-cbc982f7e00c@microchip.com>
Message-ID: <20211001121953.yjzuqhbowg24jucz@ti.com>

On 01/10/21 11:43AM, Tudor.Ambarus at microchip.com wrote:
> On 8/16/21 10:09 PM, Pratyush Yadav wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 27/07/21 07:51AM, Tudor Ambarus wrote:
> >> Locking ops are not discoverable via SFDP, use late_init() call.
> >>
> >> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> > 
> > Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
> > 
> > One question though. Have you tested these flashes (this one and the
> > ones in the previous patch) to make sure you are not causing any
> > regressions? While I don't see anything wrong with the patches, it would
> > be good to have some test reports.
> 
> sst26vf064b was tested, I thought I specified it in the cover letter.

You did indeed. I missed that when reading the series. Sorry.

> I haven't tested locking, but will do. It's not a tragedy if we slip few
> bugs anyway, we're here to squash them.
> > 
> >> ---
> >>  drivers/mtd/spi-nor/sst.c | 8 ++------
> >>  1 file changed, 2 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
> >> index 980f4c09c91d..29d100febdbf 100644
> >> --- a/drivers/mtd/spi-nor/sst.c
> >> +++ b/drivers/mtd/spi-nor/sst.c
> >> @@ -46,15 +46,11 @@ static const struct spi_nor_locking_ops sst26vf_locking_ops = {
> >>       .is_locked = sst26vf_is_locked,
> >>  };
> >>
> >> -static void sst26vf_default_init(struct spi_nor *nor)
> >> +static void sst26vf_late_init(struct spi_nor *nor)
> >>  {
> >>       nor->params->locking_ops = &sst26vf_locking_ops;
> >>  }
> >>
> >> -static const struct spi_nor_fixups sst26vf_fixups = {
> >> -     .default_init = sst26vf_default_init,
> >> -};
> >> -
> >>  static const struct flash_info sst_parts[] = {
> >>       /* SST -- large erase sizes are "overlays", "sectors" are 4K */
> >>       { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8,
> >> @@ -88,7 +84,7 @@ static const struct flash_info sst_parts[] = {
> >>       { "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
> >>                             SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >>                             SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
> >> -             .fixups = &sst26vf_fixups },
> >> +             .late_init = sst26vf_late_init},
> >>  };
> >>
> >>  static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
> >> --
> >> 2.25.1
> >>
> > 
> > --
> > Regards,
> > Pratyush Yadav
> > Texas Instruments Inc.
> > 
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From Tudor.Ambarus at microchip.com  Fri Oct  1 05:31:03 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 12:31:03 +0000
Subject: [PATCH v2 15/35] mtd: spi-nor: core: Call
 spi_nor_post_sfdp_fixups() only when SFDP is defined
In-Reply-To: <20210816193137.xyb4v4edgyge3k54@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-16-tudor.ambarus@microchip.com>
 <20210816193137.xyb4v4edgyge3k54@ti.com>
Message-ID: <ef9b5335-413c-5bd8-2987-df95c73f6b4f@microchip.com>

On 8/16/21 10:31 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> spi_nor_post_sfdp_fixups() was called even when there were no SFDP
>> tables defined and the function name was misleading.
>>
>> We introduced the late_init() hook which is used to tweak various
>> parameters that could not be extracted by other means, i.e. when
>> parameters are not defined in the JESD216 SFDP standard, or when
>> the flash_info flags are incomplete.
>>
>> Use spi_nor_post_sfdp_fixups() just to fix SFDP data. post_sfdp()
>> hook is as of now used just by s28hs512t, mt35xu512aba, and both
>> support SFDP, there's no functional change with this patch.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c | 66 +++++++++++++++++---------------------
>>  1 file changed, 29 insertions(+), 37 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 15ccc9994215..1f38fa8ab2fa 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -2509,6 +2509,25 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
>>               nor->info->fixups->default_init(nor);
>>  }
>>
>> +/**
>> + * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
>> + * after SFDP has been parsed.
>> + * @nor:     pointer to a 'struct spi_nor'
>> + *
>> + * Typically used to tweak various parameters that could not be extracted by
>> + * other means (i.e. when information provided by the SFDP tables are
>> + * incomplete or wrong).
> 
> Do we want to keep the "incomplete" here? Wouldn't incomplete
> information (like missing parameter tables) be more suited for
> late_init()?
> 

will update, thanks

>> + */
>> +static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
>> +{
>> +     if (nor->manufacturer && nor->manufacturer->fixups &&
>> +         nor->manufacturer->fixups->post_sfdp)
>> +             nor->manufacturer->fixups->post_sfdp(nor);
>> +
>> +     if (nor->info->fixups && nor->info->fixups->post_sfdp)
>> +             nor->info->fixups->post_sfdp(nor);
>> +}
>> +
>>  /**
>>   * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
>>   * based on JESD216 SFDP standard.
>> @@ -2523,11 +2542,12 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>>
>>       memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>>
>> -     if (spi_nor_parse_sfdp(nor)) {
>> -             memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>> -             nor->addr_width = 0;
>> -             nor->flags &= ~SNOR_F_4B_OPCODES;
>> -     }
>> +     if (!spi_nor_parse_sfdp(nor))
>> +             return spi_nor_post_sfdp_fixups(nor);
> 
> Huh. I didn't know you could do return foo() in a void function if foo()
> is also void. Dunno how I feel about this though. It definitely confused
> me for a bit.
> 
>> +
>> +     memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>> +     nor->addr_width = 0;
>> +     nor->flags &= ~SNOR_F_4B_OPCODES;
> 
> I feel like the new flow makes these 3 lines more confusing. Earlier,
> these were called under if (spi_nor_parse_sfdp()) so it was a bit easier
> to make the connection that these are undoing the changes performed by
> that function. Now it is a little harder to spot. I think a comment is
> in order.
> 

I'll revisit this when reaching patch 27/35.

cheers,
ta

From prabhakar.csengg at gmail.com  Fri Oct  1 05:53:30 2021
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Fri, 1 Oct 2021 13:53:30 +0100
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <YVb5RXvh9agIS7MG@ninjato>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <YVXMc1A4D/y4kjim@shikoro>
 <CA+V-a8sDSsyTGfTeQfG_ZhfrJHCm+2kBTEDWaoFMTgsMOmxEgQ@mail.gmail.com>
 <YVbM3z7x+D0MCkTF@ninjato>
 <CA+V-a8uyQmW3+4hAt4534spKeQHDoeZzuJJE4RY70KLZfYOXoA@mail.gmail.com>
 <YVb5RXvh9agIS7MG@ninjato>
Message-ID: <CA+V-a8vQ2EoMW18aEq5Ssa71M6VvA6YtOzU2UAe7L1Puorr07Q@mail.gmail.com>

Hi Wolfram,

On Fri, Oct 1, 2021 at 1:04 PM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
>
> Hi Prabhakar,
>
> I checked the G2L datasheet and reconsidered. It is better if your patch
> goes in first. That means...
>
> > > > > Is RPCIF_CMNCR_IO3FV and RPCIF_CMNCR_IO2FV actually documented in your
> > > > > datasheets? I am asking because I have a patch pending to remove writing
> > > > > to undocumented locations. So, I was aboout to remove the IO3FV and
> > > > > IO2FV macros.
> > > > >
> > > > Yes they are documented, you should be able to download the HW manual from [1]
> > >
> > > Great, then I will keep them!
>
> ... that you could change the comments here from "undocumented" to
> "documened for G2L" or similar.
>
> > > > > > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > > > > > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > > > > > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > > > > > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> > > > >
> > > > > regmap_update_bits?
> > > > >
> > > > Im a bit hesitant to use regmap_update_bits() here as some of the bits
> > > > are not documented.
>
> Here you can keep your code as is. I will change it afterwards if needed
> once I clarified all undocumented locations.
>
Thanks, will re-spin the patches with comments fixed.

> Thanks and have a nice weekend,
>
You too.

Cheers,
Prabhakar

>    Wolfram
>


From Tudor.Ambarus at microchip.com  Fri Oct  1 07:18:11 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 1 Oct 2021 14:18:11 +0000
Subject: [PATCH v2 16/35] mtd: spi-nor: core: Mark default_init() as
 deprecated
In-Reply-To: <20210816193602.ze2w6qczvtgpwwdi@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-17-tudor.ambarus@microchip.com>
 <20210816193602.ze2w6qczvtgpwwdi@ti.com>
Message-ID: <33dad358-b6f7-292b-2f02-7b5c9f9c8b2a@microchip.com>

On 8/16/21 10:36 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> The goal is to remove the spagetti init of params. The flash should
>> be initialized by the SFDP data, and when SFDP tables are not defined,
>> by the flash_info flags. SFDP data can be corrected by the
>> post_{bfpt, sfdp} when wrong, and in case of flash_info flags init,
>> we'll use the late_init() hook, where checking for the
>> SPI_NOR_SKIP_SFDP flag.
> 
> Why depreciate it? It is not like we have external callers that we need
> to notify. We know and control all the users of this function. Just move
> all users to late_init() and delete this. You have already done a large
> part of that work in the previous patches. Why not convert all other
> callers as well? Is there some complicated piece of code that stops you
> from touching it for now?

Nothing complicated, but I don't have flashes to test. Let's take them one by one:

drivers/mtd/spi-nor/gigadevice.c:static void gd25q256_default_init(struct spi_nor *nor)
sets nor->params->quad_enable method. Quad enable is SFDP discoverable, if I replace
the default_init() with late_init() I'll risk to overwrite the method discovered by SFDP.

drivers/mtd/spi-nor/issi.c:     .default_init = issi_default_init,
same for ISSI. Here it is a manufacturer default init, which is worse. All flashes
have to be checked. This is another reason why I strongly prefer late_init() calls
to set flags per flash and not at manufacturer level.

drivers/mtd/spi-nor/micron-st.c:static void mt35xu512aba_default_init(struct spi_nor *nor)
you have this flash. If the octal_dtr_enable method is not SFDP discoverable, I can
move if to late_init(). I'm waiting for your call. I'll need a tested-by after I'll
make the patch.

drivers/mtd/spi-nor/micron-st.c:        .default_init = micron_st_default_init,
This one is hard to get rid of. I won't be surprised if these fields are overwritten
when parsing SFDP. Moving them in late_init() will nullify SFDP parsing.

drivers/mtd/spi-nor/spansion.c:static void s28hs512t_default_init(struct spi_nor *nor)
you have this flash. I'll move it to late init if octal_dtr_enable method is not SFDP
discoverable. I'll need a tested-by.

drivers/mtd/spi-nor/winbond.c:static void winbond_default_init(struct spi_nor *nor)
4byte addr mode is SFDP discoverable, if I move it in late_init() I'll overwrite what
I get from SFDP.

So just mark the hook as deprecated should be enough for now (at least for this release).
We'll probably never have all these flashes at hand, so maybe we'll agree for a time limit
after which we'll switch to late_init() or post_bfpt/sfpd() solely based on datasheet info.
If the datasheets will be wrong, we'll have bugs and people will scream, but nothing that
we can't handle/fix.

Cheers,
ta

> 
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.h | 5 ++---
>>  1 file changed, 2 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index 13d5c5edfd27..625f4eed75f1 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -289,9 +289,8 @@ struct spi_nor_flash_parameter {
>>
>>  /**
>>   * struct spi_nor_fixups - SPI NOR fixup hooks
>> - * @default_init: called after default flash parameters init. Used to tweak
>> - *                flash parameters when information provided by the flash_info
>> - *                table is incomplete or wrong.
>> + * @default_init: Deprecated. Use the post_{bfpt, sfdp}, or the late_init()
>> + *                hooks instead.
>>   * @post_bfpt: called after the BFPT table has been parsed
>>   * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
>>   *             that do not support RDSFDP). Typically used to tweak various
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From p.yadav at ti.com  Fri Oct  1 10:06:50 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 1 Oct 2021 22:36:50 +0530
Subject: [PATCH v2 16/35] mtd: spi-nor: core: Mark default_init() as
 deprecated
In-Reply-To: <33dad358-b6f7-292b-2f02-7b5c9f9c8b2a@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-17-tudor.ambarus@microchip.com>
 <20210816193602.ze2w6qczvtgpwwdi@ti.com>
 <33dad358-b6f7-292b-2f02-7b5c9f9c8b2a@microchip.com>
Message-ID: <20211001170648.s3fgb3jcyctqf35w@ti.com>

On 01/10/21 02:18PM, Tudor.Ambarus at microchip.com wrote:
> On 8/16/21 10:36 PM, Pratyush Yadav wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 27/07/21 07:52AM, Tudor Ambarus wrote:
> >> The goal is to remove the spagetti init of params. The flash should
> >> be initialized by the SFDP data, and when SFDP tables are not defined,
> >> by the flash_info flags. SFDP data can be corrected by the
> >> post_{bfpt, sfdp} when wrong, and in case of flash_info flags init,
> >> we'll use the late_init() hook, where checking for the
> >> SPI_NOR_SKIP_SFDP flag.
> > 
> > Why depreciate it? It is not like we have external callers that we need
> > to notify. We know and control all the users of this function. Just move
> > all users to late_init() and delete this. You have already done a large
> > part of that work in the previous patches. Why not convert all other
> > callers as well? Is there some complicated piece of code that stops you
> > from touching it for now?
> 
> Nothing complicated, but I don't have flashes to test. Let's take them one by one:
> 
> drivers/mtd/spi-nor/gigadevice.c:static void gd25q256_default_init(struct spi_nor *nor)
> sets nor->params->quad_enable method. Quad enable is SFDP discoverable, if I replace
> the default_init() with late_init() I'll risk to overwrite the method discovered by SFDP.
> 
> drivers/mtd/spi-nor/issi.c:     .default_init = issi_default_init,
> same for ISSI. Here it is a manufacturer default init, which is worse. All flashes
> have to be checked. This is another reason why I strongly prefer late_init() calls
> to set flags per flash and not at manufacturer level.
> 
> drivers/mtd/spi-nor/micron-st.c:static void mt35xu512aba_default_init(struct spi_nor *nor)
> you have this flash. If the octal_dtr_enable method is not SFDP discoverable, I can
> move if to late_init(). I'm waiting for your call. I'll need a tested-by after I'll
> make the patch.
> 
> drivers/mtd/spi-nor/micron-st.c:        .default_init = micron_st_default_init,
> This one is hard to get rid of. I won't be surprised if these fields are overwritten
> when parsing SFDP. Moving them in late_init() will nullify SFDP parsing.
> 
> drivers/mtd/spi-nor/spansion.c:static void s28hs512t_default_init(struct spi_nor *nor)
> you have this flash. I'll move it to late init if octal_dtr_enable method is not SFDP
> discoverable. I'll need a tested-by.
> 
> drivers/mtd/spi-nor/winbond.c:static void winbond_default_init(struct spi_nor *nor)
> 4byte addr mode is SFDP discoverable, if I move it in late_init() I'll overwrite what
> I get from SFDP.
> 
> So just mark the hook as deprecated should be enough for now (at least for this release).
> We'll probably never have all these flashes at hand, so maybe we'll agree for a time limit
> after which we'll switch to late_init() or post_bfpt/sfpd() solely based on datasheet info.
> If the datasheets will be wrong, we'll have bugs and people will scream, but nothing that
> we can't handle/fix.

Ok, makes sense to me.

> 
> Cheers,
> ta
> 
> > 
> >>
> >> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> >> ---
> >>  drivers/mtd/spi-nor/core.h | 5 ++---
> >>  1 file changed, 2 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> >> index 13d5c5edfd27..625f4eed75f1 100644
> >> --- a/drivers/mtd/spi-nor/core.h
> >> +++ b/drivers/mtd/spi-nor/core.h
> >> @@ -289,9 +289,8 @@ struct spi_nor_flash_parameter {
> >>
> >>  /**
> >>   * struct spi_nor_fixups - SPI NOR fixup hooks
> >> - * @default_init: called after default flash parameters init. Used to tweak
> >> - *                flash parameters when information provided by the flash_info
> >> - *                table is incomplete or wrong.
> >> + * @default_init: Deprecated. Use the post_{bfpt, sfdp}, or the late_init()
> >> + *                hooks instead.
> >>   * @post_bfpt: called after the BFPT table has been parsed
> >>   * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
> >>   *             that do not support RDSFDP). Typically used to tweak various
> >> --
> >> 2.25.1
> >>
> > 
> > --
> > Regards,
> > Pratyush Yadav
> > Texas Instruments Inc.
> > 
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From andriy.shevchenko at linux.intel.com  Fri Oct  1 10:15:30 2021
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri,  1 Oct 2021 20:15:30 +0300
Subject: [PATCH v1 1/1] mtd: spi-nor: intel-spi: Add support for Intel Ice
 Lake-N SPI serial flash
Message-ID: <20211001171530.15283-1-andriy.shevchenko@linux.intel.com>

Intel Ice Lake-N has the same SPI serial flash controller as Ice Lake-LP.
Add Ice Lake-N PCI ID to the driver list of supported devices.

The device can be found on MacBookPro16,2 [1].

[1]: https://linux-hardware.org/?probe=f1c5cf0c43

Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/mtd/spi-nor/controllers/intel-spi-pci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
index 1bc53b8bb88a..f9bcd2dabb4f 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
@@ -70,6 +70,7 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
 	{ PCI_VDEVICE(INTEL, 0x19e0), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x1bca), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x34a4), (unsigned long)&bxt_info },
+	{ PCI_VDEVICE(INTEL, 0x38a4), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x43a4), (unsigned long)&cnl_info },
 	{ PCI_VDEVICE(INTEL, 0x4b24), (unsigned long)&bxt_info },
 	{ PCI_VDEVICE(INTEL, 0x4da4), (unsigned long)&bxt_info },
-- 
2.33.0



From michael at walle.cc  Fri Oct  1 10:21:08 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 01 Oct 2021 19:21:08 +0200
Subject: =?US-ASCII?Q?Re=3A_=5BPATCH_v1_1/1=5D_mtd=3A_spi-nor=3A_intel-spi=3A_Ad?=
 =?US-ASCII?Q?d_support_for_Intel_Ice_Lake-N_SPI_serial_flash?=
In-Reply-To: <20211001171530.15283-1-andriy.shevchenko@linux.intel.com>
References: <20211001171530.15283-1-andriy.shevchenko@linux.intel.com>
Message-ID: <0D47CDDE-0F9E-4D5D-8524-1D911BF52CEF@walle.cc>

Am 1. Oktober 2021 19:15:30 MESZ schrieb Andy Shevchenko <andriy.shevchenko at linux.intel.com>:
>Intel Ice Lake-N has the same SPI serial flash controller as Ice Lake-LP.
>Add Ice Lake-N PCI ID to the driver list of supported devices.
>
>The device can be found on MacBookPro16,2 [1].
>
>[1]: https://linux-hardware.org/?probe=f1c5cf0c43
>
>Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

Hi Andy, 

there is currently a rewrite of this driver (to use spi-mem)
in progress:

https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/

Could you try that series with your hardware? 

-michael 


From andriy.shevchenko at linux.intel.com  Fri Oct  1 12:36:11 2021
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Fri, 1 Oct 2021 22:36:11 +0300
Subject: [PATCH v1 1/1] mtd: spi-nor: intel-spi: Add support for Intel
 Ice Lake-N SPI serial flash
In-Reply-To: <0D47CDDE-0F9E-4D5D-8524-1D911BF52CEF@walle.cc>
References: <20211001171530.15283-1-andriy.shevchenko@linux.intel.com>
 <0D47CDDE-0F9E-4D5D-8524-1D911BF52CEF@walle.cc>
Message-ID: <YVdjKzD/SeNkfT5d@smile.fi.intel.com>

On Fri, Oct 01, 2021 at 07:21:08PM +0200, Michael Walle wrote:
> Am 1. Oktober 2021 19:15:30 MESZ schrieb Andy Shevchenko <andriy.shevchenko at linux.intel.com>:
> >Intel Ice Lake-N has the same SPI serial flash controller as Ice Lake-LP.
> >Add Ice Lake-N PCI ID to the driver list of supported devices.
> >
> >The device can be found on MacBookPro16,2 [1].
> >
> >[1]: https://linux-hardware.org/?probe=f1c5cf0c43
> >
> >Signed-off-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> 
> Hi Andy, 
> 
> there is currently a rewrite of this driver (to use spi-mem)
> in progress:
> 
> https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/
> 
> Could you try that series with your hardware? 

It's not mine - can't test myself. I'm helping to enable Linux on it.
But okay, I postpone this till the reworked version will be applied.

-- 
With Best Regards,
Andy Shevchenko




From jbglaw at lug-owl.de  Fri Oct  1 12:28:36 2021
From: jbglaw at lug-owl.de (Jan-Benedict Glaw)
Date: Fri, 1 Oct 2021 21:28:36 +0200
Subject: [PATCH] Don't overflow when writing a key
Message-ID: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>

Hi!

I'm mass-building the GNU Toolchain, Linux, NetBSD and others and got
a warning with recent GCC versions when building Linux's
ARM-based aspeed_g4_defconfig:

[mk all 2021-10-01 14:10:14]   arm-linux-gnueabihf-gcc -Wp,-MMD,fs/ubifs/.journal.o.d -nostdinc -isystem /var/lib/laminar/run/linux-arm-aspeed_g4_defconfig/9/toolchain/bin/../lib/gcc/arm-linux-gnueabihf/12.0.0/include -I./arch/arm/include -I./arch/arm/include/generated  -I./include -I./arch/arm/include/uapi -I./arch/arm/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -mlittle-endian -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -fno-dwarf2-cfi-asm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -fno-ipa-sra -mabi=aapcs-linux -mfpu=vfp -marm -Wa,-mno-warn-deprecated -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=1024 -fstack-protector-strong -Wimplicit-fallthrough=5 -Wno-main -Wno-unused-but-set-variable -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -fno-stack-clash-protection -g -gdwarf-4 -fno-var-tracking -femit-struct-debug-baseonly -pg -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned    -DKBUILD_MODFILE='"fs/ubifs/ubifs"' -DKBUILD_BASENAME='"journal"' -DKBUILD_MODNAME='"ubifs"' -D__KBUILD_MODNAME=kmod_ubifs -c -o fs/ubifs/journal.o fs/ubifs/journal.c
[mk all 2021-10-01 14:10:15] In file included from ./include/linux/string.h:262,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/bitmap.h:10,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/cpumask.h:12,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/smp.h:13,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/lockdep.h:14,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/spinlock.h:63,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/wait.h:9,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/wait_bit.h:8,
[mk all 2021-10-01 14:10:15]                  from ./include/linux/fs.h:6,
[mk all 2021-10-01 14:10:15]                  from fs/ubifs/ubifs.h:16,
[mk all 2021-10-01 14:10:15]                  from fs/ubifs/journal.c:49:
[mk all 2021-10-01 14:10:15] In function 'memset',
[mk all 2021-10-01 14:10:15]     inlined from 'key_write.part.0' at fs/ubifs/key.h:439:2:
[mk all 2021-10-01 14:10:15] ./include/linux/fortify-string.h:172:17: error: call to '__write_overflow' declared with attribute error: detected write beyond size of object passed as 1st parameter
[mk all 2021-10-01 14:10:15]   172 |                 __write_overflow();
[mk all 2021-10-01 14:10:15]       |                 ^~~~~~~~~~~~~~~~~~
[mk all 2021-10-01 14:10:15] make[2]: *** [scripts/Makefile.build:277: fs/ubifs/journal.o] Error 1
[mk all 2021-10-01 14:10:15] make[1]: *** [scripts/Makefile.build:540: fs/ubifs] Error 2
[mk all 2021-10-01 14:10:15] make: *** [Makefile:1868: fs] Error 2


This seems to be correct as the struct is declared using
UBIFS_SK_LEN (= 8), but used to use UBIFS_MAX_KEY_LEN (= 16), which
would overflow by 8 bytes.

Here's a suggested patch that is NOT tested as I don't have the UBIFS
in use (knowingly) anywhere:

diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
index 8142d9d6fe5d..40edcca7ba62 100644
--- a/fs/ubifs/key.h
+++ b/fs/ubifs/key.h
@@ -436,7 +436,7 @@ static inline void key_write(const struct ubifs_info *c,
 
 	t->j32[0] = cpu_to_le32(from->u32[0]);
 	t->j32[1] = cpu_to_le32(from->u32[1]);
-	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
+	memset(to + 8, 0, UBIFS_SK_LEN - 8);
 }
 
 /**



Please keep me in Cc: as I'm not subscribed.

Thanks,
  Jan-Benedict

-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211001/8d83953d/attachment.sig>

From mauro.lima at eclypsium.com  Fri Oct  1 13:23:23 2021
From: mauro.lima at eclypsium.com (Mauro Lima)
Date: Fri, 1 Oct 2021 17:23:23 -0300
Subject: [PATCH 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <20210930100719.2176-2-mika.westerberg@linux.intel.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-2-mika.westerberg@linux.intel.com>
Message-ID: <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>

Hi all!

On Thu, Sep 30, 2021 at 7:07 AM Mika Westerberg
<mika.westerberg at linux.intel.com> wrote:
>
> Currently the driver tries to disable the BIOS write protection
> automatically even if this is not what the user wants. For this reason
> modify the driver so that by default it does not touch the write
> protection. Only if specifically asked by the user (setting writeable=1
> command line parameter) the driver tries to disable the BIOS write
> protection.
>
> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> ---
>  drivers/mfd/lpc_ich.c                         | 59 +++++++++++++++++--
>  .../mtd/spi-nor/controllers/intel-spi-pci.c   | 29 +++++----
>  drivers/mtd/spi-nor/controllers/intel-spi.c   | 41 ++++++-------
>  include/linux/platform_data/x86/intel-spi.h   |  6 +-
>  4 files changed, 96 insertions(+), 39 deletions(-)
>
> diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
> index f10e53187f67..9ffab9aafd81 100644
> --- a/drivers/mfd/lpc_ich.c
> +++ b/drivers/mfd/lpc_ich.c
> @@ -63,6 +63,8 @@
>  #define SPIBASE_BYT            0x54
>  #define SPIBASE_BYT_SZ         512
>  #define SPIBASE_BYT_EN         BIT(1)
> +#define BYT_BCR                        0xfc
> +#define BYT_BCR_WPD            BIT(0)
>
>  #define SPIBASE_LPT            0x3800
>  #define SPIBASE_LPT_SZ         512
> @@ -1084,12 +1086,57 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
>         return ret;
>  }
>
> +static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
> +{
> +       u32 val;
> +
> +       val = readl(base + BYT_BCR);
> +       if (!(val & BYT_BCR_WPD)) {
> +               val |= BYT_BCR_WPD;
> +               writel(val, base + BYT_BCR);
> +               val = readl(base + BYT_BCR);
> +       }
> +
> +       return val & BYT_BCR_WPD;
> +}
> +
> +static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
> +{
> +       struct pci_dev *pdev = data;
> +       u32 bcr;
> +
> +       pci_read_config_dword(pdev, BCR, &bcr);
> +       if (!(bcr & BCR_WPD)) {
> +               bcr |= BCR_WPD;
> +               pci_write_config_dword(pdev, BCR, bcr);
> +               pci_read_config_dword(pdev, BCR, &bcr);
> +       }
> +
> +       return bcr & BCR_WPD;
> +}
> +
> +static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
> +{
> +       unsigned int spi = PCI_DEVFN(13, 2);
> +       struct pci_bus *bus = data;
> +       u32 bcr;
> +
> +       pci_bus_read_config_dword(bus, spi, BCR, &bcr);
> +       if (!(bcr & BCR_WPD)) {
> +               bcr |= BCR_WPD;
> +               pci_bus_write_config_dword(bus, spi, BCR, bcr);
> +               pci_bus_read_config_dword(bus, spi, BCR, &bcr);
> +       }
> +
> +       return bcr & BCR_WPD;
> +}
> +
>  static int lpc_ich_init_spi(struct pci_dev *dev)
>  {
>         struct lpc_ich_priv *priv = pci_get_drvdata(dev);
>         struct resource *res = &intel_spi_res[0];
>         struct intel_spi_boardinfo *info;
> -       u32 spi_base, rcba, bcr;
> +       u32 spi_base, rcba;
>
>         info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
>         if (!info)
> @@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
>                 if (spi_base & SPIBASE_BYT_EN) {
>                         res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
>                         res->end = res->start + SPIBASE_BYT_SZ - 1;
> +
> +                       info->set_writeable = lpc_ich_byt_set_writeable;
>                 }
>                 break;
>
> @@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
>                         res->start = spi_base + SPIBASE_LPT;
>                         res->end = res->start + SPIBASE_LPT_SZ - 1;
>
> -                       pci_read_config_dword(dev, BCR, &bcr);
> -                       info->writeable = !!(bcr & BCR_WPD);
> +                       info->set_writeable = lpc_ich_lpt_set_writeable;
> +                       info->data = dev;
>                 }
>                 break;
>
> @@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
>                         res->start = spi_base & 0xfffffff0;
>                         res->end = res->start + SPIBASE_APL_SZ - 1;
>
> -                       pci_bus_read_config_dword(bus, spi, BCR, &bcr);
> -                       info->writeable = !!(bcr & BCR_WPD);
> +                       info->set_writeable = lpc_ich_bxt_set_writeable;
> +                       info->data = bus;
>                 }
>
>                 pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
> diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
> index 1bc53b8bb88a..508f7ca098ef 100644
> --- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
> +++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
> @@ -16,12 +16,30 @@
>  #define BCR            0xdc
>  #define BCR_WPD                BIT(0)
>
> +static bool intel_spi_pci_set_writeable(void __iomem *base, void *data)
> +{
> +       struct pci_dev *pdev = data;
> +       u32 bcr;
> +
> +       /* Try to make the chip read/write */
> +       pci_read_config_dword(pdev, BCR, &bcr);
> +       if (!(bcr & BCR_WPD)) {
> +               bcr |= BCR_WPD;
> +               pci_write_config_dword(pdev, BCR, bcr);
> +               pci_read_config_dword(pdev, BCR, &bcr);
> +       }
> +
> +       return bcr & BCR_WPD;
> +}
> +
>  static const struct intel_spi_boardinfo bxt_info = {
>         .type = INTEL_SPI_BXT,
> +       .set_writeable = intel_spi_pci_set_writeable,
>  };
>
>  static const struct intel_spi_boardinfo cnl_info = {
>         .type = INTEL_SPI_CNL,
> +       .set_writeable = intel_spi_pci_set_writeable,
>  };
>
>  static int intel_spi_pci_probe(struct pci_dev *pdev,
> @@ -29,7 +47,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
>  {
>         struct intel_spi_boardinfo *info;
>         struct intel_spi *ispi;
> -       u32 bcr;
>         int ret;
>
>         ret = pcim_enable_device(pdev);
> @@ -41,15 +58,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
>         if (!info)
>                 return -ENOMEM;
>
> -       /* Try to make the chip read/write */
> -       pci_read_config_dword(pdev, BCR, &bcr);
> -       if (!(bcr & BCR_WPD)) {
> -               bcr |= BCR_WPD;
> -               pci_write_config_dword(pdev, BCR, bcr);
> -               pci_read_config_dword(pdev, BCR, &bcr);
> -       }
> -       info->writeable = !!(bcr & BCR_WPD);
> -
> +       info->data = pdev;
>         ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
>         if (IS_ERR(ispi))
>                 return PTR_ERR(ispi);
> diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
> index a413892ff449..f35597cbea0c 100644
> --- a/drivers/mtd/spi-nor/controllers/intel-spi.c
> +++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
> @@ -131,7 +131,6 @@
>   * @sregs: Start of software sequencer registers
>   * @nregions: Maximum number of regions
>   * @pr_num: Maximum number of protected range registers
> - * @writeable: Is the chip writeable
>   * @locked: Is SPI setting locked
>   * @swseq_reg: Use SW sequencer in register reads/writes
>   * @swseq_erase: Use SW sequencer in erase operation
> @@ -149,7 +148,6 @@ struct intel_spi {
>         void __iomem *sregs;
>         size_t nregions;
>         size_t pr_num;
> -       bool writeable;
>         bool locked;
>         bool swseq_reg;
>         bool swseq_erase;
> @@ -304,6 +302,14 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
>                                   INTEL_SPI_TIMEOUT * 1000);
>  }
>
> +static bool intel_spi_set_writeable(struct intel_spi *ispi)
> +{
> +       if (!ispi->info->set_writeable)
> +               return false;
> +
> +       return ispi->info->set_writeable(ispi->base, ispi->info->data);
> +}
> +
>  static int intel_spi_init(struct intel_spi *ispi)
>  {
>         u32 opmenu0, opmenu1, lvscc, uvscc, val;
> @@ -316,19 +322,6 @@ static int intel_spi_init(struct intel_spi *ispi)
>                 ispi->nregions = BYT_FREG_NUM;
>                 ispi->pr_num = BYT_PR_NUM;
>                 ispi->swseq_reg = true;
> -
> -               if (writeable) {
> -                       /* Disable write protection */
> -                       val = readl(ispi->base + BYT_BCR);
> -                       if (!(val & BYT_BCR_WPD)) {
> -                               val |= BYT_BCR_WPD;
> -                               writel(val, ispi->base + BYT_BCR);
> -                               val = readl(ispi->base + BYT_BCR);
> -                       }
> -
> -                       ispi->writeable = !!(val & BYT_BCR_WPD);
> -               }
> -
>                 break;
>
>         case INTEL_SPI_LPT:
> @@ -358,6 +351,12 @@ static int intel_spi_init(struct intel_spi *ispi)
>                 return -EINVAL;
>         }
>
> +       /* Try to disable write protection if user asked to do so */
> +       if (writeable && !intel_spi_set_writeable(ispi)) {
> +               dev_warn(ispi->dev, "can't disable chip write protection\n");
> +               writeable = false;
> +       }
> +
>         /* Disable #SMI generation from HW sequencer */
>         val = readl(ispi->base + HSFSTS_CTL);
>         val &= ~HSFSTS_CTL_FSMIE;
> @@ -884,9 +883,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
>                 /*
>                  * If any of the regions have protection bits set, make the
>                  * whole partition read-only to be on the safe side.
> +                *
> +                * Also if the user did not ask the chip to be writeable
> +                * mask the bit too.
>                  */
> -               if (intel_spi_is_protected(ispi, base, limit))
> -                       ispi->writeable = false;
> +               if (!writeable || intel_spi_is_protected(ispi, base, limit))
> +                       part->mask_flags |= MTD_WRITEABLE;
>
>                 end = (limit << 12) + 4096;
>                 if (end > part->size)
> @@ -927,7 +929,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
>
>         ispi->dev = dev;
>         ispi->info = info;
> -       ispi->writeable = info->writeable;
>
>         ret = intel_spi_init(ispi);
>         if (ret)
> @@ -945,10 +946,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
>
>         intel_spi_fill_partition(ispi, &part);
>
> -       /* Prevent writes if not explicitly enabled */
> -       if (!ispi->writeable || !writeable)
> -               ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
> -
>         ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
>         if (ret)
>                 return ERR_PTR(ret);
> diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/intel-spi.h
> index 7f53a5c6f35e..7dda3f690465 100644
> --- a/include/linux/platform_data/x86/intel-spi.h
> +++ b/include/linux/platform_data/x86/intel-spi.h
> @@ -19,11 +19,13 @@ enum intel_spi_type {
>  /**
>   * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
>   * @type: Type which this controller is compatible with
> - * @writeable: The chip is writeable
> + * @set_writeable: Try to make the chip writeable (optional)
> + * @data: Data to be passed to @set_writeable can be %NULL
>   */
>  struct intel_spi_boardinfo {
>         enum intel_spi_type type;
> -       bool writeable;
> +       bool (*set_writeable)(void __iomem *base, void *data);
> +       void *data;
>  };
>
>  #endif /* INTEL_SPI_PDATA_H */
> --
> 2.33.0
>
Question for maintainers: With these changes is it safe to remove the
*(DANGEROUS)* tag from menuconfig?
Thanks, Mauro.


From michael at walle.cc  Sat Oct  2 05:58:26 2021
From: michael at walle.cc (Michael Walle)
Date: Sat, 02 Oct 2021 14:58:26 +0200
Subject: [PATCH v2 09/35] mtd: spi-nor: atmel: Use flash late_init() for
 locking
In-Reply-To: <88abe817-9d2f-35f6-746c-1640b166aab8@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-10-tudor.ambarus@microchip.com>
 <20210816190629.3kg4cbf5d7h7gyk5@ti.com>
 <a9d41aa96a8749b599d4479f18479c5d@walle.cc>
 <88abe817-9d2f-35f6-746c-1640b166aab8@microchip.com>
Message-ID: <0fdfe86c904a064ab61cde6eb177555a@walle.cc>

Am 2021-10-01 13:40, schrieb Tudor.Ambarus at microchip.com:
> On 9/10/21 12:44 AM, Michael Walle wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> Am 2021-08-16 21:06, schrieb Pratyush Yadav:
>>> On 27/07/21 07:51AM, Tudor Ambarus wrote:
>>>> Locking is not described in JESD216 SFDP standard, place the locking
>>>> init in late_init().
>> 
>> Btw, we should differentiate between the block protection
>> bits and individual block locking. At least the latter is described
>> in the SFDP (I've seen it in the XTX SFDP, haven't checked the
>> standard yet).
> 
> that's probably a vendor specific table, not something standardized by 
> SFDP.

correct.

>>> You are chaning the order of setting the locking ops here. Earlier,
>>> they
>>> were set before we parsed SFDP. Now they are set after we parse SFDP.
>>> Though I don't see it making much of a difference.
> 
> Right, as the locking is not covered by SFDP, we should place it after
> parsing SFDP.
> 
>>> 
>>>> 
>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>>>> ---
>>>> ?drivers/mtd/spi-nor/atmel.c | 30 +++++++++++-------------------
>>>> ?1 file changed, 11 insertions(+), 19 deletions(-)
>>>> 
>>>> diff --git a/drivers/mtd/spi-nor/atmel.c 
>>>> b/drivers/mtd/spi-nor/atmel.c
>>>> index 1fea5cab492c..b937ef734e55 100644
>>>> --- a/drivers/mtd/spi-nor/atmel.c
>>>> +++ b/drivers/mtd/spi-nor/atmel.c
>>>> @@ -48,15 +48,11 @@ static const struct spi_nor_locking_ops
>>>> atmel_at25fs_locking_ops = {
>>>> ???? .is_locked = atmel_at25fs_is_locked,
>>>> ?};
>>>> 
>>>> -static void atmel_at25fs_default_init(struct spi_nor *nor)
>>>> +static void atmel_at25fs_late_init(struct spi_nor *nor)
>>>> ?{
>>>> ???? nor->params->locking_ops = &atmel_at25fs_locking_ops;
>>>> ?}
>>>> 
>>>> -static const struct spi_nor_fixups atmel_at25fs_fixups = {
>>>> -??? .default_init = atmel_at25fs_default_init,
>>>> -};
>>>> -
>>>> ?/**
>>>> ? * atmel_set_global_protection - Do a Global Protect or Unprotect
>>>> command
>>>> ? * @nor:??? pointer to 'struct spi_nor'
>>>> @@ -146,34 +142,30 @@ static const struct spi_nor_locking_ops
>>>> atmel_global_protection_ops = {
>>>> ???? .is_locked = atmel_is_global_protected,
>>>> ?};
>>>> 
>>>> -static void atmel_global_protection_default_init(struct spi_nor 
>>>> *nor)
>>>> +static void atmel_global_protection_late_init(struct spi_nor *nor)
>>>> ?{
>>>> ???? nor->params->locking_ops = &atmel_global_protection_ops;
>>>> ?}
>>>> 
>>>> -static const struct spi_nor_fixups atmel_global_protection_fixups = 
>>>> {
>>>> -??? .default_init = atmel_global_protection_default_init,
>>>> -};
>>>> -
>>>> ?static const struct flash_info atmel_parts[] = {
>>>> ???? /* Atmel -- some are (confusingly) marketed as "DataFlash" */
>>>> ???? { "at25fs010",? INFO(0x1f6601, 0, 32 * 1024,?? 4, SECT_4K |
>>>> SPI_NOR_HAS_LOCK)
>>>> -??????????? .fixups = &atmel_at25fs_fixups },
>>>> +??????????? .late_init = atmel_at25fs_late_init },
>>>> ???? { "at25fs040",? INFO(0x1f6604, 0, 64 * 1024,?? 8, SECT_4K |
>>>> SPI_NOR_HAS_LOCK)
>>>> -??????????? .fixups = &atmel_at25fs_fixups },
>>>> +??????????? .late_init = atmel_at25fs_late_init },
>>>> 
>>>> ???? { "at25df041a", INFO(0x1f4401, 0, 64 * 1024,?? 8,
>>>> ????????????????????????? SECT_4K | SPI_NOR_HAS_LOCK | 
>>>> SPI_NOR_SWP_IS_VOLATILE)
>>>> -??????????????????? .fixups = &atmel_global_protection_fixups },
>>>> +??????????? .late_init = atmel_global_protection_late_init },
>>> 
>>> Won't you be better off setting this in the manufacturer late_init()?
>>> It
>>> seems common for most atmel flashes.
>>> 
>>> Of course, this would cause a problem for atmel flashes that don't 
>>> have
>>> this at all, since we would set locking for those as well. But I 
>>> think
>>> we can avoid that by checking for SNOR_F_HAS_LOCK in
>>> spi_nor_register_locking_ops().
>> 
>> +1
>> 
> 
> we also have the atmel_at25fs_late_init() method. setting it per
> manufacturer will result
> in setting the manufacturer locking ops for at25fs as well, which will
> be overwritten by the
> at25fs locking ops. For those that don't support locking at all, we
> should clear the locking
> ops as you said. This will make the code a little difficult to follow
> and we return a bit
> to spaghetti. defining late_init() takes only a line anyway. I would
> keep the code as it is
> if you don't mind. We can ask ourselves about scalability when we have
> lots of entries,
> we can reevaluate this in the future. Tell me if you have strong
> opinions on this.

What about the following:

int atmel_late_init(struct spi_nor *nor)
{
     if (nor->info->flags & SPI_NOR_HAS_LOCK)
         nor->params->locking_ops = &atmel_global_protection_ops;
}

Of course it depends on wether we expect these ops to be the ones
used for most atmel flashes.

The at25fs would then overwrite the ops in their .late_init.

In any case, I don't have a strong opinion either way.

-michael


From michael at walle.cc  Sat Oct  2 06:14:07 2021
From: michael at walle.cc (Michael Walle)
Date: Sat, 02 Oct 2021 15:14:07 +0200
Subject: [PATCH v2 14/35] mtd: spi-nor: spansion: Use manufacturer
 late_init()
In-Reply-To: <d5f6181f-850c-122f-ebd3-57ac6c3eb1c6@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-15-tudor.ambarus@microchip.com>
 <ebfc420928ef28bb508148b41f55b0e6@walle.cc>
 <d5f6181f-850c-122f-ebd3-57ac6c3eb1c6@microchip.com>
Message-ID: <dd418648f206faa64f10dd1c81caae31@walle.cc>

Am 2021-10-01 14:14, schrieb Tudor.Ambarus at microchip.com:
> On 9/10/21 1:02 AM, Michael Walle wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>>> spansion_post_sfdp_fixups() was called regardless if the flash 
>>> defined
>>> SFDP tables or not. A better place for this kind of parameters init 
>>> is
>>> in manufacturer's late_init() hook. post_sfdp() should be called only
>>> when SFDP is defined. No functional change in this patch.
>>> 
>>> Instead of doing the 4b opcodes settings at manufacturer level, thus
>>> also for every flash that will be introduced, this should be done
>>> just where it is needed, per flash. I'll let this for other patch.
>> 
>> Mh, then why does some flashes define SPI_NOR_4B_OPCODES. It's
>> unclear to me when you would use SPI_NOR_4B_OPCODES and when
> 
> check patch 18/35, I dropped the SPI_NOR_4B_OPCODES flash_info entry 
> flag.

I wasn't that far down the patch series when I reviewed this patch. Ok.

> 4b-opcodes support is SFDP discoverable. Where flashes define the 4bait 
> table,
> they will fill the support by setting SPI NOR SNOR_F_4B_OPCODES flag. 
> Where the
> 4bait table is not defined, SNOR_F_4B_OPCODES should be set in a
> late_init() hook.
> 
>> this individual fixup. Also right now, these SPI_NOR_4B_OPCODES
>> flags for the spansion flashes are superfluous, no?
>> 
> 
> there's no spansion flash_info entry that explicitly declare 
> SPI_NOR_4B_OPCODES,
> if that's what you meant.

after patch 18/35, yes ;)

Reviewed-by: Michael Walle <michael at walle.cc>


From schaecsn at gmx.net  Sat Oct  2 14:12:34 2021
From: schaecsn at gmx.net (Stefan Schaeckeler)
Date: Sat,  2 Oct 2021 14:12:34 -0700 (PDT)
Subject: [PATCH 0/1] ubifs: ubifs to export filesystem error counters
In-Reply-To: <160773399.91203.1632175069460.JavaMail.zimbra@nod.at> (message
 from Richard Weinberger on Mon, 20 Sep 2021 23:57:49 +0200 (CEST))
References: <20210907214034.11676-1-schaecsn@gmx.net>
 <20210920024824.9E053899858@corona.crabdance.com>
 <160773399.91203.1632175069460.JavaMail.zimbra@nod.at>
Message-ID: <20211002211234.C8546899763@corona.crabdance.com>

Hello Richard,

> > Hello mtd/ubifs,
> >
> > I just want to check back on what you think about having a sysfs for ubifs and
> > starting with these three callbacks
> >
> > /sys/fs/ubifs/ubiX_Y/errors_magic
> > /sys/fs/ubifs/ubiX_Y/errors_node
> > /sys/fs/ubifs/ubiX_Y/errors_crc
>
> I didn't have a chance to review your changes to far but in general I like the idea
> if exposing such an interface.
> Sorry for being a slow maintainer.

I just wonder if you still like the idea of a sysfs for ubifs. At one point we
should then move forward.

 Stefan


From richard at nod.at  Sun Oct  3 12:58:25 2021
From: richard at nod.at (Richard Weinberger)
Date: Sun, 3 Oct 2021 21:58:25 +0200 (CEST)
Subject: [PATCH 1/1] ubifs: ubifs to export filesystem error counters
In-Reply-To: <20210907214034.11676-2-schaecsn@gmx.net>
References: <20210907214034.11676-1-schaecsn@gmx.net>
 <20210907214034.11676-2-schaecsn@gmx.net>
Message-ID: <1815586081.32955.1633291105033.JavaMail.zimbra@nod.at>

Stefan,

----- Urspr?ngliche Mail -----
> Von: "schaecsn" <schaecsn at gmx.net>
> An: "richard" <richard at nod.at>, "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel"
> <linux-kernel at vger.kernel.org>
> CC: "schaecsn" <schaecsn at gmx.net>, "Stefan Schaeckeler" <sschaeck at cisco.com>
> Gesendet: Dienstag, 7. September 2021 23:40:34
> Betreff: [PATCH 1/1] ubifs: ubifs to export filesystem error counters

> Not all ubifs filesystem errors are propagated to userspace.
> 
> Export bad magic, bad node and crc errors via sysfs. This allows userspace
> to notice filesystem errors:
> 
> /sys/fs/ubifs/ubiX_Y/errors_magic
> /sys/fs/ubifs/ubiX_Y/errors_node
> /sys/fs/ubifs/ubiX_Y/errors_crc
> 
> The counters are reset to 0 with a remount. Writing anything into the
> counters also clears them.

I think this is a nice feature. Thanks for implementing it.
Please see some minor nits below.

Is there a specific reason why you didn't implement it via UBIFS's debugfs interface?
sysfs is ABI, so we cannot change much anymore.

> Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
> ---
> fs/ubifs/Makefile |   2 +-
> fs/ubifs/io.c     |   6 ++
> fs/ubifs/super.c  |  17 ++++-
> fs/ubifs/sysfs.c  | 187 ++++++++++++++++++++++++++++++++++++++++++++++
> fs/ubifs/sysfs.h  |  39 ++++++++++
> fs/ubifs/ubifs.h  |  11 +++
> 6 files changed, 260 insertions(+), 2 deletions(-)
> create mode 100644 fs/ubifs/sysfs.c
> create mode 100644 fs/ubifs/sysfs.h
> 
> diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
> index 5c4b845754a7..314c80b24a76 100644
> --- a/fs/ubifs/Makefile
> +++ b/fs/ubifs/Makefile
> @@ -5,7 +5,7 @@ ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
> ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
> ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
> ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
> -ubifs-y += misc.o
> +ubifs-y += misc.o sysfs.o
> ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
> ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
> ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
> diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
> index 00b61dba62b7..0b158e420cc1 100644
> --- a/fs/ubifs/io.c
> +++ b/fs/ubifs/io.c
> @@ -238,6 +238,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void
> *buf, int len,
> 		if (!quiet)
> 			ubifs_err(c, "bad magic %#08x, expected %#08x",
> 				  magic, UBIFS_NODE_MAGIC);
> +		if (c->stats)
> +			c->stats->magic_errors++;

Please wrap this into a helper function.

> 		err = -EUCLEAN;
> 		goto out;
> 	}
> @@ -246,6 +248,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void
> *buf, int len,
> 	if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
> 		if (!quiet)
> 			ubifs_err(c, "bad node type %d", type);
> +		if (c->stats)
> +			c->stats->node_errors++;

Same.

> 		goto out;
> 	}
> 
> @@ -270,6 +274,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void
> *buf, int len,
> 		if (!quiet)
> 			ubifs_err(c, "bad CRC: calculated %#08x, read %#08x",
> 				  crc, node_crc);
> +		if (c->stats)
> +			c->stats->crc_errors++;

Same.

> 		err = -EUCLEAN;
> 		goto out;
> 	}
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index f0fb25727d96..50b934854a84 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -24,6 +24,7 @@
> #include <linux/mount.h>
> #include <linux/math64.h>
> #include <linux/writeback.h>
> +#include "sysfs.h"
> #include "ubifs.h"
> 
> static int ubifs_default_version_set(const char *val, const struct kernel_param
> *kp)
> @@ -1264,6 +1265,10 @@ static int mount_ubifs(struct ubifs_info *c)
> 	if (err)
> 		return err;
> 
> +	err = ubifs_sysfs_register(c);
> +	if (err)
> +		goto out_debugging;
> +
> 	err = check_volume_empty(c);
> 	if (err)
> 		goto out_free;
> @@ -1641,6 +1646,8 @@ static int mount_ubifs(struct ubifs_info *c)
> 	vfree(c->sbuf);
> 	kfree(c->bottom_up_buf);
> 	kfree(c->sup_node);
> +	ubifs_sysfs_unregister(c);
> +out_debugging:
> 	ubifs_debugging_exit(c);
> 	return err;
> }
> @@ -1684,6 +1691,7 @@ static void ubifs_umount(struct ubifs_info *c)
> 	kfree(c->bottom_up_buf);
> 	kfree(c->sup_node);
> 	ubifs_debugging_exit(c);
> +	ubifs_sysfs_unregister(c);
> }
> 
> /**
> @@ -2436,14 +2444,20 @@ static int __init ubifs_init(void)
> 
> 	dbg_debugfs_init();
> 
> +	err = ubifs_sysfs_init();
> +	if (err)
> +		goto out_dbg;
> +
> 	err = register_filesystem(&ubifs_fs_type);
> 	if (err) {
> 		pr_err("UBIFS error (pid %d): cannot register file system, error %d",
> 		       current->pid, err);
> -		goto out_dbg;
> +		goto out_sysfs;
> 	}
> 	return 0;
> 
> +out_sysfs:
> +	ubifs_sysfs_exit();
> out_dbg:
> 	dbg_debugfs_exit();
> 	ubifs_compressors_exit();
> @@ -2462,6 +2476,7 @@ static void __exit ubifs_exit(void)
> 	WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) != 0);
> 
> 	dbg_debugfs_exit();
> +	ubifs_sysfs_exit();
> 	ubifs_compressors_exit();
> 	unregister_shrinker(&ubifs_shrinker_info);
> 
> diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
> new file mode 100644
> index 000000000000..bac53a0f0451
> --- /dev/null
> +++ b/fs/ubifs/sysfs.c
> @@ -0,0 +1,187 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * This file is part of UBIFS.
> + *
> + * Copyright (C) 2021 Cisco Systems
> + *
> + * Author: Stefan Schaeckeler
> + */
> +
> +
> +#include <linux/fs.h>
> +
> +#include "sysfs.h"
> +#include "ubifs.h"
> +
> +
> +enum attr_id_t {
> +	attr_errors_magic,
> +	attr_errors_node,
> +	attr_errors_crc,
> +};
> +
> +struct ubifs_attr {
> +	struct attribute attr;
> +	enum attr_id_t attr_id;
> +};
> +
> +#define UBIFS_ATTR(_name, _mode, _id)					\
> +static struct ubifs_attr ubifs_attr_##_name = {				\
> +	.attr = {.name = __stringify(_name), .mode = _mode },		\
> +	.attr_id = attr_##_id,						\
> +}
> +
> +#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
> +
> +UBIFS_ATTR_FUNC(errors_magic, 0644);
> +UBIFS_ATTR_FUNC(errors_crc, 0644);
> +UBIFS_ATTR_FUNC(errors_node, 0644);

I'm not sure whether everyone should be allowed to read these stats.
dmesg is also restricted these days. An unprivileged user should not see the
errors he can indirectly trigger.

> +#define ATTR_LIST(name) (&ubifs_attr_##name.attr)
> +
> +static struct attribute *ubifs_attrs[] = {
> +	ATTR_LIST(errors_magic),
> +	ATTR_LIST(errors_node),
> +	ATTR_LIST(errors_crc),
> +	NULL,
> +};
> +
> +
> +static ssize_t ubifs_attr_show(struct kobject *kobj,
> +			       struct attribute *attr, char *buf)
> +{
> +	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
> +					      kobj);
> +
> +	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
> +
> +	switch (a->attr_id) {
> +	case attr_errors_magic:
> +		return snprintf(buf, PAGE_SIZE, "%u\n",
> +				sbi->stats->magic_errors);
> +	case attr_errors_node:
> +		return snprintf(buf, PAGE_SIZE, "%u\n",
> +				sbi->stats->node_errors);
> +	case attr_errors_crc:
> +		return snprintf(buf, PAGE_SIZE, "%u\n",
> +				sbi->stats->crc_errors);

Please use sysfs_emit().

> +	}
> +	return 0;
> +};
> +
> +
> +static ssize_t ubifs_attr_store(struct kobject *kobj,
> +			       struct attribute *attr,
> +			       const char *buf, size_t len)
> +{
> +	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
> +					      kobj);
> +
> +	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
> +
> +	switch (a->attr_id) {
> +	case attr_errors_magic:
> +		sbi->stats->magic_errors = 0;
> +		break;
> +	case attr_errors_node:
> +		sbi->stats->node_errors = 0;
> +		break;
> +	case attr_errors_crc:
> +		sbi->stats->crc_errors = 0;
> +		break;
> +	}
> +	return len;
> +}
> +
> +
> +static void ubifs_sb_release(struct kobject *kobj)
> +{
> +	struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
> +
> +	complete(&c->kobj_unregister);
> +}
> +
> +
> +static const struct sysfs_ops ubifs_attr_ops = {
> +	.show	= ubifs_attr_show,
> +	.store	= ubifs_attr_store,
> +};
> +
> +static struct kobj_type ubifs_sb_ktype = {
> +	.default_attrs	= ubifs_attrs,
> +	.sysfs_ops	= &ubifs_attr_ops,
> +	.release	= ubifs_sb_release,
> +};
> +
> +static struct kobj_type ubifs_ktype = {
> +	.sysfs_ops	= &ubifs_attr_ops,
> +};
> +
> +static struct kset ubifs_kset = {
> +	.kobj	= {.ktype = &ubifs_ktype},
> +};
> +
> +
> +int ubifs_sysfs_register(struct ubifs_info *c)
> +{
> +	int ret, n;
> +	char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];
> +
> +	c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
> +	if (!c->stats) {
> +		ret = -ENOMEM;
> +		goto out_last;
> +	}
> +	n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
> +		     c->vi.ubi_num, c->vi.vol_id);
> +
> +	if (n == UBIFS_DFS_DIR_LEN) {
> +		/* The array size is too small */
> +		ret = -EINVAL;
> +		goto out_last;

Where is c->stats released in case of an error?

> +	}
> +
> +	c->kobj.kset = &ubifs_kset;
> +	init_completion(&c->kobj_unregister);
> +
> +
> +	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
> +				   "%s", dfs_dir_name);
> +	if (ret)
> +		goto out_put;
> +
> +	return 0;
> +
> +out_put:
> +	kobject_put(&c->kobj);
> +	wait_for_completion(&c->kobj_unregister);
> +out_last:
> +	ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
> +		  c->vi.ubi_num, c->vi.vol_id, ret);
> +	return ret;
> +}
> +
> +void ubifs_sysfs_unregister(struct ubifs_info *c)
> +{
> +	kobject_del(&c->kobj);
> +	kobject_put(&c->kobj);
> +	wait_for_completion(&c->kobj_unregister);
> +
> +	kfree(c->stats);
> +}
> +
> +int __init ubifs_sysfs_init(void)
> +{
> +	int ret;
> +
> +	kobject_set_name(&ubifs_kset.kobj, "ubifs");
> +	ubifs_kset.kobj.parent = fs_kobj;
> +	ret = kset_register(&ubifs_kset);
> +
> +	return ret;
> +}
> +
> +void ubifs_sysfs_exit(void)
> +{
> +	kset_unregister(&ubifs_kset);
> +}
> diff --git a/fs/ubifs/sysfs.h b/fs/ubifs/sysfs.h
> new file mode 100644
> index 000000000000..a10a82585af8
> --- /dev/null
> +++ b/fs/ubifs/sysfs.h

Do we really need a new header file?
Usually most run-time stuff of UBIFS is part of ubifs.h.

> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * This file is part of UBIFS.
> + *
> + * Copyright (C) 2021 Cisco Systems
> + *
> + * Author: Stefan Schaeckeler
> + */
> +
> +#ifndef __UBIFS_SYSFS_H__
> +#define __UBIFS_SYSFS_H__
> +
> +struct ubifs_info;
> +
> +/*
> + * The UBIFS sysfs directory name pattern and maximum name length (3 for "ubi"
> + * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
> + */
> +#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
> +#define UBIFS_DFS_DIR_LEN  (3 + 1 + 2*2 + 1)
> +
> +/**
> + * ubifs_stats_info - per-FS statistics information.
> + * @magic_errors: number of bad magic numbers (will be reset with a new mount).
> + * @node_errors: number of bad nodes (will be reset with a new mount).
> + * @crc_errors: number of bad crcs (will be reset with a new mount).
> + */
> +struct ubifs_stats_info {
> +	unsigned int magic_errors;
> +	unsigned int node_errors;
> +	unsigned int crc_errors;
> +};
> +
> +int ubifs_sysfs_init(void);
> +void ubifs_sysfs_exit(void);
> +int ubifs_sysfs_register(struct ubifs_info *c);
> +void ubifs_sysfs_unregister(struct ubifs_info *c);
> +
> +#endif
> diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
> index c38066ce9ab0..bfc0f20b41a1 100644
> --- a/fs/ubifs/ubifs.h
> +++ b/fs/ubifs/ubifs.h
> @@ -27,12 +27,15 @@
> #include <linux/security.h>
> #include <linux/xattr.h>
> #include <linux/random.h>
> +#include <linux/sysfs.h>
> +#include <linux/completion.h>
> #include <crypto/hash_info.h>
> #include <crypto/hash.h>
> #include <crypto/algapi.h>
> 
> #include <linux/fscrypt.h>
> 
> +#include "sysfs.h"
> #include "ubifs-media.h"
> 
> /* Version of this UBIFS implementation */
> @@ -1251,6 +1254,10 @@ struct ubifs_debug_info;
>  * @mount_opts: UBIFS-specific mount options
>  *
>  * @dbg: debugging-related information
> + * @stats: statistics exported over sysfs
> + *
> + * @kobj: kobject for /sys/fs/ubifs/
> + * @kobj_unregister: completion to unregister sysfs kobject
>  */
> struct ubifs_info {
> 	struct super_block *vfs_sb;
> @@ -1286,6 +1293,9 @@ struct ubifs_info {
> 	spinlock_t cs_lock;
> 	wait_queue_head_t cmt_wq;
> 
> +	struct kobject kobj;
> +	struct completion kobj_unregister;
> +
> 	unsigned int big_lpt:1;
> 	unsigned int space_fixup:1;
> 	unsigned int double_hash:1;
> @@ -1493,6 +1503,7 @@ struct ubifs_info {
> 	struct ubifs_mount_opts mount_opts;
> 
> 	struct ubifs_debug_info *dbg;
> +	struct ubifs_stats_info *stats;
> };
> 
> extern struct list_head ubifs_infos;
> --
> 2.32.0


From Tudor.Ambarus at microchip.com  Sun Oct  3 20:18:04 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 03:18:04 +0000
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <20210817121626.5vcwuluheqfqrqc3@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
Message-ID: <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>

On 8/17/21 3:16 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> Get rid of flash_info flags that indicate settings which can be
>> discovered when parsing SFDP. It will be clearer who sets what,
>> and we'll restrict the flash settings that a developer can choose to
>> only settings that are not SFDP discoverable.
>>
>> Whether a flash supports 4byte opcodes or not, is discoverable when
>> parsing the optional 4-byte address instruction table. Flashes that
>> do not support the 4bait SFDP table should set the SNOR_F_4B_OPCODES
>> flag in the late_init() call. Flashes that define the 4bait SFDP table
>> but gets it wrong, should set the flag in a post_sfdp fixup hook.
> 
> I like the idea, not so much the execution. More on this below.
> 
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c       |  3 ---
>>  drivers/mtd/spi-nor/core.h       | 32 ++++++++++++++++----------------
>>  drivers/mtd/spi-nor/gigadevice.c |  7 ++++---
>>  drivers/mtd/spi-nor/issi.c       | 12 ++++++------
>>  drivers/mtd/spi-nor/macronix.c   | 18 ++++++++++--------
>>  drivers/mtd/spi-nor/micron-st.c  | 22 +++++++++++++---------
>>  drivers/mtd/spi-nor/spansion.c   | 12 ++++++------
>>  7 files changed, 55 insertions(+), 51 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 6a8617346764..240d5c31af88 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -3204,9 +3204,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>>       if (ret)
>>               return ret;
>>
>> -     if (info->flags & SPI_NOR_4B_OPCODES)
>> -             nor->flags |= SNOR_F_4B_OPCODES;
>> -
>>       if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
>>               nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
>>
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index 625f4eed75f1..dfdc51a26cad 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -348,40 +348,36 @@ struct flash_info {
>>                                        * S3AN flashes have specific opcode to
>>                                        * read the status register.
>>                                        */
>> -#define SPI_NOR_4B_OPCODES   BIT(11) /*
>> -                                      * Use dedicated 4byte address op codes
>> -                                      * to support memory size above 128Mib.
>> -                                      */
>> -#define NO_CHIP_ERASE                BIT(12) /* Chip does not support chip erase */
>> -#define SPI_NOR_SKIP_SFDP    BIT(13) /* Skip parsing of SFDP tables */
>> -#define USE_CLSR             BIT(14) /* use CLSR command */
>> -#define SPI_NOR_OCTAL_READ   BIT(15) /* Flash supports Octal Read */
>> -#define SPI_NOR_TB_SR_BIT6   BIT(16) /*
>> +#define NO_CHIP_ERASE                BIT(11) /* Chip does not support chip erase */
>> +#define SPI_NOR_SKIP_SFDP    BIT(12) /* Skip parsing of SFDP tables */
>> +#define USE_CLSR             BIT(13) /* use CLSR command */
>> +#define SPI_NOR_OCTAL_READ   BIT(14) /* Flash supports Octal Read */
>> +#define SPI_NOR_TB_SR_BIT6   BIT(15) /*
>>                                        * Top/Bottom (TB) is bit 6 of
>>                                        * status register. Must be used with
>>                                        * SPI_NOR_HAS_TB.
>>                                        */
>> -#define SPI_NOR_4BIT_BP              BIT(17) /*
>> +#define SPI_NOR_4BIT_BP              BIT(16) /*
>>                                        * Flash SR has 4 bit fields (BP0-3)
>>                                        * for block protection.
>>                                        */
>> -#define SPI_NOR_BP3_SR_BIT6  BIT(18) /*
>> +#define SPI_NOR_BP3_SR_BIT6  BIT(17) /*
>>                                        * BP3 is bit 6 of status register.
>>                                        * Must be used with SPI_NOR_4BIT_BP.
>>                                        */
>> -#define SPI_NOR_OCTAL_DTR_READ       BIT(19) /* Flash supports octal DTR Read. */
>> -#define SPI_NOR_OCTAL_DTR_PP BIT(20) /* Flash supports Octal DTR Page Program */
>> -#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(21) /*
>> +#define SPI_NOR_OCTAL_DTR_READ       BIT(18) /* Flash supports octal DTR Read. */
>> +#define SPI_NOR_OCTAL_DTR_PP BIT(19) /* Flash supports Octal DTR Page Program */
>> +#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(20) /*
>>                                                * Flash enables the best
>>                                                * available I/O mode via a
>>                                                * volatile bit.
>>                                                */
>> -#define SPI_NOR_SWP_IS_VOLATILE      BIT(22) /*
>> +#define SPI_NOR_SWP_IS_VOLATILE      BIT(21) /*
>>                                        * Flash has volatile software write
>>                                        * protection bits. Usually these will
>>                                        * power-up in a write-protected state.
>>                                        */
>> -#define SPI_NOR_PARSE_SFDP   BIT(23) /*
>> +#define SPI_NOR_PARSE_SFDP   BIT(22) /*
>>                                        * Flash initialized based on the SFDP
>>                                        * tables.
>>                                        */
>> @@ -569,4 +565,8 @@ static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
>>       return mtd->priv;
>>  }
>>
>> +static inline void snor_f_4b_opcodes(struct spi_nor *nor)
> 
> Maybe snor_set_f_4b_opcodes()?

snor_f comes from SPI NOR Flags I guess, so probably snor_f_set_4b_opcodes if we're
going this path.

> 
>> +{
>> +     nor->flags |= SNOR_F_4B_OPCODES;
>> +}
>>  #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
>> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
>> index 447d84bb2128..ff523fe734ef 100644
>> --- a/drivers/mtd/spi-nor/gigadevice.c
>> +++ b/drivers/mtd/spi-nor/gigadevice.c
>> @@ -47,9 +47,10 @@ static const struct flash_info gigadevice_parts[] = {
>>                          SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
>>       { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
>>                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                        SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK |
>> -                        SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
>> -             .fixups = &gd25q256_fixups },
>> +                        SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
>> +                        SPI_NOR_TB_SR_BIT6)
>> +             .fixups = &gd25q256_fixups,
>> +             .late_init = snor_f_4b_opcodes, },
>>  };
>>
>>  const struct spi_nor_manufacturer spi_nor_gigadevice = {
>> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
>> index 1e5bb5408b68..aeff8f60cbae 100644
>> --- a/drivers/mtd/spi-nor/issi.c
>> +++ b/drivers/mtd/spi-nor/issi.c
>> @@ -45,9 +45,9 @@ static const struct flash_info issi_parts[] = {
>>       { "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
>>                            SECT_4K | SPI_NOR_DUAL_READ) },
>>       { "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
>> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                          SPI_NOR_4B_OPCODES)
>> -             .fixups = &is25lp256_fixups },
>> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .fixups = &is25lp256_fixups,
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
>>                            SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>>       { "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
>> @@ -55,9 +55,9 @@ static const struct flash_info issi_parts[] = {
>>       { "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
>>                            SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>>       { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
>> -                         SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                         SPI_NOR_4B_OPCODES)
>> -             .fixups = &is25lp256_fixups },
>> +                         SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .fixups = &is25lp256_fixups,
>> +             .late_init = snor_f_4b_opcodes, },
>>
>>       /* PMC */
>>       { "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
>> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
>> index fba85efafb47..9709eb68b613 100644
>> --- a/drivers/mtd/spi-nor/macronix.c
>> +++ b/drivers/mtd/spi-nor/macronix.c
>> @@ -105,29 +105,31 @@ static const struct flash_info macronix_parts[] = {
>>       { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
>>                             SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>>               .fixups = &mx25l25635_fixups },
>> -     { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
>> -                           SECT_4K | SPI_NOR_4B_OPCODES) },
>> +     { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024,
>>                             SECT_4K | SPI_NOR_DUAL_READ |
>> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                           SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
>>                             SECT_4K | SPI_NOR_DUAL_READ |
>>                             SPI_NOR_QUAD_READ) },
>>       { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
>>       { "mx66l51235f", INFO(0xc2201a, 0, 64 * 1024, 1024,
>> -                           SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                           SPI_NOR_4B_OPCODES) },
>> +                           SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
>>                             SECT_4K | SPI_NOR_DUAL_READ |
>> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                           SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048,
>>                             SECT_4K | SPI_NOR_DUAL_READ |
>>                             SPI_NOR_QUAD_READ) },
>>       { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
>>                             SPI_NOR_QUAD_READ) },
>>       { "mx66u2g45g",  INFO(0xc2253c, 0, 64 * 1024, 4096,
>> -                           SECT_4K | SPI_NOR_DUAL_READ |
>> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                           SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>  };
>>
>>  static void macronix_default_init(struct spi_nor *nor)
>> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
>> index c224e59820a1..72cc4673bf88 100644
>> --- a/drivers/mtd/spi-nor/micron-st.c
>> +++ b/drivers/mtd/spi-nor/micron-st.c
>> @@ -121,13 +121,13 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
>>  static const struct flash_info micron_parts[] = {
>>       { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
>>                              SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
>> -                            SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ |
>> -                            SPI_NOR_OCTAL_DTR_PP |
>> +                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP |
>>                              SPI_NOR_IO_MODE_EN_VOLATILE)
>> -       .fixups = &mt35xu512aba_fixups},
>> +       .fixups = &mt35xu512aba_fixups,
>> +       .late_init = snor_f_4b_opcodes, },
> 
> This flash populated the 4BAIT table, so you can simply drop the flag.

I'll do this in a dedicated patch, I'll need your tested-by tag.

> No need for the late_init().
> 
> This makes me think that many other flashes might also have the 4BAIT
> table but the developers chose to add this flag here since at that time
> the norm was to populate all flash capabilities. I think we could be
> able to drop many more .late_init like this. But unfortunately someone
> needs to do the hard work of checking each flash, and most flash
> datasheets don't even list the SFDP contents.
> 
> So while I think in the ideal world we would go check each flash, I
> think this is an acceptable compromise. Let's not let perfection be the
> enemy of good.

The patch doesn't change how the code works now. If some flashes can drop
some flags, we can drop them in dedicated patches.

> 
> While we are on this topic, I find this a bit "ugly". Having to set
> late_init() for setting these flags for each flash is not exactly very
> clean or readable. I don't know how the future will look like, but if
> each flash/family needs its own late_init() to set some flags, it won't
> be very readable. We seem to be trading one type of complexity for
> another. I dunno which is the lesser evil though...

Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
the late_init() function to see what's there. As you saw, late_init() can be
used for tweaking flash's parameters, settings and methods, not just NOR flags,
so I would expect that this hook to be present among flashes that don't define
the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
the hook will be there anyway.

This patch opens the door on how we could handle the flash_info flags. All flash_info
flags that can be determined when parsing SFDP can be removed and use for flashes that
skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
1/ flashes with SFDP will set the flags as:
SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
2/ flashes without SFDP:
SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
and a late_init() for SNOR_F equivalents of flash_info flags from
spi_nor_info_init_params()
3/ flashes that collide, one with SFDP and the other without:
SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
and a late_init() for SNOR_F equivalents of flash_info flags from
spi_nor_info_init_params(), that will be used for the flash without SFDP.
4/ individual flash, no collisions, a flavor supports SFDP, the other not:
SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
and a late_init() for SNOR_F equivalents of flash_info flags from
spi_nor_info_init_params(), that will be used for the flash without SFDP.

Let me know what you think or if I missed something.

Cheers,
ta

> 
>>       { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
>> -                         SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
>> -                         SPI_NOR_4B_OPCODES) },
>> +                         SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ)
>> +       .late_init = snor_f_4b_opcodes, },
>>  };
>>
>>  static const struct flash_info st_parts[] = {
>> @@ -149,25 +149,29 @@ static const struct flash_info st_parts[] = {
>>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
>>       { "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
>>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
>> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                            SPI_NOR_QUAD_READ)
>> +       .late_init = snor_f_4b_opcodes, },
>>       { "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
>>                             USE_FSR | SPI_NOR_DUAL_READ |
>>                             SPI_NOR_QUAD_READ) },
>>       { "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
>>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
>> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                            SPI_NOR_QUAD_READ)
>> +       .late_init = snor_f_4b_opcodes, },
>>       { "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512,
>>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
>>       { "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
>>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
>> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                            SPI_NOR_QUAD_READ)
>> +       .late_init = snor_f_4b_opcodes, },
>>       { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024,
>>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
>>                             SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
>>                             SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
>>       { "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
>>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
>> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
>> +                            SPI_NOR_QUAD_READ)
>> +       .late_init = snor_f_4b_opcodes, },
>>       { "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024,
>>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
>>                             SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
>> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
>> index aad7170768b4..af10833f56d8 100644
>> --- a/drivers/mtd/spi-nor/spansion.c
>> +++ b/drivers/mtd/spi-nor/spansion.c
>> @@ -259,14 +259,14 @@ static const struct flash_info spansion_parts[] = {
>>       { "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16,
>>                            SECT_4K | SPI_NOR_DUAL_READ) },
>>       { "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128,
>> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                          SPI_NOR_4B_OPCODES) },
>> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256,
>> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                          SPI_NOR_4B_OPCODES) },
>> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512,
>> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                          SPI_NOR_4B_OPCODES) },
>> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
>> +             .late_init = snor_f_4b_opcodes, },
>>       { "cy15x104q",  INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1,
>>                             SPI_NOR_NO_ERASE) },
>>       { "s28hs512t",   INFO(0x345b1a,      0, 256 * 1024, 256,
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Sun Oct  3 20:52:16 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 03:52:16 +0000
Subject: [PATCH v2 19/35] mtd: spi-nor: Get rid of
 SPI_NOR_IO_MODE_EN_VOLATILE flag
In-Reply-To: <20210817122108.nr2elnkiyatdp2hz@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-20-tudor.ambarus@microchip.com>
 <20210817122108.nr2elnkiyatdp2hz@ti.com>
Message-ID: <490dc958-1033-5807-5a67-8e7f6d064fd7@microchip.com>

On 8/17/21 3:21 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> Get rid of flash_info flags that indicate settings which can be
>> discovered when parsing SFDP. It will be clearer who sets what,
>> and we'll restrict the flash settings that a developer can choose to
>> only settings that are not SFDP discoverable.
>>
>> SNOR_F_IO_MODE_EN_VOLATILE is discoverable when parsing the optional
>> SCCR Map SFDP table. Flashes that do not define this table should set
>> the flag in the late_init() call. Flashes that define the SFDP optional
>> table but get the value wrong, should fix it in a post_sfdp fixup hook.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c      |  3 ---
>>  drivers/mtd/spi-nor/core.h      |  9 ++-------
>>  drivers/mtd/spi-nor/micron-st.c | 11 ++++++++---
>>  3 files changed, 10 insertions(+), 13 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 240d5c31af88..9885d434ea83 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -3204,9 +3204,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>>       if (ret)
>>               return ret;
>>
>> -     if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
>> -             nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
>> -
>>       ret = spi_nor_set_addr_width(nor);
>>       if (ret)
>>               return ret;
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index dfdc51a26cad..987797a789c8 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -367,17 +367,12 @@ struct flash_info {
>>                                        */
>>  #define SPI_NOR_OCTAL_DTR_READ       BIT(18) /* Flash supports octal DTR Read. */
>>  #define SPI_NOR_OCTAL_DTR_PP BIT(19) /* Flash supports Octal DTR Page Program */
>> -#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(20) /*
>> -                                              * Flash enables the best
>> -                                              * available I/O mode via a
>> -                                              * volatile bit.
> 
> We are losing the information contained in the comment. I think you
> should move it to SNOR_F_IO_MODE_EN_VOLATILE's declaration.

ok

> 
>> -                                              */
>> -#define SPI_NOR_SWP_IS_VOLATILE      BIT(21) /*
>> +#define SPI_NOR_SWP_IS_VOLATILE      BIT(20) /*
>>                                        * Flash has volatile software write
>>                                        * protection bits. Usually these will
>>                                        * power-up in a write-protected state.
>>                                        */
>> -#define SPI_NOR_PARSE_SFDP   BIT(22) /*
>> +#define SPI_NOR_PARSE_SFDP   BIT(21) /*
>>                                        * Flash initialized based on the SFDP
>>                                        * tables.
>>                                        */
>> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
>> index 72cc4673bf88..31ebd4c9b431 100644
>> --- a/drivers/mtd/spi-nor/micron-st.c
>> +++ b/drivers/mtd/spi-nor/micron-st.c
>> @@ -118,13 +118,18 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
>>       .post_sfdp = mt35xu512aba_post_sfdp_fixup,
>>  };
>>
>> +static void mt35xu512aba_late_init(struct spi_nor *nor)
>> +{
>> +     nor->flags |= SNOR_F_4B_OPCODES;
> 
> Like I mentioned in the previous email, you can drop this since the
> flash populates the 4BAIT table.

ok

> 
>> +     nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
>> +}
>> +
>>  static const struct flash_info micron_parts[] = {
>>       { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
>>                              SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
>> -                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP |
>> -                            SPI_NOR_IO_MODE_EN_VOLATILE)
>> +                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
>>         .fixups = &mt35xu512aba_fixups,
>> -       .late_init = snor_f_4b_opcodes, },
>> +       .late_init = mt35xu512aba_late_init, },
>>       { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
>>                           SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ)
>>         .late_init = snor_f_4b_opcodes, },
> 
> I forgot to say this in the previous email, but since this flash is the
> same family as the one above, it should also have the 4BAIT table, and
> should not need this late_init. But I don't have access to this part so
> I can't say with 100% certainty.
> 

yeah, we don't update flash entries solely by datasheet, we can't update it without
testing it.

Cheers,
ta

From Tudor.Ambarus at microchip.com  Sun Oct  3 21:17:25 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 04:17:25 +0000
Subject: [PATCH v2 26/35] mtd: spi-nor: core: Introduce
 spi_nor_init_default_params()
In-Reply-To: <20210824173018.n6fw6t6mg4bwah37@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-27-tudor.ambarus@microchip.com>
 <20210824173018.n6fw6t6mg4bwah37@ti.com>
Message-ID: <42dd1311-7e75-a57c-c62c-d0d452608cdf@microchip.com>

On 8/24/21 8:30 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> Called for all flashes, regardless if they define SFDP tables or not.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c | 92 +++++++++++++++++++++-----------------
>>  1 file changed, 52 insertions(+), 40 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index b3a01d7d6f0b..9193317f897d 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -2543,6 +2543,56 @@ static int spi_nor_setup(struct spi_nor *nor,
>>       return spi_nor_set_addr_width(nor);
>>  }
>>
>> +/**
>> + * spi_nor_init_default_params() - Default initialization of flash parameters
>> + * and settings. Done for all flashes, regardless is they define SFDP tables
>> + * or not.
>> + * @nor:     pointer to a 'struct spi_nor'.
>> + */
>> +static void spi_nor_init_default_params(struct spi_nor *nor)
>> +{
>> +     struct spi_nor_flash_parameter *params = nor->params;
>> +     const struct flash_info *info = nor->info;
>> +     struct device_node *np = spi_nor_get_flash_node(nor);
>> +
>> +     params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>> +     params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>> +     params->setup = spi_nor_default_setup;
>> +     params->otp.org = &info->otp_org;
>> +
>> +     /* Default to 16-bit Write Status (01h) Command */
>> +     nor->flags |= SNOR_F_HAS_16BIT_SR;
>> +
>> +     /* Set SPI NOR sizes. */
>> +     params->writesize = 1;
>> +     params->size = (u64)info->sector_size * info->n_sectors;
>> +     params->page_size = info->page_size;
> 
> I think these two lines should go in spi_nor_info_init_params() since
> you are using the nor info to initialize these parameters. Otherwise,
> what even is the difference between these two functions?

I think a better name for spi_nor_info_init_params() is
spi_nor_nonsfdp_info_init_params(). This method will eventually be called
just for non SFDP flashes. Check conversation in 18/35.

And maybe I should rename spi_nor_nonsfdp_flags_init to
spi_nor_nonsfdp_info_init_snor_f.
> 
>> +
>> +     if (!(info->flags & SPI_NOR_NO_FR)) {
>> +             /* Default to Fast Read for DT and non-DT platform devices. */
>> +             params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>> +
>> +             /* Mask out Fast Read if not requested at DT instantiation. */
>> +             if (np && !of_property_read_bool(np, "m25p,fast-read"))
>> +                     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>> +     }
>> +
>> +     /* (Fast) Read settings. */
>> +     params->hwcaps.mask |= SNOR_HWCAPS_READ;
>> +     spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>> +                               0, 0, SPINOR_OP_READ,
>> +                               SNOR_PROTO_1_1_1);
>> +
>> +     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>> +             spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>> +                                       0, 8, SPINOR_OP_READ_FAST,
>> +                                       SNOR_PROTO_1_1_1);
>> +     /* Page Program settings. */
>> +     params->hwcaps.mask |= SNOR_HWCAPS_PP;
>> +     spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>> +                             SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>> +}
>> +
>>  /**
>>   * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
>>   * settings based on MFR register and ->default_init() hook.
>> @@ -2609,43 +2659,8 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
>>       struct spi_nor_flash_parameter *params = nor->params;
>>       struct spi_nor_erase_map *map = &params->erase_map;
>>       const struct flash_info *info = nor->info;
>> -     struct device_node *np = spi_nor_get_flash_node(nor);
>>       u8 i, erase_mask;
>>
>> -     /* Initialize default flash parameters and settings. */
>> -     params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>> -     params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>> -     params->setup = spi_nor_default_setup;
>> -     params->otp.org = &info->otp_org;
>> -
>> -     /* Default to 16-bit Write Status (01h) Command */
>> -     nor->flags |= SNOR_F_HAS_16BIT_SR;
>> -
>> -     /* Set SPI NOR sizes. */
>> -     params->writesize = 1;
>> -     params->size = (u64)info->sector_size * info->n_sectors;
>> -     params->page_size = info->page_size;
>> -
>> -     if (!(info->flags & SPI_NOR_NO_FR)) {
>> -             /* Default to Fast Read for DT and non-DT platform devices. */
>> -             params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>> -
>> -             /* Mask out Fast Read if not requested at DT instantiation. */
>> -             if (np && !of_property_read_bool(np, "m25p,fast-read"))
>> -                     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>> -     }
>> -
>> -     /* (Fast) Read settings. */
>> -     params->hwcaps.mask |= SNOR_HWCAPS_READ;
>> -     spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>> -                               0, 0, SPINOR_OP_READ,
>> -                               SNOR_PROTO_1_1_1);
>> -
>> -     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>> -             spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>> -                                       0, 8, SPINOR_OP_READ_FAST,
>> -                                       SNOR_PROTO_1_1_1);
>> -
>>       if (info->flags & SPI_NOR_DUAL_READ) {
>>               params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
>>               spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],
>> @@ -2674,11 +2689,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
>>                                         SNOR_PROTO_8_8_8_DTR);
>>       }
>>
>> -     /* Page Program settings. */
>> -     params->hwcaps.mask |= SNOR_HWCAPS_PP;
>> -     spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>> -                             SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>> -
>>       if (info->flags & SPI_NOR_OCTAL_DTR_PP) {
>>               params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
>>               /*
>> @@ -2823,6 +2833,8 @@ static int spi_nor_init_params(struct spi_nor *nor)
>>       if (!nor->params)
>>               return -ENOMEM;
>>
>> +     spi_nor_init_default_params(nor);
>> +
>>       spi_nor_info_init_params(nor);
>>
>>       spi_nor_manufacturer_init_params(nor);
> 
> I am neutral towards this patch. I don't think it improves much, but at
> the same time it doesn't make anything worse either.

I think it helps readability. It splits spi_nor_init_params() into smaller logical chunks,
based on the type of initialization. We should usually avoid long methods where we can split
them in logical chunks, it makes the code pleasant to read.

Cheers,
ta
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From Tudor.Ambarus at microchip.com  Sun Oct  3 22:01:40 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 05:01:40 +0000
Subject: [PATCH v2 27/35] mtd: spi-nor: core: Init flash params based on
 SFDP first for new flash additions
In-Reply-To: <20210824175138.vggtefa5xoomcjto@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-28-tudor.ambarus@microchip.com>
 <20210824175138.vggtefa5xoomcjto@ti.com>
Message-ID: <ca0df88f-2d62-a27a-624b-6640d437e535@microchip.com>

On 8/24/21 8:51 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> Remove the spagetti way of initializing flash parameters and settings,
>> at least for the new flash additions (for now). All flash entries should
>> be converted to either use SPI_NOR_PARSE_SFDP or SPI_NOR_SKIP_SFDP.
>> SPI_NOR_SKIP_SFDP should be set either when the SFDP tables are completely
>> wrong and we can't parse relevant data, or when the SFDP tables are not
>> defined at all, or when RDSFDP command is not supported by the flash.
>> After all the flash entries will be converted to use these flags and after
>> the default_init() hook will be removed, the
>> spi_nor_init_params_deprecated() will be replaced by
>> spi_nor_info_init_params(). The flash parameters and settings will be
>> initialized either by parsing SFDP, or via the flash info flags.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c | 103 +++++++++++++++++++++++++------------
>>  1 file changed, 70 insertions(+), 33 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 9193317f897d..ef06a8d6abb8 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -2627,28 +2627,6 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
>>               nor->info->fixups->post_sfdp(nor);
>>  }
>>
>> -/**
>> - * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
>> - * based on JESD216 SFDP standard.
>> - * @nor:     pointer to a 'struct spi_nor'.
>> - *
>> - * The method has a roll-back mechanism: in case the SFDP parsing fails, the
>> - * legacy flash parameters and settings will be restored.
>> - */
>> -static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>> -{
>> -     struct spi_nor_flash_parameter sfdp_params;
>> -
>> -     memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>> -
>> -     if (!spi_nor_parse_sfdp(nor))
>> -             return spi_nor_post_sfdp_fixups(nor);
>> -
>> -     memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>> -     nor->addr_width = 0;
>> -     nor->flags &= ~SNOR_F_4B_OPCODES;
>> -}
>> -
>>  /**
>>   * spi_nor_info_init_params() - Initialize the flash's parameters and settings
>>   * based on nor->info data.
>> @@ -2722,6 +2700,39 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
>>       spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
>>  }
>>
>> +/**
>> + * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
>> + * based on JESD216 SFDP standard.
>> + * @nor:     pointer to a 'struct spi_nor'.
> 
> Missing documentation for treat_id_collisions.

ok

> 
> Also, I assume this will go away when we get rid of
> spi_nor_init_params_deprecated(), correct?

correct

> 
>> + *
>> + * The method has a roll-back mechanism: in case the SFDP parsing fails, the
>> + * legacy flash parameters and settings will be restored.
>> + */
>> +static void spi_nor_sfdp_init_params(struct spi_nor *nor,
>> +                                  bool treat_id_collisions)
>> +{
>> +     struct spi_nor_flash_parameter sfdp_params;
>> +
>> +     memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>> +
>> +     if (!spi_nor_parse_sfdp(nor))
>> +             return spi_nor_post_sfdp_fixups(nor);
>> +
>> +     memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>> +     nor->addr_width = 0;
>> +     nor->flags &= ~SNOR_F_4B_OPCODES;
>> +
>> +     if (!treat_id_collisions)
>> +             return;
> 
> No, this doesn't seem quite right. Why would you not want to treat ID
> collisions for flashes that use spi_nor_init_params_deprecated()? What
> makes this not possible for them?

I think I wanted to motivate people to switch to the parse SFDP first idea.
Why would we care for those flashes that use deprecated methods?

> 
> Anyway, even if we don't want to treat ID collisions for those flashes,
> we can't just return here. In the previous code, nor->params is already
> initialized by spi_nor_info_init_params() so restoring that via memcpy()
> would make sense since it would restore the info-initialized state. Now
> it would be just 0, with no useful information in there. You are bound
> to run into errors somewhere down the line.

you're correct!

> 
> So I think you either need to make this function return an error and
> propagate it up the call chain or run spi_nor_info_init_params() for
> both type of flashes to make sure we do our best effort to initialize
> the flash.
> 
>> +     /*
>> +      * Fallback to flash info params init in case the SFDP parsing fails.
>> +      * Used to handle ID collisions between flashes that define the SFDP
>> +      * tables and flashes that don't.
>> +      */
>> +     spi_nor_info_init_params(nor);
>> +     spi_nor_manufacturer_init_params(nor);
>> +}
>> +
>>  /**
>>   * spi_nor_late_init_params() - Late initialization of default flash parameters.
>>   * @nor:     pointer to a 'struct spi_nor'
>> @@ -2797,7 +2808,9 @@ static void spi_nor_nonsfdp_flags_init(struct spi_nor *nor)
>>  }
>>
>>  /**
>> - * spi_nor_init_params() - Initialize the flash's parameters and settings.
>> + * spi_nor_init_params_deprecated() - Initialize the flash's parameters and
>> + * settings. The function is deprecated, it will be removed and replaced with
>> + * spi_nor_info_init_params().
>>   * @nor:     pointer to a 'struct spi_nor'.
>>   *
>>   * The flash parameters and settings are initialized based on a sequence of
>> @@ -2821,11 +2834,40 @@ static void spi_nor_nonsfdp_flags_init(struct spi_nor *nor)
>>   *    Please note that there are ->post_{bfpt, sfdp}() fixup hooks that can
>>   *    overwrite the flash parameters and settings immediately after table
>>   *    parsing.
>> + */
>> +static void spi_nor_init_params_deprecated(struct spi_nor *nor)
>> +{
>> +     spi_nor_info_init_params(nor);
>> +     spi_nor_manufacturer_init_params(nor);
>> +
>> +     if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> +                              SPI_NOR_OCTAL_READ | SPI_NOR_OCTAL_DTR_READ)) &&
>> +         !(nor->info->flags & SPI_NOR_SKIP_SFDP))
>> +             spi_nor_sfdp_init_params(nor, false);
>> +}
>> +
>> +/**
>> + * spi_nor_init_params() - Initialize the flash's parameters and settings.
>> + * @nor:     pointer to a 'struct spi_nor'.
>> + *
>> + * The flash parameters and settings are initialized based on a sequence of
>> + * calls that are ordered by priority:
>> + *
>> + * 1/ Default flash parameters initialization. The initializations are done
>> + *    for all the flashes, regardless if the support SFDP or not.
>> + *           spi_nor_init_default_params()
>> + * which can be overwritten by:
>>   *
>> + * 2/ SFDP based or the deprecated way of initializing flash parameters.
>> + * Ideally at this step the flash parameters init will be done either by
>> + * parsing SFDP, where supported, or statically via flash_info flags.
>> + *           spi_nor_sfdp_init_params() or spi_nor_init_params_deprecated()
>>   * which can be overwritten by:
>> - * 4/ Late flash parameters initialization, used to initialize flash
>> + *
>> + * 3/ Late flash parameters initialization, used to initialize flash
>>   * parameters that are not declared in the JESD216 SFDP standard.
>>   *           spi_nor_late_init_params()
>> + *
> 
> Not really related to this patch, but we need to document the return
> value here as well.

ok

Cheers,
ta

> 
>>   */
>>  static int spi_nor_init_params(struct spi_nor *nor)
>>  {
>> @@ -2835,15 +2877,10 @@ static int spi_nor_init_params(struct spi_nor *nor)
>>
>>       spi_nor_init_default_params(nor);
>>
>> -     spi_nor_info_init_params(nor);
>> -
>> -     spi_nor_manufacturer_init_params(nor);
>> -
>> -     if ((nor->info->flags & (SPI_NOR_PARSE_SFDP |
>> -                              SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> -                              SPI_NOR_OCTAL_READ | SPI_NOR_OCTAL_DTR_READ)) &&
>> -         !(nor->info->flags & SPI_NOR_SKIP_SFDP))
>> -             spi_nor_sfdp_init_params(nor);
>> +     if (nor->info->flags & SPI_NOR_PARSE_SFDP)
>> +             spi_nor_sfdp_init_params(nor, true);
>> +     else
>> +             spi_nor_init_params_deprecated(nor);
>>
>>       spi_nor_late_init_params(nor);
>>
>> --
>> 2.25.1
>>
> 
> --
> Regards,
> Pratyush Yadav
> Texas Instruments Inc.
> 


From mika.westerberg at linux.intel.com  Sun Oct  3 22:18:04 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Mon, 4 Oct 2021 08:18:04 +0300
Subject: [PATCH 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-2-mika.westerberg@linux.intel.com>
 <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>
Message-ID: <YVqOjF/xjqFV+Dl3@lahna>

Hi,

On Fri, Oct 01, 2021 at 05:23:23PM -0300, Mauro Lima wrote:
> Question for maintainers: With these changes is it safe to remove the
> *(DANGEROUS)* tag from menuconfig?

I don't think we want to remove that. This driver is not for regular
users, at least in its current form.


From ceggers at arri.de  Sun Oct  3 22:54:15 2021
From: ceggers at arri.de (Christian Eggers)
Date: Mon, 4 Oct 2021 07:54:15 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
Message-ID: <3160469.44csPzL39Z@n95hx1g2>

On Monday, 29 July 2019, 08:41:51 CEST, Greg Ungerer wrote:
> Hi Miquel,
> 
> I am experiencing a problem with NAND flash DMA timeouts on
> iMX6ull based boards. The problem is very similar to that
> described in:
> 
>    https://linux-mtd.infradead.narkive.com/JIUulfFB/gpmi-imx6ull-timeout-on-dma
> 
> That didn't come to any specific resolution that I could see
> in that thread.

Hi all,

I am joining this thread because I am also affected by this problem. I use
kernel 5.10.65-rt53 but I have seen this issue on many previous versions. In the
past I only recognized this on my development setup but now this has been found
by our testing team.

In our test setup we simply perform a reboot every 30s. After 5 to 200 cycles
the test stops due to this error.

The kernel version I use already includes:

> Han Xu <han.xu at nxp.com>
> mtd: rawnand: gpmi: Fix the random DMA timeout issue

Additionally I tried ...

> Michael Trimarchi <michael at amarulasolutions.com>
> mtd: nand: Calculate the clock before enable it

... but the problem still persists.

In my case, some registers show different values (annotated below):

> 
> The boot trace on the console for me looks like this:
> 
> nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xda
  nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
> nand: Micron MT29F2G08ABAEAWP
  nand: Micron MT29F4G08ABADAH4
> nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> gpmi-nand 1806000.gpmi-nand: DMA timeout, last DMA
> gpmi-nand 1806000.gpmi-nand: Show GPMI registers :
> gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x20830002
> gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x01c6800c
> gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00010101
> gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0xe0000000
> gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x23023336
> gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x000001ee
> gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0xff000001
> gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x00000001
  gpmi-nand 1806000.nand-controller: offset 0x0c0 : 0x00000202
> gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x05020000
> gpmi-nand 1806000.gpmi-nand: Show BCH registers :
> gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x00000100
  gpmi-nand 1806000.nand-controller: offset 0x000 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000010
> gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0x030a2080
  gpmi-nand 1806000.nand-controller: offset 0x080 : 0x070a4080
> gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x083e2080
  gpmi-nand 1806000.nand-controller: offset 0x090 : 0x10da4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x070a4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0x10da4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x070a4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x10da4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0e0 : 0x070a4080
> gpmi-nand 1806000.gpmi-nand: offset 0x0f0 : 0x10da4080
> gpmi-nand 1806000.gpmi-nand: offset 0x100 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x110 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x120 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x130 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x140 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: offset 0x150 : 0x20484342
> gpmi-nand 1806000.gpmi-nand: offset 0x160 : 0x01000000
> gpmi-nand 1806000.gpmi-nand: offset 0x170 : 0x00000000
> gpmi-nand 1806000.gpmi-nand: BCH Geometry :
> GF length              : 13
> ECC Strength           : 8
> Page Size in Bytes     : 2110
> Metadata Size in Bytes : 10
> ECC Chunk0 Size in Bytes: 512
> ECC Chunkn Size in Bytes: 512
  ECC Chunk Size in Bytes: 512
> ECC Chunk Count        : 4
> Payload Size in Bytes  : 2048
> Auxiliary Size in Bytes: 16
> Auxiliary Status Offset: 12
> Block Mark Byte Offset : 1999
> Block Mark Bit Offset  : 0

Please let me know if further information is required.

regards
Christian






From schaecsn at gmx.net  Sun Oct  3 22:57:58 2021
From: schaecsn at gmx.net (Stefan Schaeckeler)
Date: Sun,  3 Oct 2021 22:57:58 -0700 (PDT)
Subject: [PATCH 1/1] ubifs: ubifs to export filesystem error counters
In-Reply-To: <1815586081.32955.1633291105033.JavaMail.zimbra@nod.at> (message
 from Richard Weinberger on Sun, 3 Oct 2021 21:58:25 +0200 (CEST))
References: <20210907214034.11676-1-schaecsn@gmx.net>
 <20210907214034.11676-2-schaecsn@gmx.net>
 <1815586081.32955.1633291105033.JavaMail.zimbra@nod.at>
Message-ID: <20211004055758.C52AD899CC4@corona.crabdance.com>

Hello Richard,

> > Not all ubifs filesystem errors are propagated to userspace.
> >
> > Export bad magic, bad node and crc errors via sysfs. This allows userspace
> > to notice filesystem errors:
> >
> > /sys/fs/ubifs/ubiX_Y/errors_magic
> > /sys/fs/ubifs/ubiX_Y/errors_node
> > /sys/fs/ubifs/ubiX_Y/errors_crc
> >
> > The counters are reset to 0 with a remount. Writing anything into the
> > counters also clears them.
>
> I think this is a nice feature. Thanks for implementing it.
> Please see some minor nits below.
>
> Is there a specific reason why you didn't implement it via UBIFS's debugfs interface?

These error counters are not meant for aiding debugging but for userspace to
monitor the sanity of the filesystem. Also ext4 exports error counters via
sysfs - it's probably a good idea to be consistent with them.

$ dir /sys/fs/ext4/sdb2/*error*
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/errors_count
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_block
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_errcode
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_func
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_ino
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_line
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_time
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_block
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_errcode
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_func
-r--r--r-- 1 root root 4096 Oct  3 13:47 /sys/fs/ext4/sdb2/last_error_ino
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_line
-r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_time
--w------- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/trigger_fs_error


> sysfs is ABI, so we cannot change much anymore.

Judging by the filesystem permissions above, ext4 does not seem to allow
resetting error counters. If you worry about unchangable ABIs then we could
play it safe and don't support write callbacks for resetting the error counters
in an initial version of the ubifs sysfs. What do you think?

When we are at it, in the current code, writing anything into a sysfs node
resets the corresponding counter. One could fine-tune that to set the counter
to whatever non-negative integer is passed.


> > +		if (c->stats)
> > +			c->stats->magic_errors++;
>
> Please wrap this into a helper function.

Ack.


> > +		if (c->stats)
> > +			c->stats->node_errors++;
>
> Same.

Ack.


> > +		if (c->stats)
> > +			c->stats->crc_errors++;
>
> Same.

Ack.


> > +#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
> > +
> > +UBIFS_ATTR_FUNC(errors_magic, 0644);
> > +UBIFS_ATTR_FUNC(errors_crc, 0644);
> > +UBIFS_ATTR_FUNC(errors_node, 0644);
>
> I'm not sure whether everyone should be allowed to read these stats.
> dmesg is also restricted these days. An unprivileged user should not see the
> errors he can indirectly trigger.

I don't mind 600, but having error counters world-readable is consistent with
ext4 (see dir above) and so I suggest to keep 644.


> > +	case attr_errors_crc:
> > +		return snprintf(buf, PAGE_SIZE, "%u\n",
> > +				sbi->stats->crc_errors);
>
> Please use sysfs_emit().

Ack.


> > +	if (n == UBIFS_DFS_DIR_LEN) {
> > +		/* The array size is too small */
> > +		ret = -EINVAL;
> > +		goto out_last;
>
> Where is c->stats released in case of an error?

My fault. Will be fixed.


> > diff --git a/fs/ubifs/sysfs.h b/fs/ubifs/sysfs.h
> > new file mode 100644
> > index 000000000000..a10a82585af8
> > --- /dev/null
> > +++ b/fs/ubifs/sysfs.h
>
> Do we really need a new header file?
> Usually most run-time stuff of UBIFS is part of ubifs.h.

I wanted to be consistent with debugfs where fs/ubifs/debug.c comes with its
own header fs/ubifs/debug.h.


I'll send out a new patch once we agree on all changes. To recap:

- write callbacks: do we remove them? If not, do we keep them as is or do we
  fine-tine them by letting a non-negative integer set the counter?

- 644 (world-readable) counters to be consistent with ext4?

- keep sysfs.h to be consistent with debugfs?

 Stefan


From michael at amarulasolutions.com  Sun Oct  3 23:27:54 2021
From: michael at amarulasolutions.com (Michael Nazzareno Trimarchi)
Date: Mon, 4 Oct 2021 08:27:54 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <3160469.44csPzL39Z@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <3160469.44csPzL39Z@n95hx1g2>
Message-ID: <CAOf5uwk3XLtTgoMuRU+hP29xQzPUj9NEuV58V5QdXXigQ0waVQ@mail.gmail.com>

Hi Christian

On Mon, Oct 4, 2021 at 7:54 AM Christian Eggers <ceggers at arri.de> wrote:
>
> On Monday, 29 July 2019, 08:41:51 CEST, Greg Ungerer wrote:
> > Hi Miquel,
> >
> > I am experiencing a problem with NAND flash DMA timeouts on
> > iMX6ull based boards. The problem is very similar to that
> > described in:
> >
> >    https://linux-mtd.infradead.narkive.com/JIUulfFB/gpmi-imx6ull-timeout-on-dma
> >
> > That didn't come to any specific resolution that I could see
> > in that thread.
>
> Hi all,
>
> I am joining this thread because I am also affected by this problem. I use
> kernel 5.10.65-rt53 but I have seen this issue on many previous versions. In the
> past I only recognized this on my development setup but now this has been found
> by our testing team.
>
> In our test setup we simply perform a reboot every 30s. After 5 to 200 cycles
> the test stops due to this error.
>
> The kernel version I use already includes:
>
> > Han Xu <han.xu at nxp.com>
> > mtd: rawnand: gpmi: Fix the random DMA timeout issue
>
> Additionally I tried ...
>
> > Michael Trimarchi <michael at amarulasolutions.com>
> > mtd: nand: Calculate the clock before enable it
>
> ... but the problem still persists.
>
> In my case, some registers show different values (annotated below):
>
> >
> > The boot trace on the console for me looks like this:
> >
> > nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xda
>   nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
> > nand: Micron MT29F2G08ABAEAWP
>   nand: Micron MT29F4G08ABADAH4
> > nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> > gpmi-nand 1806000.gpmi-nand: DMA timeout, last DMA
> > gpmi-nand 1806000.gpmi-nand: Show GPMI registers :
> > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x20830002
> > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x01c6800c
> > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00010101
> > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0xe0000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x23023336
> > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x000001ee
> > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0xff000001
> > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x00000001
>   gpmi-nand 1806000.nand-controller: offset 0x0c0 : 0x00000202
> > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x05020000
> > gpmi-nand 1806000.gpmi-nand: Show BCH registers :
> > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x00000100
>   gpmi-nand 1806000.nand-controller: offset 0x000 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000010
> > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0x030a2080
>   gpmi-nand 1806000.nand-controller: offset 0x080 : 0x070a4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x083e2080
>   gpmi-nand 1806000.nand-controller: offset 0x090 : 0x10da4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x070a4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0x10da4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x070a4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x10da4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0e0 : 0x070a4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x0f0 : 0x10da4080
> > gpmi-nand 1806000.gpmi-nand: offset 0x100 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x110 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x120 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x130 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x140 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x150 : 0x20484342
> > gpmi-nand 1806000.gpmi-nand: offset 0x160 : 0x01000000
> > gpmi-nand 1806000.gpmi-nand: offset 0x170 : 0x00000000
> > gpmi-nand 1806000.gpmi-nand: BCH Geometry :
> > GF length              : 13
> > ECC Strength           : 8
> > Page Size in Bytes     : 2110
> > Metadata Size in Bytes : 10
> > ECC Chunk0 Size in Bytes: 512
> > ECC Chunkn Size in Bytes: 512
>   ECC Chunk Size in Bytes: 512
> > ECC Chunk Count        : 4
> > Payload Size in Bytes  : 2048
> > Auxiliary Size in Bytes: 16
> > Auxiliary Status Offset: 12
> > Block Mark Byte Offset : 1999
> > Block Mark Bit Offset  : 0
>
> Please let me know if further information is required.

I need to continue on it, during the following days. I have stopped
moving to LTS 4.19.y and with my partial revert.
The problem as usual was to go to production on some devices. Anyway I
have the device that has this problem. I can
restart next weekend. One of the thing I notice that make not work on imx28 is:

       if (sdr->tRC_min >= 30000) {
               /* ONFI non-EDO modes [0-3] */
               hw->clk_rate = 22000000;
               wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
       } else if (sdr->tRC_min >= 25000) {
               /* ONFI EDO mode 4 */
               hw->clk_rate = 80000000;
               wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
       } else {
               /* ONFI EDO mode 5 */
               hw->clk_rate = 100000000;
               wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
       }

Here there is an assumption that your clk_rate can be set to that rate
but on imx28, the parent clock of the NAND one can not
let it go to those speed. Changing it let it really set to the wrong
value, so imx28 was totally broken. The other computation was based
not on fixed clock rate but I think even on clk_get_rate

Michael

>
> regards
> Christian
>
>
>
>


-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com


From sean at geanix.com  Sun Oct  3 23:56:09 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon,  4 Oct 2021 08:56:09 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in suspend
Message-ID: <20211004065608.3190348-1-sean@geanix.com>

This will prevent nand_get_device() from returning -EBUSY.
It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
access to the mtd device.

Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
that will in turn hard error on every error returened.
We have seen during ubifs tries to call mtd_write before the mtd device
is resumed.

Exec_op[0] speed things up, so we see this race when the device is
resuming. But it's actually "mtd: rawnand: Simplify the locking" that
allows it to return -EBUSY, before that commit it would have waited for
the mtd device to resume.

Tested on a iMX6ULL.

[0]:
ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---

I did this a RFC as we probably will need to remove the suspended
variable as it's kinda made obsolute by this change.
Should we introduce a new mutex? Or maybe a spin_lock?

 drivers/mtd/nand/raw/nand_base.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..0ea343404cac 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4567,7 +4567,6 @@ static int nand_suspend(struct mtd_info *mtd)
 		ret = chip->ops.suspend(chip);
 	if (!ret)
 		chip->suspended = 1;
-	mutex_unlock(&chip->lock);
 
 	return ret;
 }
@@ -4580,7 +4579,6 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
-	mutex_lock(&chip->lock);
 	if (chip->suspended) {
 		if (chip->ops.resume)
 			chip->ops.resume(chip);
-- 
2.33.0



From boris.brezillon at collabora.com  Mon Oct  4 01:41:47 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 4 Oct 2021 10:41:47 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004065608.3190348-1-sean@geanix.com>
References: <20211004065608.3190348-1-sean@geanix.com>
Message-ID: <20211004104147.579f3b01@collabora.com>

On Mon,  4 Oct 2021 08:56:09 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> This will prevent nand_get_device() from returning -EBUSY.
> It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> access to the mtd device.
> 
> Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> that will in turn hard error on every error returened.
> We have seen during ubifs tries to call mtd_write before the mtd device
> is resumed.

I think the problem is here. Why would UBIFS/UBI try to write something
to a device that's not resumed yet (or has been suspended already, if
you hit this in the suspend path).

> 
> Exec_op[0] speed things up, so we see this race when the device is
> resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> allows it to return -EBUSY, before that commit it would have waited for
> the mtd device to resume.

Uh, wait. If nand_resume() was called before any writes/reads this
wouldn't happen. IMHO, the problem is not that we return -EBUSY without
blocking, the problem is that someone issues a write/read before calling
mtd_resume().

> 
> Tested on a iMX6ULL.
> 
> [0]:
> ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
> 
> I did this a RFC as we probably will need to remove the suspended
> variable as it's kinda made obsolute by this change.
> Should we introduce a new mutex? Or maybe a spin_lock?
> 
>  drivers/mtd/nand/raw/nand_base.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..0ea343404cac 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -4567,7 +4567,6 @@ static int nand_suspend(struct mtd_info *mtd)
>  		ret = chip->ops.suspend(chip);
>  	if (!ret)
>  		chip->suspended = 1;
> -	mutex_unlock(&chip->lock);

Hm, I'm not sure keeping the lock when you're in a suspended state
is a good idea. It just papers over another bug IMO (see above).

>  
>  	return ret;
>  }
> @@ -4580,7 +4579,6 @@ static void nand_resume(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  
> -	mutex_lock(&chip->lock);
>  	if (chip->suspended) {
>  		if (chip->ops.resume)
>  			chip->ops.resume(chip);



From sean at geanix.com  Mon Oct  4 01:55:09 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 4 Oct 2021 10:55:09 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004104147.579f3b01@collabora.com>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
Message-ID: <20211004085509.iikxtdvxpt6bri5c@skn-laptop>

On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:
> On Mon,  4 Oct 2021 08:56:09 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > This will prevent nand_get_device() from returning -EBUSY.
> > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > access to the mtd device.
> > 
> > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > that will in turn hard error on every error returened.
> > We have seen during ubifs tries to call mtd_write before the mtd device
> > is resumed.
> 
> I think the problem is here. Why would UBIFS/UBI try to write something
> to a device that's not resumed yet (or has been suspended already, if
> you hit this in the suspend path).
> 
> > 
> > Exec_op[0] speed things up, so we see this race when the device is
> > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > allows it to return -EBUSY, before that commit it would have waited for
> > the mtd device to resume.
> 
> Uh, wait. If nand_resume() was called before any writes/reads this
> wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> blocking, the problem is that someone issues a write/read before calling
> mtd_resume().
> 

The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.

"""
Last important change to mention: we now return -EBUSY when someone
tries to access a device that as been suspended, and propagate this
error to the upper layer.
"""

IMHO "mtd: rawnand: Simplify the locking" should never had been merged
before the upper layers was fixed to handle -EBUSY. ;)
Which they still not are...

Yes, guess there is data in the ubifs queue when going into suspend,
then the ubifs kthread is starting writing when the cpu resumes.
Before mtd_resume() and other pm_resume() handles are called.

How would you have ubifs to wait for mtd_resume()? If you don't like
this mutex solution?

> > 
> > Tested on a iMX6ULL.
> > 
> > [0]:
> > ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> > 
> > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> > ---
> > 
> > I did this a RFC as we probably will need to remove the suspended
> > variable as it's kinda made obsolute by this change.
> > Should we introduce a new mutex? Or maybe a spin_lock?
> > 
> >  drivers/mtd/nand/raw/nand_base.c | 2 --
> >  1 file changed, 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..0ea343404cac 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -4567,7 +4567,6 @@ static int nand_suspend(struct mtd_info *mtd)
> >  		ret = chip->ops.suspend(chip);
> >  	if (!ret)
> >  		chip->suspended = 1;
> > -	mutex_unlock(&chip->lock);
> 
> Hm, I'm not sure keeping the lock when you're in a suspended state
> is a good idea. It just papers over another bug IMO (see above).
> 
> >  
> >  	return ret;
> >  }
> > @@ -4580,7 +4579,6 @@ static void nand_resume(struct mtd_info *mtd)
> >  {
> >  	struct nand_chip *chip = mtd_to_nand(mtd);
> >  
> > -	mutex_lock(&chip->lock);
> >  	if (chip->suspended) {
> >  		if (chip->ops.resume)
> >  			chip->ops.resume(chip);
> 


From p.yadav at ti.com  Mon Oct  4 02:52:41 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Mon, 4 Oct 2021 15:22:41 +0530
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20210930100719.2176-3-mika.westerberg@linux.intel.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
Message-ID: <20211004095239.dyowgkyq5lnfdag2@ti.com>

On 30/09/21 01:07PM, Mika Westerberg wrote:
> The preferred way to implement SPI-NOR controller drivers is through SPI
> subsubsystem utilizing the SPI MEM core functions. This converts the
> Intel SPI flash controller driver over the SPI MEM by moving the driver
> from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> SPI MEM functions. The driver name will be changed from intel-spi to
> spi-intel to match the convention used in the SPI subsystem.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> ---
>  drivers/mtd/spi-nor/controllers/Kconfig       |  36 ---
>  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
>  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
>  drivers/spi/Kconfig                           |  38 +++
>  drivers/spi/Makefile                          |   3 +
>  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
>  .../spi-intel-platform.c}                     |  21 +-
>  .../intel-spi.c => spi/spi-intel.c}           | 300 +++++++++++-------
>  drivers/spi/spi-intel.h                       |  19 ++
>  include/linux/mfd/lpc_ich.h                   |   2 +-
>  .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
>  11 files changed, 252 insertions(+), 217 deletions(-)
>  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (80%)
>  create mode 100644 drivers/spi/spi-intel.h
>  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)
> 
[...]
> +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> +				      const struct spi_mem_op *op)
> +{
> +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
>  
> -			offs += erase_size;
> -			len -= erase_size;
> +	if (op->cmd.dtr)
> +		return false;
> +
> +	if (ispi->swseq_reg && ispi->locked) {
> +		int i;
> +
> +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> +			if (ispi->opcodes[i] == op->cmd.opcode)
> +				return true;
>  		}
>  
> -		return 0;
> +		return false;
>  	}
>  
> -	/* Not needed with HW sequencer erase, make sure it is cleared */
> -	ispi->atomic_preopcode = 0;
> +	switch (op->cmd.opcode) {
> +	case SPINOR_OP_RDID:
> +	case SPINOR_OP_RDSR:
> +	case SPINOR_OP_WRSR:
> +		return true;
>  
> -	while (len > 0) {
> -		writel(offs, ispi->base + FADDR);
> +	case SPINOR_OP_READ:
> +	case SPINOR_OP_READ_FAST:
> +	case SPINOR_OP_READ_4B:
> +	case SPINOR_OP_READ_FAST_4B:
> +		return true;

I think the checks need to be stricter here. For example, I don't see 
you pass in protocol width (dual, quad, octal, etc.) to intel_spi_read() 
so I assume it can only do a certain protocol. You need to make sure 
that other protocols are rejected here.

Similarly, you also don't pass in dummy cycles to intel_spi_read(), so I 
assume it can only do a fix number of dummy cycles. Need to make sure 
you reject unsupported ones. Same for other opcodes/cases.

>  
> -		val = readl(ispi->base + HSFSTS_CTL);
> -		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> -		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> -		val |= cmd;
> -		val |= HSFSTS_CTL_FGO;
> -		writel(val, ispi->base + HSFSTS_CTL);
> +	case SPINOR_OP_PP:
> +	case SPINOR_OP_PP_4B:
> +	case SPINOR_OP_WREN:
> +	case SPINOR_OP_WRDI:
> +		return true;
>  
> -		ret = intel_spi_wait_hw_busy(ispi);
> -		if (ret)
> -			return ret;
> +	case SPINOR_OP_SE:
> +	case SPINOR_OP_SE_4B:
> +		return ispi->erase_64k;
>  
> -		status = readl(ispi->base + HSFSTS_CTL);
> -		if (status & HSFSTS_CTL_FCERR)
> -			return -EIO;
> -		else if (status & HSFSTS_CTL_AEL)
> -			return -EACCES;
> +	case SPINOR_OP_BE_4K:
> +	case SPINOR_OP_BE_4K_4B:
> +		return true;
> +	}
> +
> +	return false;
> +}
>  
> -		offs += erase_size;
> -		len -= erase_size;
> +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
> +{
> +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> +	size_t nbytes = op->data.nbytes;
> +	u8 opcode = op->cmd.opcode;
> +
> +	if (op->addr.nbytes) {
> +		if  (op->data.dir == SPI_MEM_DATA_IN)
> +			return intel_spi_read(ispi, op->addr.val, nbytes,
> +					      op->data.buf.in);
> +		else if (op->data.dir == SPI_MEM_DATA_OUT)
> +			return intel_spi_write(ispi, op->addr.val, nbytes,
> +					       op->data.buf.out);
> +		else if (op->data.dir == SPI_MEM_NO_DATA)
> +			return intel_spi_erase(ispi, opcode, op->addr.val);
> +	} else {
> +		if  (op->data.dir == SPI_MEM_DATA_IN)
> +			return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
> +						  nbytes);
> +		else if (op->data.dir == SPI_MEM_DATA_OUT)
> +			return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
> +						   nbytes);
> +		else if (op->data.dir == SPI_MEM_NO_DATA)
> +			return intel_spi_write_reg(ispi, opcode, NULL, 0);
>  	}
>  
> -	return 0;
> +	return -EINVAL;
> +}
> +
[...]

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From boris.brezillon at collabora.com  Mon Oct  4 02:58:17 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 4 Oct 2021 11:58:17 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
Message-ID: <20211004115817.18739936@collabora.com>

On Mon, 4 Oct 2021 10:55:09 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:
> > On Mon,  4 Oct 2021 08:56:09 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > This will prevent nand_get_device() from returning -EBUSY.
> > > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > > access to the mtd device.
> > > 
> > > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > > that will in turn hard error on every error returened.
> > > We have seen during ubifs tries to call mtd_write before the mtd device
> > > is resumed.  
> > 
> > I think the problem is here. Why would UBIFS/UBI try to write something
> > to a device that's not resumed yet (or has been suspended already, if
> > you hit this in the suspend path).
> >   
> > > 
> > > Exec_op[0] speed things up, so we see this race when the device is
> > > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > > allows it to return -EBUSY, before that commit it would have waited for
> > > the mtd device to resume.  
> > 
> > Uh, wait. If nand_resume() was called before any writes/reads this
> > wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> > blocking, the problem is that someone issues a write/read before calling
> > mtd_resume().
> >   
> 
> The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.
> 
> """
> Last important change to mention: we now return -EBUSY when someone
> tries to access a device that as been suspended, and propagate this
> error to the upper layer.
> """
> 
> IMHO "mtd: rawnand: Simplify the locking" should never had been merged
> before the upper layers was fixed to handle -EBUSY. ;)
> Which they still not are...

That's not really the problem here. Upper layers should never get
-EBUSY in the first place if the MTD device was resumed before the UBI
device. Looks like we have a missing UBI -> MTD parenting link, which
would explain why things don't get resumed in the right order. Can you
try with the following diff applied?

---
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index f399edc82191..1981ce8f3a26 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -905,6 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int
ubi_num, ubi->dev.release = dev_release;
        ubi->dev.class = &ubi_class;
        ubi->dev.groups = ubi_dev_groups;
+       ubi->dev.parent = &mtd->dev;
 
        ubi->mtd = mtd;
        ubi->ubi_num = ubi_num;



From mika.westerberg at linux.intel.com  Mon Oct  4 03:07:43 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Mon, 4 Oct 2021 13:07:43 +0300
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211004095239.dyowgkyq5lnfdag2@ti.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com>
Message-ID: <YVrSbyEsSLMOu1bU@lahna>

Hi,

On Mon, Oct 04, 2021 at 03:22:41PM +0530, Pratyush Yadav wrote:
> On 30/09/21 01:07PM, Mika Westerberg wrote:
> > The preferred way to implement SPI-NOR controller drivers is through SPI
> > subsubsystem utilizing the SPI MEM core functions. This converts the
> > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > SPI MEM functions. The driver name will be changed from intel-spi to
> > spi-intel to match the convention used in the SPI subsystem.
> > 
> > Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> > ---
> >  drivers/mtd/spi-nor/controllers/Kconfig       |  36 ---
> >  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
> >  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
> >  drivers/spi/Kconfig                           |  38 +++
> >  drivers/spi/Makefile                          |   3 +
> >  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
> >  .../spi-intel-platform.c}                     |  21 +-
> >  .../intel-spi.c => spi/spi-intel.c}           | 300 +++++++++++-------
> >  drivers/spi/spi-intel.h                       |  19 ++
> >  include/linux/mfd/lpc_ich.h                   |   2 +-
> >  .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
> >  11 files changed, 252 insertions(+), 217 deletions(-)
> >  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
> >  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
> >  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
> >  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (80%)
> >  create mode 100644 drivers/spi/spi-intel.h
> >  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)
> > 
> [...]
> > +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> > +				      const struct spi_mem_op *op)
> > +{
> > +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> >  
> > -			offs += erase_size;
> > -			len -= erase_size;
> > +	if (op->cmd.dtr)
> > +		return false;
> > +
> > +	if (ispi->swseq_reg && ispi->locked) {
> > +		int i;
> > +
> > +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> > +			if (ispi->opcodes[i] == op->cmd.opcode)
> > +				return true;
> >  		}
> >  
> > -		return 0;
> > +		return false;
> >  	}
> >  
> > -	/* Not needed with HW sequencer erase, make sure it is cleared */
> > -	ispi->atomic_preopcode = 0;
> > +	switch (op->cmd.opcode) {
> > +	case SPINOR_OP_RDID:
> > +	case SPINOR_OP_RDSR:
> > +	case SPINOR_OP_WRSR:
> > +		return true;
> >  
> > -	while (len > 0) {
> > -		writel(offs, ispi->base + FADDR);
> > +	case SPINOR_OP_READ:
> > +	case SPINOR_OP_READ_FAST:
> > +	case SPINOR_OP_READ_4B:
> > +	case SPINOR_OP_READ_FAST_4B:
> > +		return true;
> 
> I think the checks need to be stricter here. For example, I don't see 
> you pass in protocol width (dual, quad, octal, etc.) to intel_spi_read() 
> so I assume it can only do a certain protocol. You need to make sure 
> that other protocols are rejected here.
> 
> Similarly, you also don't pass in dummy cycles to intel_spi_read(), so I 
> assume it can only do a fix number of dummy cycles. Need to make sure 
> you reject unsupported ones. Same for other opcodes/cases.

Unfortunately there is no way to tell the controller any of these. It
simply does "read" or "write" (as we command it) and internally then
uses whatever it got from the SFDP tables of the flash chip. That's why
we just claim to support all these operations and let the controller do
its thing (whatever it is).

Hope this clarifies.


From sean at geanix.com  Mon Oct  4 03:12:46 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 4 Oct 2021 12:12:46 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004115817.18739936@collabora.com>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
Message-ID: <20211004101246.kagtezizympxupat@skn-laptop>

On Mon, Oct 04, 2021 at 11:58:17AM +0200, Boris Brezillon wrote:
> On Mon, 4 Oct 2021 10:55:09 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:
> > > On Mon,  4 Oct 2021 08:56:09 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:
> > >   
> > > > This will prevent nand_get_device() from returning -EBUSY.
> > > > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > > > access to the mtd device.
> > > > 
> > > > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > > > that will in turn hard error on every error returened.
> > > > We have seen during ubifs tries to call mtd_write before the mtd device
> > > > is resumed.  
> > > 
> > > I think the problem is here. Why would UBIFS/UBI try to write something
> > > to a device that's not resumed yet (or has been suspended already, if
> > > you hit this in the suspend path).
> > >   
> > > > 
> > > > Exec_op[0] speed things up, so we see this race when the device is
> > > > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > > > allows it to return -EBUSY, before that commit it would have waited for
> > > > the mtd device to resume.  
> > > 
> > > Uh, wait. If nand_resume() was called before any writes/reads this
> > > wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> > > blocking, the problem is that someone issues a write/read before calling
> > > mtd_resume().
> > >   
> > 
> > The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.
> > 
> > """
> > Last important change to mention: we now return -EBUSY when someone
> > tries to access a device that as been suspended, and propagate this
> > error to the upper layer.
> > """
> > 
> > IMHO "mtd: rawnand: Simplify the locking" should never had been merged
> > before the upper layers was fixed to handle -EBUSY. ;)
> > Which they still not are...
> 
> That's not really the problem here. Upper layers should never get
> -EBUSY in the first place if the MTD device was resumed before the UBI
> device. Looks like we have a missing UBI -> MTD parenting link, which
> would explain why things don't get resumed in the right order. Can you
> try with the following diff applied?
> 
> ---
> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> index f399edc82191..1981ce8f3a26 100644
> --- a/drivers/mtd/ubi/build.c
> +++ b/drivers/mtd/ubi/build.c
> @@ -905,6 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int
> ubi_num, ubi->dev.release = dev_release;
>         ubi->dev.class = &ubi_class;
>         ubi->dev.groups = ubi_dev_groups;
> +       ubi->dev.parent = &mtd->dev;
>  
>         ubi->mtd = mtd;
>         ubi->ubi_num = ubi_num;
> 

No change:
[   71.739193] Filesystems sync: 34.212 seconds
[   71.755044] Freezing user space processes ... (elapsed 0.004 seconds) done.
[   71.767289] OOM killer disabled.
[   71.770552] Freezing remaining freezable tasks ... (elapsed 0.004 seconds) done.
[   71.782182] printk: Suspending console(s) (use no_console_suspend to debug)
[   71.824391] nand_suspend
[   71.825177] gpmi_pm_suspend
[   71.825676] PM: suspend devices took 0.040 seconds
[   71.825971] nand_write_oob - nand_get_device() returned -EBUSY
[   71.825985] ubi0 error: ubi_io_write: error -16 while writing 4096 bytes to PEB 986:65536, written 0 bytes
[   71.826029] CPU: 0 PID: 7 Comm: kworker/u2:0 Not tainted 5.15.0-rc3-dirty #43
[   71.826043] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[   71.826054] Workqueue: writeback wb_workfn (flush-ubifs_0_8)
[   71.826094] [<c010da84>] (unwind_backtrace) from [<c010a1b4>] (show_stack+0x10/0x14)
[   71.826122] [<c010a1b4>] (show_stack) from [<c0989c30>] (dump_stack_lvl+0x40/0x4c)
[   71.826151] [<c0989c30>] (dump_stack_lvl) from [<c05ed690>] (ubi_io_write+0x510/0x6b0)
[   71.826178] [<c05ed690>] (ubi_io_write) from [<c05ea2f0>] (ubi_eba_write_leb+0xd0/0x968)
[   71.826204] [<c05ea2f0>] (ubi_eba_write_leb) from [<c05e8754>] (ubi_leb_write+0xd0/0xe8)
[   71.826232] [<c05e8754>] (ubi_leb_write) from [<c03d67bc>] (ubifs_leb_write+0x68/0x104)
[   71.826263] [<c03d67bc>] (ubifs_leb_write) from [<c03d79e8>] (ubifs_wbuf_write_nolock+0x28c/0x74c)
[   71.826291] [<c03d79e8>] (ubifs_wbuf_write_nolock) from [<c03ca18c>] (ubifs_jnl_write_data+0x1b8/0x2b4)
[   71.826319] [<c03ca18c>] (ubifs_jnl_write_data) from [<c03cd184>] (do_writepage+0x190/0x284)
[   71.826342] [<c03cd184>] (do_writepage) from [<c023083c>] (__writepage+0x14/0x68)
[   71.826367] [<c023083c>] (__writepage) from [<c0231748>] (write_cache_pages+0x1c8/0x3f0)
[   71.826390] [<c0231748>] (write_cache_pages) from [<c0233854>] (do_writepages+0xcc/0x1f4)
[   71.826413] [<c0233854>] (do_writepages) from [<c02d03dc>] (__writeback_single_inode+0x2c/0x1b4)
[   71.826440] [<c02d03dc>] (__writeback_single_inode) from [<c02d0a64>] (writeback_sb_inodes+0x200/0x470)
[   71.826466] [<c02d0a64>] (writeback_sb_inodes) from [<c02d0d10>] (__writeback_inodes_wb+0x3c/0xf4)
[   71.826493] [<c02d0d10>] (__writeback_inodes_wb) from [<c02d0f58>] (wb_writeback+0x190/0x1f0)
[   71.826520] [<c02d0f58>] (wb_writeback) from [<c02d21d8>] (wb_workfn+0x2c0/0x3d4)
[   71.826545] [<c02d21d8>] (wb_workfn) from [<c013ac04>] (process_one_work+0x1e0/0x440)
[   71.826574] [<c013ac04>] (process_one_work) from [<c013aeac>] (worker_thread+0x48/0x594)
[   71.826600] [<c013aeac>] (worker_thread) from [<c0142364>] (kthread+0x134/0x15c)
[   71.826625] [<c0142364>] (kthread) from [<c0100150>] (ret_from_fork+0x14/0x24)

[...]

[   71.921673] gpmi_pm_resume
[   71.923319] nand_resume
[   71.936120] PM: resume devices took 0.100 seconds
[   72.314551] ci_hdrc ci_hdrc.0: freeing queued request
[   72.521656] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
[   75.006404] OOM killer enabled.
[   75.009562] Restarting tasks ...
[   75.074123] done.
[   75.095540] PM: suspend exit

With the RFC PATCH:
[ 3702.682122] Filesystems sync: 33.416 seconds
[ 3702.695350] Freezing user space processes ... (elapsed 0.001 seconds) done.
[ 3702.704218] OOM killer disabled.
[ 3702.707559] Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
[ 3702.718696] printk: Suspending console(s) (use no_console_suspend to debug)
[ 3702.757660] nand_suspend
[ 3702.758577] gpmi_pm_suspend
[ 3702.759072] PM: suspend devices took 0.040 seconds
[ 3702.761618] Disabling non-boot CPUs ...
[ 3702.854985] gpmi_pm_resume
[ 3702.856623] nand_resume
[ 3702.867796] PM: resume devices took 0.110 seconds
[ 3702.895019] OOM killer enabled.
[ 3702.898291] Restarting tasks ... done.
[ 3702.950723] PM: suspend exit


From mbsf1602 at gmail.com  Mon Oct  4 04:24:21 2021
From: mbsf1602 at gmail.com (fgjh hkllk)
Date: Mon, 4 Oct 2021 19:24:21 +0800
Subject: =?UTF-8?B?56Wd5L2g5bmz5a6J?=
Message-ID: <CADUj2twtM5-MxsHgr524ZF3vt1K+tMQ2vnfDxhH8MSYtjYq9nQ@mail.gmail.com>

                                    ????



                                 ???????
                                 ???????
                                 ?????

                                 ???????
                                 ???????
                                 ?????








?? > ???? > ????



                             ???????????????



???????????????????????????????????????Juc?????????????????????????????????????????????????????????????Jemma?????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????

???????????????????????????????????????????????????????????????????????????????????????????????????????

?????????????????????

?????????????

????????????????????????????????????????????????????????????

??????????????????????????????????????????????????????????????????????????????????????????????????????????
???????????????????????????????????????????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????

???????????????????????????????????????????????????????????????????????????????????????????????????????????

???????????????

?????????????????????????????????????????????????????????

??????????????????????????????????????????????????????????????????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

????????????????????????????????

????????????

?????????????????????????????????????????????????????????????????????????????????????????????????????????

???????????????????????????????????????????????????????????????????????

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

??????????

?????????????????????????????????????????

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????[1]

?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????[2]

??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

???????????

???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

????????????????????????????????????????????

???????

????????????????????????????????????????????????????????????????????????????????????

???????????????????????????????????????????????????????????????

??
[1] ????????????????????? ?
[2] ????????????????????? ?


http://www.minghui.org/mh/articles/2021/2/19/????????-??????-421107.html

??????????

Email ??? ?????????freeget.one at gmail.com ?
xiazai at upup.info????????????????
???? ???????????????
????https://git.io/fgp88 https://git.io/umexe
????https://git.io/fgm88
https://s3.amazonaws.com/693/um.apk
?????????????????????
????IE?Edge?Chrome ????????
????
??APP ??
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ????-read.pdf
Type: application/pdf
Size: 3471535 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0004.pdf>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ????-read.pdf
Type: application/pdf
Size: 6973212 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0005.pdf>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ????-?????????????? ??.doc
Type: application/msword
Size: 5767680 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0002.doc>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ??????-read.pdf
Type: application/pdf
Size: 2340903 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0006.pdf>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ?????_doc.doc
Type: application/msword
Size: 429056 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0003.doc>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ?????????.pdf
Type: application/pdf
Size: 5369264 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211004/51c70ecd/attachment-0007.pdf>

From Tudor.Ambarus at microchip.com  Mon Oct  4 04:25:29 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 11:25:29 +0000
Subject: [PATCH 1/2] dt-bindings: mtd: spi-nor: Add output-driver-strength
 property
In-Reply-To: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
References: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
Message-ID: <0cf4389f-cb91-44aa-a4be-48878d1221de@microchip.com>

On 10/4/21 2:15 PM, Alexander Stein wrote:
> [You don't often get email from alexander.stein at tq-systems.com. Learn why this is important at http://aka.ms/LearnAboutSenderIdentification.]
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> 
> This property is for optimizing output voltage impedance and is
> specific to each board.
> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
> I checked Micron and Macronix datasheets. Both have similar but not
> identical supported values. Also the register locations are different.
> For those reasons I decided to specify the Ohms value directly and let
> the device specfic driver figure out if it is supported where to write
> it to.
> BTW: Are the Ohm values and the corresponding register bits standardized
> somewhere?

Please check JEDEC Standard No. 216D.01, I see a SCCR Map which defines Output
Driver Strength values.

> 
>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> index ed590d7c6e37..7d7f20a741b5 100644
> --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> @@ -72,6 +72,12 @@ properties:
>        be used on such systems, to denote the absence of a reliable reset
>        mechanism.
> 
> +  output-driver-strength:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Output driver strength in Ohms which optimizes the impedance at Vcc/2
> +      output voltage.
> +
>    label: true
> 
>    partitions:
> --
> 2.25.1
> 


From Tudor.Ambarus at microchip.com  Mon Oct  4 04:26:26 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 11:26:26 +0000
Subject: [PATCH 2/2] mtd: spi-nor: micron-st: Add support for
 output-driver-strength
In-Reply-To: <20211004111529.211089-2-Alexander.Stein@tq-systems.com>
References: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
 <20211004111529.211089-2-Alexander.Stein@tq-systems.com>
Message-ID: <c3490462-9f07-9f69-ecc1-e51b61622ff9@microchip.com>

On 10/4/21 2:15 PM, Alexander Stein wrote:
> [You don't often get email from alexander.stein at tq-systems.com. Learn why this is important at http://aka.ms/LearnAboutSenderIdentification.]
> 
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> 
> Micron flashes support this by the Bits [2:0] in the Enhanced Volatile
> Configuration Register.
> Checked datasheets:
> - n25q_128mb_3v_65nm.pdf
> - mt25t-qljs-L512-xBA-xxT.pdf
> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---

Does the micron flash define the SCCR SFDP map?

From Tudor.Ambarus at microchip.com  Mon Oct  4 04:36:11 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 11:36:11 +0000
Subject: [PATCH v2 27/35] mtd: spi-nor: core: Init flash params based on
 SFDP first for new flash additions
In-Reply-To: <ca0df88f-2d62-a27a-624b-6640d437e535@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-28-tudor.ambarus@microchip.com>
 <20210824175138.vggtefa5xoomcjto@ti.com>
 <ca0df88f-2d62-a27a-624b-6640d437e535@microchip.com>
Message-ID: <0d5fa73b-1a1b-bb62-56da-91472e94a392@microchip.com>

On 10/4/21 8:01 AM, Tudor.Ambarus at microchip.com wrote:

cut

>>> +     if (!treat_id_collisions)
>>> +             return;
>>
>> No, this doesn't seem quite right. Why would you not want to treat ID
>> collisions for flashes that use spi_nor_init_params_deprecated()? What
>> makes this not possible for them?
> 
> I think I wanted to motivate people to switch to the parse SFDP first idea.
> Why would we care for those flashes that use deprecated methods?
> 

No, no, I'm wrong.

cut

>>> +     if (nor->info->flags & SPI_NOR_PARSE_SFDP)
>>> +             spi_nor_sfdp_init_params(nor, true);
>>> +     else
>>> +             spi_nor_init_params_deprecated(nor);

deprecated maybe it's not the best name, because here falls also the
non-SFDP compliant flashes, which are not mandatory seen as deprecated.

I'll rework this and resubmit.


From boris.brezillon at collabora.com  Mon Oct  4 04:47:00 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 4 Oct 2021 13:47:00 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004101246.kagtezizympxupat@skn-laptop>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
Message-ID: <20211004134700.26327f6f@collabora.com>

On Mon, 4 Oct 2021 12:12:46 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Mon, Oct 04, 2021 at 11:58:17AM +0200, Boris Brezillon wrote:
> > On Mon, 4 Oct 2021 10:55:09 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:  
> > > > On Mon,  4 Oct 2021 08:56:09 +0200
> > > > Sean Nyekjaer <sean at geanix.com> wrote:
> > > >     
> > > > > This will prevent nand_get_device() from returning -EBUSY.
> > > > > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > > > > access to the mtd device.
> > > > > 
> > > > > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > > > > that will in turn hard error on every error returened.
> > > > > We have seen during ubifs tries to call mtd_write before the mtd device
> > > > > is resumed.    
> > > > 
> > > > I think the problem is here. Why would UBIFS/UBI try to write something
> > > > to a device that's not resumed yet (or has been suspended already, if
> > > > you hit this in the suspend path).
> > > >     
> > > > > 
> > > > > Exec_op[0] speed things up, so we see this race when the device is
> > > > > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > > > > allows it to return -EBUSY, before that commit it would have waited for
> > > > > the mtd device to resume.    
> > > > 
> > > > Uh, wait. If nand_resume() was called before any writes/reads this
> > > > wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> > > > blocking, the problem is that someone issues a write/read before calling
> > > > mtd_resume().
> > > >     
> > > 
> > > The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.
> > > 
> > > """
> > > Last important change to mention: we now return -EBUSY when someone
> > > tries to access a device that as been suspended, and propagate this
> > > error to the upper layer.
> > > """
> > > 
> > > IMHO "mtd: rawnand: Simplify the locking" should never had been merged
> > > before the upper layers was fixed to handle -EBUSY. ;)
> > > Which they still not are...  
> > 
> > That's not really the problem here. Upper layers should never get
> > -EBUSY in the first place if the MTD device was resumed before the UBI
> > device. Looks like we have a missing UBI -> MTD parenting link, which
> > would explain why things don't get resumed in the right order. Can you
> > try with the following diff applied?
> > 
> > ---
> > diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> > index f399edc82191..1981ce8f3a26 100644
> > --- a/drivers/mtd/ubi/build.c
> > +++ b/drivers/mtd/ubi/build.c
> > @@ -905,6 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int
> > ubi_num, ubi->dev.release = dev_release;
> >         ubi->dev.class = &ubi_class;
> >         ubi->dev.groups = ubi_dev_groups;
> > +       ubi->dev.parent = &mtd->dev;
> >  
> >         ubi->mtd = mtd;
> >         ubi->ubi_num = ubi_num;
> >   
> 
> No change:
> [   71.739193] Filesystems sync: 34.212 seconds
> [   71.755044] Freezing user space processes ... (elapsed 0.004 seconds) done.
> [   71.767289] OOM killer disabled.
> [   71.770552] Freezing remaining freezable tasks ... (elapsed 0.004 seconds) done.
> [   71.782182] printk: Suspending console(s) (use no_console_suspend to debug)
> [   71.824391] nand_suspend
> [   71.825177] gpmi_pm_suspend
> [   71.825676] PM: suspend devices took 0.040 seconds
> [   71.825971] nand_write_oob - nand_get_device() returned -EBUSY
> [   71.825985] ubi0 error: ubi_io_write: error -16 while writing 4096 bytes to PEB 986:65536, written 0 bytes
> [   71.826029] CPU: 0 PID: 7 Comm: kworker/u2:0 Not tainted 5.15.0-rc3-dirty #43
> [   71.826043] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
> [   71.826054] Workqueue: writeback wb_workfn (flush-ubifs_0_8)
> [   71.826094] [<c010da84>] (unwind_backtrace) from [<c010a1b4>] (show_stack+0x10/0x14)
> [   71.826122] [<c010a1b4>] (show_stack) from [<c0989c30>] (dump_stack_lvl+0x40/0x4c)
> [   71.826151] [<c0989c30>] (dump_stack_lvl) from [<c05ed690>] (ubi_io_write+0x510/0x6b0)
> [   71.826178] [<c05ed690>] (ubi_io_write) from [<c05ea2f0>] (ubi_eba_write_leb+0xd0/0x968)
> [   71.826204] [<c05ea2f0>] (ubi_eba_write_leb) from [<c05e8754>] (ubi_leb_write+0xd0/0xe8)
> [   71.826232] [<c05e8754>] (ubi_leb_write) from [<c03d67bc>] (ubifs_leb_write+0x68/0x104)
> [   71.826263] [<c03d67bc>] (ubifs_leb_write) from [<c03d79e8>] (ubifs_wbuf_write_nolock+0x28c/0x74c)
> [   71.826291] [<c03d79e8>] (ubifs_wbuf_write_nolock) from [<c03ca18c>] (ubifs_jnl_write_data+0x1b8/0x2b4)
> [   71.826319] [<c03ca18c>] (ubifs_jnl_write_data) from [<c03cd184>] (do_writepage+0x190/0x284)
> [   71.826342] [<c03cd184>] (do_writepage) from [<c023083c>] (__writepage+0x14/0x68)
> [   71.826367] [<c023083c>] (__writepage) from [<c0231748>] (write_cache_pages+0x1c8/0x3f0)
> [   71.826390] [<c0231748>] (write_cache_pages) from [<c0233854>] (do_writepages+0xcc/0x1f4)
> [   71.826413] [<c0233854>] (do_writepages) from [<c02d03dc>] (__writeback_single_inode+0x2c/0x1b4)
> [   71.826440] [<c02d03dc>] (__writeback_single_inode) from [<c02d0a64>] (writeback_sb_inodes+0x200/0x470)
> [   71.826466] [<c02d0a64>] (writeback_sb_inodes) from [<c02d0d10>] (__writeback_inodes_wb+0x3c/0xf4)
> [   71.826493] [<c02d0d10>] (__writeback_inodes_wb) from [<c02d0f58>] (wb_writeback+0x190/0x1f0)
> [   71.826520] [<c02d0f58>] (wb_writeback) from [<c02d21d8>] (wb_workfn+0x2c0/0x3d4)
> [   71.826545] [<c02d21d8>] (wb_workfn) from [<c013ac04>] (process_one_work+0x1e0/0x440)
> [   71.826574] [<c013ac04>] (process_one_work) from [<c013aeac>] (worker_thread+0x48/0x594)
> [   71.826600] [<c013aeac>] (worker_thread) from [<c0142364>] (kthread+0x134/0x15c)
> [   71.826625] [<c0142364>] (kthread) from [<c0100150>] (ret_from_fork+0x14/0x24)

I'm not entirely sure, but given the timing, it looks like this
actually happens in the suspend path, not it the resume path. What I
don't get is why we still have a kernel thread running at that point.

> 
> [...]
> 
> [   71.921673] gpmi_pm_resume
> [   71.923319] nand_resume
> [   71.936120] PM: resume devices took 0.100 seconds
> [   72.314551] ci_hdrc ci_hdrc.0: freeing queued request
> [   72.521656] IPv6: ADDRCONF(NETDEV_CHANGE): usb0: link becomes ready
> [   75.006404] OOM killer enabled.
> [   75.009562] Restarting tasks ...
> [   75.074123] done.
> [   75.095540] PM: suspend exit
> 
> With the RFC PATCH:
> [ 3702.682122] Filesystems sync: 33.416 seconds
> [ 3702.695350] Freezing user space processes ... (elapsed 0.001 seconds) done.
> [ 3702.704218] OOM killer disabled.
> [ 3702.707559] Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done.
> [ 3702.718696] printk: Suspending console(s) (use no_console_suspend to debug)
> [ 3702.757660] nand_suspend
> [ 3702.758577] gpmi_pm_suspend
> [ 3702.759072] PM: suspend devices took 0.040 seconds
> [ 3702.761618] Disabling non-boot CPUs ...
> [ 3702.854985] gpmi_pm_resume
> [ 3702.856623] nand_resume
> [ 3702.867796] PM: resume devices took 0.110 seconds
> [ 3702.895019] OOM killer enabled.
> [ 3702.898291] Restarting tasks ... done.
> [ 3702.950723] PM: suspend exit



From Alexander.Stein at ew.tq-group.com  Mon Oct  4 05:10:53 2021
From: Alexander.Stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 4 Oct 2021 12:10:53 +0000
Subject: AW: (EXT) Re: [PATCH 2/2] mtd: spi-nor: micron-st: Add support for
 output-driver-strength
Message-ID: <kcEE.Dc11rDoPQ8iRcxif5TBAOA.gESl4Bi51wE@vtuxmail01.tq-net.de>

Hello,

> Does the micron flash define the SCCR SFDP map?

As far as I can tell, it only defines the Basis SPI protocol and the 4-byte Adress Instruction Table.
Dunno when the SCCR SFDP map was added, but this flash only announces JESD216B (SFDP 1.6)

Is there some tool for dumping/decoding the SFDP available?

Best regards,
Alexander



From manivannan.sadhasivam at linaro.org  Mon Oct  4 05:39:26 2021
From: manivannan.sadhasivam at linaro.org (Manivannan Sadhasivam)
Date: Mon,  4 Oct 2021 18:09:26 +0530
Subject: [PATCH] MAINTAINERS: Add entry for Qualcomm NAND controller driver
Message-ID: <20211004123926.53462-1-manivannan.sadhasivam@linaro.org>

Since I maintain the dt-binding for this controller, I'm stepping
forward to maintain the driver also.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
---
 MAINTAINERS | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2c9165e4e816..8cfd8ae9e69e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15580,6 +15580,14 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/regulator/vqmmc-ipq4019-regulator.yaml
 F:	drivers/regulator/vqmmc-ipq4019-regulator.c
 
+QUALCOMM NAND CONTROLLER DRIVER
+M:	Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>
+L:	linux-mtd at lists.infradead.org
+L:	linux-arm-msm at vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
+F:	drivers/mtd/nand/raw/qcom_nandc.c
+
 QUALCOMM RMNET DRIVER
 M:	Subash Abhinov Kasiviswanathan <subashab at codeaurora.org>
 M:	Sean Tranchetti <stranche at codeaurora.org>
-- 
2.25.1



From andy.shevchenko at gmail.com  Mon Oct  4 07:29:47 2021
From: andy.shevchenko at gmail.com (Andy Shevchenko)
Date: Mon, 4 Oct 2021 17:29:47 +0300
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20210930100719.2176-3-mika.westerberg@linux.intel.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
Message-ID: <CAHp75VdtOHn4ED-ixdDngBQw10OnKmbtTv=ydLs6dYbkjyqW4Q@mail.gmail.com>

On Thu, Sep 30, 2021 at 1:08 PM Mika Westerberg
<mika.westerberg at linux.intel.com> wrote:
>
> The preferred way to implement SPI-NOR controller drivers is through SPI
> subsubsystem utilizing the SPI MEM core functions. This converts the
> Intel SPI flash controller driver over the SPI MEM by moving the driver
> from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> SPI MEM functions. The driver name will be changed from intel-spi to
> spi-intel to match the convention used in the SPI subsystem.

...

> +config SPI_INTEL_PCI
> +       tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
> +       depends on PCI && (X86 || COMPILE_TEST)

Perhaps two entries, one of which will be the same as for platform case?

> +       depends on SPI_MEM
> +       select SPI_INTEL
> +       help
> +         This enables PCI support for the Intel PCH/PCU SPI controller in
> +         master mode. This controller is present in modern Intel hardware
> +         and is used to hold BIOS and other persistent settings. Using
> +         this driver it is possible to upgrade BIOS directly from Linux.
> +
> +         Say N here unless you know what you are doing. Overwriting the
> +         SPI flash may render the system unbootable.
> +
> +         To compile this driver as a module, choose M here: the module
> +         will be called spi-intel-pci.
> +
> +config SPI_INTEL_PLATFORM
> +       tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
> +       depends on X86 || COMPILE_TEST
> +       depends on SPI_MEM
> +       select SPI_INTEL
> +       help
> +         This enables platform support for the Intel PCH/PCU SPI
> +         controller in master mode. This controller is present in modern
> +         Intel hardware and is used to hold BIOS and other persistent
> +         settings. Using this driver it is possible to upgrade BIOS
> +         directly from Linux.
> +
> +         Say N here unless you know what you are doing. Overwriting the
> +         SPI flash may render the system unbootable.
> +
> +         To compile this driver as a module, choose M here: the module
> +         will be called spi-intel-platform.

...

+ Blank line ?

>  #include <linux/mtd/partitions.h>
>  #include <linux/mtd/spi-nor.h>

+ Blank line?

> +#include <linux/spi/flash.h>
> +#include <linux/spi/spi.h>
> +#include <linux/spi/spi-mem.h>

The rationale is to show that we use two sub(sub)sytems here.

...

> -                       dev_err(ispi->dev, "read error: %llx: %#x\n", from,
> +                       dev_err(ispi->dev, "read error: %x: %#x\n", from,
>                                 status);

Now one line?

...

> -                       dev_err(ispi->dev, "write error: %llx: %#x\n", to,
> +                       dev_err(ispi->dev, "write error: %x: %#x\n", to,
>                                 status);

Ditto.

...

> +               ret = intel_spi_sw_cycle(ispi, opcode, 0,
> +                                        OPTYPE_WRITE_WITH_ADDR);
> +               return ret ? ret : 0;

Why not simply return intel_spi_dw_cycle(...); ?

...

> +       val = readl(ispi->base + HSFSTS_CTL);
> +       val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> +       val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;

> +       val |= cmd;
> +       val |= HSFSTS_CTL_FGO;

Maybe swap these lines to group constants?

...

> +       status = readl(ispi->base + HSFSTS_CTL);
> +       if (status & HSFSTS_CTL_FCERR)
> +               return -EIO;

> +       else if (status & HSFSTS_CTL_AEL)

Redundant 'else'

> +               return -EACCES;

...

> +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
> +{
> +       struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> +       size_t nbytes = op->data.nbytes;
> +       u8 opcode = op->cmd.opcode;
> +
> +       if (op->addr.nbytes) {
> +               if  (op->data.dir == SPI_MEM_DATA_IN)
> +                       return intel_spi_read(ispi, op->addr.val, nbytes,
> +                                             op->data.buf.in);

> +               else if (op->data.dir == SPI_MEM_DATA_OUT)

Redundant 'else' here and nearby.

> +                       return intel_spi_write(ispi, op->addr.val, nbytes,
> +                                              op->data.buf.out);
> +               else if (op->data.dir == SPI_MEM_NO_DATA)
> +                       return intel_spi_erase(ispi, opcode, op->addr.val);
> +       } else {
> +               if  (op->data.dir == SPI_MEM_DATA_IN)
> +                       return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
> +                                                 nbytes);
> +               else if (op->data.dir == SPI_MEM_DATA_OUT)
> +                       return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
> +                                                  nbytes);
> +               else if (op->data.dir == SPI_MEM_NO_DATA)
> +                       return intel_spi_write_reg(ispi, opcode, NULL, 0);
>         }

> +       return -EINVAL;
> +}

-- 
With Best Regards,
Andy Shevchenko


From miquel.raynal at bootlin.com  Mon Oct  4 08:33:51 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 4 Oct 2021 17:33:51 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <CAOf5uwk3XLtTgoMuRU+hP29xQzPUj9NEuV58V5QdXXigQ0waVQ@mail.gmail.com>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <3160469.44csPzL39Z@n95hx1g2>
 <CAOf5uwk3XLtTgoMuRU+hP29xQzPUj9NEuV58V5QdXXigQ0waVQ@mail.gmail.com>
Message-ID: <20211004173351.36a66ccb@xps13>

Hi Michael, Christian,

michael at amarulasolutions.com wrote on Mon, 4 Oct 2021 08:27:54 +0200:

> Hi Christian
> 
> On Mon, Oct 4, 2021 at 7:54 AM Christian Eggers <ceggers at arri.de> wrote:
> >
> > On Monday, 29 July 2019, 08:41:51 CEST, Greg Ungerer wrote:  
> > > Hi Miquel,
> > >
> > > I am experiencing a problem with NAND flash DMA timeouts on
> > > iMX6ull based boards. The problem is very similar to that
> > > described in:
> > >
> > >    https://linux-mtd.infradead.narkive.com/JIUulfFB/gpmi-imx6ull-timeout-on-dma
> > >
> > > That didn't come to any specific resolution that I could see
> > > in that thread.  
> >
> > Hi all,
> >
> > I am joining this thread because I am also affected by this problem. I use
> > kernel 5.10.65-rt53 but I have seen this issue on many previous versions. In the
> > past I only recognized this on my development setup but now this has been found
> > by our testing team.
> >
> > In our test setup we simply perform a reboot every 30s. After 5 to 200 cycles
> > the test stops due to this error.
> >
> > The kernel version I use already includes:
> >  
> > > Han Xu <han.xu at nxp.com>
> > > mtd: rawnand: gpmi: Fix the random DMA timeout issue  
> >
> > Additionally I tried ...
> >  
> > > Michael Trimarchi <michael at amarulasolutions.com>
> > > mtd: nand: Calculate the clock before enable it  
> >
> > ... but the problem still persists.
> >
> > In my case, some registers show different values (annotated below):
> >  
> > >
> > > The boot trace on the console for me looks like this:
> > >
> > > nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xda  
> >   nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc  
> > > nand: Micron MT29F2G08ABAEAWP  
> >   nand: Micron MT29F4G08ABADAH4  
> > > nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> > > gpmi-nand 1806000.gpmi-nand: DMA timeout, last DMA
> > > gpmi-nand 1806000.gpmi-nand: Show GPMI registers :
> > > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x20830002
> > > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x01c6800c
> > > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00010101
> > > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0xe0000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x23023336
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x000001ee
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0xff000001
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x00000001  
> >   gpmi-nand 1806000.nand-controller: offset 0x0c0 : 0x00000202  
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x05020000
> > > gpmi-nand 1806000.gpmi-nand: Show BCH registers :
> > > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x00000100  
> >   gpmi-nand 1806000.nand-controller: offset 0x000 : 0x00000000  
> > > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000010
> > > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0x030a2080  
> >   gpmi-nand 1806000.nand-controller: offset 0x080 : 0x070a4080  
> > > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x083e2080  
> >   gpmi-nand 1806000.nand-controller: offset 0x090 : 0x10da4080  
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x070a4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0x10da4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x070a4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x10da4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0e0 : 0x070a4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x0f0 : 0x10da4080
> > > gpmi-nand 1806000.gpmi-nand: offset 0x100 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x110 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x120 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x130 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x140 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x150 : 0x20484342
> > > gpmi-nand 1806000.gpmi-nand: offset 0x160 : 0x01000000
> > > gpmi-nand 1806000.gpmi-nand: offset 0x170 : 0x00000000
> > > gpmi-nand 1806000.gpmi-nand: BCH Geometry :
> > > GF length              : 13
> > > ECC Strength           : 8
> > > Page Size in Bytes     : 2110
> > > Metadata Size in Bytes : 10
> > > ECC Chunk0 Size in Bytes: 512
> > > ECC Chunkn Size in Bytes: 512  
> >   ECC Chunk Size in Bytes: 512  
> > > ECC Chunk Count        : 4
> > > Payload Size in Bytes  : 2048
> > > Auxiliary Size in Bytes: 16
> > > Auxiliary Status Offset: 12
> > > Block Mark Byte Offset : 1999
> > > Block Mark Bit Offset  : 0  
> >
> > Please let me know if further information is required.  
> 
> I need to continue on it, during the following days. I have stopped
> moving to LTS 4.19.y and with my partial revert.
> The problem as usual was to go to production on some devices. Anyway I
> have the device that has this problem. I can
> restart next weekend. One of the thing I notice that make not work on imx28 is:
> 
>        if (sdr->tRC_min >= 30000) {
>                /* ONFI non-EDO modes [0-3] */
>                hw->clk_rate = 22000000;
>                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
>        } else if (sdr->tRC_min >= 25000) {
>                /* ONFI EDO mode 4 */
>                hw->clk_rate = 80000000;
>                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
>        } else {
>                /* ONFI EDO mode 5 */
>                hw->clk_rate = 100000000;
>                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
>        }
> 
> Here there is an assumption that your clk_rate can be set to that rate
> but on imx28, the parent clock of the NAND one can not
> let it go to those speed. Changing it let it really set to the wrong
> value, so imx28 was totally broken. The other computation was based
> not on fixed clock rate but I think even on clk_get_rate

Interesting finding. I guess we should try to apply the desired block
rate and if the final clock rate is too far from what is achievable and
works we should refuse the requested configuration. The core will
automatically try the slowest -but perhaps working- modes.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Mon Oct  4 08:39:38 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 4 Oct 2021 17:39:38 +0200
Subject: [RFC PATCH 1/1] mtd: block2mtd: add support for an optional
 custom MTD label
In-Reply-To: <87h7e32yhz.fsf@gmail.com>
References: <20210928154937.2668575-1-troglobit@gmail.com>
 <20210928180521.4516405c@xps13> <87h7e32yhz.fsf@gmail.com>
Message-ID: <20211004173938.12dc2d9a@xps13>

Hi Joachim,

troglobit at gmail.com wrote on Wed, 29 Sep 2021 17:27:20 +0200:

> Hi Miquel!
> 
> On Tue, Sep 28, 2021 at 18:05, Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> > Hi Joachim,
> > troglobit at gmail.com wrote on Tue, 28 Sep 2021 17:49:38 +0200:  
> >> This patch adds support for an optional MTD label for mtd2block emulated
> >> MTD devices.  Useful when, e.g. testing device images using Qemu.  The
> >> following /etc/fstab line in can then be used to mount a file system
> >> regardless of the actual MTD partition number:
> >> 
> >>     mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0
> >> 
> >> Kernel command line syntax:
> >> 
> >>     block2mtd.block2mtd=/dev/sda,,Config
> >> 
> >> The ',,' is the optional erase_size, which like before this patch,
> >> defaults to PAGE_SIZE when omitted.  
> > We already have a label property that can be added in the DT, isn't
> > it enough?  
> 
> Unless I'm missing something, no.  Sorry if if the description was a bit
> unclear.  Let me try expanding on it a bit.
> 
> The block2mtd driver is used a lot when emulating proper MTDs, I'm sure
> we are not alone in building system images that a flashed to an MTD
> device, which we want to be able to test in Qemu before deploying.
> 
> So what we typically do is have a read-only rootfs (squashfs) on one
> partition, and another for config data that uses overlayfs to get a
> writable /etc, for instance.  This is a reduced example, and the order
> of parititions sometimes differ, so we use parition labels. When we test
> in Qemu there's only the automatic DTB from Qemu itself that's injected,
> e.g.
> 
>   qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic       \
> 	-kernel Image -initrd rootfs.img -append               \
>           "root=/dev/ram block2mtd.block2mtd=/dev/vda"         \
>         -drive file=config.img,if=none,format=raw,id=hd0       \
>         -device virtio-blk-device,drive=hd0
> 
> With the default blockt2mtd args we convert the emulated disk to be
> used as an MTD partition, but the name we get in Linux is not the
> name we have in our /etc/fstab on a real target.
> 
>   # cat /proc/mtd 
>   dev:    size   erasesize  name
>   mtd0: 00f00000 00001000 "block2mtd: /dev/vda"
> 
> With the patch we can align the two cases; the embedded system and the
> emulated one, by using the same paritition label.  I.e., with the patch
> and the new argument to the kernel cmdline:
> 
>   qemu-system-aarch64 -M virt -cpu cortex-a53 -nographic       \
> 	-kernel Image -initrd rootfs.img -append               \
>           "root=/dev/ram block2mtd.block2mtd=/dev/vda,,Config" \
>         -drive file=config.img,if=none,format=raw,id=hd0       \
>         -device virtio-blk-device,drive=hd0
> 
> Linux gives the emulated MTD the same partition name we use in the
> real embedded system:
> 
>   # cat /proc/mtd 
>   dev:    size   erasesize  name
>   mtd0: 00f00000 00001000 "Config"

I don't know this portion of the code very well, but indeed if this is
something only declared on the cmdline I understand the request.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Mon Oct  4 08:40:48 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 4 Oct 2021 17:40:48 +0200
Subject: [PATCH 9/9] mtd: rawnand: xway: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20210928222258.199726-10-miquel.raynal@bootlin.com>
References: <20210928222258.199726-1-miquel.raynal@bootlin.com>
 <20210928222258.199726-10-miquel.raynal@bootlin.com>
Message-ID: <20211004174048.608b07ef@xps13>

Hi Jan,

miquel.raynal at bootlin.com wrote on Wed, 29 Sep 2021 00:22:48 +0200:

> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: d525914b5bd8 ("mtd: rawnand: xway: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Cc: Jan Hoffmann <jan at 3e8.eu>

I think you already tested this change and validated it, would you mind
providing your Tested-by?

> Cc: Kestrel seventyfour <kestrelseventyfour at gmail.com>
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  drivers/mtd/nand/raw/xway_nand.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
> index 26751976e502..236fd8c5a958 100644
> --- a/drivers/mtd/nand/raw/xway_nand.c
> +++ b/drivers/mtd/nand/raw/xway_nand.c
> @@ -148,9 +148,8 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len)
>  
>  static int xway_attach_chip(struct nand_chip *chip)
>  {
> -	chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
> -
> -	if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
> +	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
> +	    chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
>  		chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
>  
>  	return 0;
> @@ -219,6 +218,13 @@ static int xway_nand_probe(struct platform_device *pdev)
>  		    | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
>  		    | cs_flag, EBU_NAND_CON);
>  
> +	/*
> +	 * This driver assumes that the default ECC engine should be TYPE_SOFT.
> +	 * Set ->engine_type before registering the NAND devices in order to
> +	 * provide a driver specific default value.
> +	 */
> +	data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
> +
>  	/* Scan to find existence of the device */
>  	err = nand_scan(&data->chip, 1);
>  	if (err)


Thanks,
Miqu?l


From han.xu at nxp.com  Mon Oct  4 09:06:20 2021
From: han.xu at nxp.com (Han Xu)
Date: Mon, 4 Oct 2021 11:06:20 -0500
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211004173351.36a66ccb@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <3160469.44csPzL39Z@n95hx1g2>
 <CAOf5uwk3XLtTgoMuRU+hP29xQzPUj9NEuV58V5QdXXigQ0waVQ@mail.gmail.com>
 <20211004173351.36a66ccb@xps13>
Message-ID: <20211004160620.3guajv5vvtfjrl7c@umbrella>

On 21/10/04 05:33PM, Miquel Raynal wrote:
> Hi Michael, Christian,
> 
> michael at amarulasolutions.com wrote on Mon, 4 Oct 2021 08:27:54 +0200:
> 
> > Hi Christian
> > 
> > On Mon, Oct 4, 2021 at 7:54 AM Christian Eggers <ceggers at arri.de> wrote:
> > >
> > > On Monday, 29 July 2019, 08:41:51 CEST, Greg Ungerer wrote:  
> > > > Hi Miquel,
> > > >
> > > > I am experiencing a problem with NAND flash DMA timeouts on
> > > > iMX6ull based boards. The problem is very similar to that
> > > > described in:
> > > >
> > > >    https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Flinux-mtd.infradead.narkive.com%2FJIUulfFB%2Fgpmi-imx6ull-timeout-on-dma&amp;data=04%7C01%7Chan.xu%40nxp.com%7C278d7b93edbb4b72923408d9874c5ffe%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637689584362563293%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&amp;sdata=uSkVTsEF9yhHt5ZstJMbPIjUQbHzjhiHMjO9eDgFSg0%3D&amp;reserved=0
> > > >
> > > > That didn't come to any specific resolution that I could see
> > > > in that thread.  
> > >
> > > Hi all,
> > >
> > > I am joining this thread because I am also affected by this problem. I use
> > > kernel 5.10.65-rt53 but I have seen this issue on many previous versions. In the
> > > past I only recognized this on my development setup but now this has been found
> > > by our testing team.
> > >
> > > In our test setup we simply perform a reboot every 30s. After 5 to 200 cycles
> > > the test stops due to this error.
> > >
> > > The kernel version I use already includes:
> > >  
> > > > Han Xu <han.xu at nxp.com>
> > > > mtd: rawnand: gpmi: Fix the random DMA timeout issue  
> > >
> > > Additionally I tried ...
> > >  
> > > > Michael Trimarchi <michael at amarulasolutions.com>
> > > > mtd: nand: Calculate the clock before enable it  
> > >
> > > ... but the problem still persists.
> > >
> > > In my case, some registers show different values (annotated below):
> > >  
> > > >
> > > > The boot trace on the console for me looks like this:
> > > >
> > > > nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xda  
> > >   nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc  
> > > > nand: Micron MT29F2G08ABAEAWP  
> > >   nand: Micron MT29F4G08ABADAH4  
> > > > nand: 256 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> > > > gpmi-nand 1806000.gpmi-nand: DMA timeout, last DMA
> > > > gpmi-nand 1806000.gpmi-nand: Show GPMI registers :
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x20830002
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x01c6800c
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00010101
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0xe0000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x23023336
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x000001ee
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0xff000001
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x00000001  
> > >   gpmi-nand 1806000.nand-controller: offset 0x0c0 : 0x00000202  
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x05020000
> > > > gpmi-nand 1806000.gpmi-nand: Show BCH registers :
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x000 : 0x00000100  
> > >   gpmi-nand 1806000.nand-controller: offset 0x000 : 0x00000000  
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x010 : 0x00000010
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x020 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x030 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x040 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x050 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x060 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x070 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x080 : 0x030a2080  
> > >   gpmi-nand 1806000.nand-controller: offset 0x080 : 0x070a4080  
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x090 : 0x083e2080  
> > >   gpmi-nand 1806000.nand-controller: offset 0x090 : 0x10da4080  
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0a0 : 0x070a4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0b0 : 0x10da4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0c0 : 0x070a4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0d0 : 0x10da4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0e0 : 0x070a4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x0f0 : 0x10da4080
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x100 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x110 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x120 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x130 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x140 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x150 : 0x20484342
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x160 : 0x01000000
> > > > gpmi-nand 1806000.gpmi-nand: offset 0x170 : 0x00000000
> > > > gpmi-nand 1806000.gpmi-nand: BCH Geometry :
> > > > GF length              : 13
> > > > ECC Strength           : 8
> > > > Page Size in Bytes     : 2110
> > > > Metadata Size in Bytes : 10
> > > > ECC Chunk0 Size in Bytes: 512
> > > > ECC Chunkn Size in Bytes: 512  
> > >   ECC Chunk Size in Bytes: 512  
> > > > ECC Chunk Count        : 4
> > > > Payload Size in Bytes  : 2048
> > > > Auxiliary Size in Bytes: 16
> > > > Auxiliary Status Offset: 12
> > > > Block Mark Byte Offset : 1999
> > > > Block Mark Bit Offset  : 0  
> > >
> > > Please let me know if further information is required.  

Could you please try to add clock dis/enable when setting clock rate, in case
clock glitches.

clk_disable_unprepare(r->clock[0]);
clk_set_rate(r->clock[0], hw->clk_rate);
clk_prepare_enable(r->clock[0]);

> > 
> > I need to continue on it, during the following days. I have stopped
> > moving to LTS 4.19.y and with my partial revert.
> > The problem as usual was to go to production on some devices. Anyway I
> > have the device that has this problem. I can
> > restart next weekend. One of the thing I notice that make not work on imx28 is:
> > 
> >        if (sdr->tRC_min >= 30000) {
> >                /* ONFI non-EDO modes [0-3] */
> >                hw->clk_rate = 22000000;
> >                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_4_TO_8NS;
> >        } else if (sdr->tRC_min >= 25000) {
> >                /* ONFI EDO mode 4 */
> >                hw->clk_rate = 80000000;
> >                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
> >        } else {
> >                /* ONFI EDO mode 5 */
> >                hw->clk_rate = 100000000;
> >                wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
> >        }
> > 
> > Here there is an assumption that your clk_rate can be set to that rate
> > but on imx28, the parent clock of the NAND one can not
> > let it go to those speed. Changing it let it really set to the wrong
> > value, so imx28 was totally broken. The other computation was based
> > not on fixed clock rate but I think even on clk_get_rate
> 
> Interesting finding. I guess we should try to apply the desired block
> rate and if the final clock rate is too far from what is achievable and
> works we should refuse the requested configuration. The core will
> automatically try the slowest -but perhaps working- modes.
> 
> Thanks,
> Miqu?l


From jan at 3e8.eu  Mon Oct  4 09:21:35 2021
From: jan at 3e8.eu (Jan Hoffmann)
Date: Mon, 4 Oct 2021 18:21:35 +0200
Subject: [PATCH 9/9] mtd: rawnand: xway: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20211004174048.608b07ef@xps13>
References: <20210928222258.199726-1-miquel.raynal@bootlin.com>
 <20210928222258.199726-10-miquel.raynal@bootlin.com>
 <20211004174048.608b07ef@xps13>
Message-ID: <62e191eb-6e85-0c7f-7447-dc2106bb0a4d@3e8.eu>

Hi Miqu?l,

> Hi Jan,
> 
> miquel.raynal at bootlin.com wrote on Wed, 29 Sep 2021 00:22:48 +0200:
> 
>> Following the introduction of the generic ECC engine infrastructure, it
>> was necessary to reorganize the code and move the ECC configuration in
>> the ->attach_chip() hook. Failing to do that properly lead to a first
>> series of fixes supposed to stabilize the situation. Unfortunately, this
>> only fixed the use of software ECC engines, preventing any other kind of
>> engine to be used, including on-die ones.
>>
>> It is now time to (finally) fix the situation by ensuring that we still
>> provide a default (eg. software ECC) but will still support different
>> ECC engines such as on-die ECC engines if properly described in the
>> device tree.
>>
>> There are no changes needed on the core side in order to do this, but we
>> just need to leverage the logic there which allows:
>> 1- a subsystem default (set to Host engines in the raw NAND world)
>> 2- a driver specific default (here set to software ECC engines)
>> 3- any type of engine requested by the user (ie. described in the DT)
>>
>> As the raw NAND subsystem has not yet been fully converted to the ECC
>> engine infrastructure, in order to provide a default ECC engine for this
>> driver we need to set chip->ecc.engine_type *before* calling
>> nand_scan(). During the initialization step, the core will consider this
>> entry as the default engine for this driver. This value may of course
>> be overloaded by the user if the usual DT properties are provided.
>>
>> Fixes: d525914b5bd8 ("mtd: rawnand: xway: Move the ECC initialization to ->attach_chip()")
>> Cc: stable at vger.kernel.org
>> Cc: Jan Hoffmann <jan at 3e8.eu>
> 
> I think you already tested this change and validated it, would you mind
> providing your Tested-by?

Yes, I tested this on a device using software ECC (Fritzbox 7412 with
Toshiba NAND chip) and on a device using on-die ECC (Fritzbox 7362 SL
with Micron NAND chip).

Tested-by: Jan Hoffmann <jan at 3e8.eu>

>> Cc: Kestrel seventyfour <kestrelseventyfour at gmail.com>
>> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
>> ---
>>   drivers/mtd/nand/raw/xway_nand.c | 12 +++++++++---
>>   1 file changed, 9 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/xway_nand.c b/drivers/mtd/nand/raw/xway_nand.c
>> index 26751976e502..236fd8c5a958 100644
>> --- a/drivers/mtd/nand/raw/xway_nand.c
>> +++ b/drivers/mtd/nand/raw/xway_nand.c
>> @@ -148,9 +148,8 @@ static void xway_write_buf(struct nand_chip *chip, const u_char *buf, int len)
>>   
>>   static int xway_attach_chip(struct nand_chip *chip)
>>   {
>> -	chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
>> -
>> -	if (chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
>> +	if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT &&
>> +	    chip->ecc.algo == NAND_ECC_ALGO_UNKNOWN)
>>   		chip->ecc.algo = NAND_ECC_ALGO_HAMMING;
>>   
>>   	return 0;
>> @@ -219,6 +218,13 @@ static int xway_nand_probe(struct platform_device *pdev)
>>   		    | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
>>   		    | cs_flag, EBU_NAND_CON);
>>   
>> +	/*
>> +	 * This driver assumes that the default ECC engine should be TYPE_SOFT.
>> +	 * Set ->engine_type before registering the NAND devices in order to
>> +	 * provide a driver specific default value.
>> +	 */
>> +	data->chip.ecc.engine_type = NAND_ECC_ENGINE_TYPE_SOFT;
>> +
>>   	/* Scan to find existence of the device */
>>   	err = nand_scan(&data->chip, 1);
>>   	if (err)
> 
> 
> Thanks,
> Miqu?l
> 

Thanks,
Jan


From Tudor.Ambarus at microchip.com  Mon Oct  4 09:28:48 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 4 Oct 2021 16:28:48 +0000
Subject: AW: (EXT) Re: [PATCH 2/2] mtd: spi-nor: micron-st: Add support
 for output-driver-strength
In-Reply-To: <kcEE.Dc11rDoPQ8iRcxif5TBAOA.gESl4Bi51wE@vtuxmail01.tq-net.de>
References: <kcEE.Dc11rDoPQ8iRcxif5TBAOA.gESl4Bi51wE@vtuxmail01.tq-net.de>
Message-ID: <73611195-2f04-9627-7170-88af6c7faf20@microchip.com>

On 10/4/21 3:10 PM, Alexander Stein wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Hello,

Hi,

> 
>> Does the micron flash define the SCCR SFDP map?
> 
> As far as I can tell, it only defines the Basis SPI protocol and the 4-byte Adress Instruction Table.
> Dunno when the SCCR SFDP map was added, but this flash only announces JESD216B (SFDP 1.6)
> 
> Is there some tool for dumping/decoding the SFDP available?
> 

you can access dump the SFDP tables via sysfs. Here's an example:

root at sama5d2-xplained:~# find / -iname spi-nor
/sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor
/sys/devices/platform/ahb/ahb:apb/f8000000.spi/spi_master/spi0/spi0.0/spi-nor
/sys/bus/spi/drivers/spi-nor
root at sama5d2-xplained:~# ls -al /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor
total 0
drwxr-xr-x 2 root root    0 Mar  9 14:51 .
drwxr-xr-x 6 root root    0 Mar  9 14:50 ..
-r--r--r-- 1 root root 4096 Mar  9 14:51 jedec_id
-r--r--r-- 1 root root 4096 Mar  9 14:51 manufacturer
-r--r--r-- 1 root root 4096 Mar  9 14:51 partname
-r--r--r-- 1 root root    0 Mar  9 14:51 sfdp
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
c22016
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
macronix
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname
mx25l3233f
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > mx25l3233f-sfdp
root at sama5d2-xplained:~# hexdump mx25l3233f-sfdp
0000000 4653 5044 0100 ff01 0000 0901 0030 ff00
0000010 00c2 0401 0060 ff00 ffff ffff ffff ffff
0000020 ffff ffff ffff ffff ffff ffff ffff ffff
0000030 20e5 fff1 ffff 01ff eb44 6b08 3b08 bb04
0000040 ffee ffff ffff ff00 ffff ff00 200c 520f
0000050 d810 ff00 ffff ffff ffff ffff ffff ffff
0000060 3600 2650 f99c 6477 cffe ffff ffff ffff
0000070

From robh at kernel.org  Mon Oct  4 10:09:49 2021
From: robh at kernel.org (Rob Herring)
Date: Mon, 4 Oct 2021 12:09:49 -0500
Subject: [PATCH v1] dt-bindings: mtd: spi-nor: use unevaluatedProperties:
 false
In-Reply-To: <20210924180705.14021-1-p.yadav@ti.com>
References: <20210924180705.14021-1-p.yadav@ti.com>
Message-ID: <YVs1XZmeIdix1m1V@robh.at.kernel.org>

On Fri, Sep 24, 2021 at 11:37:05PM +0530, Pratyush Yadav wrote:
> Many SPI controllers need to add properties to slave devices. This could
> be the delay in clock or data lines, etc. These properties are
> controller specific but need to be defined in the slave node because
> they are per-slave and there can be multiple slaves attached to a
> controller.
> 
> If these properties are not added to the slave binding, then the dtbs
> check emits a warning. But these properties do not make much sense in
> the slave binding because they are controller-specific and they will
> just pollute every slave binding.
> 
> One option is to add a separate schema that collects all such properties
> from all such controllers. Slave bindings can simply refer to this
> binding and they should be rid of the warnings.
> 
> There are some limitations with this approach:
> 
> 1. There is no way to specify required properties. The schema would
> contain properties for all controllers and there would be no way to know
> which controller is being used.
> 
> 2. There would be no way to restrict additional properties. Since this
> schema will be used with an allOf operator, additionalProperties would
> need to be true. In addition, the slave schema will have to set
> unevaluatedProperties: false.

I don't see what is the problem. If there's a $ref, then 
unevaluatedProperties is what should be used.

> 
> A much simpler option would be to make controller schemas specify those
> properties in patternProperties and set unevaluatedProperties to false
> on slave schemas, which is done in the previous approach anyway. This
> approach would have the same limitations as the 2nd limitation in the
> previous approach. But it does not have the 1st limitation since the
> properties of all controllers are not collected in a single schema, but
> instead reside in the same schema as the controller. It also has the
> added benefit of being much simpler.
> 
> The SPI NOR binding is taken as the first one to follow this. Other
> bindings like SPI NAND can follow in later patches.
> 
> Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
> 
> ---
> I sent the first approach mentioned in the commit message some time ago
> [0]. When re-rolling this series I realized that if we are going to use
> unevaluatedProperties: false, then it would be much simpler to just keep
> everything else as-is. This has clear positives with no negatives
> relative to [0], as explained in the commit message.
> 
> [0] https://lore.kernel.org/all/20210609111707.9555-1-p.yadav at ti.com/T/#u
> 
>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> index ed590d7c6e37..81be0620b264 100644
> --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> @@ -88,7 +88,7 @@ patternProperties:
>    "^otp(-[0-9]+)?$":
>      type: object
> 
> -additionalProperties: false
> +unevaluatedProperties: false

This only works until unevaluatedProperties support is actually 
implemented. Then it's back to the same warnings. In the mean time, we'd 
be allowing any extra random properties to be added for everyone.

Rob


From robh at kernel.org  Mon Oct  4 11:30:22 2021
From: robh at kernel.org (Rob Herring)
Date: Mon, 4 Oct 2021 13:30:22 -0500
Subject: [PATCH 1/6] dt-bindings: memory: renesas, rpc-if: Add support for
 the R9A07G044
In-Reply-To: <20210928140721.8805-2-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-2-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <YVtIPqHyi/z03yxS@robh.at.kernel.org>

On Tue, 28 Sep 2021 15:07:16 +0100, Lad Prabhakar wrote:
> SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
> the RPC-IF interface found on R-Car Gen3 SoC's.
> 
> This patch adds a new compatible string to identify the RZ/G2L family
> so that the timing values on RZ/G2L can be adjusted.
> 
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> ---
>  .../memory-controllers/renesas,rpc-if.yaml    | 51 ++++++++++++++-----
>  1 file changed, 37 insertions(+), 14 deletions(-)
> 

Reviewed-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Mon Oct  4 11:30:33 2021
From: robh at kernel.org (Rob Herring)
Date: Mon, 4 Oct 2021 13:30:33 -0500
Subject: [PATCH 2/6] dt-bindings: memory: renesas,rpc-if: Add optional
 interrupts property
In-Reply-To: <20210928140721.8805-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <YVtISflCYbhKZzdJ@robh.at.kernel.org>

On Tue, 28 Sep 2021 15:07:17 +0100, Lad Prabhakar wrote:
> For completeness add optional interrupts property.
> 
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> ---
>  .../devicetree/bindings/memory-controllers/renesas,rpc-if.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 

Reviewed-by: Rob Herring <robh at kernel.org>


From ceggers at arri.de  Mon Oct  4 23:02:50 2021
From: ceggers at arri.de (Christian Eggers)
Date: Tue, 5 Oct 2021 08:02:50 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211004160620.3guajv5vvtfjrl7c@umbrella>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211004173351.36a66ccb@xps13> <20211004160620.3guajv5vvtfjrl7c@umbrella>
Message-ID: <2229542.ElGaqSPkdT@n95hx1g2>

On Monday, 4 October 2021, 18:06:20 CEST, Han Xu wrote:
> 
> Could you please try to add clock dis/enable when setting clock rate, in case
> clock glitches.
> 
> clk_disable_unprepare(r->clock[0]);
> clk_set_rate(r->clock[0], hw->clk_rate);
> clk_prepare_enable(r->clock[0]);
> 
This looks promising! Last night I had a successful test run with more than 
600 reboots! The test only stopped because my network was disturbed by the
daily backup run...

I'll do further tests within the next 24 hours.

regards
Christian





From sean at geanix.com  Tue Oct  5 00:09:30 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 5 Oct 2021 09:09:30 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211004134700.26327f6f@collabora.com>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
Message-ID: <20211005070930.epgxb5qzumk4awxq@skn-laptop>

On Mon, Oct 04, 2021 at 01:47:00PM +0200, Boris Brezillon wrote:
> On Mon, 4 Oct 2021 12:12:46 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Mon, Oct 04, 2021 at 11:58:17AM +0200, Boris Brezillon wrote:
> > > On Mon, 4 Oct 2021 10:55:09 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:
> > >   
> > > > On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:  
> > > > > On Mon,  4 Oct 2021 08:56:09 +0200
> > > > > Sean Nyekjaer <sean at geanix.com> wrote:
> > > > >     
> > > > > > This will prevent nand_get_device() from returning -EBUSY.
> > > > > > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > > > > > access to the mtd device.
> > > > > > 
> > > > > > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > > > > > that will in turn hard error on every error returened.
> > > > > > We have seen during ubifs tries to call mtd_write before the mtd device
> > > > > > is resumed.    
> > > > > 
> > > > > I think the problem is here. Why would UBIFS/UBI try to write something
> > > > > to a device that's not resumed yet (or has been suspended already, if
> > > > > you hit this in the suspend path).
> > > > >     
> > > > > > 
> > > > > > Exec_op[0] speed things up, so we see this race when the device is
> > > > > > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > > > > > allows it to return -EBUSY, before that commit it would have waited for
> > > > > > the mtd device to resume.    
> > > > > 
> > > > > Uh, wait. If nand_resume() was called before any writes/reads this
> > > > > wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> > > > > blocking, the problem is that someone issues a write/read before calling
> > > > > mtd_resume().
> > > > >     
> > > > 
> > > > The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.
> > > > 
> > > > """
> > > > Last important change to mention: we now return -EBUSY when someone
> > > > tries to access a device that as been suspended, and propagate this
> > > > error to the upper layer.
> > > > """
> > > > 
> > > > IMHO "mtd: rawnand: Simplify the locking" should never had been merged
> > > > before the upper layers was fixed to handle -EBUSY. ;)
> > > > Which they still not are...  
> > > 
> > > That's not really the problem here. Upper layers should never get
> > > -EBUSY in the first place if the MTD device was resumed before the UBI
> > > device. Looks like we have a missing UBI -> MTD parenting link, which
> > > would explain why things don't get resumed in the right order. Can you
> > > try with the following diff applied?
> > > 
> > > ---
> > > diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> > > index f399edc82191..1981ce8f3a26 100644
> > > --- a/drivers/mtd/ubi/build.c
> > > +++ b/drivers/mtd/ubi/build.c
> > > @@ -905,6 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int
> > > ubi_num, ubi->dev.release = dev_release;
> > >         ubi->dev.class = &ubi_class;
> > >         ubi->dev.groups = ubi_dev_groups;
> > > +       ubi->dev.parent = &mtd->dev;
> > >  
> > >         ubi->mtd = mtd;
> > >         ubi->ubi_num = ubi_num;
> > >   
> > 
> > No change:
> > [   71.739193] Filesystems sync: 34.212 seconds
> > [   71.755044] Freezing user space processes ... (elapsed 0.004 seconds) done.
> > [   71.767289] OOM killer disabled.
> > [   71.770552] Freezing remaining freezable tasks ... (elapsed 0.004 seconds) done.
> > [   71.782182] printk: Suspending console(s) (use no_console_suspend to debug)
> > [   71.824391] nand_suspend
> > [   71.825177] gpmi_pm_suspend
> > [   71.825676] PM: suspend devices took 0.040 seconds
> > [   71.825971] nand_write_oob - nand_get_device() returned -EBUSY
> > [   71.825985] ubi0 error: ubi_io_write: error -16 while writing 4096 bytes to PEB 986:65536, written 0 bytes
> > [   71.826029] CPU: 0 PID: 7 Comm: kworker/u2:0 Not tainted 5.15.0-rc3-dirty #43
> > [   71.826043] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
> > [   71.826054] Workqueue: writeback wb_workfn (flush-ubifs_0_8)
> > [   71.826094] [<c010da84>] (unwind_backtrace) from [<c010a1b4>] (show_stack+0x10/0x14)
> > [   71.826122] [<c010a1b4>] (show_stack) from [<c0989c30>] (dump_stack_lvl+0x40/0x4c)
> > [   71.826151] [<c0989c30>] (dump_stack_lvl) from [<c05ed690>] (ubi_io_write+0x510/0x6b0)
> > [   71.826178] [<c05ed690>] (ubi_io_write) from [<c05ea2f0>] (ubi_eba_write_leb+0xd0/0x968)
> > [   71.826204] [<c05ea2f0>] (ubi_eba_write_leb) from [<c05e8754>] (ubi_leb_write+0xd0/0xe8)
> > [   71.826232] [<c05e8754>] (ubi_leb_write) from [<c03d67bc>] (ubifs_leb_write+0x68/0x104)
> > [   71.826263] [<c03d67bc>] (ubifs_leb_write) from [<c03d79e8>] (ubifs_wbuf_write_nolock+0x28c/0x74c)
> > [   71.826291] [<c03d79e8>] (ubifs_wbuf_write_nolock) from [<c03ca18c>] (ubifs_jnl_write_data+0x1b8/0x2b4)
> > [   71.826319] [<c03ca18c>] (ubifs_jnl_write_data) from [<c03cd184>] (do_writepage+0x190/0x284)
> > [   71.826342] [<c03cd184>] (do_writepage) from [<c023083c>] (__writepage+0x14/0x68)
> > [   71.826367] [<c023083c>] (__writepage) from [<c0231748>] (write_cache_pages+0x1c8/0x3f0)
> > [   71.826390] [<c0231748>] (write_cache_pages) from [<c0233854>] (do_writepages+0xcc/0x1f4)
> > [   71.826413] [<c0233854>] (do_writepages) from [<c02d03dc>] (__writeback_single_inode+0x2c/0x1b4)
> > [   71.826440] [<c02d03dc>] (__writeback_single_inode) from [<c02d0a64>] (writeback_sb_inodes+0x200/0x470)
> > [   71.826466] [<c02d0a64>] (writeback_sb_inodes) from [<c02d0d10>] (__writeback_inodes_wb+0x3c/0xf4)
> > [   71.826493] [<c02d0d10>] (__writeback_inodes_wb) from [<c02d0f58>] (wb_writeback+0x190/0x1f0)
> > [   71.826520] [<c02d0f58>] (wb_writeback) from [<c02d21d8>] (wb_workfn+0x2c0/0x3d4)
> > [   71.826545] [<c02d21d8>] (wb_workfn) from [<c013ac04>] (process_one_work+0x1e0/0x440)
> > [   71.826574] [<c013ac04>] (process_one_work) from [<c013aeac>] (worker_thread+0x48/0x594)
> > [   71.826600] [<c013aeac>] (worker_thread) from [<c0142364>] (kthread+0x134/0x15c)
> > [   71.826625] [<c0142364>] (kthread) from [<c0100150>] (ret_from_fork+0x14/0x24)
> 
> I'm not entirely sure, but given the timing, it looks like this
> actually happens in the suspend path, not it the resume path. What I
> don't get is why we still have a kernel thread running at that point.

Have you seen the reproducer script?
---
root at iwg26-v1:/data/root# cat /data/crash.sh
#!/bin/sh -x

echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup

rm /data/test50M
dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
cp /tmp/test50M /data/ &
sleep 1
echo mem > /sys/power/state
---

As seen in the log above disk is synced before suspend.
cp is continuing to copy data to ubifs.
And then user space processes are frozen.
At this point the kernel thread would have unwritten data.

We tried to solve this with:
https://lkml.org/lkml/2021/9/1/280

/Sean


From troglobit at gmail.com  Tue Oct  5 01:03:59 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Tue,  5 Oct 2021 10:03:59 +0200
Subject: [PATCH 1/1] mtd: block2mtd: add support for an optional custom MTD
 label
Message-ID: <20211005080359.170360-1-troglobit@gmail.com>

This patch adds support for an optional MTD label for mtd2block emulated
MTD devices.  Useful when, e.g. testing device images using Qemu.  The
following /etc/fstab line in can then be used to mount a file system
regardless of the actual MTD partition number:

    mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0

Kernel command line syntax:

    block2mtd.block2mtd=/dev/sda,,Config

The ',,' is the optional erase_size, which like before this patch,
defaults to PAGE_SIZE when omitted.

Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
---
 drivers/mtd/devices/block2mtd.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index c08721b11642..9465b8ff48f6 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -214,7 +214,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 
 
 static struct block2mtd_dev *add_device(char *devname, int erase_size,
-		int timeout)
+		char *label, int timeout)
 {
 #ifndef MODULE
 	int i;
@@ -278,7 +278,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	/* Setup the MTD structure */
 	/* make the name contain the block device in */
-	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	if (!label)
+		name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	else
+		name = kstrdup(label, GFP_KERNEL);
 	if (!name)
 		goto err_destroy_mutex;
 
@@ -304,7 +307,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	list_add(&dev->list, &blkmtd_device_list);
 	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
-		dev->mtd.index,
+		dev->mtd.index, label ? label :
 		dev->mtd.name + strlen("block2mtd: "),
 		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
@@ -381,8 +384,8 @@ static int block2mtd_setup2(const char *val)
 	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
 	char buf[80 + 12 + 80 + 8];
 	char *str = buf;
-	char *token[2];
-	char *name;
+	char *token[3];
+	char *name, *label = NULL;
 	size_t erase_size = PAGE_SIZE;
 	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
 	int i, ret;
@@ -395,7 +398,7 @@ static int block2mtd_setup2(const char *val)
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < 3; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str) {
@@ -414,7 +417,7 @@ static int block2mtd_setup2(const char *val)
 		return 0;
 	}
 
-	if (token[1]) {
+	if (token[1] && strlen(token[1])) {
 		ret = parse_num(&erase_size, token[1]);
 		if (ret) {
 			pr_err("illegal erase size\n");
@@ -422,7 +425,12 @@ static int block2mtd_setup2(const char *val)
 		}
 	}
 
-	add_device(name, erase_size, timeout);
+	if (token[2]) {
+		label = token[2];
+		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
+	}
+
+	add_device(name, erase_size, label, timeout);
 
 	return 0;
 }
@@ -456,7 +464,7 @@ static int block2mtd_setup(const char *val, const struct kernel_param *kp)
 
 
 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
 
 static int __init block2mtd_init(void)
 {
-- 
2.25.1



From boris.brezillon at collabora.com  Tue Oct  5 01:23:00 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 5 Oct 2021 10:23:00 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211005070930.epgxb5qzumk4awxq@skn-laptop>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
Message-ID: <20211005102300.5da6d480@collabora.com>

On Tue, 5 Oct 2021 09:09:30 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Mon, Oct 04, 2021 at 01:47:00PM +0200, Boris Brezillon wrote:
> > On Mon, 4 Oct 2021 12:12:46 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > On Mon, Oct 04, 2021 at 11:58:17AM +0200, Boris Brezillon wrote:  
> > > > On Mon, 4 Oct 2021 10:55:09 +0200
> > > > Sean Nyekjaer <sean at geanix.com> wrote:
> > > >     
> > > > > On Mon, Oct 04, 2021 at 10:41:47AM +0200, Boris Brezillon wrote:    
> > > > > > On Mon,  4 Oct 2021 08:56:09 +0200
> > > > > > Sean Nyekjaer <sean at geanix.com> wrote:
> > > > > >       
> > > > > > > This will prevent nand_get_device() from returning -EBUSY.
> > > > > > > It will force mtd_write()/mtd_read() to wait for the nand_resume() to unlock
> > > > > > > access to the mtd device.
> > > > > > > 
> > > > > > > Then we avoid -EBUSY is returned to ubifsi via mtd_write()/mtd_read(),
> > > > > > > that will in turn hard error on every error returened.
> > > > > > > We have seen during ubifs tries to call mtd_write before the mtd device
> > > > > > > is resumed.      
> > > > > > 
> > > > > > I think the problem is here. Why would UBIFS/UBI try to write something
> > > > > > to a device that's not resumed yet (or has been suspended already, if
> > > > > > you hit this in the suspend path).
> > > > > >       
> > > > > > > 
> > > > > > > Exec_op[0] speed things up, so we see this race when the device is
> > > > > > > resuming. But it's actually "mtd: rawnand: Simplify the locking" that
> > > > > > > allows it to return -EBUSY, before that commit it would have waited for
> > > > > > > the mtd device to resume.      
> > > > > > 
> > > > > > Uh, wait. If nand_resume() was called before any writes/reads this
> > > > > > wouldn't happen. IMHO, the problem is not that we return -EBUSY without
> > > > > > blocking, the problem is that someone issues a write/read before calling
> > > > > > mtd_resume().
> > > > > >       
> > > > > 
> > > > > The commit msg from "mtd: rawnand: Simplify the locking" states this clearly.
> > > > > 
> > > > > """
> > > > > Last important change to mention: we now return -EBUSY when someone
> > > > > tries to access a device that as been suspended, and propagate this
> > > > > error to the upper layer.
> > > > > """
> > > > > 
> > > > > IMHO "mtd: rawnand: Simplify the locking" should never had been merged
> > > > > before the upper layers was fixed to handle -EBUSY. ;)
> > > > > Which they still not are...    
> > > > 
> > > > That's not really the problem here. Upper layers should never get
> > > > -EBUSY in the first place if the MTD device was resumed before the UBI
> > > > device. Looks like we have a missing UBI -> MTD parenting link, which
> > > > would explain why things don't get resumed in the right order. Can you
> > > > try with the following diff applied?
> > > > 
> > > > ---
> > > > diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> > > > index f399edc82191..1981ce8f3a26 100644
> > > > --- a/drivers/mtd/ubi/build.c
> > > > +++ b/drivers/mtd/ubi/build.c
> > > > @@ -905,6 +905,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int
> > > > ubi_num, ubi->dev.release = dev_release;
> > > >         ubi->dev.class = &ubi_class;
> > > >         ubi->dev.groups = ubi_dev_groups;
> > > > +       ubi->dev.parent = &mtd->dev;
> > > >  
> > > >         ubi->mtd = mtd;
> > > >         ubi->ubi_num = ubi_num;
> > > >     
> > > 
> > > No change:
> > > [   71.739193] Filesystems sync: 34.212 seconds
> > > [   71.755044] Freezing user space processes ... (elapsed 0.004 seconds) done.
> > > [   71.767289] OOM killer disabled.
> > > [   71.770552] Freezing remaining freezable tasks ... (elapsed 0.004 seconds) done.
> > > [   71.782182] printk: Suspending console(s) (use no_console_suspend to debug)
> > > [   71.824391] nand_suspend
> > > [   71.825177] gpmi_pm_suspend
> > > [   71.825676] PM: suspend devices took 0.040 seconds
> > > [   71.825971] nand_write_oob - nand_get_device() returned -EBUSY
> > > [   71.825985] ubi0 error: ubi_io_write: error -16 while writing 4096 bytes to PEB 986:65536, written 0 bytes
> > > [   71.826029] CPU: 0 PID: 7 Comm: kworker/u2:0 Not tainted 5.15.0-rc3-dirty #43
> > > [   71.826043] Hardware name: Freescale i.MX6 Ultralite (Device Tree)
> > > [   71.826054] Workqueue: writeback wb_workfn (flush-ubifs_0_8)
> > > [   71.826094] [<c010da84>] (unwind_backtrace) from [<c010a1b4>] (show_stack+0x10/0x14)
> > > [   71.826122] [<c010a1b4>] (show_stack) from [<c0989c30>] (dump_stack_lvl+0x40/0x4c)
> > > [   71.826151] [<c0989c30>] (dump_stack_lvl) from [<c05ed690>] (ubi_io_write+0x510/0x6b0)
> > > [   71.826178] [<c05ed690>] (ubi_io_write) from [<c05ea2f0>] (ubi_eba_write_leb+0xd0/0x968)
> > > [   71.826204] [<c05ea2f0>] (ubi_eba_write_leb) from [<c05e8754>] (ubi_leb_write+0xd0/0xe8)
> > > [   71.826232] [<c05e8754>] (ubi_leb_write) from [<c03d67bc>] (ubifs_leb_write+0x68/0x104)
> > > [   71.826263] [<c03d67bc>] (ubifs_leb_write) from [<c03d79e8>] (ubifs_wbuf_write_nolock+0x28c/0x74c)
> > > [   71.826291] [<c03d79e8>] (ubifs_wbuf_write_nolock) from [<c03ca18c>] (ubifs_jnl_write_data+0x1b8/0x2b4)
> > > [   71.826319] [<c03ca18c>] (ubifs_jnl_write_data) from [<c03cd184>] (do_writepage+0x190/0x284)
> > > [   71.826342] [<c03cd184>] (do_writepage) from [<c023083c>] (__writepage+0x14/0x68)
> > > [   71.826367] [<c023083c>] (__writepage) from [<c0231748>] (write_cache_pages+0x1c8/0x3f0)
> > > [   71.826390] [<c0231748>] (write_cache_pages) from [<c0233854>] (do_writepages+0xcc/0x1f4)
> > > [   71.826413] [<c0233854>] (do_writepages) from [<c02d03dc>] (__writeback_single_inode+0x2c/0x1b4)
> > > [   71.826440] [<c02d03dc>] (__writeback_single_inode) from [<c02d0a64>] (writeback_sb_inodes+0x200/0x470)
> > > [   71.826466] [<c02d0a64>] (writeback_sb_inodes) from [<c02d0d10>] (__writeback_inodes_wb+0x3c/0xf4)
> > > [   71.826493] [<c02d0d10>] (__writeback_inodes_wb) from [<c02d0f58>] (wb_writeback+0x190/0x1f0)
> > > [   71.826520] [<c02d0f58>] (wb_writeback) from [<c02d21d8>] (wb_workfn+0x2c0/0x3d4)
> > > [   71.826545] [<c02d21d8>] (wb_workfn) from [<c013ac04>] (process_one_work+0x1e0/0x440)
> > > [   71.826574] [<c013ac04>] (process_one_work) from [<c013aeac>] (worker_thread+0x48/0x594)
> > > [   71.826600] [<c013aeac>] (worker_thread) from [<c0142364>] (kthread+0x134/0x15c)
> > > [   71.826625] [<c0142364>] (kthread) from [<c0100150>] (ret_from_fork+0x14/0x24)  
> > 
> > I'm not entirely sure, but given the timing, it looks like this
> > actually happens in the suspend path, not it the resume path. What I
> > don't get is why we still have a kernel thread running at that point.  
> 
> Have you seen the reproducer script?

How would I know about this script or your previous attempt (mentioned
at the end of this email) given I was not Cc-ed on the previous
discussion, and nothing mentions it in this RFC...

> ---
> root at iwg26-v1:/data/root# cat /data/crash.sh
> #!/bin/sh -x
> 
> echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup
> 
> rm /data/test50M
> dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
> cp /tmp/test50M /data/ &
> sleep 1
> echo mem > /sys/power/state
> ---
> 
> As seen in the log above disk is synced before suspend.
> cp is continuing to copy data to ubifs.
> And then user space processes are frozen.
> At this point the kernel thread would have unwritten data.
> 
> We tried to solve this with:
> https://lkml.org/lkml/2021/9/1/280

I see. It's still unclear to me when the write happens. Is it in the
suspend path (before the system is actually suspended), or in the
resume path (when the system is being resumed).

Anyway, let's admit writing to a storage device while it's suspended is
a valid use case and requires the storage layer to put this request on
old. This wait should not, IMHO, be handled at the NAND level, but at
the MTD level (using a waitqueue, and an atomic to make
suspended/resumed transitions safe). And abusing a mutex to implement
that is certainly not a good idea.


From sean at geanix.com  Tue Oct  5 01:49:38 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 5 Oct 2021 10:49:38 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211005102300.5da6d480@collabora.com>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
Message-ID: <20211005084938.jcbw24umhehoiirs@skn-laptop>

On Tue, Oct 05, 2021 at 10:23:00AM +0200, Boris Brezillon wrote:
> On Tue, 5 Oct 2021 09:09:30 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:

[ ... ]

> > 
> > Have you seen the reproducer script?
> 
> How would I know about this script or your previous attempt (mentioned
> at the end of this email) given I was not Cc-ed on the previous
> discussion, and nothing mentions it in this RFC...
> 

That's why I shared it here ;)
Initially I thought this was a bug introduced by exec_op.

> > ---
> > root at iwg26-v1:/data/root# cat /data/crash.sh
> > #!/bin/sh -x
> > 
> > echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup
> > 
> > rm /data/test50M
> > dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
> > cp /tmp/test50M /data/ &
> > sleep 1
> > echo mem > /sys/power/state
> > ---
> > 
> > As seen in the log above disk is synced before suspend.
> > cp is continuing to copy data to ubifs.
> > And then user space processes are frozen.
> > At this point the kernel thread would have unwritten data.
> > 
> > We tried to solve this with:
> > https://lkml.org/lkml/2021/9/1/280
> 
> I see. It's still unclear to me when the write happens. Is it in the
> suspend path (before the system is actually suspended), or in the
> resume path (when the system is being resumed).
> 
> Anyway, let's admit writing to a storage device while it's suspended is
> a valid use case and requires the storage layer to put this request on
> old. This wait should not, IMHO, be handled at the NAND level, but at
> the MTD level (using a waitqueue, and an atomic to make
> suspended/resumed transitions safe). And abusing a mutex to implement
> that is certainly not a good idea.

I did't say this was the right solution ;) I actually asked in the RFC:
"Should we introduce a new mutex? Or maybe a spin_lock?"

What are you proposing, a waitqueue in mtd_info? That gets checked in
mtd_write()/mtd_read()?

/Sean


From boris.brezillon at collabora.com  Tue Oct  5 01:58:36 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 5 Oct 2021 10:58:36 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211005084938.jcbw24umhehoiirs@skn-laptop>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
Message-ID: <20211005105836.6c300f25@collabora.com>

On Tue, 5 Oct 2021 10:49:38 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Tue, Oct 05, 2021 at 10:23:00AM +0200, Boris Brezillon wrote:
> > On Tue, 5 Oct 2021 09:09:30 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:  
> 
> [ ... ]
> 
> > > 
> > > Have you seen the reproducer script?  
> > 
> > How would I know about this script or your previous attempt (mentioned
> > at the end of this email) given I was not Cc-ed on the previous
> > discussion, and nothing mentions it in this RFC...
> >   
> 
> That's why I shared it here ;)
> Initially I thought this was a bug introduced by exec_op.
> 
> > > ---
> > > root at iwg26-v1:/data/root# cat /data/crash.sh
> > > #!/bin/sh -x
> > > 
> > > echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup
> > > 
> > > rm /data/test50M
> > > dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
> > > cp /tmp/test50M /data/ &
> > > sleep 1
> > > echo mem > /sys/power/state
> > > ---
> > > 
> > > As seen in the log above disk is synced before suspend.
> > > cp is continuing to copy data to ubifs.
> > > And then user space processes are frozen.
> > > At this point the kernel thread would have unwritten data.
> > > 
> > > We tried to solve this with:
> > > https://lkml.org/lkml/2021/9/1/280  
> > 
> > I see. It's still unclear to me when the write happens. Is it in the
> > suspend path (before the system is actually suspended), or in the
> > resume path (when the system is being resumed).
> > 
> > Anyway, let's admit writing to a storage device while it's suspended is
> > a valid use case and requires the storage layer to put this request on
> > old. This wait should not, IMHO, be handled at the NAND level, but at
> > the MTD level (using a waitqueue, and an atomic to make
> > suspended/resumed transitions safe). And abusing a mutex to implement
> > that is certainly not a good idea.  
> 
> I did't say this was the right solution ;) I actually asked in the RFC:
> "Should we introduce a new mutex? Or maybe a spin_lock?"
> 
> What are you proposing, a waitqueue in mtd_info? That gets checked in
> mtd_write()/mtd_read()?

Yes, and replacing the suspended state by an atomic, and providing a
helper to wait on the device readiness. Helper you will call in every
path involving a communication with the HW, not just mtd_read/write()
(you're missing erase at least, and I fear there are other hooks that
might lead to commands being issued to the device). But before we get
there, I think it's important to understand what the kernel expects.
IOW, if and when threads can do a request on a suspended device, and
when it's acceptable to wait (vs returning -EBUSY), otherwise I fear
we'll end up with deadlocks in the suspend/resume path.


From songkai01 at inspur.com  Mon Oct  4 23:56:55 2021
From: songkai01 at inspur.com (Kai Song)
Date: Tue, 5 Oct 2021 14:56:55 +0800
Subject: [PATCH] ubi: Fix a mistake in comment
Message-ID: <20211005065656.13497-1-songkai01@inspur.com>

Fixes: 2a734bb8d502 ("UBI: use debugfs for the extra checks knobs")
There is a mistake in docstrings, it should be ubi_debugfs_exit_dev
instead of dbg_debug_exit_dev.

Signed-off-by: Kai Song <songkai01 at inspur.com>
---
 drivers/mtd/ubi/debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 3c0c8eca4d51..31d427ee191a 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -562,7 +562,7 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
 }
 
 /**
- * dbg_debug_exit_dev - free all debugfs files corresponding to device @ubi
+ * ubi_debugfs_exit_dev - free all debugfs files corresponding to device @ubi
  * @ubi: UBI device description object
  */
 void ubi_debugfs_exit_dev(struct ubi_device *ubi)
-- 
2.27.0



From wsa+renesas at sang-engineering.com  Tue Oct  5 02:14:44 2021
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Tue, 5 Oct 2021 11:14:44 +0200
Subject: [PATCH 6/6] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <YVwXhFalcYr72CZT@kunai>

Hi Prabhakar,

some updates after internal discussions I had.

> +#define RPCIF_CMNCR_MOIIO_HIZ(val) (RPCIF_CMNCR_MOIIO0(val) | \
> +				 RPCIF_CMNCR_MOIIO1(val) | \
> +				 RPCIF_CMNCR_MOIIO2(val) | RPCIF_CMNCR_MOIIO3(val))

Shimoda-san rightfully said that '_HIZ' should be removed from the macro
name because HIZ implies the value 3.


>  #define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* undocumented */
>  #define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* undocumented */

As discussed before, mention here that they are documented for G2L.
Sadly, we can't use them with Gen3...

> -#define RPCIF_CMNCR_IOFV_HIZ	(RPCIF_CMNCR_IO0FV(3) | RPCIF_CMNCR_IO2FV(3) | \
> -				 RPCIF_CMNCR_IO3FV(3))
> +#define RPCIF_CMNCR_IOFV_HIZ(val) (RPCIF_CMNCR_IO0FV(val) | RPCIF_CMNCR_IO2FV(val) | \
> +				 RPCIF_CMNCR_IO3FV(val))

... which means we should remove this macro entirely because it is
forbidden for Gen3. I think it is best to use the RPCIF_CMNCR_IO<n>FV
macros directly where we need them.

Do you agree?

Kind regards,

   Wolfram

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211005/d9abaeab/attachment.sig>

From p.zabel at pengutronix.de  Tue Oct  5 02:34:07 2021
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 05 Oct 2021 11:34:07 +0200
Subject: [PATCH 3/3] reset: socfpga: add empty driver allowing consumers
 to probe
In-Reply-To: <20210920124141.1166544-4-pan@semihalf.com>
References: <20210920124141.1166544-1-pan@semihalf.com>
 <20210920124141.1166544-4-pan@semihalf.com>
Message-ID: <ce254cc123f2809976c2f2404941a9074c458309.camel@pengutronix.de>

Hi Pawe?,

On Mon, 2021-09-20 at 14:41 +0200, Pawe? Anikiel wrote:
> The early reset driver doesn't ever probe, which causes consuming
> devices to be unable to probe. Add an empty driver to set this device
> as available, allowing consumers to probe.
> 
> Signed-off-by: Pawe? Anikiel <pan at semihalf.com>
> ---
>  drivers/reset/reset-socfpga.c | 26 ++++++++++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
> index 2a72f861f798..8c6492e5693c 100644
> --- a/drivers/reset/reset-socfpga.c
> +++ b/drivers/reset/reset-socfpga.c
> @@ -92,3 +92,29 @@ void __init socfpga_reset_init(void)
>  	for_each_matching_node(np, socfpga_early_reset_dt_ids)
>  		a10_reset_init(np);
>  }
> +
> +/*
> + * The early driver is problematic, because it doesn't register
> + * itself as a driver. This causes certain device links to prevent
> + * consumer devices from probing. The hacky solution is to register
> + * an empty driver, whose only job is to attach itself to the reset
> + * manager and call probe.
> + */
> +static const struct of_device_id socfpga_reset_dt_ids[] = {
> +	{ .compatible = "altr,rst-mgr", },
> +	{ /* sentinel */ },
> +};
> +
> +static int reset_simple_probe(struct platform_device *pdev)
> +{
> +	return 0;
> +}
> +
> +static struct platform_driver reset_socfpga_driver = {
> +	.probe	= reset_simple_probe,
> +	.driver = {
> +		.name		= "socfpga-reset",
> +		.of_match_table	= socfpga_reset_dt_ids,
> +	},
> +};
> +builtin_platform_driver(reset_socfpga_driver);

If we can just let devlink delay all consumers until the empty driver is
probed, does the reset controller have to be registered early at all?

regards
Philipp


From mika.westerberg at linux.intel.com  Tue Oct  5 02:41:39 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Tue, 5 Oct 2021 12:41:39 +0300
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <CAHp75VdtOHn4ED-ixdDngBQw10OnKmbtTv=ydLs6dYbkjyqW4Q@mail.gmail.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <CAHp75VdtOHn4ED-ixdDngBQw10OnKmbtTv=ydLs6dYbkjyqW4Q@mail.gmail.com>
Message-ID: <YVwd09KZwOQVvh4g@lahna>

Hi Andy,

On Mon, Oct 04, 2021 at 05:29:47PM +0300, Andy Shevchenko wrote:
> On Thu, Sep 30, 2021 at 1:08 PM Mika Westerberg
> <mika.westerberg at linux.intel.com> wrote:
> >
> > The preferred way to implement SPI-NOR controller drivers is through SPI
> > subsubsystem utilizing the SPI MEM core functions. This converts the
> > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > SPI MEM functions. The driver name will be changed from intel-spi to
> > spi-intel to match the convention used in the SPI subsystem.
> 
> ...
> 
> > +config SPI_INTEL_PCI
> > +       tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
> > +       depends on PCI && (X86 || COMPILE_TEST)
> 
> Perhaps two entries, one of which will be the same as for platform case?

Sure will do that in v2.

> > +       depends on SPI_MEM
> > +       select SPI_INTEL
> > +       help
> > +         This enables PCI support for the Intel PCH/PCU SPI controller in
> > +         master mode. This controller is present in modern Intel hardware
> > +         and is used to hold BIOS and other persistent settings. Using
> > +         this driver it is possible to upgrade BIOS directly from Linux.
> > +
> > +         Say N here unless you know what you are doing. Overwriting the
> > +         SPI flash may render the system unbootable.
> > +
> > +         To compile this driver as a module, choose M here: the module
> > +         will be called spi-intel-pci.
> > +
> > +config SPI_INTEL_PLATFORM
> > +       tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
> > +       depends on X86 || COMPILE_TEST
> > +       depends on SPI_MEM
> > +       select SPI_INTEL
> > +       help
> > +         This enables platform support for the Intel PCH/PCU SPI
> > +         controller in master mode. This controller is present in modern
> > +         Intel hardware and is used to hold BIOS and other persistent
> > +         settings. Using this driver it is possible to upgrade BIOS
> > +         directly from Linux.
> > +
> > +         Say N here unless you know what you are doing. Overwriting the
> > +         SPI flash may render the system unbootable.
> > +
> > +         To compile this driver as a module, choose M here: the module
> > +         will be called spi-intel-platform.
> 
> ...
> 
> + Blank line ?

OK

> 
> >  #include <linux/mtd/partitions.h>
> >  #include <linux/mtd/spi-nor.h>
> 
> + Blank line?

OK

> > +#include <linux/spi/flash.h>
> > +#include <linux/spi/spi.h>
> > +#include <linux/spi/spi-mem.h>
> 
> The rationale is to show that we use two sub(sub)sytems here.

Yup, got it.

> ...
> 
> > -                       dev_err(ispi->dev, "read error: %llx: %#x\n", from,
> > +                       dev_err(ispi->dev, "read error: %x: %#x\n", from,
> >                                 status);
> 
> Now one line?
> 
> ...
> 
> > -                       dev_err(ispi->dev, "write error: %llx: %#x\n", to,
> > +                       dev_err(ispi->dev, "write error: %x: %#x\n", to,
> >                                 status);
> 
> Ditto.

Sure for both.
> 
> ...
> 
> > +               ret = intel_spi_sw_cycle(ispi, opcode, 0,
> > +                                        OPTYPE_WRITE_WITH_ADDR);
> > +               return ret ? ret : 0;
> 
> Why not simply return intel_spi_dw_cycle(...); ?

Good point. Will fix that.

> ...
> 
> > +       val = readl(ispi->base + HSFSTS_CTL);
> > +       val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> > +       val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> 
> > +       val |= cmd;
> > +       val |= HSFSTS_CTL_FGO;
> 
> Maybe swap these lines to group constants?

OK

> ...
> 
> > +       status = readl(ispi->base + HSFSTS_CTL);
> > +       if (status & HSFSTS_CTL_FCERR)
> > +               return -EIO;
> 
> > +       else if (status & HSFSTS_CTL_AEL)
> 
> Redundant 'else'

Right.

> > +               return -EACCES;
> 
> ...
> 
> > +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
> > +{
> > +       struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> > +       size_t nbytes = op->data.nbytes;
> > +       u8 opcode = op->cmd.opcode;
> > +
> > +       if (op->addr.nbytes) {
> > +               if  (op->data.dir == SPI_MEM_DATA_IN)
> > +                       return intel_spi_read(ispi, op->addr.val, nbytes,
> > +                                             op->data.buf.in);
> 
> > +               else if (op->data.dir == SPI_MEM_DATA_OUT)
> 
> Redundant 'else' here and nearby.

Right. I'll fix these in v2.

> > +                       return intel_spi_write(ispi, op->addr.val, nbytes,
> > +                                              op->data.buf.out);
> > +               else if (op->data.dir == SPI_MEM_NO_DATA)
> > +                       return intel_spi_erase(ispi, opcode, op->addr.val);
> > +       } else {
> > +               if  (op->data.dir == SPI_MEM_DATA_IN)
> > +                       return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
> > +                                                 nbytes);
> > +               else if (op->data.dir == SPI_MEM_DATA_OUT)
> > +                       return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
> > +                                                  nbytes);
> > +               else if (op->data.dir == SPI_MEM_NO_DATA)
> > +                       return intel_spi_write_reg(ispi, opcode, NULL, 0);
> >         }
> 
> > +       return -EINVAL;
> > +}
> 
> -- 
> With Best Regards,
> Andy Shevchenko


From pan at semihalf.com  Tue Oct  5 04:12:05 2021
From: pan at semihalf.com (=?UTF-8?Q?Pawe=C5=82_Anikiel?=)
Date: Tue, 5 Oct 2021 13:12:05 +0200
Subject: [PATCH 3/3] reset: socfpga: add empty driver allowing consumers
 to probe
In-Reply-To: <ce254cc123f2809976c2f2404941a9074c458309.camel@pengutronix.de>
References: <20210920124141.1166544-1-pan@semihalf.com>
 <20210920124141.1166544-4-pan@semihalf.com>
 <ce254cc123f2809976c2f2404941a9074c458309.camel@pengutronix.de>
Message-ID: <CAF9_jYQVpG8imn3zjAGKeZqZqDPtWRYWLQjNSXi2SXjjzAKvfA@mail.gmail.com>

On Tue, Oct 5, 2021 at 11:34 AM Philipp Zabel <p.zabel at pengutronix.de> wrote:
>
> Hi Pawe?,
>
> On Mon, 2021-09-20 at 14:41 +0200, Pawe? Anikiel wrote:
> > The early reset driver doesn't ever probe, which causes consuming
> > devices to be unable to probe. Add an empty driver to set this device
> > as available, allowing consumers to probe.
> >
> > Signed-off-by: Pawe? Anikiel <pan at semihalf.com>
> > ---
> >  drivers/reset/reset-socfpga.c | 26 ++++++++++++++++++++++++++
> >  1 file changed, 26 insertions(+)
> >
> > diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
> > index 2a72f861f798..8c6492e5693c 100644
> > --- a/drivers/reset/reset-socfpga.c
> > +++ b/drivers/reset/reset-socfpga.c
> > @@ -92,3 +92,29 @@ void __init socfpga_reset_init(void)
> >       for_each_matching_node(np, socfpga_early_reset_dt_ids)
> >               a10_reset_init(np);
> >  }
> > +
> > +/*
> > + * The early driver is problematic, because it doesn't register
> > + * itself as a driver. This causes certain device links to prevent
> > + * consumer devices from probing. The hacky solution is to register
> > + * an empty driver, whose only job is to attach itself to the reset
> > + * manager and call probe.
> > + */
> > +static const struct of_device_id socfpga_reset_dt_ids[] = {
> > +     { .compatible = "altr,rst-mgr", },
> > +     { /* sentinel */ },
> > +};
> > +
> > +static int reset_simple_probe(struct platform_device *pdev)
> > +{
> > +     return 0;
> > +}
> > +
> > +static struct platform_driver reset_socfpga_driver = {
> > +     .probe  = reset_simple_probe,
> > +     .driver = {
> > +             .name           = "socfpga-reset",
> > +             .of_match_table = socfpga_reset_dt_ids,
> > +     },
> > +};
> > +builtin_platform_driver(reset_socfpga_driver);
>
> If we can just let devlink delay all consumers until the empty driver is
> probed, does the reset controller have to be registered early at all?
>
> regards
> Philipp

I asked Dinh if the reset controller code needs to be called early:

>That's correct. It's for one of the SP timers.
>
>On 9/16/21 6:13 AM, Pawe? Anikiel wrote:
>> Hi,
>>
>> I would like to ask you about the following commit:
>>> commit b3ca9888f35fa6919569cf27c929dc0ac49e9716
>>> Author: Dinh Nguyen <dinguyen at kernel.org>
>>> Date:   Tue Nov 13 12:50:48 2018 -0600
>>>
>>>      reset: socfpga: add an early reset driver for SoCFPGA
>>>
>>>      Create a separate reset driver that uses the reset operations in
>>>      reset-simple. The reset driver for the SoCFPGA platform needs to
>>>      register early in order to be able bring online timers that needed
>>>      early in the kernel bootup.
>>>      [...]
>> Which online timers is this commit message referring to? I couldn't find
>> any information about this. Without this patch the kernel seems to work
>> fine on an Arria 10 (with Mercury AA1 module). What's the exact reason
>> a regular platform driver isn't sufficient?
>>
>> Best regards,
>> Pawe?
>>


From p.zabel at pengutronix.de  Tue Oct  5 03:22:25 2021
From: p.zabel at pengutronix.de (Philipp Zabel)
Date: Tue, 05 Oct 2021 12:22:25 +0200
Subject: [PATCH 3/3] reset: socfpga: add empty driver allowing consumers
 to probe
In-Reply-To: <CAF9_jYQVpG8imn3zjAGKeZqZqDPtWRYWLQjNSXi2SXjjzAKvfA@mail.gmail.com>
References: <20210920124141.1166544-1-pan@semihalf.com>
 <20210920124141.1166544-4-pan@semihalf.com>
 <ce254cc123f2809976c2f2404941a9074c458309.camel@pengutronix.de>
 <CAF9_jYQVpG8imn3zjAGKeZqZqDPtWRYWLQjNSXi2SXjjzAKvfA@mail.gmail.com>
Message-ID: <6993ccdaf8f3f248f4ff1c739445e0f798ee0efa.camel@pengutronix.de>

On Tue, 2021-10-05 at 13:12 +0200, Pawe? Anikiel wrote:
> On Tue, Oct 5, 2021 at 11:34 AM Philipp Zabel <p.zabel at pengutronix.de> wrote:
> > Hi Pawe?,
> > 
> > On Mon, 2021-09-20 at 14:41 +0200, Pawe? Anikiel wrote:
> > > The early reset driver doesn't ever probe, which causes consuming
> > > devices to be unable to probe. Add an empty driver to set this device
> > > as available, allowing consumers to probe.
> > > 
> > > Signed-off-by: Pawe? Anikiel <pan at semihalf.com>
> > > ---
> > >  drivers/reset/reset-socfpga.c | 26 ++++++++++++++++++++++++++
> > >  1 file changed, 26 insertions(+)
> > > 
> > > diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
> > > index 2a72f861f798..8c6492e5693c 100644
> > > --- a/drivers/reset/reset-socfpga.c
> > > +++ b/drivers/reset/reset-socfpga.c
> > > @@ -92,3 +92,29 @@ void __init socfpga_reset_init(void)
> > >       for_each_matching_node(np, socfpga_early_reset_dt_ids)
> > >               a10_reset_init(np);
> > >  }
> > > +
> > > +/*
> > > + * The early driver is problematic, because it doesn't register
> > > + * itself as a driver. This causes certain device links to prevent
> > > + * consumer devices from probing. The hacky solution is to register
> > > + * an empty driver, whose only job is to attach itself to the reset
> > > + * manager and call probe.
> > > + */
> > > +static const struct of_device_id socfpga_reset_dt_ids[] = {
> > > +     { .compatible = "altr,rst-mgr", },
> > > +     { /* sentinel */ },
> > > +};
> > > +
> > > +static int reset_simple_probe(struct platform_device *pdev)
> > > +{
> > > +     return 0;
> > > +}
> > > +
> > > +static struct platform_driver reset_socfpga_driver = {
> > > +     .probe  = reset_simple_probe,
> > > +     .driver = {
> > > +             .name           = "socfpga-reset",
> > > +             .of_match_table = socfpga_reset_dt_ids,
> > > +     },
> > > +};
> > > +builtin_platform_driver(reset_socfpga_driver);
> > 
> > If we can just let devlink delay all consumers until the empty driver is
> > probed, does the reset controller have to be registered early at all?
> > 
> > regards
> > Philipp
> 
> I asked Dinh if the reset controller code needs to be called early:
> 
> > That's correct. It's for one of the SP timers.

Ah, right, those call of_reset_control_get() from TIMER_OF_DECLARE().
Thank you, I'll apply this to reset/fixes.

regards
Philipp


From Tudor.Ambarus at microchip.com  Tue Oct  5 04:59:06 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Tue, 5 Oct 2021 11:59:06 +0000
Subject: [PATCH 1/3] dt-bindings: mtd: spi-nor: add n25q00 schema
In-Reply-To: <20210923185902.6wgkuz4jcelcawrq@ti.com>
References: <20210920124141.1166544-1-pan@semihalf.com>
 <20210920124141.1166544-2-pan@semihalf.com>
 <20210923185902.6wgkuz4jcelcawrq@ti.com>
Message-ID: <0b9b656d-df4d-6062-2b0d-70aea02f378f@microchip.com>

On 9/23/21 9:59 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> +Tudor
> 
> On 20/09/21 02:41PM, Pawe? Anikiel wrote:
>> Add schema for the n25q00 NOR flash memory.
>>
>> Signed-off-by: Pawe? Anikiel <pan at semihalf.com>
>> ---
>>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> index ed590d7c6e37..efb3c5e05c5a 100644
>> --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> @@ -18,7 +18,7 @@ properties:
>>        - items:
>>            - pattern: "^((((micron|spansion|st),)?\
>>                (m25p(40|80|16|32|64|128)|\
>> -              n25q(32b|064|128a11|128a13|256a|512a|164k)))|\
>> +              n25q(00|32b|064|128a11|128a13|256a|512a|164k)))|\
> 
> IIUC this is supposed to only be for legacy/old flashes that started out
> using flash-specific compatibles. Any new flashes should simply use
> jedec,spi-nor unless there is a legitimate reason to do so.

that's correct, the generic compatible should suffice for these flashes.

> 
> Until you justify that reason,
> 
> Nacked-by: Pratyush Yadav <p.yadav at ti.com>

I agree.

Cheers,
ta

From tudor.ambarus at microchip.com  Tue Oct  5 05:11:24 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Tue, 5 Oct 2021 15:11:24 +0300
Subject: [PATCH] MAINTAINERS: Add spi-nor device tree binding under SPI
 NOR maintainers
In-Reply-To: <20210923191026.19184-1-p.yadav@ti.com>
References: <20210923191026.19184-1-p.yadav@ti.com>
Message-ID: <163343574378.37829.16814957321321688865.b4-ty@microchip.com>

On Fri, 24 Sep 2021 00:40:26 +0530, Pratyush Yadav wrote:
> The binding is for the SPI NOR subsystem so the patches should be sent
> to its maintainers. Currently the patches get sent to Rob Herring and
> MTD maintainers who might not always have the full picture.

Applied to spi-nor/next, thanks!

[1/1] MAINTAINERS: Add spi-nor device tree binding under SPI NOR maintainers
      https://git.kernel.org/mtd/c/3f491d11d8cb

Best regards,
-- 
Tudor Ambarus <tudor.ambarus at microchip.com>


From robh at kernel.org  Tue Oct  5 05:26:38 2021
From: robh at kernel.org (Rob Herring)
Date: Tue, 05 Oct 2021 07:26:38 -0500
Subject: [PATCH 1/2] dt-bindings: mtd: spi-nor: Add output-driver-strength
 property
In-Reply-To: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
References: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
Message-ID: <1633436798.695084.3226817.nullmailer@robh.at.kernel.org>

On Mon, 04 Oct 2021 13:15:28 +0200, Alexander Stein wrote:
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> 
> This property is for optimizing output voltage impedance and is
> specific to each board.
> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
> I checked Micron and Macronix datasheets. Both have similar but not
> identical supported values. Also the register locations are different.
> For those reasons I decided to specify the Ohms value directly and let
> the device specfic driver figure out if it is supported where to write
> it to.
> BTW: Are the Ohm values and the corresponding register bits standardized
> somewhere?
> 
>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 

Running 'make dtbs_check' with the schema in this patch gives the
following warnings. Consider if they are expected or the schema is
incorrect. These may not be new warnings.

Note that it is not yet a requirement to have 0 warnings for dtbs_check.
This will change in the future.

Full log is available here: https://patchwork.ozlabs.org/patch/1536062


firmware-flash at 0: $nodename:0: 'firmware-flash at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/mmp3-dell-ariel.dt.yaml

Flash at 0: $nodename:0: 'Flash at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml

flash at 0: 'at91bootstrap at 0', 'bootloader at 40000', 'bootloaderenv at 140000', 'bootloaderenvred at 100000', 'dtb at 180000', 'kernel at 200000' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/at91-sam9x60ek.dt.yaml
	arch/arm/boot/dts/at91-sama5d27_som1_ek.dt.yaml
	arch/arm/boot/dts/at91-sama5d2_icp.dt.yaml

flash at 0: 'at91bootstrap at 0', 'bootloader at 40000', 'bootloaderenv at 140000', 'bootloaderenvred at 100000', 'dtb at 180000', 'kernel at 200000', 'misc at 800000' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/at91-sama5d2_xplained.dt.yaml

flash at 0: 'cdns,block-size', 'cdns,page-size', 'cdns,read-delay', 'cdns,tchsh-ns', 'cdns,tsd2d-ns', 'cdns,tshsl-ns', 'cdns,tslch-ns' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dt.yaml
	arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dt.yaml
	arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dt.yaml

flash at 0: 'cdns,read-delay', 'cdns,tchsh-ns', 'cdns,tsd2d-ns', 'cdns,tshsl-ns', 'cdns,tslch-ns' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm64/boot/dts/ti/k3-am642-evm.dt.yaml
	arch/arm64/boot/dts/ti/k3-am642-sk.dt.yaml
	arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic.dt.yaml
	arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced.dt.yaml
	arch/arm64/boot/dts/ti/k3-am654-base-board.dt.yaml
	arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dt.yaml
	arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dt.yaml
	arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dt.yaml

flash at 0: compatible: 'oneOf' conditional failed, one must be fixed:
	arch/arm/boot/dts/ls1021a-tsn.dt.yaml

flash at 0: 'm25p,default-addr-width' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/bcm953012hr.dt.yaml
	arch/arm/boot/dts/bcm953012k.dt.yaml

flash at 0: 'mode' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/kirkwood-cloudbox.dt.yaml
	arch/arm/boot/dts/kirkwood-d2net.dt.yaml
	arch/arm/boot/dts/kirkwood-is2.dt.yaml
	arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dt.yaml
	arch/arm/boot/dts/kirkwood-nas2big.dt.yaml
	arch/arm/boot/dts/kirkwood-net2big.dt.yaml
	arch/arm/boot/dts/kirkwood-net5big.dt.yaml
	arch/arm/boot/dts/kirkwood-ns2.dt.yaml
	arch/arm/boot/dts/kirkwood-ns2lite.dt.yaml
	arch/arm/boot/dts/kirkwood-ns2max.dt.yaml
	arch/arm/boot/dts/kirkwood-ns2mini.dt.yaml
	arch/arm/boot/dts/kirkwood-t5325.dt.yaml

flash at 0: 'spi-cpha', 'spi-cpol' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm/boot/dts/r8a7742-iwg21d-q7-dbcm-ca.dt.yaml
	arch/arm/boot/dts/r8a7742-iwg21d-q7.dt.yaml
	arch/arm/boot/dts/r8a7743-iwg20d-q7-dbcm-ca.dt.yaml
	arch/arm/boot/dts/r8a7743-iwg20d-q7.dt.yaml
	arch/arm/boot/dts/r8a7744-iwg20d-q7-dbcm-ca.dt.yaml
	arch/arm/boot/dts/r8a7744-iwg20d-q7.dt.yaml
	arch/arm/boot/dts/r8a7745-iwg22d-sodimm-dbhd-ca.dt.yaml
	arch/arm/boot/dts/r8a7745-iwg22d-sodimm.dt.yaml
	arch/arm/boot/dts/r8a77470-iwg23s-sbc.dt.yaml
	arch/arm/boot/dts/r8a7790-lager.dt.yaml
	arch/arm/boot/dts/r8a7790-stout.dt.yaml
	arch/arm/boot/dts/r8a7791-koelsch.dt.yaml
	arch/arm/boot/dts/r8a7792-wheat.dt.yaml
	arch/arm/boot/dts/r8a7793-gose.dt.yaml
	arch/arm/boot/dts/r8a7794-alt.dt.yaml
	arch/arm/boot/dts/r8a7794-silk.dt.yaml

flash at 0: 'ti,spi-wdelay' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/da850-lego-ev3.dt.yaml

flash at 1: 'spi-cpha', 'spi-cpol' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dt.yaml

flash at 2: compatible: 'oneOf' conditional failed, one must be fixed:
	arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dt.yaml

flash at 2: 'spi-cpha', 'spi-cpol' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1028a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1046a-qds.dt.yaml
	arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dt.yaml

flash: 'spi-cpha', 'spi-cpol' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/lpc4357-ea4357-devkit.dt.yaml
	arch/arm/boot/dts/lpc4357-myd-lpc4357.dt.yaml

m25p128 at 0: $nodename:0: 'm25p128 at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/kirkwood-rd88f6192.dt.yaml
	arch/arm/boot/dts/kirkwood-ts219-6281.dt.yaml
	arch/arm/boot/dts/kirkwood-ts219-6282.dt.yaml
	arch/arm/boot/dts/kirkwood-ts419-6281.dt.yaml
	arch/arm/boot/dts/kirkwood-ts419-6282.dt.yaml

m25p128 at 0: 'mode' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/kirkwood-rd88f6192.dt.yaml
	arch/arm/boot/dts/kirkwood-ts219-6281.dt.yaml
	arch/arm/boot/dts/kirkwood-ts219-6282.dt.yaml
	arch/arm/boot/dts/kirkwood-ts419-6281.dt.yaml
	arch/arm/boot/dts/kirkwood-ts419-6282.dt.yaml

m25p16 at 0: $nodename:0: 'm25p16 at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/kirkwood-b3.dt.yaml

m25p16 at 0: 'mode' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/kirkwood-b3.dt.yaml

m25p32 at 1: $nodename:0: 'm25p32 at 1' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx50-evk.dt.yaml
	arch/arm/boot/dts/imx53-smd.dt.yaml

m25p32 at 1: compatible: 'oneOf' conditional failed, one must be fixed:
	arch/arm/boot/dts/imx53-smd.dt.yaml

m25p40 at 0: $nodename:0: 'm25p40 at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/kirkwood-dreamplug.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lsqvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lsvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswsxl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswxl.dt.yaml
	arch/arm/boot/dts/kirkwood-lschlv2.dt.yaml
	arch/arm/boot/dts/kirkwood-lsxhl.dt.yaml

m25p40 at 0: 'mode' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/kirkwood-dreamplug.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lsqvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lsvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswsxl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswvl.dt.yaml
	arch/arm/boot/dts/kirkwood-linkstation-lswxl.dt.yaml
	arch/arm/boot/dts/kirkwood-lschlv2.dt.yaml
	arch/arm/boot/dts/kirkwood-lsxhl.dt.yaml

m25p80 at 0: $nodename:0: 'm25p80 at 0' does not match '^flash(@.*)?$'
	arch/arm64/boot/dts/marvell/armada-3720-db.dt.yaml
	arch/arm64/boot/dts/marvell/armada-3720-uDPU.dt.yaml
	arch/arm64/boot/dts/qcom/ipq8074-hk01.dt.yaml
	arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dt.yaml
	arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dt.yaml
	arch/arm/boot/dts/am335x-phycore-rdk.dt.yaml
	arch/arm/boot/dts/am335x-regor-rdk.dt.yaml
	arch/arm/boot/dts/am335x-wega-rdk.dt.yaml
	arch/arm/boot/dts/am571x-idk.dt.yaml
	arch/arm/boot/dts/am572x-idk.dt.yaml
	arch/arm/boot/dts/am574x-idk.dt.yaml
	arch/arm/boot/dts/at91-vinco.dt.yaml
	arch/arm/boot/dts/da850-evm.dt.yaml
	arch/arm/boot/dts/imx28-evk.dt.yaml
	arch/arm/boot/dts/imx28-m28evk.dt.yaml
	arch/arm/boot/dts/imx6dl-aristainetos_4.dt.yaml
	arch/arm/boot/dts/imx6dl-aristainetos_7.dt.yaml
	arch/arm/boot/dts/imx6dl-dfi-fs700-m60.dt.yaml
	arch/arm/boot/dts/imx6dl-nitrogen6x.dt.yaml
	arch/arm/boot/dts/imx6dl-rex-basic.dt.yaml
	arch/arm/boot/dts/imx6dl-sabreauto.dt.yaml
	arch/arm/boot/dts/imx6dl-sabrelite.dt.yaml
	arch/arm/boot/dts/imx6dl-sabresd.dt.yaml
	arch/arm/boot/dts/imx6q-cm-fx6.dt.yaml
	arch/arm/boot/dts/imx6q-dfi-fs700-m60.dt.yaml
	arch/arm/boot/dts/imx6q-dmo-edmqmx6.dt.yaml
	arch/arm/boot/dts/imx6q-gw5400-a.dt.yaml
	arch/arm/boot/dts/imx6q-nitrogen6x.dt.yaml
	arch/arm/boot/dts/imx6qp-sabreauto.dt.yaml
	arch/arm/boot/dts/imx6qp-sabresd.dt.yaml
	arch/arm/boot/dts/imx6q-rex-pro.dt.yaml
	arch/arm/boot/dts/imx6q-sabreauto.dt.yaml
	arch/arm/boot/dts/imx6q-sabrelite.dt.yaml
	arch/arm/boot/dts/imx6q-sabresd.dt.yaml
	arch/arm/boot/dts/imx6q-utilite-pro.dt.yaml
	arch/arm/boot/dts/imx6sl-evk.dt.yaml
	arch/arm/boot/dts/keystone-k2g-evm.dt.yaml
	arch/arm/boot/dts/keystone-k2g-ice.dt.yaml
	arch/arm/boot/dts/kirkwood-dir665.dt.yaml
	arch/arm/boot/dts/kirkwood-ds109.dt.yaml
	arch/arm/boot/dts/kirkwood-ds110jv10.dt.yaml
	arch/arm/boot/dts/kirkwood-ds111.dt.yaml
	arch/arm/boot/dts/kirkwood-ds112.dt.yaml
	arch/arm/boot/dts/kirkwood-ds209.dt.yaml
	arch/arm/boot/dts/kirkwood-ds210.dt.yaml
	arch/arm/boot/dts/kirkwood-ds212.dt.yaml
	arch/arm/boot/dts/kirkwood-ds212j.dt.yaml
	arch/arm/boot/dts/kirkwood-ds409.dt.yaml
	arch/arm/boot/dts/kirkwood-ds409slim.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411j.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411slim.dt.yaml
	arch/arm/boot/dts/kirkwood-rs212.dt.yaml
	arch/arm/boot/dts/kirkwood-rs409.dt.yaml
	arch/arm/boot/dts/kirkwood-rs411.dt.yaml

m25p80 at 0: 'cdns,read-delay', 'cdns,tchsh-ns', 'cdns,tsd2d-ns', 'cdns,tshsl-ns', 'cdns,tslch-ns' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/keystone-k2g-evm.dt.yaml
	arch/arm/boot/dts/keystone-k2g-ice.dt.yaml

m25p80 at 0: compatible: 'oneOf' conditional failed, one must be fixed:
	arch/arm/boot/dts/imx6q-cm-fx6.dt.yaml
	arch/arm/boot/dts/imx6q-gw5400-a.dt.yaml
	arch/arm/boot/dts/imx6q-utilite-pro.dt.yaml

m25p80 at 0: 'mode' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/kirkwood-ds109.dt.yaml
	arch/arm/boot/dts/kirkwood-ds110jv10.dt.yaml
	arch/arm/boot/dts/kirkwood-ds111.dt.yaml
	arch/arm/boot/dts/kirkwood-ds112.dt.yaml
	arch/arm/boot/dts/kirkwood-ds209.dt.yaml
	arch/arm/boot/dts/kirkwood-ds210.dt.yaml
	arch/arm/boot/dts/kirkwood-ds212.dt.yaml
	arch/arm/boot/dts/kirkwood-ds212j.dt.yaml
	arch/arm/boot/dts/kirkwood-ds409.dt.yaml
	arch/arm/boot/dts/kirkwood-ds409slim.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411j.dt.yaml
	arch/arm/boot/dts/kirkwood-ds411slim.dt.yaml
	arch/arm/boot/dts/kirkwood-rs212.dt.yaml
	arch/arm/boot/dts/kirkwood-rs409.dt.yaml
	arch/arm/boot/dts/kirkwood-rs411.dt.yaml

m25p80 at 1: $nodename:0: 'm25p80 at 1' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6dl-aristainetos2_4.dt.yaml
	arch/arm/boot/dts/imx6dl-aristainetos2_7.dt.yaml

mx66l51235l at 0: $nodename:0: 'mx66l51235l at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/stm32mp157c-ev1.dt.yaml

mx66l51235l at 1: $nodename:0: 'mx66l51235l at 1' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/stm32mp157c-ev1.dt.yaml

n25q032 at 0: $nodename:0: 'n25q032 at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6q-b450v3.dt.yaml
	arch/arm/boot/dts/imx6q-b650v3.dt.yaml
	arch/arm/boot/dts/imx6q-b850v3.dt.yaml
	arch/arm/boot/dts/imx6q-dms-ba16.dt.yaml

n25q256a at 0: $nodename:0: 'n25q256a at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6sx-sdb.dt.yaml
	arch/arm/boot/dts/imx6sx-sdb-mqs.dt.yaml
	arch/arm/boot/dts/imx6sx-sdb-sai.dt.yaml
	arch/arm/boot/dts/imx6ul-14x14-evk.dt.yaml
	arch/arm/boot/dts/imx6ull-14x14-evk.dt.yaml
	arch/arm/boot/dts/imx6ulz-14x14-evk.dt.yaml

n25q256a at 2: $nodename:0: 'n25q256a at 2' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6sx-sdb.dt.yaml
	arch/arm/boot/dts/imx6sx-sdb-mqs.dt.yaml
	arch/arm/boot/dts/imx6sx-sdb-sai.dt.yaml

s25fl016k at 0: $nodename:0: 's25fl016k at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/qcom-ipq8064-rb3011.dt.yaml

s25fl128s at 0: $nodename:0: 's25fl128s at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6sx-sdb-reva.dt.yaml

s25fl128s at 2: $nodename:0: 's25fl128s at 2' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/imx6sx-sdb-reva.dt.yaml

s25fl256 at 0: $nodename:0: 's25fl256 at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/am3874-iceboard.dt.yaml

s25fl256 at 0: 'bootenv at 2', 'fs at 5', 'fsbl at 0', 'ipmi at 4', 'kernel at 3', 'ssbl at 1' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/am3874-iceboard.dt.yaml

spi-flash at 0: $nodename:0: 'spi-flash at 0' does not match '^flash(@.*)?$'
	arch/arm64/boot/dts/allwinner/sun50i-a64-orangepi-win.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-g12b-a311d-khadas-vim3.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2-plus.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-g12b-s922x-khadas-vim3.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-gxl-s805x-libretech-ac.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-gxl-s905d-libretech-pc.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-gxl-s905x-libretech-cc-v2.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-gxm-s912-libretech-pc.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-sm1-khadas-vim3l.dt.yaml
	arch/arm64/boot/dts/amlogic/meson-sm1-odroid-hc4.dt.yaml
	arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dt.yaml
	arch/arm64/boot/dts/broadcom/stingray/bcm958742k.dt.yaml
	arch/arm64/boot/dts/freescale/imx8mm-kontron-n801x-s.dt.yaml
	arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dt.yaml
	arch/arm64/boot/dts/marvell/armada-7040-db.dt.yaml
	arch/arm64/boot/dts/marvell/armada-7040-db.dt.yaml
	arch/arm64/boot/dts/marvell/armada-8040-db.dt.yaml
	arch/arm64/boot/dts/marvell/armada-8040-db.dt.yaml
	arch/arm64/boot/dts/marvell/armada-8040-puzzle-m801.dt.yaml
	arch/arm64/boot/dts/marvell/cn9130-crb-A.dt.yaml
	arch/arm64/boot/dts/marvell/cn9130-crb-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9130-db-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9130-db.dt.yaml
	arch/arm64/boot/dts/marvell/cn9131-db-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9131-db-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9131-db.dt.yaml
	arch/arm64/boot/dts/marvell/cn9131-db.dt.yaml
	arch/arm64/boot/dts/marvell/cn9132-db-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9132-db-B.dt.yaml
	arch/arm64/boot/dts/marvell/cn9132-db.dt.yaml
	arch/arm64/boot/dts/marvell/cn9132-db.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-burnet.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-damu.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel14.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku1.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-fennel-sku6.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-juniper-sku16.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kappa.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-kenzo.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku0.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-willow-sku1.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku16.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku272.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku288.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama-sku32.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku0.dt.yaml
	arch/arm64/boot/dts/mediatek/mt8183-kukui-krane-sku176.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb134.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb135.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dt.yaml
	arch/arm/boot/dts/armada-370-db.dt.yaml
	arch/arm/boot/dts/armada-370-seagate-personal-cloud-2bay.dt.yaml
	arch/arm/boot/dts/armada-370-seagate-personal-cloud.dt.yaml
	arch/arm/boot/dts/armada-370-synology-ds213j.dt.yaml
	arch/arm/boot/dts/armada-375-db.dt.yaml
	arch/arm/boot/dts/armada-385-clearfog-gtr-l8.dt.yaml
	arch/arm/boot/dts/armada-385-clearfog-gtr-s4.dt.yaml
	arch/arm/boot/dts/armada-385-db-88f6820-amc.dt.yaml
	arch/arm/boot/dts/armada-385-db-ap.dt.yaml
	arch/arm/boot/dts/armada-385-synology-ds116.dt.yaml
	arch/arm/boot/dts/armada-388-clearfog-base.dt.yaml
	arch/arm/boot/dts/armada-388-clearfog.dt.yaml
	arch/arm/boot/dts/armada-388-clearfog-pro.dt.yaml
	arch/arm/boot/dts/armada-388-db.dt.yaml
	arch/arm/boot/dts/armada-388-gp.dt.yaml
	arch/arm/boot/dts/armada-388-helios4.dt.yaml
	arch/arm/boot/dts/armada-388-rd.dt.yaml
	arch/arm/boot/dts/armada-398-db.dt.yaml
	arch/arm/boot/dts/armada-xp-axpwifiap.dt.yaml
	arch/arm/boot/dts/armada-xp-crs305-1g-4s-bit.dt.yaml
	arch/arm/boot/dts/armada-xp-crs305-1g-4s.dt.yaml
	arch/arm/boot/dts/armada-xp-crs326-24g-2s-bit.dt.yaml
	arch/arm/boot/dts/armada-xp-crs326-24g-2s.dt.yaml
	arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s-bit.dt.yaml
	arch/arm/boot/dts/armada-xp-crs328-4c-20s-4s.dt.yaml
	arch/arm/boot/dts/armada-xp-db.dt.yaml
	arch/arm/boot/dts/armada-xp-gp.dt.yaml
	arch/arm/boot/dts/armada-xp-synology-ds414.dt.yaml
	arch/arm/boot/dts/at91-dvk_som60.dt.yaml
	arch/arm/boot/dts/imx6ul-kontron-n6310-s-43.dt.yaml
	arch/arm/boot/dts/imx6ul-kontron-n6310-s.dt.yaml
	arch/arm/boot/dts/sun8i-v3-sl631-imx179.dt.yaml
	arch/arm/boot/dts/tegra114-dalmore.dt.yaml
	arch/arm/boot/dts/tegra124-jetson-tk1.dt.yaml
	arch/arm/boot/dts/tegra124-venice2.dt.yaml
	arch/arm/boot/dts/tegra20-trimslice.dt.yaml

spi_flash at 0: $nodename:0: 'spi_flash at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/am57xx-cl-som-am57x.dt.yaml
	arch/arm/boot/dts/am57xx-sbc-am57x.dt.yaml
	arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dt.yaml

spiflash at 0: $nodename:0: 'spiflash at 0' does not match '^flash(@.*)?$'
	arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-it.dt.yaml
	arch/arm64/boot/dts/rockchip/rk3328-rock64.dt.yaml
	arch/arm64/boot/dts/rockchip/rk3399-gru-bob.dt.yaml
	arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dt.yaml
	arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-inx.dt.yaml
	arch/arm64/boot/dts/rockchip/rk3399-gru-scarlet-kd.dt.yaml

spi_flash at 0: 'at91bootstrap at 0', 'bootloader at 40000', 'bootloaderenv at 140000', 'bootloaderenvred at 100000', 'dtb at 180000', 'kernel at 200000' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/at91-sama5d27_wlsom1_ek.dt.yaml

spi-flash at 0: compatible: 'oneOf' conditional failed, one must be fixed:
	arch/arm/boot/dts/armada-370-db.dt.yaml

spi-flash at 1: $nodename:0: 'spi-flash at 1' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/armada-385-atl-x530.dt.yaml
	arch/arm/boot/dts/tegra30-beaver.dt.yaml
	arch/arm/boot/dts/tegra30-cardhu-a02.dt.yaml
	arch/arm/boot/dts/tegra30-cardhu-a04.dt.yaml

spi-flash at 9: $nodename:0: 'spi-flash at 9' does not match '^flash(@.*)?$'
	arch/arm64/boot/dts/microchip/sparx5_pcb125.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb134.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb135.dt.yaml
	arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dt.yaml

spi-nor at 0: $nodename:0: 'spi-nor at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/armada-385-turris-omnia.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-gbs.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-gbs.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-gsj.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml

spi-nor at 0: 'partitions at 80000000' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/nuvoton-npcm730-gbs.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-gsj.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml

spi-nor at 0: 'partitions at A0000000' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-evb.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml

spi-nor at 1: $nodename:0: 'spi-nor at 1' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/nuvoton-npcm730-gbs.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml

spi-nor at 1: 'npcm,fiu-rx-bus-width', 'partitions at 88000000' do not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dt.yaml

spi-nor at 1: 'partitions at 88000000' does not match any of the regexes: '^otp(-[0-9]+)?$', '^partition@', 'pinctrl-[0-9]+'
	arch/arm/boot/dts/nuvoton-npcm730-kudo.dt.yaml

w25q64cvzpig at 0: $nodename:0: 'w25q64cvzpig at 0' does not match '^flash(@.*)?$'
	arch/arm/boot/dts/am437x-cm-t43.dt.yaml
	arch/arm/boot/dts/am437x-sbc-t43.dt.yaml



From geert at linux-m68k.org  Tue Oct  5 07:46:37 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 5 Oct 2021 16:46:37 +0200
Subject: [PATCH 1/6] dt-bindings: memory: renesas, rpc-if: Add support for
 the R9A07G044
In-Reply-To: <20210928140721.8805-2-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-2-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdVy7RxUSWQOUDKB3-8igjYGBXO4ZYy=DamgQPqknXaUkw@mail.gmail.com>

On Tue, Sep 28, 2021 at 4:07 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
> the RPC-IF interface found on R-Car Gen3 SoC's.
>
> This patch adds a new compatible string to identify the RZ/G2L family
> so that the timing values on RZ/G2L can be adjusted.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From jbglaw at lug-owl.de  Tue Oct  5 07:49:36 2021
From: jbglaw at lug-owl.de (Jan-Benedict Glaw)
Date: Tue, 5 Oct 2021 16:49:36 +0200
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
Message-ID: <20211005144936.xnkzugjr3oygauei@lug-owl.de>

Hi,

On Fri, 2021-10-01 21:28:36 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:
> diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
> index 8142d9d6fe5d..40edcca7ba62 100644
> --- a/fs/ubifs/key.h
> +++ b/fs/ubifs/key.h
> @@ -436,7 +436,7 @@ static inline void key_write(const struct ubifs_info *c,
>  
>  	t->j32[0] = cpu_to_le32(from->u32[0]);
>  	t->j32[1] = cpu_to_le32(from->u32[1]);
> -	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
> +	memset(to + 8, 0, UBIFS_SK_LEN - 8);
>  }
>  
>  /**

I wanted to give this little patch a ping since there wasn't a reply
until now and I think it might fix an overflow.

Please keep me Cc'ed since I'm not on this list!

Thanks,
  Jan-Benedict

-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211005/b34ada80/attachment.sig>

From geert at linux-m68k.org  Tue Oct  5 08:11:53 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 5 Oct 2021 17:11:53 +0200
Subject: [PATCH 2/6] dt-bindings: memory: renesas,rpc-if: Add optional
 interrupts property
In-Reply-To: <20210928140721.8805-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdWSsrV-9Kxz=zS3CVKSbo2OkwyaVK2Jx-+X68W-cqAdvQ@mail.gmail.com>

On Tue, Sep 28, 2021 at 4:07 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> For completeness add optional interrupts property.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From geert at linux-m68k.org  Tue Oct  5 08:25:51 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Tue, 5 Oct 2021 17:25:51 +0200
Subject: [PATCH 3/6] spi: spi-rpc-if: Check return value of rpcif_sw_init()
In-Reply-To: <20210928140721.8805-4-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-4-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdXVxOtvXu_DM5FjFzNcPbLtrRJ9W2R6CHmCc0ZJg9JJYw@mail.gmail.com>

Hi Prabhakar,

Thanks for your patch!

On Tue, Sep 28, 2021 at 4:07 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> rpcif_sw_init() can fail so make sure we check the return value
> of it and on error exit rpcif_spi_probe() callback with error code.

Indeed, it will now fail earlier if CONFIG_RESET_CONTROLLER=n
Patch sent
https://lore.kernel.org/all/d4383bd1a97c0490c0bdc9dae5695f4230d4a420.1633447185.git.geert+renesas at glider.be

> Fixes: eb8d6d464a27 ("spi: add Renesas RPC-IF driver")
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From dphadke at linux.microsoft.com  Tue Oct  5 17:03:14 2021
From: dphadke at linux.microsoft.com (Dhananjay Phadke)
Date: Tue,  5 Oct 2021 17:03:14 -0700
Subject: [PATCH 3/6] mtd: spi-nor: aspeed: Refactor
 registration/unregistration
In-Reply-To: <20210929115409.21254-4-zev@bewilderbeest.net>
References: <20210929115409.21254-4-zev@bewilderbeest.net>
Message-ID: <1633478594-16793-1-git-send-email-dphadke@linux.microsoft.com>



On Wed, 29 Sep 2021, Zev Weiss wrote:

> We now have separate functions for registering and unregistering
> individual flash chips, instead of the entire controller.  This is a
> preparatory step for allowing userspace to request that a specific
> chip be attached or detached at runtime.
>
> Signed-off-by: Zev Weiss <zev at bewilderbeest.net>
> ---
> drivers/mtd/spi-nor/controllers/aspeed-smc.c | 73 ++++++++++++--------
> 1 file changed, 45 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/controllers/aspeed-smc.c b/drivers/mtd/spi-nor/controllers/aspeed-smc.c
> index 7225870e8b18..3c153104a905 100644
> --- a/drivers/mtd/spi-nor/controllers/aspeed-smc.c
> +++ b/drivers/mtd/spi-nor/controllers/aspeed-smc.c
> @@ -107,9 +107,10 @@ struct aspeed_smc_controller {
> 	const struct aspeed_smc_info *info;	/* type info of controller */
> 	void __iomem *regs;			/* controller registers */
> 	void __iomem *ahb_base;			/* per-chip windows resource */
> +	struct resource *ahb_res;		/* resource for AHB address space */
> 	u32 ahb_window_size;			/* full mapping window size */
>
> -	struct aspeed_smc_chip *chips[];	/* pointers to attached chips */
> +	struct aspeed_smc_chip *chips[];	/* pointers to connected chips */
> };
>
> /*
> @@ -399,15 +400,24 @@ static ssize_t aspeed_smc_write_user(struct spi_nor *nor, loff_t to,
> 	return len;
> }
>
> +static int aspeed_smc_unregister_chip(struct aspeed_smc_chip *chip)
> +{
> +	return mtd_device_unregister(&chip->nor.mtd);
> +}
> +
> static int aspeed_smc_unregister(struct aspeed_smc_controller *controller)
> {
> 	struct aspeed_smc_chip *chip;
> -	int n;
> +	int n, ret;
>
> 	for (n = 0; n < controller->info->nce; n++) {
> 		chip = controller->chips[n];
> -		if (chip)
> -			mtd_device_unregister(&chip->nor.mtd);
> +		if (chip) {
> +			ret = aspeed_smc_unregister_chip(chip);
> +			if (ret)
> +				dev_warn(controller->dev, "failed to unregister CS%d: %d\n",
> +				         n, ret);
> +		}
> 	}
>
> 	return 0;
> @@ -756,14 +766,39 @@ static const struct spi_nor_controller_ops aspeed_smc_controller_ops = {
> 	.write = aspeed_smc_write_user,
> };
>
> -static int aspeed_smc_setup_flash(struct aspeed_smc_controller *controller,
> -				  struct device_node *np, struct resource *r)
> +static int aspeed_smc_register_chip(struct aspeed_smc_chip *chip)
> {
> -	const struct spi_nor_hwcaps hwcaps = {
> +	static const struct spi_nor_hwcaps hwcaps = {
> 		.mask = SNOR_HWCAPS_READ |
> 			SNOR_HWCAPS_READ_FAST |
> 			SNOR_HWCAPS_PP,
> 	};
> +	int ret;
> +
> +	ret = aspeed_smc_chip_setup_init(chip, chip->controller->ahb_res);
> +	if (ret)
> +		goto out;
> +
> +	/*
> +	 * TODO: Add support for Dual and Quad SPI protocols attach when board
> +	 * support is present as determined by of property.
> +	 */
> +	ret = spi_nor_scan(&chip->nor, NULL, &hwcaps);
> +	if (ret)
> +		goto out;
> +
> +	ret = aspeed_smc_chip_setup_finish(chip);
> +	if (ret)
> +		goto out;
> +
> +	ret = mtd_device_register(&chip->nor.mtd, NULL, 0);
> +out:
> +	return ret;
> +}

I was looking into this driver probe walking sub-nodes.

It looks like all controller drivers are doing / have to do similar work -

(1) Parse common dt bindings documented in Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
(2) Run spi_nor_scan() with tweaked/reduced capabilities.
(3) mtd_register_device().

It would be good to absorb this workflow in mtd/spi-nor core and add 'reserved' as common
dt property to avoid (2) and (3) from probe.


Regards,
Dhananjay



From matthias.schiffer at ew.tq-group.com  Wed Oct  6 05:32:11 2021
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Wed, 06 Oct 2021 14:32:11 +0200
Subject: (EXT) Re: [PATCH 1/2] mtd: spi-nor: micron-st: sync flags of
 mt25ql02g and mt25qu02g with other mt25q
In-Reply-To: <f3dbab898e9f1946129e5733095bdf3c@walle.cc>
References: <c7b6c666aef9a8a2195acabe9954a417f04b6582.1627039534.git.matthias.schiffer@ew.tq-group.com>
 <f3dbab898e9f1946129e5733095bdf3c@walle.cc>
Message-ID: <3258026683c916a3a42e98ba76628228cddacb23.camel@ew.tq-group.com>

On Tue, 2021-07-27 at 09:09 +0200, Michael Walle wrote:
> Am 2021-07-23 13:27, schrieb Matthias Schiffer:
> > All mt25q variants have the same features.
> > 
> > Unlike the smaller variants, no n25q with 2G exists, so we don't need 
> > to
> > match on the extended ID to distinguish n25q and mt25q series for these
> > models.
> 
> But why shouldn't we? What if there will be another flash with
> the same first three id bytes?

How do you suggest we proceed here? At the moment there are entries
matching on 0x20b[ab]22 (ignoring the extended ID) with the name
mt25q[lu]02g.

Should I change these entries to match on on the extended ID
0x20b[ab]22 / 0x104400 instead when I add the bits for the features
specific to the variant, removing support for other 0x20b[ab]22
variants that may or may not actually exist? Keeping both entries (with
and without extended ID match) would preserve compatiblity with such
variants, but this approach seems problematic to me as well, as I can't
even give a name to the more generic entries (and there is no natural
extension of the n25q naming scheme to a 2G variant).


> 
> > Signed-off-by: Matthias Schiffer <matthias.schiffer at ew.tq-group.com>
> > ---
> >  drivers/mtd/spi-nor/micron-st.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/mtd/spi-nor/micron-st.c 
> > b/drivers/mtd/spi-nor/micron-st.c
> > index c224e59820a1..d5baa8762c8d 100644
> > --- a/drivers/mtd/spi-nor/micron-st.c
> > +++ b/drivers/mtd/spi-nor/micron-st.c
> > @@ -181,11 +181,11 @@ static const struct flash_info st_parts[] = {
> >  			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
> >  			      NO_CHIP_ERASE) },
> >  	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
> > -			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
> > -			      NO_CHIP_ERASE) },
> 
> This bothers me. I'm not sure how this will work. I see that
> chip erase is command 0xc7, but both the new and the old flash
> just supports 0xc3 (DIE ERASE). Did you test these changes?

I finally got my hands on hardware with this flash again (well, a
mt25qu01g, I don't think we have the 2G variants anywhere) and I can
confirm that the chip erase does not work with my patch. I will send an
updated version that keeps NO_CHIP_ERASE.


> 
> > +			      SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> > +			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >  	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096,
> >  			      SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> > -			      SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
> > +			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> > 
> >  	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
> >  	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
> 
> -michael



From richard at nod.at  Wed Oct  6 23:59:03 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 7 Oct 2021 08:59:03 +0200 (CEST)
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <20211005144936.xnkzugjr3oygauei@lug-owl.de>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
Message-ID: <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "Jan-Benedict Glaw" <jbglaw at lug-owl.de>
> An: "linux-mtd" <linux-mtd at lists.infradead.org>
> CC: "Artem Bityutskiy" <artem.bityutskiy at linux.intel.com>, "richard" <richard at nod.at>
> Gesendet: Dienstag, 5. Oktober 2021 16:49:36
> Betreff: PING: [PATCH] Don't overflow when writing a key

> Hi,
> 
> On Fri, 2021-10-01 21:28:36 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:
>> diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
>> index 8142d9d6fe5d..40edcca7ba62 100644
>> --- a/fs/ubifs/key.h
>> +++ b/fs/ubifs/key.h
>> @@ -436,7 +436,7 @@ static inline void key_write(const struct ubifs_info *c,
>>  
>>  	t->j32[0] = cpu_to_le32(from->u32[0]);
>>  	t->j32[1] = cpu_to_le32(from->u32[1]);
>> -	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
>> +	memset(to + 8, 0, UBIFS_SK_LEN - 8);
>>  }
>>  
>>  /**
> 
> I wanted to give this little patch a ping since there wasn't a reply

In MTD's patchwork it is marked as "Under review", so it is not lost.

> until now and I think it might fix an overflow.

Your fix looks legit but since I'm traveling I need to give it a deeper
thought when I'm back home.
I'm a little puzzled why nobody noticed the stack corruption so far,
key_write() has been doing since ever.

Thanks,
//richard


From zhengxunli.mxic at gmail.com  Thu Oct  7 23:57:55 2021
From: zhengxunli.mxic at gmail.com (Zhengxun)
Date: Fri,  8 Oct 2021 14:57:55 +0800
Subject: [PATCH 0/4] mtd: spinand: Add continuous read mode support
Message-ID: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>

This series add support continuous read mode for SPI NAND.

The Macronix SPI NAND supports conventional read mode and continuous
read modes. If the configuration register bit ?CONT? = 0, the device
is in conventional read mode. The page read operation and page read
cache Random/ sequential operation is supported in the conventional
read mode. If the configuration register bit ?CONT? = 1, the device
is in continuous read mode and only continuous read operation is
supported. During the continuous read mode, the page read cache
related commands are not supported. (Page Cache Sequential (31h),
Page Read Cache Random (30h) and Page Read Cache End (3Fh)).

The continuous read operation including: firstly, starting with the 
page read command and the 1 st page data will be read into the cache
after the read latency tRD_CONT1. Secondly, Issuing the Read From
Cache commands (03h/0Bh/3Bh/6Bh/BBh/EBh) to read out the data from
cache continuously. The cache is divided into two halves, while one 
half of the cache is outputting the data, the other half will be
loaded for the new data; therefore, the host can read out the data
continuously from page to page. Multiple of Read From Cache commands
can be issued in one continuous read operation, each Read From Cache
command is required to read multiple 4-byte data exactly; otherwise,
the data output will be out of sequence from one Read From Cache
command to another Read From Cache command. After all the data is
read out, the host should issue Exit Continuous Read Command (63h)
to terminate this continuous read operation.

The data output for each page will always start from byte 0 and a
full page data (2KB) should be read out for each page. If the host
just wants to read out partial page data, Exit Continuous Read
Command (63h) should be issued to terminate the current continuous
read operation.

Zhengxun (4):
  mtd: spinand: Add support continuous read mode
  mtd: spinand: Add continuous read exit command
  mtd: spinand: Add support continuous read operation
  mtd: spinand: macronix: Add support for Macronix MX31LF2GE4BC SPI NAND
    flash

 drivers/mtd/nand/spi/core.c     | 65 +++++++++++++++++++++++++++++++++++------
 drivers/mtd/nand/spi/macronix.c | 11 +++++++
 include/linux/mtd/spinand.h     | 10 +++++++
 3 files changed, 77 insertions(+), 9 deletions(-)

-- 
2.7.4



From zhengxunli.mxic at gmail.com  Thu Oct  7 23:57:56 2021
From: zhengxunli.mxic at gmail.com (Zhengxun)
Date: Fri,  8 Oct 2021 14:57:56 +0800
Subject: [PATCH 1/4] mtd: spinand: Add support continuous read mode
In-Reply-To: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
References: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
Message-ID: <1633676279-29708-2-git-send-email-zhengxunli.mxic@gmail.com>

The patch supports setting the "CONT" bit of the configuration
register and adding a continuous read mode flag for identification.

Signed-off-by: Zhengxun <zhengxunli.mxic at gmail.com>
---
 drivers/mtd/nand/spi/core.c | 17 +++++++++++++++++
 include/linux/mtd/spinand.h |  2 ++
 2 files changed, 19 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 2c8685f..bcdd438 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -193,6 +193,23 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
 			       enable ? CFG_QUAD_ENABLE : 0);
 }
 
+static int spinand_continuous_read_enable(struct spinand_device *spinand)
+{
+	if (!(spinand->flags & SPINAND_HAS_CONT_READ_BIT))
+		return 0;
+
+	return spinand_upd_cfg(spinand, CFG_CONT_READ_ENABLE,
+			       CFG_CONT_READ_ENABLE);
+}
+
+static int spinand_continuous_read_disable(struct spinand_device *spinand)
+{
+	if (!(spinand->flags & SPINAND_HAS_CONT_READ_BIT))
+		return 0;
+
+	return spinand_upd_cfg(spinand, CFG_CONT_READ_ENABLE, 0);
+}
+
 static int spinand_ecc_enable(struct spinand_device *spinand,
 			      bool enable)
 {
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 6988956..04be10e 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -154,6 +154,7 @@
 #define REG_CFG			0xb0
 #define CFG_OTP_ENABLE		BIT(6)
 #define CFG_ECC_ENABLE		BIT(4)
+#define CFG_CONT_READ_ENABLE	BIT(2)
 #define CFG_QUAD_ENABLE		BIT(0)
 
 /* status register */
@@ -307,6 +308,7 @@ struct spinand_ecc_info {
 
 #define SPINAND_HAS_QE_BIT		BIT(0)
 #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+#define SPINAND_HAS_CONT_READ_BIT	BIT(2)
 
 /**
  * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
-- 
2.7.4



From zhengxunli.mxic at gmail.com  Thu Oct  7 23:57:57 2021
From: zhengxunli.mxic at gmail.com (Zhengxun)
Date: Fri,  8 Oct 2021 14:57:57 +0800
Subject: [PATCH 2/4] mtd: spinand: Add continuous read exit command
In-Reply-To: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
References: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
Message-ID: <1633676279-29708-3-git-send-email-zhengxunli.mxic@gmail.com>

Add a continuous read exit command to terminate continuous read
operation.

Signed-off-by: Zhengxun <zhengxunli.mxic at gmail.com>
---
 drivers/mtd/nand/spi/core.c | 10 ++++++++++
 include/linux/mtd/spinand.h |  6 ++++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index bcdd438..0d9632f 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -431,6 +431,16 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
 	return 0;
 }
 
+static int spinand_continuous_read_exit(struct spinand_device *spinand)
+{
+	struct spi_mem_op op = SPINAND_EXIT_CONT_READ;
+
+	if (!(spinand->flags & SPINAND_HAS_CONT_READ_BIT))
+		return 0;
+
+	return spi_mem_exec_op(spinand->spimem, &op);
+}
+
 static int spinand_write_to_cache_op(struct spinand_device *spinand,
 				     const struct nand_page_io_req *req)
 {
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 04be10e..e044aba 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -122,6 +122,12 @@
 		   SPI_MEM_OP_DUMMY(ndummy, 4),				\
 		   SPI_MEM_OP_DATA_IN(len, buf, 4))
 
+#define SPINAND_EXIT_CONT_READ						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(0x63, 1),				\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_PROG_EXEC_OP(addr)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1),				\
 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
-- 
2.7.4



From zhengxunli.mxic at gmail.com  Thu Oct  7 23:57:58 2021
From: zhengxunli.mxic at gmail.com (Zhengxun)
Date: Fri,  8 Oct 2021 14:57:58 +0800
Subject: [PATCH 3/4] mtd: spinand: Add support continuous read operation
In-Reply-To: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
References: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
Message-ID: <1633676279-29708-4-git-send-email-zhengxunli.mxic@gmail.com>

The patch adds a continuous read start flag to support continuous
read operations. The continuous read operation only issues a page
read command (13h), issues multiple read commands from the cache
(03h/0Bh/3Bh/6Bh/BBh/EBh) to read continuous address data, and
finally issues an exit continuous read command (63h) to terminate
this continuous read operation.

Since the continuous read mode can only read the entire page of data
(2KB) and cannot read the oob data, the dynamic change mode is added
to enable continuous read mode and disable continuous read mode in
spinand_mtd_read to avoid writing and erasing operation is abnormal.

Signed-off-by: Zhengxun <zhengxunli.mxic at gmail.com>
---
 drivers/mtd/nand/spi/core.c | 38 +++++++++++++++++++++++++++++---------
 include/linux/mtd/spinand.h |  2 ++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 0d9632f..0369453 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -195,6 +195,8 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
 
 static int spinand_continuous_read_enable(struct spinand_device *spinand)
 {
+	spinand->cont_read_start = false;
+
 	if (!(spinand->flags & SPINAND_HAS_CONT_READ_BIT))
 		return 0;
 
@@ -598,16 +600,22 @@ static int spinand_read_page(struct spinand_device *spinand,
 	if (ret)
 		return ret;
 
-	ret = spinand_load_page_op(spinand, req);
-	if (ret)
-		return ret;
+	if (!spinand->cont_read_start) {
 
-	ret = spinand_wait(spinand,
-			   SPINAND_READ_INITIAL_DELAY_US,
-			   SPINAND_READ_POLL_DELAY_US,
-			   &status);
-	if (ret < 0)
-		return ret;
+		ret = spinand_load_page_op(spinand, req);
+		if (ret)
+			return ret;
+
+		ret = spinand_wait(spinand,
+				   SPINAND_READ_INITIAL_DELAY_US,
+				   SPINAND_READ_POLL_DELAY_US,
+				   &status);
+		if (ret < 0)
+			return ret;
+
+		if (spinand->flags & SPINAND_HAS_CONT_READ_BIT)
+			spinand->cont_read_start = true;
+	}
 
 	spinand_ondie_ecc_save_status(nand, status);
 
@@ -667,6 +675,10 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 
 	mutex_lock(&spinand->lock);
 
+	ret = spinand_continuous_read_enable(spinand);
+	if (ret)
+		return ret;
+
 	nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) {
 		if (disable_ecc)
 			iter.req.mode = MTD_OPS_RAW;
@@ -689,6 +701,14 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 		ops->oobretlen += iter.req.ooblen;
 	}
 
+	ret = spinand_continuous_read_exit(spinand);
+	if (ret)
+		return ret;
+
+	ret = spinand_continuous_read_disable(spinand);
+	if (ret)
+		return ret;
+
 	mutex_unlock(&spinand->lock);
 
 	if (ecc_failed && !ret)
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index e044aba..c2a41a3 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -422,6 +422,7 @@ struct spinand_dirmap {
  *		because the spi-mem interface explicitly requests that buffers
  *		passed in spi_mem_op be DMA-able, so we can't based the bufs on
  *		the stack
+ * @cont_read_start: record the continuous read status
  * @manufacturer: SPI NAND manufacturer information
  * @priv: manufacturer private data
  */
@@ -450,6 +451,7 @@ struct spinand_device {
 	u8 *databuf;
 	u8 *oobbuf;
 	u8 *scratchbuf;
+	bool cont_read_start;
 	const struct spinand_manufacturer *manufacturer;
 	void *priv;
 };
-- 
2.7.4



From zhengxunli.mxic at gmail.com  Thu Oct  7 23:57:59 2021
From: zhengxunli.mxic at gmail.com (Zhengxun)
Date: Fri,  8 Oct 2021 14:57:59 +0800
Subject: [PATCH 4/4] mtd: spinand: macronix: Add support for Macronix
 MX31LF2GE4BC SPI NAND flash
In-Reply-To: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
References: <1633676279-29708-1-git-send-email-zhengxunli.mxic@gmail.com>
Message-ID: <1633676279-29708-5-git-send-email-zhengxunli.mxic@gmail.com>

The Macronix MX31LF2GE4BC are 3V, 2Gbit serial SLC NAND flash device.

MX"31", means SPI NAND
MX31"LF", LF means 3V
MX31LF"2G", 2G means 2Gbits
MX31LF2G"E4", E4 means internal ECC and Quad I/O(x4)

Validated via normal(default) and QUAD mode by read, erase, read back,
on Xilinx Zynq PicoZed FPGA board which included Macronix
SPI Host(drivers/spi/spi-mxic.c).

Signed-off-by: Zhengxun <zhengxunli.mxic at gmail.com>
---
 drivers/mtd/nand/spi/macronix.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index 3f31f13..43cfd85 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -176,6 +176,17 @@ static const struct spinand_info macronix_spinand_table[] = {
 		     SPINAND_HAS_QE_BIT,
 		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
 				     mx35lf1ge4ab_ecc_get_status)),
+	SPINAND_INFO("MX31LF2GE4BC",
+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x2e),
+		     NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
+		     NAND_ECCREQ(8, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+					      &write_cache_variants,
+					      &update_cache_variants),
+		     SPINAND_HAS_QE_BIT | SPINAND_HAS_CONT_READ_BIT,
+		     SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
+				     mx35lf1ge4ab_ecc_get_status)),
+
 	SPINAND_INFO("MX31UF1GE4BC",
 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x9e),
 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
-- 
2.7.4



From michael at walle.cc  Thu Oct  7 00:08:18 2021
From: michael at walle.cc (Michael Walle)
Date: Thu, 07 Oct 2021 09:08:18 +0200
Subject: (EXT) Re: [PATCH 1/2] mtd: spi-nor: micron-st: sync flags of
 mt25ql02g and mt25qu02g with other mt25q
In-Reply-To: <3258026683c916a3a42e98ba76628228cddacb23.camel@ew.tq-group.com>
References: <c7b6c666aef9a8a2195acabe9954a417f04b6582.1627039534.git.matthias.schiffer@ew.tq-group.com>
 <f3dbab898e9f1946129e5733095bdf3c@walle.cc>
 <3258026683c916a3a42e98ba76628228cddacb23.camel@ew.tq-group.com>
Message-ID: <969e9169b77bb314aaa2e97789c76c00@walle.cc>

Am 2021-10-06 14:32, schrieb Matthias Schiffer:
> On Tue, 2021-07-27 at 09:09 +0200, Michael Walle wrote:
>> Am 2021-07-23 13:27, schrieb Matthias Schiffer:
>> > All mt25q variants have the same features.
>> >
>> > Unlike the smaller variants, no n25q with 2G exists, so we don't need
>> > to
>> > match on the extended ID to distinguish n25q and mt25q series for these
>> > models.
>> 
>> But why shouldn't we? What if there will be another flash with
>> the same first three id bytes?
> 
> How do you suggest we proceed here? At the moment there are entries
> matching on 0x20b[ab]22 (ignoring the extended ID) with the name
> mt25q[lu]02g.
> 
> Should I change these entries to match on on the extended ID
> 0x20b[ab]22 / 0x104400 instead when I add the bits for the features
> specific to the variant, removing support for other 0x20b[ab]22
> variants that may or may not actually exist? Keeping both entries (with
> and without extended ID match) would preserve compatiblity with such
> variants, but this approach seems problematic to me as well, as I can't
> even give a name to the more generic entries (and there is no natural
> extension of the n25q naming scheme to a 2G variant).

Mh, what do you think of adding three entries and make the last one,
the one with the short id, as a fallback so to speak. This should
retrain backwards compatibility, right? It should probably have a
comment because the order will matter then.

-michael


From matthias.schiffer at ew.tq-group.com  Thu Oct  7 00:18:22 2021
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Thu, 07 Oct 2021 09:18:22 +0200
Subject: (EXT) Re: (EXT) Re: [PATCH 1/2] mtd: spi-nor: micron-st: sync
 flags of mt25ql02g and mt25qu02g with other mt25q
In-Reply-To: <969e9169b77bb314aaa2e97789c76c00@walle.cc>
References: <c7b6c666aef9a8a2195acabe9954a417f04b6582.1627039534.git.matthias.schiffer@ew.tq-group.com>
 <f3dbab898e9f1946129e5733095bdf3c@walle.cc>
 <3258026683c916a3a42e98ba76628228cddacb23.camel@ew.tq-group.com>
 <969e9169b77bb314aaa2e97789c76c00@walle.cc>
Message-ID: <0e2ad27b00d85c1dfa489d91b54d2a3af41f5edb.camel@ew.tq-group.com>

On Thu, 2021-10-07 at 09:08 +0200, Michael Walle wrote:
> Am 2021-10-06 14:32, schrieb Matthias Schiffer:
> > On Tue, 2021-07-27 at 09:09 +0200, Michael Walle wrote:
> > > Am 2021-07-23 13:27, schrieb Matthias Schiffer:
> > > > All mt25q variants have the same features.
> > > > 
> > > > Unlike the smaller variants, no n25q with 2G exists, so we don't need
> > > > to
> > > > match on the extended ID to distinguish n25q and mt25q series for these
> > > > models.
> > > 
> > > But why shouldn't we? What if there will be another flash with
> > > the same first three id bytes?
> > 
> > How do you suggest we proceed here? At the moment there are entries
> > matching on 0x20b[ab]22 (ignoring the extended ID) with the name
> > mt25q[lu]02g.
> > 
> > Should I change these entries to match on on the extended ID
> > 0x20b[ab]22 / 0x104400 instead when I add the bits for the features
> > specific to the variant, removing support for other 0x20b[ab]22
> > variants that may or may not actually exist? Keeping both entries (with
> > and without extended ID match) would preserve compatiblity with such
> > variants, but this approach seems problematic to me as well, as I can't
> > even give a name to the more generic entries (and there is no natural
> > extension of the n25q naming scheme to a 2G variant).
> 
> Mh, what do you think of adding three entries and make the last one,
> the one with the short id, as a fallback so to speak. This should
> retrain backwards compatibility, right? It should probably have a
> comment because the order will matter then.
> 
> -michael

Is it okay for multiple entries to use the same value for the "name"
field? In the existing definitions I couldn't find any example of
different ID matches mapping to the same name.



From richard at nod.at  Thu Oct  7 00:20:05 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 7 Oct 2021 09:20:05 +0200 (CEST)
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
Message-ID: <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "richard" <richard at nod.at>
> An: "Jan-Benedict Glaw" <jbglaw at lug-owl.de>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "Artem Bityutskiy" <artem.bityutskiy at linux.intel.com>
> Gesendet: Donnerstag, 7. Oktober 2021 08:59:03
> Betreff: Re: PING: [PATCH] Don't overflow when writing a key

> ----- Urspr?ngliche Mail -----
>> Von: "Jan-Benedict Glaw" <jbglaw at lug-owl.de>
>> An: "linux-mtd" <linux-mtd at lists.infradead.org>
>> CC: "Artem Bityutskiy" <artem.bityutskiy at linux.intel.com>, "richard"
>> <richard at nod.at>
>> Gesendet: Dienstag, 5. Oktober 2021 16:49:36
>> Betreff: PING: [PATCH] Don't overflow when writing a key
> 
>> Hi,
>> 
>> On Fri, 2021-10-01 21:28:36 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:
>>> diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
>>> index 8142d9d6fe5d..40edcca7ba62 100644
>>> --- a/fs/ubifs/key.h
>>> +++ b/fs/ubifs/key.h
>>> @@ -436,7 +436,7 @@ static inline void key_write(const struct ubifs_info *c,
>>>  
>>>  	t->j32[0] = cpu_to_le32(from->u32[0]);
>>>  	t->j32[1] = cpu_to_le32(from->u32[1]);
>>> -	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
>>> +	memset(to + 8, 0, UBIFS_SK_LEN - 8);
>>>  }
>>>  
>>>  /**
>> 
>> I wanted to give this little patch a ping since there wasn't a reply
> 
> In MTD's patchwork it is marked as "Under review", so it is not lost.
> 
>> until now and I think it might fix an overflow.
> 
> Your fix looks legit but since I'm traveling I need to give it a deeper
> thought when I'm back home.
> I'm a little puzzled why nobody noticed the stack corruption so far,
> key_write() has been doing since ever.

Typing that mail triggered already a deeper thought. :-D

key_write() takes a ubifs_key as source and writes to a buffer.
It assumes that the passed ubifs_key is in simple key format (being UBIFS_SK_LEN long)
and it assumes the buffer is UBIFS_MAX_KEY_LEN long.
So, the destination is *not* a union ubifs_key structure.

We have three callers of key_write(), all in journal.c

1. ubifs_jnl_write_data
key_write(c, key, &data->key);

data is struct ubifs_data_node where key is of size UBIFS_MAX_KEY_LEN.

2. ubifs_jnl_update

Same with struct ubifs_dent_node

3. ubifs_jnl_delete_xattr

Same again.

All three objects are slab allocated, did you check, is too few memory allocated?
In other words, how did you calculate the size of target buffer?

Thanks,
//richard


From michael at walle.cc  Thu Oct  7 00:37:27 2021
From: michael at walle.cc (Michael Walle)
Date: Thu, 07 Oct 2021 09:37:27 +0200
Subject: (EXT) Re: (EXT) Re: [PATCH 1/2] mtd: spi-nor: micron-st: sync
 flags of mt25ql02g and mt25qu02g with other mt25q
In-Reply-To: <0e2ad27b00d85c1dfa489d91b54d2a3af41f5edb.camel@ew.tq-group.com>
References: <c7b6c666aef9a8a2195acabe9954a417f04b6582.1627039534.git.matthias.schiffer@ew.tq-group.com>
 <f3dbab898e9f1946129e5733095bdf3c@walle.cc>
 <3258026683c916a3a42e98ba76628228cddacb23.camel@ew.tq-group.com>
 <969e9169b77bb314aaa2e97789c76c00@walle.cc>
 <0e2ad27b00d85c1dfa489d91b54d2a3af41f5edb.camel@ew.tq-group.com>
Message-ID: <6ea1852ddc390cf18db0ae927b88b2b9@walle.cc>

Am 2021-10-07 09:18, schrieb Matthias Schiffer:
> On Thu, 2021-10-07 at 09:08 +0200, Michael Walle wrote:
>> Am 2021-10-06 14:32, schrieb Matthias Schiffer:
>> > On Tue, 2021-07-27 at 09:09 +0200, Michael Walle wrote:
>> > > Am 2021-07-23 13:27, schrieb Matthias Schiffer:
>> > > > All mt25q variants have the same features.
>> > > >
>> > > > Unlike the smaller variants, no n25q with 2G exists, so we don't need
>> > > > to
>> > > > match on the extended ID to distinguish n25q and mt25q series for these
>> > > > models.
>> > >
>> > > But why shouldn't we? What if there will be another flash with
>> > > the same first three id bytes?
>> >
>> > How do you suggest we proceed here? At the moment there are entries
>> > matching on 0x20b[ab]22 (ignoring the extended ID) with the name
>> > mt25q[lu]02g.
>> >
>> > Should I change these entries to match on on the extended ID
>> > 0x20b[ab]22 / 0x104400 instead when I add the bits for the features
>> > specific to the variant, removing support for other 0x20b[ab]22
>> > variants that may or may not actually exist? Keeping both entries (with
>> > and without extended ID match) would preserve compatiblity with such
>> > variants, but this approach seems problematic to me as well, as I can't
>> > even give a name to the more generic entries (and there is no natural
>> > extension of the n25q naming scheme to a 2G variant).
>> 
>> Mh, what do you think of adding three entries and make the last one,
>> the one with the short id, as a fallback so to speak. This should
>> retrain backwards compatibility, right? It should probably have a
>> comment because the order will matter then.
>> 
>> -michael
> 
> Is it okay for multiple entries to use the same value for the "name"
> field? In the existing definitions I couldn't find any example of
> different ID matches mapping to the same name.

You're right, thats probably not good. Ok, if there is no objection
from Tudor, I'd say we change the entry of the mt25 variant to the
longer one. If there is a flash chip out there which matched the
shorter one, but not the longer one, thats probably not a mt25 anyway.

-michael


From rogerq at kernel.org  Thu Oct  7 01:03:50 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu, 7 Oct 2021 11:03:50 +0300
Subject: [PATCH v4 7/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <654bb29d-5580-3035-fc43-546a7e88e224@canonical.com>
References: <20210914122705.15421-1-rogerq@kernel.org>
 <20210914122705.15421-8-rogerq@kernel.org>
 <654bb29d-5580-3035-fc43-546a7e88e224@canonical.com>
Message-ID: <8c1568e8-8b88-05c3-12ac-46dd77404163@kernel.org>

Hi Krzysztof,

On 15/09/2021 10:20, Krzysztof Kozlowski wrote:
> On 14/09/2021 14:27, Roger Quadros wrote:
>> Convert omap-gpmc.txt to ti,gpmc.yaml.
>>
>> Signed-off-by: Roger Quadros <rogerq at kernel.org>
>> ---
>>  .../bindings/memory-controllers/omap-gpmc.txt | 157 ----------------
>>  .../bindings/memory-controllers/ti,gpmc.yaml  | 172 ++++++++++++++++++
>>  2 files changed, 172 insertions(+), 157 deletions(-)
>>  delete mode 100644 Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
>>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
>> deleted file mode 100644
>> index c1359f4d48d7..000000000000
>> --- a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
>> +++ /dev/null
>> @@ -1,157 +0,0 @@
>> -Device tree bindings for OMAP general purpose memory controllers (GPMC)
>> -
>> -The actual devices are instantiated from the child nodes of a GPMC node.
>> -
>> -Required properties:
>> -
>> - - compatible:		Should be set to one of the following:
>> -
>> -			ti,omap2420-gpmc (omap2420)
>> -			ti,omap2430-gpmc (omap2430)
>> -			ti,omap3430-gpmc (omap3430 & omap3630)
>> -			ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
>> -			ti,am3352-gpmc   (am335x devices)
>> -
>> - - reg:			A resource specifier for the register space
>> -			(see the example below)
>> - - ti,hwmods:		Should be set to "ti,gpmc" until the DT transition is
>> -			completed.
>> - - #address-cells:	Must be set to 2 to allow memory address translation
>> - - #size-cells:		Must be set to 1 to allow CS address passing
>> - - gpmc,num-cs:		The maximum number of chip-select lines that controller
>> -			can support.
>> - - gpmc,num-waitpins:	The maximum number of wait pins that controller can
>> -			support.
>> - - ranges:		Must be set up to reflect the memory layout with four
>> -			integer values for each chip-select line in use:
>> -
>> -			   <cs-number> 0 <physical address of mapping> <size>
>> -
>> -			Currently, calculated values derived from the contents
>> -			of the per-CS register GPMC_CONFIG7 (as set up by the
>> -			bootloader) are used for the physical address decoding.
>> -			As this will change in the future, filling correct
>> -			values here is a requirement.
>> - - interrupt-controller: The GPMC driver implements and interrupt controller for
>> -			the NAND events "fifoevent" and "termcount" plus the
>> -			rising/falling edges on the GPMC_WAIT pins.
>> -			The interrupt number mapping is as follows
>> -			0 - NAND_fifoevent
>> -			1 - NAND_termcount
>> -			2 - GPMC_WAIT0 pin edge
>> -			3 - GPMC_WAIT1 pin edge, and so on.
>> - - interrupt-cells:	Must be set to 2
>> - - gpio-controller:	The GPMC driver implements a GPIO controller for the
>> -			GPMC WAIT pins that can be used as general purpose inputs.
>> -			0 maps to GPMC_WAIT0 pin.
>> - - gpio-cells:		Must be set to 2
>> -
>> -Required properties when using NAND prefetch dma:
>> - - dmas			GPMC NAND prefetch dma channel
>> - - dma-names		Must be set to "rxtx"
>> -
>> -Timing properties for child nodes. All are optional and default to 0.
>> -
>> - - gpmc,sync-clk-ps:	Minimum clock period for synchronous mode, in picoseconds
>> -
>> - Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
>> - - gpmc,cs-on-ns:	Assertion time
>> - - gpmc,cs-rd-off-ns:	Read deassertion time
>> - - gpmc,cs-wr-off-ns:	Write deassertion time
>> -
>> - ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
>> - - gpmc,adv-on-ns:	Assertion time
>> - - gpmc,adv-rd-off-ns:	Read deassertion time
>> - - gpmc,adv-wr-off-ns:	Write deassertion time
>> - - gpmc,adv-aad-mux-on-ns:	Assertion time for AAD
>> - - gpmc,adv-aad-mux-rd-off-ns:	Read deassertion time for AAD
>> - - gpmc,adv-aad-mux-wr-off-ns:	Write deassertion time for AAD
>> -
>> - WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
>> - - gpmc,we-on-ns	Assertion time
>> - - gpmc,we-off-ns:	Deassertion time
>> -
>> - OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
>> - - gpmc,oe-on-ns:	Assertion time
>> - - gpmc,oe-off-ns:	Deassertion time
>> - - gpmc,oe-aad-mux-on-ns:	Assertion time for AAD
>> - - gpmc,oe-aad-mux-off-ns:	Deassertion time for AAD
>> -
>> - Access time and cycle time timings (in nanoseconds) corresponding to
>> - GPMC_CONFIG5:
>> - - gpmc,page-burst-access-ns: 	Multiple access word delay
>> - - gpmc,access-ns:		Start-cycle to first data valid delay
>> - - gpmc,rd-cycle-ns:		Total read cycle time
>> - - gpmc,wr-cycle-ns:		Total write cycle time
>> - - gpmc,bus-turnaround-ns:	Turn-around time between successive accesses
>> - - gpmc,cycle2cycle-delay-ns:	Delay between chip-select pulses
>> - - gpmc,clk-activation-ns: 	GPMC clock activation time
>> - - gpmc,wait-monitoring-ns:	Start of wait monitoring with regard to valid
>> -				data
>> -
>> -Boolean timing parameters. If property is present parameter enabled and
>> -disabled if omitted:
>> - - gpmc,adv-extra-delay:	ADV signal is delayed by half GPMC clock
>> - - gpmc,cs-extra-delay:		CS signal is delayed by half GPMC clock
>> - - gpmc,cycle2cycle-diffcsen:	Add "cycle2cycle-delay" between successive
>> -				accesses to a different CS
>> - - gpmc,cycle2cycle-samecsen:	Add "cycle2cycle-delay" between successive
>> -				accesses to the same CS
>> - - gpmc,oe-extra-delay:		OE signal is delayed by half GPMC clock
>> - - gpmc,we-extra-delay:		WE signal is delayed by half GPMC clock
>> - - gpmc,time-para-granularity:	Multiply all access times by 2
>> -
>> -The following are only applicable to OMAP3+ and AM335x:
>> - - gpmc,wr-access-ns:		In synchronous write mode, for single or
>> -				burst accesses, defines the number of
>> -				GPMC_FCLK cycles from start access time
>> -				to the GPMC_CLK rising edge used by the
>> -				memory device for the first data capture.
>> - - gpmc,wr-data-mux-bus-ns:	In address-data multiplex mode, specifies
>> -				the time when the first data is driven on
>> -				the address-data bus.
>> -
>> -GPMC chip-select settings properties for child nodes. All are optional.
>> -
>> -- gpmc,burst-length	Page/burst length. Must be 4, 8 or 16.
>> -- gpmc,burst-wrap	Enables wrap bursting
>> -- gpmc,burst-read	Enables read page/burst mode
>> -- gpmc,burst-write	Enables write page/burst mode
>> -- gpmc,device-width	Total width of device(s) connected to a GPMC
>> -			chip-select in bytes. The GPMC supports 8-bit
>> -			and 16-bit devices and so this property must be
>> -			1 or 2.
>> -- gpmc,mux-add-data	Address and data multiplexing configuration.
>> -			Valid values are 1 for address-address-data
>> -			multiplexing mode and 2 for address-data
>> -			multiplexing mode.
>> -- gpmc,sync-read	Enables synchronous read. Defaults to asynchronous
>> -			is this is not set.
>> -- gpmc,sync-write	Enables synchronous writes. Defaults to asynchronous
>> -			is this is not set.
>> -- gpmc,wait-pin		Wait-pin used by client. Must be less than
>> -			"gpmc,num-waitpins".
>> -- gpmc,wait-on-read	Enables wait monitoring on reads.
>> -- gpmc,wait-on-write	Enables wait monitoring on writes.
>> -
>> -Example for an AM33xx board:
>> -
>> -	gpmc: gpmc at 50000000 {
>> -		compatible = "ti,am3352-gpmc";
>> -		ti,hwmods = "gpmc";
>> -		reg = <0x50000000 0x2000>;
>> -		interrupts = <100>;
>> -		dmas = <&edma 52 0>;
>> -		dma-names = "rxtx";
>> -		gpmc,num-cs = <8>;
>> -		gpmc,num-waitpins = <2>;
>> -		#address-cells = <2>;
>> -		#size-cells = <1>;
>> -		ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
>> -		interrupt-controller;
>> -		#interrupt-cells = <2>;
>> -		gpio-controller;
>> -		#gpio-cells = <2>;
>> -
>> -		/* child nodes go here */
>> -	};
>> diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
>> new file mode 100644
>> index 000000000000..d6cd39bd3940
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
>> @@ -0,0 +1,172 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/memory-controllers/ti,gpmc.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Texas Instruments GPMC Memory Controller device-tree bindings
>> +
>> +maintainers:
>> +  - Tony Lindgren <tony at atomide.com>
>> +  - Roger Quadros <rogerq at kernel.org>
>> +
>> +description:
>> +  The GPMC is a unified memory controller dedicated for interfacing
>> +  with external memory devices like
>> +  - Asynchronous SRAM-like memories and ASICs
>> +  - Asynchronous, synchronous, and page mode burst NOR flash
>> +  - NAND flash
>> +  - Pseudo-SRAM devices
>> +
>> +properties:
>> +  compatible:
>> +    items:
>> +      - enum:
>> +          - ti,omap2420-gpmc
>> +          - ti,omap2430-gpmc
>> +          - ti,omap3430-gpmc
>> +          - ti,omap4430-gpmc
>> +          - ti,am3352-gpmc
> 
> How about putting them in alphabetical order?

OK.

> 
>> +
>> +  reg:
>> +    maxItems: 1
>> +
>> +  interrupts:
>> +    maxItems: 1
>> +
>> +  clocks:
>> +    maxItems: 1
>> +    description: |
>> +      Functional clock. Used for bus timing calculations and
>> +      GPMC configuration.
>> +
>> +  clock-names:
>> +    items:
>> +      - const: fck
>> +
>> +  dmas:
>> +    items:
>> +      - description: DMA channel for GPMC NAND prefetch
>> +
>> +  dma-names:
>> +    items:
>> +      - const: rxtx
>> +
>> +  "#address-cells": true
>> +
>> +  "#size-cells": true
>> +
>> +  gpmc,num-cs:
>> +    description: maximum number of supported chip-select lines.
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +
>> +  gpmc,num-waitpins:
>> +    description: maximum number of supported wait pins.
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +
>> +  ranges:
>> +    minItems: 1
>> +    description: |
>> +      Must be set up to reflect the memory layout with four
>> +      integer values for each chip-select line in use,
>> +      <cs-number> 0 <physical address of mapping> <size>
>> +    items:
>> +      - description: NAND bank 0
>> +      - description: NOR/SRAM bank 0
>> +      - description: NOR/SRAM bank 1
>> +
>> +  '#interrupt-cells':
>> +    const: 2
>> +
>> +  interrupt-controller:
>> +    description: |
>> +      The GPMC driver implements and interrupt controller for
>> +      the NAND events "fifoevent" and "termcount" plus the
>> +      rising/falling edges on the GPMC_WAIT pins.
>> +      The interrupt number mapping is as follows
>> +      0 - NAND_fifoevent
>> +      1 - NAND_termcount
>> +      2 - GPMC_WAIT0 pin edge
>> +      3 - GPMC_WAIT1 pin edge, and so on.
>> +
>> +  '#gpio-cells':
>> +    const: 2
>> +
>> +  gpio-controller:
>> +    description: |
>> +      The GPMC driver implements a GPIO controller for the
>> +      GPMC WAIT pins that can be used as general purpose inputs.
>> +      0 maps to GPMC_WAIT0 pin.
>> +
>> +  ti,hwmods:
>> +    description:
>> +      Name of the HWMOD associated with GPMC. This is for legacy
>> +      omap2/3 platforms only.
>> +    $ref: /schemas/types.yaml#/definitions/string
>> +    deprecated: true
>> +
>> +  ti,no-idle-on-init:
>> +    description:
>> +      Prevent idling the module at init. This is for legacy omap2/3
>> +      platforms only.
>> +    type: boolean
>> +    deprecated: true
>> +
>> +patternProperties:
>> +  "@[0-7],[a-f0-9]+$":
>> +    type: object
>> +    description: |
>> +      The child device node represents the device connected to the GPMC
>> +      bus. The device can be a NAND chip, SRAM device, NOR device
>> +      or an ASIC.
>> +
>> +    allOf:
>> +      - $ref: "ti,gpmc-child.yaml"
>> +
>> +    unevaluatedProperties: false
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - gpmc,num-cs
>> +  - gpmc,num-waitpins
>> +  - "#address-cells"
>> +  - "#size-cells"
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/interrupt-controller/arm-gic.h>
>> +    #include <dt-bindings/gpio/gpio.h>
>> +
>> +    gpmc: memory-controller at 50000000 {
>> +      compatible = "ti,am3352-gpmc";
>> +      reg = <0x50000000 0x2000>;
>> +      interrupts = <100>;
>> +      clocks = <&l3s_clkctrl>;
>> +      clock-names = "fck";
>> +      dmas = <&edma 52 0>;
>> +      dma-names = "rxtx";
>> +      gpmc,num-cs = <8>;
>> +      gpmc,num-waitpins = <2>;
>> +      #address-cells = <2>;
>> +      #size-cells = <1>;
>> +      ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
>> +      interrupt-controller;
>> +      #interrupt-cells = <2>;
>> +      gpio-controller;
>> +      #gpio-cells = <2>;
>> +
>> +      nand at 0,0 {
>> +        compatible = "ti,omap2-nand";
>> +        reg = <0 0 4>;
>> +        interrupt-parent = <&gpmc>;
>> +        interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
>> +                     <1 IRQ_TYPE_NONE>; /* termcount */
> 
> Why these are interrupts of unspecified type (NONE)?

These are not external interrupt pins but internal to the SoC.
So they don't have any meaning for rising/falling edge or low/high level.

> 
>> +        ti,nand-xfer-type = "prefetch-dma";
>> +        ti,nand-ecc-opt = "bch16";
>> +        ti,elm-id = <&elm>;
>> +        rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */
>> +      };
>> +    };
>>
> 
> 
> Best regards,
> Krzysztof
> 

cheers,
-roger


From mika.westerberg at linux.intel.com  Thu Oct  7 04:21:32 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Thu,  7 Oct 2021 14:21:32 +0300
Subject: [PATCH v2 3/3] Documentation / MTD: Rename the intel-spi driver
In-Reply-To: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
Message-ID: <20211007112132.30934-4-mika.westerberg@linux.intel.com>

Since the driver is renamed (and moved) update the BIOS upgrade guide
accordingly from intel-spi to spi-intel. Keep the guide under MTD
documentation because this is pretty much still about MTD and SPI-NOR.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
---
 Documentation/driver-api/mtd/index.rst                    | 2 +-
 .../driver-api/mtd/{intel-spi.rst => spi-intel.rst}       | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)
 rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)

diff --git a/Documentation/driver-api/mtd/index.rst b/Documentation/driver-api/mtd/index.rst
index 436ba5a851d7..6a4278f409d7 100644
--- a/Documentation/driver-api/mtd/index.rst
+++ b/Documentation/driver-api/mtd/index.rst
@@ -7,6 +7,6 @@ Memory Technology Device (MTD)
 .. toctree::
    :maxdepth: 1
 
-   intel-spi
+   spi-intel
    nand_ecc
    spi-nor
diff --git a/Documentation/driver-api/mtd/intel-spi.rst b/Documentation/driver-api/mtd/spi-intel.rst
similarity index 94%
rename from Documentation/driver-api/mtd/intel-spi.rst
rename to Documentation/driver-api/mtd/spi-intel.rst
index 0465f6879262..df854f20ead1 100644
--- a/Documentation/driver-api/mtd/intel-spi.rst
+++ b/Documentation/driver-api/mtd/spi-intel.rst
@@ -1,5 +1,5 @@
 ==============================
-Upgrading BIOS using intel-spi
+Upgrading BIOS using spi-intel
 ==============================
 
 Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
@@ -11,12 +11,12 @@ avoid accidental (or on purpose) overwrite of the content.
 Not all manufacturers protect the SPI serial flash, mainly because it
 allows upgrading the BIOS image directly from an OS.
 
-The intel-spi driver makes it possible to read and write the SPI serial
+The spi-intel driver makes it possible to read and write the SPI serial
 flash, if certain protection bits are not set and locked. If it finds
 any of them set, the whole MTD device is made read-only to prevent
 partial overwrites. By default the driver exposes SPI serial flash
 contents as read-only but it can be changed from kernel command line,
-passing "intel-spi.writeable=1".
+passing "spi_intel.writeable=1".
 
 Please keep in mind that overwriting the BIOS image on SPI serial flash
 might render the machine unbootable and requires special equipment like
@@ -32,7 +32,7 @@ Linux.
     serial flash. Distros like Debian and Fedora have this prepackaged with
     name "mtd-utils".
 
- 3) Add "intel-spi.writeable=1" to the kernel command line and reboot
+ 3) Add "spi_intel.writeable=1" to the kernel command line and reboot
     the board (you can also reload the driver passing "writeable=1" as
     module parameter to modprobe).
 
-- 
2.33.0



From mika.westerberg at linux.intel.com  Thu Oct  7 04:21:30 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Thu,  7 Oct 2021 14:21:30 +0300
Subject: [PATCH v2 1/3] mtd: spi-nor: intel-spi: Disable write protection only
 if asked
In-Reply-To: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
Message-ID: <20211007112132.30934-2-mika.westerberg@linux.intel.com>

Currently the driver tries to disable the BIOS write protection
automatically even if this is not what the user wants. For this reason
modify the driver so that by default it does not touch the write
protection. Only if specifically asked by the user (setting writeable=1
command line parameter) the driver tries to disable the BIOS write
protection.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
---
 drivers/mfd/lpc_ich.c                         | 59 +++++++++++++++++--
 .../mtd/spi-nor/controllers/intel-spi-pci.c   | 29 +++++----
 drivers/mtd/spi-nor/controllers/intel-spi.c   | 41 ++++++-------
 include/linux/platform_data/x86/intel-spi.h   |  6 +-
 4 files changed, 96 insertions(+), 39 deletions(-)

diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index f10e53187f67..9ffab9aafd81 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -63,6 +63,8 @@
 #define SPIBASE_BYT		0x54
 #define SPIBASE_BYT_SZ		512
 #define SPIBASE_BYT_EN		BIT(1)
+#define BYT_BCR			0xfc
+#define BYT_BCR_WPD		BIT(0)
 
 #define SPIBASE_LPT		0x3800
 #define SPIBASE_LPT_SZ		512
@@ -1084,12 +1086,57 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
 	return ret;
 }
 
+static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
+{
+	u32 val;
+
+	val = readl(base + BYT_BCR);
+	if (!(val & BYT_BCR_WPD)) {
+		val |= BYT_BCR_WPD;
+		writel(val, base + BYT_BCR);
+		val = readl(base + BYT_BCR);
+	}
+
+	return val & BYT_BCR_WPD;
+}
+
+static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
+{
+	struct pci_dev *pdev = data;
+	u32 bcr;
+
+	pci_read_config_dword(pdev, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_write_config_dword(pdev, BCR, bcr);
+		pci_read_config_dword(pdev, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
+static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
+{
+	unsigned int spi = PCI_DEVFN(13, 2);
+	struct pci_bus *bus = data;
+	u32 bcr;
+
+	pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_bus_write_config_dword(bus, spi, BCR, bcr);
+		pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
 	struct lpc_ich_priv *priv = pci_get_drvdata(dev);
 	struct resource *res = &intel_spi_res[0];
 	struct intel_spi_boardinfo *info;
-	u32 spi_base, rcba, bcr;
+	u32 spi_base, rcba;
 
 	info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 		if (spi_base & SPIBASE_BYT_EN) {
 			res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
 			res->end = res->start + SPIBASE_BYT_SZ - 1;
+
+			info->set_writeable = lpc_ich_byt_set_writeable;
 		}
 		break;
 
@@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 			res->start = spi_base + SPIBASE_LPT;
 			res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-			pci_read_config_dword(dev, BCR, &bcr);
-			info->writeable = !!(bcr & BCR_WPD);
+			info->set_writeable = lpc_ich_lpt_set_writeable;
+			info->data = dev;
 		}
 		break;
 
@@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 			res->start = spi_base & 0xfffffff0;
 			res->end = res->start + SPIBASE_APL_SZ - 1;
 
-			pci_bus_read_config_dword(bus, spi, BCR, &bcr);
-			info->writeable = !!(bcr & BCR_WPD);
+			info->set_writeable = lpc_ich_bxt_set_writeable;
+			info->data = bus;
 		}
 
 		pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
index 1bc53b8bb88a..508f7ca098ef 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
@@ -16,12 +16,30 @@
 #define BCR		0xdc
 #define BCR_WPD		BIT(0)
 
+static bool intel_spi_pci_set_writeable(void __iomem *base, void *data)
+{
+	struct pci_dev *pdev = data;
+	u32 bcr;
+
+	/* Try to make the chip read/write */
+	pci_read_config_dword(pdev, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_write_config_dword(pdev, BCR, bcr);
+		pci_read_config_dword(pdev, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
 static const struct intel_spi_boardinfo bxt_info = {
 	.type = INTEL_SPI_BXT,
+	.set_writeable = intel_spi_pci_set_writeable,
 };
 
 static const struct intel_spi_boardinfo cnl_info = {
 	.type = INTEL_SPI_CNL,
+	.set_writeable = intel_spi_pci_set_writeable,
 };
 
 static int intel_spi_pci_probe(struct pci_dev *pdev,
@@ -29,7 +47,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 {
 	struct intel_spi_boardinfo *info;
 	struct intel_spi *ispi;
-	u32 bcr;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -41,15 +58,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	/* Try to make the chip read/write */
-	pci_read_config_dword(pdev, BCR, &bcr);
-	if (!(bcr & BCR_WPD)) {
-		bcr |= BCR_WPD;
-		pci_write_config_dword(pdev, BCR, bcr);
-		pci_read_config_dword(pdev, BCR, &bcr);
-	}
-	info->writeable = !!(bcr & BCR_WPD);
-
+	info->data = pdev;
 	ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
 	if (IS_ERR(ispi))
 		return PTR_ERR(ispi);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
index a413892ff449..f35597cbea0c 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
@@ -131,7 +131,6 @@
  * @sregs: Start of software sequencer registers
  * @nregions: Maximum number of regions
  * @pr_num: Maximum number of protected range registers
- * @writeable: Is the chip writeable
  * @locked: Is SPI setting locked
  * @swseq_reg: Use SW sequencer in register reads/writes
  * @swseq_erase: Use SW sequencer in erase operation
@@ -149,7 +148,6 @@ struct intel_spi {
 	void __iomem *sregs;
 	size_t nregions;
 	size_t pr_num;
-	bool writeable;
 	bool locked;
 	bool swseq_reg;
 	bool swseq_erase;
@@ -304,6 +302,14 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
 				  INTEL_SPI_TIMEOUT * 1000);
 }
 
+static bool intel_spi_set_writeable(struct intel_spi *ispi)
+{
+	if (!ispi->info->set_writeable)
+		return false;
+
+	return ispi->info->set_writeable(ispi->base, ispi->info->data);
+}
+
 static int intel_spi_init(struct intel_spi *ispi)
 {
 	u32 opmenu0, opmenu1, lvscc, uvscc, val;
@@ -316,19 +322,6 @@ static int intel_spi_init(struct intel_spi *ispi)
 		ispi->nregions = BYT_FREG_NUM;
 		ispi->pr_num = BYT_PR_NUM;
 		ispi->swseq_reg = true;
-
-		if (writeable) {
-			/* Disable write protection */
-			val = readl(ispi->base + BYT_BCR);
-			if (!(val & BYT_BCR_WPD)) {
-				val |= BYT_BCR_WPD;
-				writel(val, ispi->base + BYT_BCR);
-				val = readl(ispi->base + BYT_BCR);
-			}
-
-			ispi->writeable = !!(val & BYT_BCR_WPD);
-		}
-
 		break;
 
 	case INTEL_SPI_LPT:
@@ -358,6 +351,12 @@ static int intel_spi_init(struct intel_spi *ispi)
 		return -EINVAL;
 	}
 
+	/* Try to disable write protection if user asked to do so */
+	if (writeable && !intel_spi_set_writeable(ispi)) {
+		dev_warn(ispi->dev, "can't disable chip write protection\n");
+		writeable = false;
+	}
+
 	/* Disable #SMI generation from HW sequencer */
 	val = readl(ispi->base + HSFSTS_CTL);
 	val &= ~HSFSTS_CTL_FSMIE;
@@ -884,9 +883,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
 		/*
 		 * If any of the regions have protection bits set, make the
 		 * whole partition read-only to be on the safe side.
+		 *
+		 * Also if the user did not ask the chip to be writeable
+		 * mask the bit too.
 		 */
-		if (intel_spi_is_protected(ispi, base, limit))
-			ispi->writeable = false;
+		if (!writeable || intel_spi_is_protected(ispi, base, limit))
+			part->mask_flags |= MTD_WRITEABLE;
 
 		end = (limit << 12) + 4096;
 		if (end > part->size)
@@ -927,7 +929,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
 
 	ispi->dev = dev;
 	ispi->info = info;
-	ispi->writeable = info->writeable;
 
 	ret = intel_spi_init(ispi);
 	if (ret)
@@ -945,10 +946,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
 
 	intel_spi_fill_partition(ispi, &part);
 
-	/* Prevent writes if not explicitly enabled */
-	if (!ispi->writeable || !writeable)
-		ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
-
 	ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/intel-spi.h
index 7f53a5c6f35e..7dda3f690465 100644
--- a/include/linux/platform_data/x86/intel-spi.h
+++ b/include/linux/platform_data/x86/intel-spi.h
@@ -19,11 +19,13 @@ enum intel_spi_type {
 /**
  * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
  * @type: Type which this controller is compatible with
- * @writeable: The chip is writeable
+ * @set_writeable: Try to make the chip writeable (optional)
+ * @data: Data to be passed to @set_writeable can be %NULL
  */
 struct intel_spi_boardinfo {
 	enum intel_spi_type type;
-	bool writeable;
+	bool (*set_writeable)(void __iomem *base, void *data);
+	void *data;
 };
 
 #endif /* INTEL_SPI_PDATA_H */
-- 
2.33.0



From mika.westerberg at linux.intel.com  Thu Oct  7 04:21:31 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Thu,  7 Oct 2021 14:21:31 +0300
Subject: [PATCH v2 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
Message-ID: <20211007112132.30934-3-mika.westerberg@linux.intel.com>

The preferred way to implement SPI-NOR controller drivers is through SPI
subsubsystem utilizing the SPI MEM core functions. This converts the
Intel SPI flash controller driver over the SPI MEM by moving the driver
from SPI-NOR subsystem to SPI subsystem and in one go make it use the
SPI MEM functions. The driver name will be changed from intel-spi to
spi-intel to match the convention used in the SPI subsystem.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
---
 drivers/mtd/spi-nor/controllers/Kconfig       |  36 ---
 drivers/mtd/spi-nor/controllers/Makefile      |   3 -
 drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
 drivers/spi/Kconfig                           |  39 +++
 drivers/spi/Makefile                          |   3 +
 .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
 .../spi-intel-platform.c}                     |  21 +-
 .../intel-spi.c => spi/spi-intel.c}           | 304 +++++++++++-------
 drivers/spi/spi-intel.h                       |  19 ++
 include/linux/mfd/lpc_ich.h                   |   2 +-
 .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
 11 files changed, 254 insertions(+), 220 deletions(-)
 delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
 rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (80%)
 create mode 100644 drivers/spi/spi-intel.h
 rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)

diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig
index 5c0e0ec2e6d1..50f4f3484d42 100644
--- a/drivers/mtd/spi-nor/controllers/Kconfig
+++ b/drivers/mtd/spi-nor/controllers/Kconfig
@@ -26,39 +26,3 @@ config SPI_NXP_SPIFI
 	  SPIFI is a specialized controller for connecting serial SPI
 	  Flash. Enable this option if you have a device with a SPIFI
 	  controller and want to access the Flash as a mtd device.
-
-config SPI_INTEL_SPI
-	tristate
-
-config SPI_INTEL_SPI_PCI
-	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
-	depends on X86 && PCI
-	select SPI_INTEL_SPI
-	help
-	  This enables PCI support for the Intel PCH/PCU SPI controller in
-	  master mode. This controller is present in modern Intel hardware
-	  and is used to hold BIOS and other persistent settings. Using
-	  this driver it is possible to upgrade BIOS directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-pci.
-
-config SPI_INTEL_SPI_PLATFORM
-	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
-	depends on X86
-	select SPI_INTEL_SPI
-	help
-	  This enables platform support for the Intel PCH/PCU SPI
-	  controller in master mode. This controller is present in modern
-	  Intel hardware and is used to hold BIOS and other persistent
-	  settings. Using this driver it is possible to upgrade BIOS
-	  directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-platform.
diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile
index e7abba491d98..6e2a1dc68466 100644
--- a/drivers/mtd/spi-nor/controllers/Makefile
+++ b/drivers/mtd/spi-nor/controllers/Makefile
@@ -2,6 +2,3 @@
 obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
 obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
 obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
-obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
-obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
-obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h
deleted file mode 100644
index f2871179fd34..000000000000
--- a/drivers/mtd/spi-nor/controllers/intel-spi.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel PCH/PCU SPI flash driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
- */
-
-#ifndef INTEL_SPI_H
-#define INTEL_SPI_H
-
-#include <linux/platform_data/x86/intel-spi.h>
-
-struct intel_spi;
-struct resource;
-
-struct intel_spi *intel_spi_probe(struct device *dev,
-	struct resource *mem, const struct intel_spi_boardinfo *info);
-int intel_spi_remove(struct intel_spi *ispi);
-
-#endif /* INTEL_SPI_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 83e352b0c8f9..5fe26de43537 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -406,6 +406,45 @@ config SPI_IMX
 	help
 	  This enables support for the Freescale i.MX SPI controllers.
 
+config SPI_INTEL
+	tristate
+
+config SPI_INTEL_PCI
+	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
+	depends on PCI
+	depends on X86 || COMPILE_TEST
+	depends on SPI_MEM
+	select SPI_INTEL
+	help
+	  This enables PCI support for the Intel PCH/PCU SPI controller in
+	  master mode. This controller is present in modern Intel hardware
+	  and is used to hold BIOS and other persistent settings. Using
+	  this driver it is possible to upgrade BIOS directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called spi-intel-pci.
+
+config SPI_INTEL_PLATFORM
+	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
+	depends on X86 || COMPILE_TEST
+	depends on SPI_MEM
+	select SPI_INTEL
+	help
+	  This enables platform support for the Intel PCH/PCU SPI
+	  controller in master mode. This controller is present in modern
+	  Intel hardware and is used to hold BIOS and other persistent
+	  settings. Using this driver it is possible to upgrade BIOS
+	  directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called spi-intel-platform.
+
 config SPI_JCORE
 	tristate "J-Core SPI Master"
 	depends on OF && (SUPERH || COMPILE_TEST)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 699db95c8441..070918a79362 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -59,6 +59,9 @@ obj-$(CONFIG_SPI_HISI_KUNPENG)		+= spi-hisi-kunpeng.o
 obj-$(CONFIG_SPI_HISI_SFC_V3XX)		+= spi-hisi-sfc-v3xx.o
 obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o
 obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
+obj-$(CONFIG_SPI_INTEL)			+= spi-intel.o
+obj-$(CONFIG_SPI_INTEL_PCI)		+= spi-intel-pci.o
+obj-$(CONFIG_SPI_INTEL_PLATFORM)	+= spi-intel-platform.o
 obj-$(CONFIG_SPI_LANTIQ_SSC)		+= spi-lantiq-ssc.o
 obj-$(CONFIG_SPI_JCORE)			+= spi-jcore.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/spi/spi-intel-pci.c
similarity index 86%
rename from drivers/mtd/spi-nor/controllers/intel-spi-pci.c
rename to drivers/spi/spi-intel-pci.c
index 508f7ca098ef..a177b10bc288 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
+++ b/drivers/spi/spi-intel-pci.c
@@ -2,16 +2,14 @@
 /*
  * Intel PCH/PCU SPI flash PCI driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/ioport.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 
-#include "intel-spi.h"
+#include "spi-intel.h"
 
 #define BCR		0xdc
 #define BCR_WPD		BIT(0)
@@ -46,7 +44,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *id)
 {
 	struct intel_spi_boardinfo *info;
-	struct intel_spi *ispi;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -59,17 +56,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 		return -ENOMEM;
 
 	info->data = pdev;
-	ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
-	if (IS_ERR(ispi))
-		return PTR_ERR(ispi);
-
-	pci_set_drvdata(pdev, ispi);
-	return 0;
-}
-
-static void intel_spi_pci_remove(struct pci_dev *pdev)
-{
-	intel_spi_remove(pci_get_drvdata(pdev));
+	return intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
 }
 
 static const struct pci_device_id intel_spi_pci_ids[] = {
@@ -98,7 +85,6 @@ static struct pci_driver intel_spi_pci_driver = {
 	.name = "intel-spi",
 	.id_table = intel_spi_pci_ids,
 	.probe = intel_spi_pci_probe,
-	.remove = intel_spi_pci_remove,
 };
 
 module_pci_driver(intel_spi_pci_driver);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c b/drivers/spi/spi-intel-platform.c
similarity index 65%
rename from drivers/mtd/spi-nor/controllers/intel-spi-platform.c
rename to drivers/spi/spi-intel-platform.c
index f80f1086f928..293e03f239de 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c
+++ b/drivers/spi/spi-intel-platform.c
@@ -2,20 +2,18 @@
 /*
  * Intel PCH/PCU SPI flash platform driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
-#include "intel-spi.h"
+#include "spi-intel.h"
 
 static int intel_spi_platform_probe(struct platform_device *pdev)
 {
 	struct intel_spi_boardinfo *info;
-	struct intel_spi *ispi;
 	struct resource *mem;
 
 	info = dev_get_platdata(&pdev->dev);
@@ -23,24 +21,11 @@ static int intel_spi_platform_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ispi = intel_spi_probe(&pdev->dev, mem, info);
-	if (IS_ERR(ispi))
-		return PTR_ERR(ispi);
-
-	platform_set_drvdata(pdev, ispi);
-	return 0;
-}
-
-static int intel_spi_platform_remove(struct platform_device *pdev)
-{
-	struct intel_spi *ispi = platform_get_drvdata(pdev);
-
-	return intel_spi_remove(ispi);
+	return intel_spi_probe(&pdev->dev, mem, info);
 }
 
 static struct platform_driver intel_spi_platform_driver = {
 	.probe = intel_spi_platform_probe,
-	.remove = intel_spi_platform_remove,
 	.driver = {
 		.name = "intel-spi",
 	},
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/spi/spi-intel.c
similarity index 80%
rename from drivers/mtd/spi-nor/controllers/intel-spi.c
rename to drivers/spi/spi-intel.c
index f35597cbea0c..d7247616338e 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi.c
+++ b/drivers/spi/spi-intel.c
@@ -2,21 +2,21 @@
 /*
  * Intel PCH/PCU SPI flash driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/err.h>
-#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/mtd/mtd.h>
+
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/spi-nor.h>
 
-#include "intel-spi.h"
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+#include "spi-intel.h"
 
 /* Offsets are from @ispi->base */
 #define BFPREG				0x00
@@ -92,8 +92,6 @@
 /* CPU specifics */
 #define BYT_PR				0x74
 #define BYT_SSFSTS_CTL			0x90
-#define BYT_BCR				0xfc
-#define BYT_BCR_WPD			BIT(0)
 #define BYT_FREG_NUM			5
 #define BYT_PR_NUM			5
 
@@ -125,10 +123,10 @@
  * struct intel_spi - Driver private data
  * @dev: Device pointer
  * @info: Pointer to board specific info
- * @nor: SPI NOR layer structure
  * @base: Beginning of MMIO space
  * @pregs: Start of protection registers
  * @sregs: Start of software sequencer registers
+ * @master: Pointer to the SPI controller structure
  * @nregions: Maximum number of regions
  * @pr_num: Maximum number of protected range registers
  * @locked: Is SPI setting locked
@@ -142,10 +140,10 @@
 struct intel_spi {
 	struct device *dev;
 	const struct intel_spi_boardinfo *info;
-	struct spi_nor nor;
 	void __iomem *base;
 	void __iomem *pregs;
 	void __iomem *sregs;
+	struct spi_controller *master;
 	size_t nregions;
 	size_t pr_num;
 	bool locked;
@@ -199,9 +197,6 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
 			readl(ispi->sregs + OPMENU1));
 	}
 
-	if (ispi->info->type == INTEL_SPI_BYT)
-		dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
-
 	dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
 	dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
 
@@ -419,7 +414,6 @@ static int intel_spi_init(struct intel_spi *ispi)
 	}
 
 	intel_spi_dump_regs(ispi);
-
 	return 0;
 }
 
@@ -553,10 +547,9 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
 	return 0;
 }
 
-static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+static int intel_spi_read_reg(struct intel_spi *ispi, u8 opcode, void *buf,
 			      size_t len)
 {
-	struct intel_spi *ispi = nor->priv;
 	int ret;
 
 	/* Address of the first chip */
@@ -574,10 +567,9 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
 	return intel_spi_read_block(ispi, buf, len);
 }
 
-static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
+static int intel_spi_write_reg(struct intel_spi *ispi, u8 opcode, const void *buf,
 			       size_t len)
 {
-	struct intel_spi *ispi = nor->priv;
 	int ret;
 
 	/*
@@ -632,10 +624,9 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
 	return intel_spi_hw_cycle(ispi, opcode, len);
 }
 
-static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
-			      u_char *read_buf)
+static ssize_t intel_spi_read(struct intel_spi *ispi, u32 from, size_t len,
+			      void *read_buf)
 {
-	struct intel_spi *ispi = nor->priv;
 	size_t block_size, retlen = 0;
 	u32 val, status;
 	ssize_t ret;
@@ -647,16 +638,6 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 	if (WARN_ON_ONCE(ispi->atomic_preopcode))
 		ispi->atomic_preopcode = 0;
 
-	switch (nor->read_opcode) {
-	case SPINOR_OP_READ:
-	case SPINOR_OP_READ_FAST:
-	case SPINOR_OP_READ_4B:
-	case SPINOR_OP_READ_FAST_4B:
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	while (len > 0) {
 		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
 
@@ -685,8 +666,7 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 			ret = -EACCES;
 
 		if (ret < 0) {
-			dev_err(ispi->dev, "read error: %llx: %#x\n", from,
-				status);
+			dev_err(ispi->dev, "read error: %x: %#x\n", from, status);
 			return ret;
 		}
 
@@ -703,10 +683,9 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 	return retlen;
 }
 
-static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
-			       const u_char *write_buf)
+static ssize_t intel_spi_write(struct intel_spi *ispi, u32 to, size_t len,
+			       const void *write_buf)
 {
-	struct intel_spi *ispi = nor->priv;
 	size_t block_size, retlen = 0;
 	u32 val, status;
 	ssize_t ret;
@@ -752,8 +731,7 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
 			ret = -EACCES;
 
 		if (ret < 0) {
-			dev_err(ispi->dev, "write error: %llx: %#x\n", to,
-				status);
+			dev_err(ispi->dev, "write error: %x: %#x\n", to, status);
 			return ret;
 		}
 
@@ -766,68 +744,148 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
 	return retlen;
 }
 
-static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
+static int intel_spi_erase(struct intel_spi *ispi, u8 opcode, u32 offs)
 {
-	size_t erase_size, len = nor->mtd.erasesize;
-	struct intel_spi *ispi = nor->priv;
 	u32 val, status, cmd;
 	int ret;
 
-	/* If the hardware can do 64k erase use that when possible */
-	if (len >= SZ_64K && ispi->erase_64k) {
+	switch (opcode) {
+	case SPINOR_OP_SE:
 		cmd = HSFSTS_CTL_FCYCLE_ERASE_64K;
-		erase_size = SZ_64K;
-	} else {
+		break;
+
+	case SPINOR_OP_BE_4K:
 		cmd = HSFSTS_CTL_FCYCLE_ERASE;
-		erase_size = SZ_4K;
+		break;
+
+	default:
+		return -EINVAL;
 	}
 
-	if (ispi->swseq_erase) {
-		while (len > 0) {
-			writel(offs, ispi->base + FADDR);
+	writel(offs, ispi->base + FADDR);
+
+	if (ispi->swseq_erase)
+		return intel_spi_sw_cycle(ispi, opcode, 0,
+					  OPTYPE_WRITE_WITH_ADDR);
+
+	/* Not needed with HW sequencer erase, make sure it is cleared */
+	ispi->atomic_preopcode = 0;
+
+	val = readl(ispi->base + HSFSTS_CTL);
+	val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
+	val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+	val |= HSFSTS_CTL_FGO;
+	val |= cmd;
+	writel(val, ispi->base + HSFSTS_CTL);
+
+	ret = intel_spi_wait_hw_busy(ispi);
+	if (ret)
+		return ret;
+
+	status = readl(ispi->base + HSFSTS_CTL);
+	if (status & HSFSTS_CTL_FCERR)
+		return -EIO;
+	if (status & HSFSTS_CTL_AEL)
+		return -EACCES;
+
+	return 0;
+}
 
-			ret = intel_spi_sw_cycle(ispi, nor->erase_opcode,
-						 0, OPTYPE_WRITE_WITH_ADDR);
-			if (ret)
-				return ret;
+static bool intel_spi_supports_mem_op(struct spi_mem *mem,
+				      const struct spi_mem_op *op)
+{
+	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
 
-			offs += erase_size;
-			len -= erase_size;
+	if (op->cmd.dtr)
+		return false;
+
+	if (ispi->swseq_reg && ispi->locked) {
+		int i;
+
+		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
+			if (ispi->opcodes[i] == op->cmd.opcode)
+				return true;
 		}
 
-		return 0;
+		return false;
 	}
 
-	/* Not needed with HW sequencer erase, make sure it is cleared */
-	ispi->atomic_preopcode = 0;
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDID:
+	case SPINOR_OP_RDSR:
+	case SPINOR_OP_WRSR:
+		return true;
 
-	while (len > 0) {
-		writel(offs, ispi->base + FADDR);
+	case SPINOR_OP_READ:
+	case SPINOR_OP_READ_FAST:
+	case SPINOR_OP_READ_4B:
+	case SPINOR_OP_READ_FAST_4B:
+		return true;
 
-		val = readl(ispi->base + HSFSTS_CTL);
-		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
-		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-		val |= cmd;
-		val |= HSFSTS_CTL_FGO;
-		writel(val, ispi->base + HSFSTS_CTL);
+	case SPINOR_OP_PP:
+	case SPINOR_OP_PP_4B:
+	case SPINOR_OP_WREN:
+	case SPINOR_OP_WRDI:
+		return true;
 
-		ret = intel_spi_wait_hw_busy(ispi);
-		if (ret)
-			return ret;
+	case SPINOR_OP_SE:
+	case SPINOR_OP_SE_4B:
+		return ispi->erase_64k;
 
-		status = readl(ispi->base + HSFSTS_CTL);
-		if (status & HSFSTS_CTL_FCERR)
-			return -EIO;
-		else if (status & HSFSTS_CTL_AEL)
-			return -EACCES;
+	case SPINOR_OP_BE_4K:
+	case SPINOR_OP_BE_4K_4B:
+		return true;
+	}
+
+	return false;
+}
 
-		offs += erase_size;
-		len -= erase_size;
+static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+	size_t nbytes = op->data.nbytes;
+	u8 opcode = op->cmd.opcode;
+
+	if (op->addr.nbytes) {
+		if  (op->data.dir == SPI_MEM_DATA_IN)
+			return intel_spi_read(ispi, op->addr.val, nbytes,
+					      op->data.buf.in);
+		if (op->data.dir == SPI_MEM_DATA_OUT)
+			return intel_spi_write(ispi, op->addr.val, nbytes,
+					       op->data.buf.out);
+		if (op->data.dir == SPI_MEM_NO_DATA)
+			return intel_spi_erase(ispi, opcode, op->addr.val);
+	} else {
+		if  (op->data.dir == SPI_MEM_DATA_IN)
+			return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
+						  nbytes);
+		if (op->data.dir == SPI_MEM_DATA_OUT)
+			return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
+						   nbytes);
+		if (op->data.dir == SPI_MEM_NO_DATA)
+			return intel_spi_write_reg(ispi, opcode, NULL, 0);
 	}
 
-	return 0;
+	return -EINVAL;
+}
+
+static const char *intel_spi_get_name(struct spi_mem *mem)
+{
+	const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+
+	/*
+	 * Return name of the flash controller device to be compatible
+	 * with the MTD version.
+	 */
+	return dev_name(ispi->dev);
 }
 
+static const struct spi_controller_mem_ops intel_spi_mem_ops = {
+	.supports_op = intel_spi_supports_mem_op,
+	.exec_op = intel_spi_exec_mem_op,
+	.get_name = intel_spi_get_name,
+};
+
 static bool intel_spi_is_protected(const struct intel_spi *ispi,
 				   unsigned int base, unsigned int limit)
 {
@@ -896,70 +954,74 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
 	}
 }
 
-static const struct spi_nor_controller_ops intel_spi_controller_ops = {
-	.read_reg = intel_spi_read_reg,
-	.write_reg = intel_spi_write_reg,
-	.read = intel_spi_read,
-	.write = intel_spi_write,
-	.erase = intel_spi_erase,
-};
+static int intel_spi_populate_chip(struct intel_spi *ispi)
+{
+	struct flash_platform_data *pdata;
+	struct spi_board_info chip;
+
+	pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->nr_parts = 1;
+	pdata->parts = devm_kcalloc(ispi->dev, sizeof(*pdata->parts),
+				    pdata->nr_parts, GFP_KERNEL);
+	if (!pdata->parts)
+		return -ENOMEM;
+
+	intel_spi_fill_partition(ispi, pdata->parts);
+
+	memset(&chip, 0, sizeof(chip));
+	snprintf(chip.modalias, 8, "spi-nor");
+	chip.platform_data = pdata;
+
+	return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV;
+}
 
-struct intel_spi *intel_spi_probe(struct device *dev,
-	struct resource *mem, const struct intel_spi_boardinfo *info)
+/**
+ * intel_spi_probe() - Probe the Intel SPI flash controller
+ * @dev: Pointer to the parent device
+ * @mem: MMIO resource
+ * @info: Platform spefific information
+ *
+ * Probes Intel SPI flash controller and creates the flash chip device.
+ * Returns %0 on success and negative errno in case of failure.
+ */
+int intel_spi_probe(struct device *dev, struct resource *mem,
+		    const struct intel_spi_boardinfo *info)
 {
-	const struct spi_nor_hwcaps hwcaps = {
-		.mask = SNOR_HWCAPS_READ |
-			SNOR_HWCAPS_READ_FAST |
-			SNOR_HWCAPS_PP,
-	};
-	struct mtd_partition part;
+	struct spi_controller *master;
 	struct intel_spi *ispi;
 	int ret;
 
-	if (!info || !mem)
-		return ERR_PTR(-EINVAL);
+	master = devm_spi_alloc_master(dev, sizeof(*ispi));
+	if (!master)
+		return -ENOMEM;
+
+	master->mem_ops = &intel_spi_mem_ops;
 
-	ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL);
-	if (!ispi)
-		return ERR_PTR(-ENOMEM);
+	ispi = spi_master_get_devdata(master);
 
 	ispi->base = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(ispi->base))
-		return ERR_CAST(ispi->base);
+		return PTR_ERR(ispi->base);
 
 	ispi->dev = dev;
+	ispi->master = master;
 	ispi->info = info;
 
 	ret = intel_spi_init(ispi);
 	if (ret)
-		return ERR_PTR(ret);
-
-	ispi->nor.dev = ispi->dev;
-	ispi->nor.priv = ispi;
-	ispi->nor.controller_ops = &intel_spi_controller_ops;
-
-	ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps);
-	if (ret) {
-		dev_info(dev, "failed to locate the chip\n");
-		return ERR_PTR(ret);
-	}
-
-	intel_spi_fill_partition(ispi, &part);
+		return ret;
 
-	ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
+	ret = devm_spi_register_master(dev, master);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
-	return ispi;
+	return intel_spi_populate_chip(ispi);
 }
 EXPORT_SYMBOL_GPL(intel_spi_probe);
 
-int intel_spi_remove(struct intel_spi *ispi)
-{
-	return mtd_device_unregister(&ispi->nor.mtd);
-}
-EXPORT_SYMBOL_GPL(intel_spi_remove);
-
 MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg at linux.intel.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-intel.h b/drivers/spi/spi-intel.h
new file mode 100644
index 000000000000..40f947f6941a
--- /dev/null
+++ b/drivers/spi/spi-intel.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Intel PCH/PCU SPI flash driver.
+ *
+ * Copyright (C) 2016 - 2021, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+ */
+
+#ifndef SPI_INTEL_H
+#define SPI_INTEL_H
+
+#include <linux/platform_data/x86/spi-intel.h>
+
+struct resource;
+
+int intel_spi_probe(struct device *dev, struct resource *mem,
+		    const struct intel_spi_boardinfo *info);
+
+#endif /* SPI_INTEL_H */
diff --git a/include/linux/mfd/lpc_ich.h b/include/linux/mfd/lpc_ich.h
index 39967a5eca6d..ea4a4b1b246a 100644
--- a/include/linux/mfd/lpc_ich.h
+++ b/include/linux/mfd/lpc_ich.h
@@ -8,7 +8,7 @@
 #ifndef LPC_ICH_H
 #define LPC_ICH_H
 
-#include <linux/platform_data/x86/intel-spi.h>
+#include <linux/platform_data/x86/spi-intel.h>
 
 /* GPIO resources */
 #define ICH_RES_GPIO	0
diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/spi-intel.h
similarity index 89%
rename from include/linux/platform_data/x86/intel-spi.h
rename to include/linux/platform_data/x86/spi-intel.h
index 7dda3f690465..a512ec37abbb 100644
--- a/include/linux/platform_data/x86/intel-spi.h
+++ b/include/linux/platform_data/x86/spi-intel.h
@@ -6,8 +6,8 @@
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#ifndef INTEL_SPI_PDATA_H
-#define INTEL_SPI_PDATA_H
+#ifndef SPI_INTEL_PDATA_H
+#define SPI_INTEL_PDATA_H
 
 enum intel_spi_type {
 	INTEL_SPI_BYT = 1,
@@ -28,4 +28,4 @@ struct intel_spi_boardinfo {
 	void *data;
 };
 
-#endif /* INTEL_SPI_PDATA_H */
+#endif /* SPI_INTEL_PDATA_H */
-- 
2.33.0



From mika.westerberg at linux.intel.com  Thu Oct  7 04:21:29 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Thu,  7 Oct 2021 14:21:29 +0300
Subject: [PATCH v2 0/3] mtd: spi-nor / spi / MFD: Convert intel-spi to SPI MEM
Message-ID: <20211007112132.30934-1-mika.westerberg@linux.intel.com>

Hi all,

Based on discussion on the patch I sent some time ago here:

  http://lists.infradead.org/pipermail/linux-mtd/2021-June/086867.html

it turns out that the preferred way to deal with the SPI flash controller
drivers is through SPI MEM which is part of Linux SPI subsystem.

This series does that for the intel-spi driver. This also renames the
driver to follow the convention used in the SPI subsystem. The first patch
improves the write protection handling to be slightly more safer. The
following two patches do the conversion itself. Note the Intel SPI flash
controller only allows commands such as read, write and so on and it
internally uses whatever addressing etc. it figured from the SFDP on the
flash device.

Previous version of the patch series can be found here:

  https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/

Changes from the previous version:

  * Arrange dependencies in Kconfig entries the same way in both glue
    drivers.
  * Added empty lines between different subsystem includes.
  * dev_err() to single line
  * Return intel_spi_sw_cycle() directly in intel_spi_erase().
  * Drop redundant elses.
  * Fixed typo in the commit message of the patch 3/3.

Mika Westerberg (3):
  mtd: spi-nor: intel-spi: Disable write protection only if asked
  mtd: spi-nor: intel-spi: Convert to SPI MEM
  Documentation / MTD: Rename the intel-spi driver

 Documentation/driver-api/mtd/index.rst        |   2 +-
 .../mtd/{intel-spi.rst => spi-intel.rst}      |   8 +-
 drivers/mfd/lpc_ich.c                         |  59 ++-
 drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
 drivers/mtd/spi-nor/controllers/Makefile      |   3 -
 drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
 drivers/spi/Kconfig                           |  39 ++
 drivers/spi/Makefile                          |   3 +
 .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  49 ++-
 .../spi-intel-platform.c}                     |  21 +-
 .../intel-spi.c => spi/spi-intel.c}           | 345 ++++++++++--------
 drivers/spi/spi-intel.h                       |  19 +
 include/linux/mfd/lpc_ich.h                   |   2 +-
 .../x86/{intel-spi.h => spi-intel.h}          |  12 +-
 14 files changed, 355 insertions(+), 264 deletions(-)
 rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)
 delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
 rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (84%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (78%)
 create mode 100644 drivers/spi/spi-intel.h
 rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (64%)

-- 
2.33.0



From sean at geanix.com  Thu Oct  7 04:43:51 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Thu, 7 Oct 2021 13:43:51 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211005105836.6c300f25@collabora.com>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
Message-ID: <20211007114351.3nafhtpefezxhanc@skn-laptop>

On Tue, Oct 05, 2021 at 10:58:36AM +0200, Boris Brezillon wrote:
> On Tue, 5 Oct 2021 10:49:38 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Tue, Oct 05, 2021 at 10:23:00AM +0200, Boris Brezillon wrote:
> > > On Tue, 5 Oct 2021 09:09:30 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:  
> > 
> > [ ... ]
> > 
> > > > 
> > > > Have you seen the reproducer script?  
> > > 
> > > How would I know about this script or your previous attempt (mentioned
> > > at the end of this email) given I was not Cc-ed on the previous
> > > discussion, and nothing mentions it in this RFC...
> > >   
> > 
> > That's why I shared it here ;)
> > Initially I thought this was a bug introduced by exec_op.
> > 
> > > > ---
> > > > root at iwg26-v1:/data/root# cat /data/crash.sh
> > > > #!/bin/sh -x
> > > > 
> > > > echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup
> > > > 
> > > > rm /data/test50M
> > > > dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
> > > > cp /tmp/test50M /data/ &
> > > > sleep 1
> > > > echo mem > /sys/power/state
> > > > ---
> > > > 
> > > > As seen in the log above disk is synced before suspend.
> > > > cp is continuing to copy data to ubifs.
> > > > And then user space processes are frozen.
> > > > At this point the kernel thread would have unwritten data.
> > > > 
> > > > We tried to solve this with:
> > > > https://lkml.org/lkml/2021/9/1/280  
> > > 
> > > I see. It's still unclear to me when the write happens. Is it in the
> > > suspend path (before the system is actually suspended), or in the
> > > resume path (when the system is being resumed).
> > > 
> > > Anyway, let's admit writing to a storage device while it's suspended is
> > > a valid use case and requires the storage layer to put this request on
> > > old. This wait should not, IMHO, be handled at the NAND level, but at
> > > the MTD level (using a waitqueue, and an atomic to make
> > > suspended/resumed transitions safe). And abusing a mutex to implement
> > > that is certainly not a good idea.  
> > 
> > I did't say this was the right solution ;) I actually asked in the RFC:
> > "Should we introduce a new mutex? Or maybe a spin_lock?"
> > 
> > What are you proposing, a waitqueue in mtd_info? That gets checked in
> > mtd_write()/mtd_read()?
> 
> Yes, and replacing the suspended state by an atomic, and providing a
> helper to wait on the device readiness. Helper you will call in every
> path involving a communication with the HW, not just mtd_read/write()
> (you're missing erase at least, and I fear there are other hooks that
> might lead to commands being issued to the device). But before we get
> there, I think it's important to understand what the kernel expects.
> IOW, if and when threads can do a request on a suspended device, and
> when it's acceptable to wait (vs returning -EBUSY), otherwise I fear
> we'll end up with deadlocks in the suspend/resume path.

I have a proposal [0] and yes I have ended up in many deadlocks during
testing. The hardest part is the locking when going into suspend.
I'm not sure the wait_queue is initialized the right place :)
And I'm kinda abusing the nand_get_device() for this...

Who do you think we should add to the discussion?

/Sean

[0]:
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..735dfff18143 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -337,11 +337,10 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  */
 static int nand_get_device(struct nand_chip *chip)
 {
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       wait_event(mtd->wait_queue, atomic_read(&chip->suspended) == 0);
        mutex_lock(&chip->lock);
-       if (chip->suspended) {
-               mutex_unlock(&chip->lock);
-               return -EBUSY;
-       }
        mutex_lock(&chip->controller->lock);

        return 0;
@@ -4562,11 +4561,15 @@ static int nand_suspend(struct mtd_info *mtd)
        struct nand_chip *chip = mtd_to_nand(mtd);
        int ret = 0;

+       atomic_inc(&chip->suspended);
        mutex_lock(&chip->lock);
        if (chip->ops.suspend)
                ret = chip->ops.suspend(chip);
-       if (!ret)
-               chip->suspended = 1;
+       if (ret) {
+               /* Wake things up again if suspend fails */
+               atomic_dec(&chip->suspended);
+               wake_up(&mtd->wait_queue);
+       }
        mutex_unlock(&chip->lock);

        return ret;
@@ -4581,10 +4584,12 @@ static void nand_resume(struct mtd_info *mtd)
        struct nand_chip *chip = mtd_to_nand(mtd);

        mutex_lock(&chip->lock);
-       if (chip->suspended) {
+       if (atomic_read(&chip->suspended)) {
                if (chip->ops.resume)
                        chip->ops.resume(chip);
-               chip->suspended = 0;
+
+               atomic_dec(&chip->suspended);
+               wake_up(&mtd->wait_queue);
        } else {
                pr_err("%s called for a chip which is not in suspended state\n",
                        __func__);
@@ -5099,6 +5104,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
        pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
                (int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
                mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
+
+       init_waitqueue_head(&mtd->wait_queue);
+
        return 0;

 free_detect_allocation:
@@ -6264,6 +6272,8 @@ static int nand_scan_tail(struct nand_chip *chip)
        if (chip->options & NAND_SKIP_BBTSCAN)
                return 0;

+       atomic_set(&chip->suspended, 0);
+
        /* Build bad block table */
        ret = nand_create_bbt(chip);
        if (ret)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..f7dcbc336170 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -360,6 +360,8 @@ struct mtd_info {
        int (*_get_device) (struct mtd_info *mtd);
        void (*_put_device) (struct mtd_info *mtd);

+       wait_queue_head_t wait_queue;
+
        /*
         * flag indicates a panic write, low level drivers can take appropriate
         * action if required to ensure writes go through
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..c25c0749f8d0 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1293,7 +1293,7 @@ struct nand_chip {

        /* Internals */
        struct mutex lock;
-       unsigned int suspended : 1;
+       atomic_t suspended;
        int cur_cs;
        int read_retries;
        struct nand_secure_region *secure_regions;


From rogerq at kernel.org  Thu Oct  7 05:08:22 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:22 +0300
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti,
 gpmc: Convert to yaml
Message-ID: <20211007120830.17221-1-rogerq@kernel.org>

Hi,

This series converts ti,gpmc memory controller and ti,gpmc-nand and
ti,gpmc-onenand MTD controller bindings to yaml.

cheers,
-roger

Changelog:
v5
- separated DT changes so easy to review
- dropped ethernet at gpmc label changes. I was trying to fix the dtbs_check
 warning "'ethernet at gpmc' does not match any of the regexes: '@[0-7],[a-f0-9]+$', 'pinctrl-[0-9]+'"
 but the patch causes a side effect for omap4-duovero-parlor.dts such that the
 GPMC timings specified in the board DTS wer not being used but
 being overridden by omap-gpmc-smsc911x.dtsi instead. This is not what we
 want.
- dropped patch "memory: gpmc-omap: "gpmc,device-width" DT property is optional"
 I will pick this up in another series. Don't want this patch to hold back the .yaml cleanup series.
- arranged compatibles in alphabetical order in ti,gpmc.yaml
- fixed example in ti,gpmc-onenand.yaml
- Rebased on 5.15-rc1
- Added Acks

v4
- reference partition.yaml in ti,gpmc-nand.yaml and ti,gpmc-onenenc.yaml
- use address-cells/size-cells: true instead of absolute size.

v3:
- fix indentation
- split GPMC child timings/settings into ti,gpmc-child.yaml
This allows us to refer to it at 3 places and avoid use of
'additionalProperties: true' at 2 places.
- specify defaults where applicable
- reordered patches
- added patch for making "gpmc,device-width" optional with defaults.
- address all review comments.

v2:
- Fix all errors in dtbs_check and dt_bindings_check
- remove references to gpmc-omap.txt
- Convert ti,gpmc-nand and ti,gpmc-onenand bindings to yaml as well

Roger Quadros (8):
  dt-bindings: mtd: Remove gpmc-nor.txt
  dt-bindings: net: Remove gpmc-eth.txt
  dt-bindings: memory-controllers: Introduce ti,gpmc-child
  dt-bindings: mtd: ti,gpmc-nand: Convert to yaml
  dt-bindings: mtd: ti,gpmc-onenand: Convert to yaml
  dt-bindings: memory-controllers: ti,gpmc: Convert to yaml
  ARM: dts: omap: Fix boolean properties
    gpmc,cycle2cycle-{same|diff}csen
  ARM: dts: omap: fix gpmc,mux-add-data type

 .../bindings/memory-controllers/omap-gpmc.txt | 157 -----------
 .../memory-controllers/ti,gpmc-child.yaml     | 245 ++++++++++++++++++
 .../bindings/memory-controllers/ti,gpmc.yaml  | 172 ++++++++++++
 .../devicetree/bindings/mtd/gpmc-nand.txt     | 147 -----------
 .../devicetree/bindings/mtd/gpmc-nor.txt      |  98 -------
 .../devicetree/bindings/mtd/gpmc-onenand.txt  |  48 ----
 .../devicetree/bindings/mtd/ti,gpmc-nand.yaml | 121 +++++++++
 .../bindings/mtd/ti,gpmc-onenand.yaml         |  81 ++++++
 .../devicetree/bindings/net/gpmc-eth.txt      |  97 -------
 arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi     |   4 +-
 arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi     |   2 +-
 arch/arm/boot/dts/omap-zoom-common.dtsi       |   4 +-
 arch/arm/boot/dts/omap2430-sdp.dts            |   4 +-
 .../arm/boot/dts/omap3-devkit8000-common.dtsi |   4 +-
 .../boot/dts/omap3-overo-tobiduo-common.dtsi  |   2 +-
 arch/arm/boot/dts/omap3-sb-t35.dtsi           |   4 +-
 16 files changed, 631 insertions(+), 559 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nand.txt
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nor.txt
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/ti,gpmc-nand.yaml
 create mode 100644 Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
 delete mode 100644 Documentation/devicetree/bindings/net/gpmc-eth.txt

-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:23 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:23 +0300
Subject: [PATCH v5 1/8] dt-bindings: mtd: Remove gpmc-nor.txt
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-2-rogerq@kernel.org>

There is no GPMC NOR compatible or device driver. GPMC is just
a bus interface over which standard (CFI/JEDC) NOR Flash chips
can be attached.

For NOR chip bindings, please refer to
Documentation/devicetree/bindings/mtd/mtd-physmap.yaml

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/mtd/gpmc-nor.txt      | 98 -------------------
 1 file changed, 98 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nor.txt

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
deleted file mode 100644
index 2133be0d52f2..000000000000
--- a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
+++ /dev/null
@@ -1,98 +0,0 @@
-Device tree bindings for NOR flash connect to TI GPMC
-
-NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
-child nodes of the GPMC controller with a name of "nor".
-
-All timing relevant properties as well as generic GPMC child properties are
-explained in a separate documents. Please refer to
-Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-Required properties:
-- bank-width: 		Width of NOR flash in bytes. GPMC supports 8-bit and
-			16-bit devices and so must be either 1 or 2 bytes.
-- compatible:		Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
-- gpmc,cs-on-ns:		Chip-select assertion time
-- gpmc,cs-rd-off-ns:	Chip-select de-assertion time for reads
-- gpmc,cs-wr-off-ns:	Chip-select de-assertion time for writes
-- gpmc,oe-on-ns:	Output-enable assertion time
-- gpmc,oe-off-ns:	Output-enable de-assertion time
-- gpmc,we-on-ns		Write-enable assertion time
-- gpmc,we-off-ns:	Write-enable de-assertion time
-- gpmc,access-ns:	Start cycle to first data capture (read access)
-- gpmc,rd-cycle-ns:	Total read cycle time
-- gpmc,wr-cycle-ns:	Total write cycle time
-- linux,mtd-name:	Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
-- reg:			Chip-select, base address (relative to chip-select)
-			and size of NOR flash. Note that base address will be
-			typically 0 as this is the start of the chip-select.
-
-Optional properties:
-- gpmc,XXX		Additional GPMC timings and settings parameters. See
-			Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-Optional properties for partition table parsing:
-- #address-cells: should be set to 1
-- #size-cells: should be set to 1
-
-Example:
-
-gpmc: gpmc at 6e000000 {
-	compatible = "ti,omap3430-gpmc", "simple-bus";
-	ti,hwmods = "gpmc";
-	reg = <0x6e000000 0x1000>;
-	interrupts = <20>;
-	gpmc,num-cs = <8>;
-	gpmc,num-waitpins = <4>;
-	#address-cells = <2>;
-	#size-cells = <1>;
-
-	ranges = <0 0 0x10000000 0x08000000>;
-
-	nor at 0,0 {
-		compatible = "cfi-flash";
-		linux,mtd-name= "intel,pf48f6000m0y1be";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		reg = <0 0 0x08000000>;
-		bank-width = <2>;
-
-		gpmc,mux-add-data;
-		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <186>;
-		gpmc,cs-wr-off-ns = <186>;
-		gpmc,adv-on-ns = <12>;
-		gpmc,adv-rd-off-ns = <48>;
-		gpmc,adv-wr-off-ns = <48>;
-		gpmc,oe-on-ns = <54>;
-		gpmc,oe-off-ns = <168>;
-		gpmc,we-on-ns = <54>;
-		gpmc,we-off-ns = <168>;
-		gpmc,rd-cycle-ns = <186>;
-		gpmc,wr-cycle-ns = <186>;
-		gpmc,access-ns = <114>;
-		gpmc,page-burst-access-ns = <6>;
-		gpmc,bus-turnaround-ns = <12>;
-		gpmc,cycle2cycle-delay-ns = <18>;
-		gpmc,wr-data-mux-bus-ns = <90>;
-		gpmc,wr-access-ns = <186>;
-		gpmc,cycle2cycle-samecsen;
-		gpmc,cycle2cycle-diffcsen;
-
-		partition at 0 {
-			label = "bootloader-nor";
-			reg = <0 0x40000>;
-		};
-		partition at 40000 {
-			label = "params-nor";
-			reg = <0x40000 0x40000>;
-		};
-		partition at 80000 {
-			label = "kernel-nor";
-			reg = <0x80000 0x200000>;
-		};
-		partition at 280000 {
-			label = "filesystem-nor";
-			reg = <0x240000 0x7d80000>;
-		};
-	};
-};
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:24 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:24 +0300
Subject: [PATCH v5 2/8] dt-bindings: net: Remove gpmc-eth.txt
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-3-rogerq@kernel.org>

There is no GPMC Ethernet compatible or device driver. GPMC is
just a bus interface over which devices like Ethernet controller
can be to.

For SMSC 911x Ethernet chip bindings, please refer to
Documentation/devicetree/bindings/net/smsc,lan9115.yaml

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Acked-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/net/gpmc-eth.txt      | 97 -------------------
 1 file changed, 97 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/net/gpmc-eth.txt

diff --git a/Documentation/devicetree/bindings/net/gpmc-eth.txt b/Documentation/devicetree/bindings/net/gpmc-eth.txt
deleted file mode 100644
index 32821066a85b..000000000000
--- a/Documentation/devicetree/bindings/net/gpmc-eth.txt
+++ /dev/null
@@ -1,97 +0,0 @@
-Device tree bindings for Ethernet chip connected to TI GPMC
-
-Besides being used to interface with external memory devices, the
-General-Purpose Memory Controller can be used to connect Pseudo-SRAM devices
-such as ethernet controllers to processors using the TI GPMC as a data bus.
-
-Ethernet controllers connected to TI GPMC are represented as child nodes of
-the GPMC controller with an "ethernet" name.
-
-All timing relevant properties as well as generic GPMC child properties are
-explained in a separate documents. Please refer to
-Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-For the properties relevant to the ethernet controller connected to the GPMC
-refer to the binding documentation of the device. For example, the documentation
-for the SMSC 911x is Documentation/devicetree/bindings/net/smsc,lan9115.yaml
-
-Child nodes need to specify the GPMC bus address width using the "bank-width"
-property but is possible that an ethernet controller also has a property to
-specify the I/O registers address width. Even when the GPMC has a maximum 16-bit
-address width, it supports devices with 32-bit word registers.
-For example with an SMSC LAN911x/912x controller connected to the TI GPMC on an
-OMAP2+ board, "bank-width = <2>;" and "reg-io-width = <4>;".
-
-Required properties:
-- bank-width: 		Address width of the device in bytes. GPMC supports 8-bit
-			and 16-bit devices and so must be either 1 or 2 bytes.
-- compatible:		Compatible string property for the ethernet child device.
-- gpmc,cs-on-ns:	Chip-select assertion time
-- gpmc,cs-rd-off-ns:	Chip-select de-assertion time for reads
-- gpmc,cs-wr-off-ns:	Chip-select de-assertion time for writes
-- gpmc,oe-on-ns:	Output-enable assertion time
-- gpmc,oe-off-ns:	Output-enable de-assertion time
-- gpmc,we-on-ns:	Write-enable assertion time
-- gpmc,we-off-ns:	Write-enable de-assertion time
-- gpmc,access-ns:	Start cycle to first data capture (read access)
-- gpmc,rd-cycle-ns:	Total read cycle time
-- gpmc,wr-cycle-ns:	Total write cycle time
-- reg:			Chip-select, base address (relative to chip-select)
-			and size of the memory mapped for the device.
-			Note that base address will be typically 0 as this
-			is the start of the chip-select.
-
-Optional properties:
-- gpmc,XXX		Additional GPMC timings and settings parameters. See
-			Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-Example:
-
-gpmc: gpmc at 6e000000 {
-	compatible = "ti,omap3430-gpmc";
-	ti,hwmods = "gpmc";
-	reg = <0x6e000000 0x1000>;
-	interrupts = <20>;
-	gpmc,num-cs = <8>;
-	gpmc,num-waitpins = <4>;
-	#address-cells = <2>;
-	#size-cells = <1>;
-
-	ranges = <5 0 0x2c000000 0x1000000>;
-
-	ethernet at 5,0 {
-		compatible = "smsc,lan9221", "smsc,lan9115";
-		reg = <5 0 0xff>;
-		bank-width = <2>;
-
-		gpmc,mux-add-data;
-		gpmc,cs-on-ns = <0>;
-		gpmc,cs-rd-off-ns = <186>;
-		gpmc,cs-wr-off-ns = <186>;
-		gpmc,adv-on-ns = <12>;
-		gpmc,adv-rd-off-ns = <48>;
-		gpmc,adv-wr-off-ns = <48>;
-		gpmc,oe-on-ns = <54>;
-		gpmc,oe-off-ns = <168>;
-		gpmc,we-on-ns = <54>;
-		gpmc,we-off-ns = <168>;
-		gpmc,rd-cycle-ns = <186>;
-		gpmc,wr-cycle-ns = <186>;
-		gpmc,access-ns = <114>;
-		gpmc,page-burst-access-ns = <6>;
-		gpmc,bus-turnaround-ns = <12>;
-		gpmc,cycle2cycle-delay-ns = <18>;
-		gpmc,wr-data-mux-bus-ns = <90>;
-		gpmc,wr-access-ns = <186>;
-		gpmc,cycle2cycle-samecsen;
-		gpmc,cycle2cycle-diffcsen;
-
-		interrupt-parent = <&gpio6>;
-		interrupts = <16>;
-		vmmc-supply = <&vddvario>;
-		vmmc_aux-supply = <&vdd33a>;
-		reg-io-width = <4>;
-
-		smsc,save-mac-address;
-	};
-};
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:25 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:25 +0300
Subject: [PATCH v5 3/8] dt-bindings: memory-controllers: Introduce ti,
 gpmc-child
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-4-rogerq@kernel.org>

This binding is meant for the child nodes of the TI GPMC node. The node
represents any device connected to the GPMC bus. It may be a Flash chip,
RAM chip or Ethernet controller, etc. These properties are meant for
configuring the GPMC settings/timings and will accompany the bindings
supported by the respective device.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Reviewed-by: Rob Herring <robh at kernel.org>
---
 .../memory-controllers/ti,gpmc-child.yaml     | 245 ++++++++++++++++++
 1 file changed, 245 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml

diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
new file mode 100644
index 000000000000..6e3995bb1630
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
@@ -0,0 +1,245 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ti,gpmc-child.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: device tree bindings for children of the Texas Instruments GPMC
+
+maintainers:
+  - Tony Lindgren <tony at atomide.com>
+  - Roger Quadros <rogerq at kernel.org>
+
+description:
+  This binding is meant for the child nodes of the GPMC node. The node
+  represents any device connected to the GPMC bus. It may be a Flash chip,
+  RAM chip or Ethernet controller, etc. These properties are meant for
+  configuring the GPMC settings/timings and will accompany the bindings
+  supported by the respective device.
+
+properties:
+  reg: true
+
+# GPMC Timing properties for child nodes. All are optional and default to 0.
+  gpmc,sync-clk-ps:
+    description: Minimum clock period for synchronous mode
+    default: 0
+
+# Chip-select signal timings corresponding to GPMC_CONFIG2:
+  gpmc,cs-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,cs-rd-off-ns:
+    description: Read deassertion time
+    default: 0
+
+  gpmc,cs-wr-off-ns:
+    description: Write deassertion time
+    default: 0
+
+# ADV signal timings corresponding to GPMC_CONFIG3:
+  gpmc,adv-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,adv-rd-off-ns:
+    description: Read deassertion time
+    default: 0
+
+  gpmc,adv-wr-off-ns:
+    description: Write deassertion time
+    default: 0
+
+  gpmc,adv-aad-mux-on-ns:
+    description: Assertion time for AAD
+    default: 0
+
+  gpmc,adv-aad-mux-rd-off-ns:
+    description: Read deassertion time for AAD
+    default: 0
+
+  gpmc,adv-aad-mux-wr-off-ns:
+    description: Write deassertion time for AAD
+    default: 0
+
+# WE signals timings corresponding to GPMC_CONFIG4:
+  gpmc,we-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,we-off-ns:
+    description: Deassertion time
+    default: 0
+
+# OE signals timings corresponding to GPMC_CONFIG4:
+  gpmc,oe-on-ns:
+    description: Assertion time
+    default: 0
+
+  gpmc,oe-off-ns:
+    description: Deassertion time
+    default: 0
+
+  gpmc,oe-aad-mux-on-ns:
+    description: Assertion time for AAD
+    default: 0
+
+  gpmc,oe-aad-mux-off-ns:
+    description: Deassertion time for AAD
+    default: 0
+
+# Access time and cycle time timings (in nanoseconds) corresponding to
+# GPMC_CONFIG5:
+  gpmc,page-burst-access-ns:
+    description: Multiple access word delay
+    default: 0
+
+  gpmc,access-ns:
+    description: Start-cycle to first data valid delay
+    default: 0
+
+  gpmc,rd-cycle-ns:
+    description: Total read cycle time
+    default: 0
+
+  gpmc,wr-cycle-ns:
+    description: Total write cycle time
+    default: 0
+
+  gpmc,bus-turnaround-ns:
+    description: Turn-around time between successive accesses
+    default: 0
+
+  gpmc,cycle2cycle-delay-ns:
+    description: Delay between chip-select pulses
+    default: 0
+
+  gpmc,clk-activation-ns:
+    description: GPMC clock activation time
+    default: 0
+
+  gpmc,wait-monitoring-ns:
+    description: Start of wait monitoring with regard to valid data
+    default: 0
+
+# Boolean timing parameters. If property is present, parameter is enabled
+# otherwise disabled.
+  gpmc,adv-extra-delay:
+    description: ADV signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,cs-extra-delay:
+    description: CS signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,cycle2cycle-diffcsen:
+    description: |
+      Add "cycle2cycle-delay" between successive accesses
+      to a different CS
+    type: boolean
+
+  gpmc,cycle2cycle-samecsen:
+    description: |
+      Add "cycle2cycle-delay" between successive accesses
+      to the same CS
+    type: boolean
+
+  gpmc,oe-extra-delay:
+    description: OE signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,we-extra-delay:
+    description: WE signal is delayed by half GPMC clock
+    type: boolean
+
+  gpmc,time-para-granularity:
+    description: Multiply all access times by 2
+    type: boolean
+
+# The following two properties are applicable only to OMAP3+ and AM335x:
+  gpmc,wr-access-ns:
+    description: |
+      In synchronous write mode, for single or
+      burst accesses, defines the number of
+      GPMC_FCLK cycles from start access time
+      to the GPMC_CLK rising edge used by the
+      memory device for the first data capture.
+    default: 0
+
+  gpmc,wr-data-mux-bus-ns:
+    description: |
+      In address-data multiplex mode, specifies
+      the time when the first data is driven on
+      the address-data bus.
+    default: 0
+
+# GPMC chip-select settings properties for child nodes. All are optional.
+  gpmc,burst-length:
+    description: Page/burst length.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 4, 8, 16]
+    default: 0
+
+  gpmc,burst-wrap:
+    description: Enables wrap bursting
+    type: boolean
+
+  gpmc,burst-read:
+    description: Enables read page/burst mode
+    type: boolean
+
+  gpmc,burst-write:
+    description: Enables write page/burst mode
+    type: boolean
+
+  gpmc,device-width:
+    description: |
+      Total width of device(s) connected to a GPMC
+      chip-select in bytes. The GPMC supports 8-bit
+      and 16-bit devices and so this property must be
+      1 or 2.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [1, 2]
+    default: 1
+
+  gpmc,mux-add-data:
+    description: |
+      Address and data multiplexing configuration.
+      Valid values are
+      0 for Non multiplexed mode
+      1 for address-address-data multiplexing mode and
+      2 for address-data multiplexing mode.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2]
+
+  gpmc,sync-read:
+    description: |
+      Enables synchronous read. Defaults to asynchronous
+      is this is not set.
+    type: boolean
+
+  gpmc,sync-write:
+    description: |
+      Enables synchronous writes. Defaults to asynchronous
+      is this is not set.
+    type: boolean
+
+  gpmc,wait-pin:
+    description: |
+      Wait-pin used by client. Must be less than "gpmc,num-waitpins".
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  gpmc,wait-on-read:
+    description: Enables wait monitoring on reads.
+    type: boolean
+
+  gpmc,wait-on-write:
+    description: Enables wait monitoring on writes.
+    type: boolean
+
+required:
+  - reg
+
+# the GPMC child will have its own native properties
+additionalProperties: true
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:26 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:26 +0300
Subject: [PATCH v5 4/8] dt-bindings: mtd: ti,gpmc-nand: Convert to yaml
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-5-rogerq@kernel.org>

Convert gpmc-nand.txt to ti,gpmc-nand.yaml.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Reviewed-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/mtd/gpmc-nand.txt     | 147 ------------------
 .../devicetree/bindings/mtd/ti,gpmc-nand.yaml | 121 ++++++++++++++
 2 files changed, 121 insertions(+), 147 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-nand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/ti,gpmc-nand.yaml

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
deleted file mode 100644
index c459f169a904..000000000000
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ /dev/null
@@ -1,147 +0,0 @@
-Device tree bindings for GPMC connected NANDs
-
-GPMC connected NAND (found on OMAP boards) are represented as child nodes of
-the GPMC controller with a name of "nand".
-
-All timing relevant properties as well as generic gpmc child properties are
-explained in a separate documents - please refer to
-Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-For NAND specific properties such as ECC modes or bus width, please refer to
-Documentation/devicetree/bindings/mtd/nand-controller.yaml
-
-
-Required properties:
-
- - compatible:	"ti,omap2-nand"
- - reg:		range id (CS number), base offset and length of the
-		NAND I/O space
- - interrupts:	Two interrupt specifiers, one for fifoevent, one for termcount.
-
-Optional properties:
-
- - nand-bus-width: 		Set this numeric value to 16 if the hardware
-				is wired that way. If not specified, a bus
-				width of 8 is assumed.
-
- - ti,nand-ecc-opt:		A string setting the ECC layout to use. One of:
-		"sw"		1-bit Hamming ecc code via software
-		"hw"		<deprecated> use "ham1" instead
-		"hw-romcode"	<deprecated> use "ham1" instead
-		"ham1"		1-bit Hamming ecc code
-		"bch4"		4-bit BCH ecc code
-		"bch8"		8-bit BCH ecc code
-		"bch16"		16-bit BCH ECC code
-		Refer below "How to select correct ECC scheme for your device ?"
-
- - ti,nand-xfer-type:		A string setting the data transfer type. One of:
-
-		"prefetch-polled"	Prefetch polled mode (default)
-		"polled"		Polled mode, without prefetch
-		"prefetch-dma"		Prefetch enabled DMA mode
-		"prefetch-irq"		Prefetch enabled irq mode
-
- - elm_id:	<deprecated> use "ti,elm-id" instead
- - ti,elm-id:	Specifies phandle of the ELM devicetree node.
-		ELM is an on-chip hardware engine on TI SoC which is used for
-		locating ECC errors for BCHx algorithms. SoC devices which have
-		ELM hardware engines should specify this device node in .dtsi
-		Using ELM for ECC error correction frees some CPU cycles.
- - rb-gpios:	GPIO specifier for the ready/busy# pin.
-
-For inline partition table parsing (optional):
-
- - #address-cells: should be set to 1
- - #size-cells: should be set to 1
-
-Example for an AM33xx board:
-
-	gpmc: gpmc at 50000000 {
-		compatible = "ti,am3352-gpmc";
-		ti,hwmods = "gpmc";
-		reg = <0x50000000 0x36c>;
-		interrupts = <100>;
-		gpmc,num-cs = <8>;
-		gpmc,num-waitpins = <2>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-		ranges = <0 0 0x08000000 0x1000000>;	/* CS0 space, 16MB */
-		elm_id = <&elm>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
-
-		nand at 0,0 {
-			compatible = "ti,omap2-nand";
-			reg = <0 0 4>;		/* CS0, offset 0, NAND I/O window 4 */
-			interrupt-parent = <&gpmc>;
-			interrupts = <0 IRQ_TYPE_NONE>, <1 IRQ_TYPE NONE>;
-			nand-bus-width = <16>;
-			ti,nand-ecc-opt = "bch8";
-			ti,nand-xfer-type = "polled";
-			rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
-
-			gpmc,sync-clk-ps = <0>;
-			gpmc,cs-on-ns = <0>;
-			gpmc,cs-rd-off-ns = <44>;
-			gpmc,cs-wr-off-ns = <44>;
-			gpmc,adv-on-ns = <6>;
-			gpmc,adv-rd-off-ns = <34>;
-			gpmc,adv-wr-off-ns = <44>;
-			gpmc,we-off-ns = <40>;
-			gpmc,oe-off-ns = <54>;
-			gpmc,access-ns = <64>;
-			gpmc,rd-cycle-ns = <82>;
-			gpmc,wr-cycle-ns = <82>;
-			gpmc,wr-access-ns = <40>;
-			gpmc,wr-data-mux-bus-ns = <0>;
-
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			/* partitions go here */
-		};
-	};
-
-How to select correct ECC scheme for your device ?
---------------------------------------------------
-Higher ECC scheme usually means better protection against bit-flips and
-increased system lifetime. However, selection of ECC scheme is dependent
-on various other factors also like;
-
-(1) support of built in hardware engines.
-	Some legacy OMAP SoC do not have ELM harware engine, so those SoC cannot
-	support ecc-schemes with hardware error-correction (BCHx_HW). However
-	such SoC can use ecc-schemes with software library for error-correction
-	(BCHx_HW_DETECTION_SW). The error correction capability with software
-	library remains equivalent to their hardware counter-part, but there is
-	slight CPU penalty when too many bit-flips are detected during reads.
-
-(2) Device parameters like OOBSIZE.
-	Other factor which governs the selection of ecc-scheme is oob-size.
-	Higher ECC schemes require more OOB/Spare area to store ECC syndrome,
-	so the device should have enough free bytes available its OOB/Spare
-	area to accommodate ECC for entire page. In general following expression
-	helps in determining if given device can accommodate ECC syndrome:
-	"2 + (PAGESIZE / 512) * ECC_BYTES" <= OOBSIZE"
-	where
-		OOBSIZE		number of bytes in OOB/spare area
-		PAGESIZE	number of bytes in main-area of device page
-		ECC_BYTES	number of ECC bytes generated to protect
-		                512 bytes of data, which is:
-				'3' for HAM1_xx ecc schemes
-				'7' for BCH4_xx ecc schemes
-				'14' for BCH8_xx ecc schemes
-				'26' for BCH16_xx ecc schemes
-
-	Example(a): For a device with PAGESIZE = 2048 and OOBSIZE = 64 and
-		trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
-		Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
-		which is greater than capacity of NAND device (OOBSIZE=64)
-		Hence, BCH16 cannot be supported on given device. But it can
-		probably use lower ecc-schemes like BCH8.
-
-	Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128 and
-		trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
-		Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
-		which can be accommodated in the OOB/Spare area of this device
-		(OOBSIZE=128). So this device can use BCH16 ecc-scheme.
diff --git a/Documentation/devicetree/bindings/mtd/ti,gpmc-nand.yaml b/Documentation/devicetree/bindings/mtd/ti,gpmc-nand.yaml
new file mode 100644
index 000000000000..beb26b9bcfb2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/ti,gpmc-nand.yaml
@@ -0,0 +1,121 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/ti,gpmc-nand.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments GPMC NAND Flash controller.
+
+maintainers:
+  - Tony Lindgren <tony at atomide.com>
+  - Roger Quadros <rogerq at kernel.org>
+
+description:
+  GPMC NAND controller/Flash is represented as a child of the
+  GPMC controller node.
+
+properties:
+  compatible:
+    const: ti,omap2-nand
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    items:
+      - description: Interrupt for fifoevent
+      - description: Interrupt for termcount
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+  ti,nand-ecc-opt:
+    description: Desired ECC algorithm
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [sw, ham1, bch4, bch8, bch16]
+
+  ti,nand-xfer-type:
+    description: Data transfer method between controller and chip.
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [prefetch-polled, polled, prefetch-dma, prefetch-irq]
+    default: prefetch-polled
+
+  ti,elm-id:
+    description:
+      phandle to the ELM (Error Location Module).
+    $ref: /schemas/types.yaml#/definitions/phandle
+
+  nand-bus-width:
+    description:
+      Bus width to the NAND chip
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [8, 16]
+    default: 8
+
+patternProperties:
+  "@[0-9a-f]+$":
+    $ref: "/schemas/mtd/partitions/partition.yaml"
+
+allOf:
+  - $ref: "/schemas/memory-controllers/ti,gpmc-child.yaml"
+
+required:
+  - compatible
+  - reg
+  - ti,nand-ecc-opt
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    gpmc: memory-controller at 50000000 {
+      compatible = "ti,am3352-gpmc";
+      dmas = <&edma 52 0>;
+      dma-names = "rxtx";
+      clocks = <&l3s_gclk>;
+      clock-names = "fck";
+      reg = <0x50000000 0x2000>;
+      interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+      gpmc,num-cs = <7>;
+      gpmc,num-waitpins = <2>;
+      #address-cells = <2>;
+      #size-cells = <1>;
+      interrupt-controller;
+      #interrupt-cells = <2>;
+      gpio-controller;
+      #gpio-cells = <2>;
+
+      ranges = <0 0 0x08000000 0x01000000>;   /* CS0 space. Min partition = 16MB */
+      nand at 0,0 {
+        compatible = "ti,omap2-nand";
+        reg = <0 0 4>;          /* device IO registers */
+        interrupt-parent = <&gpmc>;
+        interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+                     <1 IRQ_TYPE_NONE>; /* termcount */
+        ti,nand-xfer-type = "prefetch-dma";
+        ti,nand-ecc-opt = "bch16";
+        ti,elm-id = <&elm>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        /* NAND generic properties */
+        nand-bus-width = <8>;
+        rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>;  /* gpmc_wait0 */
+
+        /* GPMC properties*/
+        gpmc,device-width = <1>;
+
+        partition at 0 {
+          label = "NAND.SPL";
+          reg = <0x00000000 0x00040000>;
+        };
+        partition at 1 {
+          label = "NAND.SPL.backup1";
+          reg = <0x00040000 0x00040000>;
+        };
+      };
+    };
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:27 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:27 +0300
Subject: [PATCH v5 5/8] dt-bindings: mtd: ti,gpmc-onenand: Convert to yaml
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-6-rogerq@kernel.org>

Convert gpmc-onenand.txt to ti,gpmc-onenand.yaml.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Reviewed-by: Rob Herring <robh at kernel.org>
---
 .../devicetree/bindings/mtd/gpmc-onenand.txt  | 48 -----------
 .../bindings/mtd/ti,gpmc-onenand.yaml         | 81 +++++++++++++++++++
 2 files changed, 81 insertions(+), 48 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt b/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
deleted file mode 100644
index e9f01a963a0a..000000000000
--- a/Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-Device tree bindings for GPMC connected OneNANDs
-
-GPMC connected OneNAND (found on OMAP boards) are represented as child nodes of
-the GPMC controller with a name of "onenand".
-
-All timing relevant properties as well as generic gpmc child properties are
-explained in a separate documents - please refer to
-Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
-
-Required properties:
-
- - compatible:		"ti,omap2-onenand"
- - reg:			The CS line the peripheral is connected to
- - gpmc,device-width:	Width of the ONENAND device connected to the GPMC
-			in bytes. Must be 1 or 2.
-
-Optional properties:
-
- - int-gpios:		GPIO specifier for the INT pin.
-
-For inline partition table parsing (optional):
-
- - #address-cells: should be set to 1
- - #size-cells: should be set to 1
-
-Example for an OMAP3430 board:
-
-	gpmc: gpmc at 6e000000 {
-		compatible = "ti,omap3430-gpmc";
-		ti,hwmods = "gpmc";
-		reg = <0x6e000000 0x1000000>;
-		interrupts = <20>;
-		gpmc,num-cs = <8>;
-		gpmc,num-waitpins = <4>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-
-		onenand at 0 {
-			compatible = "ti,omap2-onenand";
-			reg = <0 0 0>; /* CS0, offset 0 */
-			gpmc,device-width = <2>;
-
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			/* partitions go here */
-		};
-	};
diff --git a/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
new file mode 100644
index 000000000000..a953f7397c40
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
@@ -0,0 +1,81 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/ti,gpmc-onenand.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OneNAND over Texas Instruments GPMC bus.
+
+maintainers:
+  - Tony Lindgren <tony at atomide.com>
+  - Roger Quadros <rogerq at kernel.org>
+
+description:
+  GPMC connected OneNAND (found on OMAP boards) are represented
+  as child nodes of the GPMC controller.
+
+properties:
+  compatible:
+    const: ti,omap2-onenand
+
+  reg:
+    items:
+      - description: |
+          Chip Select number, register offset and size of
+          OneNAND register window.
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+  int-gpios:
+    description: GPIO specifier for the INT pin.
+
+patternProperties:
+  "@[0-9a-f]+$":
+    $ref: "/schemas/mtd/partitions/partition.yaml"
+
+allOf:
+  - $ref: "/schemas/memory-controllers/ti,gpmc-child.yaml"
+
+required:
+  - compatible
+  - reg
+  - "#address-cells"
+  - "#size-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    gpmc: memory-controller at 6e000000 {
+      compatible = "ti,omap3430-gpmc";
+      reg = <0x6e000000 0x02d0>;
+      interrupts = <20>;
+      gpmc,num-cs = <8>;
+      gpmc,num-waitpins = <4>;
+      clocks = <&l3s_clkctrl>;
+      clock-names = "fck";
+      #address-cells = <2>;
+      #size-cells = <1>;
+
+      ranges = <0 0 0x01000000 0x01000000>,   /* 16 MB for OneNAND */
+               <1 0 0x02000000 0x01000000>;   /* 16 MB for smc91c96 */
+
+      onenand at 0,0 {
+        compatible = "ti,omap2-onenand";
+        reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
+        #address-cells = <1>;
+        #size-cells = <1>;
+
+        partition at 0 {
+          label = "bootloader";
+          reg = <0x00000000 0x00100000>;
+        };
+
+        partition at 100000 {
+          label = "config";
+          reg = <0x00100000 0x002c0000>;
+        };
+      };
+    };
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:28 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:28 +0300
Subject: [PATCH v5 6/8] dt-bindings: memory-controllers: ti,
 gpmc: Convert to yaml
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-7-rogerq@kernel.org>

Convert omap-gpmc.txt to ti,gpmc.yaml.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
Reviewed-by: Rob Herring <robh at kernel.org>
---
 .../bindings/memory-controllers/omap-gpmc.txt | 157 ----------------
 .../bindings/memory-controllers/ti,gpmc.yaml  | 172 ++++++++++++++++++
 2 files changed, 172 insertions(+), 157 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
 create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml

diff --git a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt b/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
deleted file mode 100644
index c1359f4d48d7..000000000000
--- a/Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
+++ /dev/null
@@ -1,157 +0,0 @@
-Device tree bindings for OMAP general purpose memory controllers (GPMC)
-
-The actual devices are instantiated from the child nodes of a GPMC node.
-
-Required properties:
-
- - compatible:		Should be set to one of the following:
-
-			ti,omap2420-gpmc (omap2420)
-			ti,omap2430-gpmc (omap2430)
-			ti,omap3430-gpmc (omap3430 & omap3630)
-			ti,omap4430-gpmc (omap4430 & omap4460 & omap543x)
-			ti,am3352-gpmc   (am335x devices)
-
- - reg:			A resource specifier for the register space
-			(see the example below)
- - ti,hwmods:		Should be set to "ti,gpmc" until the DT transition is
-			completed.
- - #address-cells:	Must be set to 2 to allow memory address translation
- - #size-cells:		Must be set to 1 to allow CS address passing
- - gpmc,num-cs:		The maximum number of chip-select lines that controller
-			can support.
- - gpmc,num-waitpins:	The maximum number of wait pins that controller can
-			support.
- - ranges:		Must be set up to reflect the memory layout with four
-			integer values for each chip-select line in use:
-
-			   <cs-number> 0 <physical address of mapping> <size>
-
-			Currently, calculated values derived from the contents
-			of the per-CS register GPMC_CONFIG7 (as set up by the
-			bootloader) are used for the physical address decoding.
-			As this will change in the future, filling correct
-			values here is a requirement.
- - interrupt-controller: The GPMC driver implements and interrupt controller for
-			the NAND events "fifoevent" and "termcount" plus the
-			rising/falling edges on the GPMC_WAIT pins.
-			The interrupt number mapping is as follows
-			0 - NAND_fifoevent
-			1 - NAND_termcount
-			2 - GPMC_WAIT0 pin edge
-			3 - GPMC_WAIT1 pin edge, and so on.
- - interrupt-cells:	Must be set to 2
- - gpio-controller:	The GPMC driver implements a GPIO controller for the
-			GPMC WAIT pins that can be used as general purpose inputs.
-			0 maps to GPMC_WAIT0 pin.
- - gpio-cells:		Must be set to 2
-
-Required properties when using NAND prefetch dma:
- - dmas			GPMC NAND prefetch dma channel
- - dma-names		Must be set to "rxtx"
-
-Timing properties for child nodes. All are optional and default to 0.
-
- - gpmc,sync-clk-ps:	Minimum clock period for synchronous mode, in picoseconds
-
- Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
- - gpmc,cs-on-ns:	Assertion time
- - gpmc,cs-rd-off-ns:	Read deassertion time
- - gpmc,cs-wr-off-ns:	Write deassertion time
-
- ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
- - gpmc,adv-on-ns:	Assertion time
- - gpmc,adv-rd-off-ns:	Read deassertion time
- - gpmc,adv-wr-off-ns:	Write deassertion time
- - gpmc,adv-aad-mux-on-ns:	Assertion time for AAD
- - gpmc,adv-aad-mux-rd-off-ns:	Read deassertion time for AAD
- - gpmc,adv-aad-mux-wr-off-ns:	Write deassertion time for AAD
-
- WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- - gpmc,we-on-ns	Assertion time
- - gpmc,we-off-ns:	Deassertion time
-
- OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
- - gpmc,oe-on-ns:	Assertion time
- - gpmc,oe-off-ns:	Deassertion time
- - gpmc,oe-aad-mux-on-ns:	Assertion time for AAD
- - gpmc,oe-aad-mux-off-ns:	Deassertion time for AAD
-
- Access time and cycle time timings (in nanoseconds) corresponding to
- GPMC_CONFIG5:
- - gpmc,page-burst-access-ns: 	Multiple access word delay
- - gpmc,access-ns:		Start-cycle to first data valid delay
- - gpmc,rd-cycle-ns:		Total read cycle time
- - gpmc,wr-cycle-ns:		Total write cycle time
- - gpmc,bus-turnaround-ns:	Turn-around time between successive accesses
- - gpmc,cycle2cycle-delay-ns:	Delay between chip-select pulses
- - gpmc,clk-activation-ns: 	GPMC clock activation time
- - gpmc,wait-monitoring-ns:	Start of wait monitoring with regard to valid
-				data
-
-Boolean timing parameters. If property is present parameter enabled and
-disabled if omitted:
- - gpmc,adv-extra-delay:	ADV signal is delayed by half GPMC clock
- - gpmc,cs-extra-delay:		CS signal is delayed by half GPMC clock
- - gpmc,cycle2cycle-diffcsen:	Add "cycle2cycle-delay" between successive
-				accesses to a different CS
- - gpmc,cycle2cycle-samecsen:	Add "cycle2cycle-delay" between successive
-				accesses to the same CS
- - gpmc,oe-extra-delay:		OE signal is delayed by half GPMC clock
- - gpmc,we-extra-delay:		WE signal is delayed by half GPMC clock
- - gpmc,time-para-granularity:	Multiply all access times by 2
-
-The following are only applicable to OMAP3+ and AM335x:
- - gpmc,wr-access-ns:		In synchronous write mode, for single or
-				burst accesses, defines the number of
-				GPMC_FCLK cycles from start access time
-				to the GPMC_CLK rising edge used by the
-				memory device for the first data capture.
- - gpmc,wr-data-mux-bus-ns:	In address-data multiplex mode, specifies
-				the time when the first data is driven on
-				the address-data bus.
-
-GPMC chip-select settings properties for child nodes. All are optional.
-
-- gpmc,burst-length	Page/burst length. Must be 4, 8 or 16.
-- gpmc,burst-wrap	Enables wrap bursting
-- gpmc,burst-read	Enables read page/burst mode
-- gpmc,burst-write	Enables write page/burst mode
-- gpmc,device-width	Total width of device(s) connected to a GPMC
-			chip-select in bytes. The GPMC supports 8-bit
-			and 16-bit devices and so this property must be
-			1 or 2.
-- gpmc,mux-add-data	Address and data multiplexing configuration.
-			Valid values are 1 for address-address-data
-			multiplexing mode and 2 for address-data
-			multiplexing mode.
-- gpmc,sync-read	Enables synchronous read. Defaults to asynchronous
-			is this is not set.
-- gpmc,sync-write	Enables synchronous writes. Defaults to asynchronous
-			is this is not set.
-- gpmc,wait-pin		Wait-pin used by client. Must be less than
-			"gpmc,num-waitpins".
-- gpmc,wait-on-read	Enables wait monitoring on reads.
-- gpmc,wait-on-write	Enables wait monitoring on writes.
-
-Example for an AM33xx board:
-
-	gpmc: gpmc at 50000000 {
-		compatible = "ti,am3352-gpmc";
-		ti,hwmods = "gpmc";
-		reg = <0x50000000 0x2000>;
-		interrupts = <100>;
-		dmas = <&edma 52 0>;
-		dma-names = "rxtx";
-		gpmc,num-cs = <8>;
-		gpmc,num-waitpins = <2>;
-		#address-cells = <2>;
-		#size-cells = <1>;
-		ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
-		interrupt-controller;
-		#interrupt-cells = <2>;
-		gpio-controller;
-		#gpio-cells = <2>;
-
-		/* child nodes go here */
-	};
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
new file mode 100644
index 000000000000..25b42d68f9b3
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
@@ -0,0 +1,172 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ti,gpmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments GPMC Memory Controller device-tree bindings
+
+maintainers:
+  - Tony Lindgren <tony at atomide.com>
+  - Roger Quadros <rogerq at kernel.org>
+
+description:
+  The GPMC is a unified memory controller dedicated for interfacing
+  with external memory devices like
+  - Asynchronous SRAM-like memories and ASICs
+  - Asynchronous, synchronous, and page mode burst NOR flash
+  - NAND flash
+  - Pseudo-SRAM devices
+
+properties:
+  compatible:
+    items:
+      - enum:
+          - ti,am3352-gpmc
+          - ti,omap2420-gpmc
+          - ti,omap2430-gpmc
+          - ti,omap3430-gpmc
+          - ti,omap4430-gpmc
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: |
+      Functional clock. Used for bus timing calculations and
+      GPMC configuration.
+
+  clock-names:
+    items:
+      - const: fck
+
+  dmas:
+    items:
+      - description: DMA channel for GPMC NAND prefetch
+
+  dma-names:
+    items:
+      - const: rxtx
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+  gpmc,num-cs:
+    description: maximum number of supported chip-select lines.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  gpmc,num-waitpins:
+    description: maximum number of supported wait pins.
+    $ref: /schemas/types.yaml#/definitions/uint32
+
+  ranges:
+    minItems: 1
+    description: |
+      Must be set up to reflect the memory layout with four
+      integer values for each chip-select line in use,
+      <cs-number> 0 <physical address of mapping> <size>
+    items:
+      - description: NAND bank 0
+      - description: NOR/SRAM bank 0
+      - description: NOR/SRAM bank 1
+
+  '#interrupt-cells':
+    const: 2
+
+  interrupt-controller:
+    description: |
+      The GPMC driver implements and interrupt controller for
+      the NAND events "fifoevent" and "termcount" plus the
+      rising/falling edges on the GPMC_WAIT pins.
+      The interrupt number mapping is as follows
+      0 - NAND_fifoevent
+      1 - NAND_termcount
+      2 - GPMC_WAIT0 pin edge
+      3 - GPMC_WAIT1 pin edge, and so on.
+
+  '#gpio-cells':
+    const: 2
+
+  gpio-controller:
+    description: |
+      The GPMC driver implements a GPIO controller for the
+      GPMC WAIT pins that can be used as general purpose inputs.
+      0 maps to GPMC_WAIT0 pin.
+
+  ti,hwmods:
+    description:
+      Name of the HWMOD associated with GPMC. This is for legacy
+      omap2/3 platforms only.
+    $ref: /schemas/types.yaml#/definitions/string
+    deprecated: true
+
+  ti,no-idle-on-init:
+    description:
+      Prevent idling the module at init. This is for legacy omap2/3
+      platforms only.
+    type: boolean
+    deprecated: true
+
+patternProperties:
+  "@[0-7],[a-f0-9]+$":
+    type: object
+    description: |
+      The child device node represents the device connected to the GPMC
+      bus. The device can be a NAND chip, SRAM device, NOR device
+      or an ASIC.
+
+    allOf:
+      - $ref: "ti,gpmc-child.yaml"
+
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - gpmc,num-cs
+  - gpmc,num-waitpins
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/gpio/gpio.h>
+
+    gpmc: memory-controller at 50000000 {
+      compatible = "ti,am3352-gpmc";
+      reg = <0x50000000 0x2000>;
+      interrupts = <100>;
+      clocks = <&l3s_clkctrl>;
+      clock-names = "fck";
+      dmas = <&edma 52 0>;
+      dma-names = "rxtx";
+      gpmc,num-cs = <8>;
+      gpmc,num-waitpins = <2>;
+      #address-cells = <2>;
+      #size-cells = <1>;
+      ranges = <0 0 0x08000000 0x10000000>; /* CS0 @addr 0x8000000, size 0x10000000 */
+      interrupt-controller;
+      #interrupt-cells = <2>;
+      gpio-controller;
+      #gpio-cells = <2>;
+
+      nand at 0,0 {
+        compatible = "ti,omap2-nand";
+        reg = <0 0 4>;
+        interrupt-parent = <&gpmc>;
+        interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+                     <1 IRQ_TYPE_NONE>; /* termcount */
+        ti,nand-xfer-type = "prefetch-dma";
+        ti,nand-ecc-opt = "bch16";
+        ti,elm-id = <&elm>;
+        rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 pin */
+      };
+    };
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:29 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:29 +0300
Subject: [PATCH v5 7/8] ARM: dts: omap: Fix boolean properties gpmc,
 cycle2cycle-{same|diff}csen
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-8-rogerq@kernel.org>

gpmc,cycle2cycle-{same|diff}csen are boolean properties. Fix them
to prevent dtbs_check errors.

Signed-off-by: Roger Quadros <rogerq at kernel.org>
---
 arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi      | 4 ++--
 arch/arm/boot/dts/omap-zoom-common.dtsi        | 4 ++--
 arch/arm/boot/dts/omap2430-sdp.dts             | 4 ++--
 arch/arm/boot/dts/omap3-devkit8000-common.dtsi | 4 ++--
 arch/arm/boot/dts/omap3-sb-t35.dtsi            | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
index ded7e8fec9eb..ce6c235f68ec 100644
--- a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
+++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
@@ -25,8 +25,8 @@
 		compatible = "smsc,lan9221", "smsc,lan9115";
 		bank-width = <2>;
 		gpmc,device-width = <1>;
-		gpmc,cycle2cycle-samecsen = <1>;
-		gpmc,cycle2cycle-diffcsen = <1>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
 		gpmc,cs-on-ns = <5>;
 		gpmc,cs-rd-off-ns = <150>;
 		gpmc,cs-wr-off-ns = <150>;
diff --git a/arch/arm/boot/dts/omap-zoom-common.dtsi b/arch/arm/boot/dts/omap-zoom-common.dtsi
index d4ad9e58b199..1e96c865d41d 100644
--- a/arch/arm/boot/dts/omap-zoom-common.dtsi
+++ b/arch/arm/boot/dts/omap-zoom-common.dtsi
@@ -27,8 +27,8 @@
 		gpmc,mux-add-data = <0>;
 		gpmc,device-width = <1>;
 		gpmc,wait-pin = <1>;
-		gpmc,cycle2cycle-samecsen = <1>;
-		gpmc,cycle2cycle-diffcsen = <1>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
 		gpmc,cs-on-ns = <5>;
 		gpmc,cs-rd-off-ns = <155>;
 		gpmc,cs-wr-off-ns = <155>;
diff --git a/arch/arm/boot/dts/omap2430-sdp.dts b/arch/arm/boot/dts/omap2430-sdp.dts
index 7d27e907533f..207070677e3a 100644
--- a/arch/arm/boot/dts/omap2430-sdp.dts
+++ b/arch/arm/boot/dts/omap2430-sdp.dts
@@ -43,8 +43,8 @@
 		gpmc,sync-clk-ps = <0>;
 		gpmc,mux-add-data = <2>;
 		gpmc,device-width = <1>;
-		gpmc,cycle2cycle-samecsen = <1>;
-		gpmc,cycle2cycle-diffcsen = <1>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
 		gpmc,cs-on-ns = <6>;
 		gpmc,cs-rd-off-ns = <187>;
 		gpmc,cs-wr-off-ns = <187>;
diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
index 2c19d6e255bd..5e55198e4576 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
@@ -267,8 +267,8 @@
 		gpmc,mux-add-data = <0>;
 		gpmc,device-width = <1>;
 		gpmc,wait-pin = <0>;
-		gpmc,cycle2cycle-samecsen = <1>;
-		gpmc,cycle2cycle-diffcsen = <1>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
 
 		gpmc,cs-on-ns = <6>;
 		gpmc,cs-rd-off-ns = <180>;
diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/omap3-sb-t35.dtsi
index fb9842fa922c..5ec0893415e0 100644
--- a/arch/arm/boot/dts/omap3-sb-t35.dtsi
+++ b/arch/arm/boot/dts/omap3-sb-t35.dtsi
@@ -108,8 +108,8 @@
 		reg = <4 0 0xff>;
 		bank-width = <2>;
 		gpmc,device-width = <1>;
-		gpmc,cycle2cycle-samecsen = <1>;
-		gpmc,cycle2cycle-diffcsen = <1>;
+		gpmc,cycle2cycle-samecsen;
+		gpmc,cycle2cycle-diffcsen;
 		gpmc,cs-on-ns = <5>;
 		gpmc,cs-rd-off-ns = <150>;
 		gpmc,cs-wr-off-ns = <150>;
-- 
2.17.1



From rogerq at kernel.org  Thu Oct  7 05:08:30 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Thu,  7 Oct 2021 15:08:30 +0300
Subject: [PATCH v5 8/8] ARM: dts: omap: fix gpmc,mux-add-data type
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <20211007120830.17221-9-rogerq@kernel.org>

gpmc,mux-add-data is not boolean.

Fixes the below errors flagged by dtbs_check.

"ethernet at 4,0:gpmc,mux-add-data: True is not of type 'array'"

Signed-off-by: Roger Quadros <rogerq at kernel.org>
---
 arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi         | 2 +-
 arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
index 7f6aefd13451..e7534fe9c53c 100644
--- a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
+++ b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
@@ -29,7 +29,7 @@
 		compatible = "smsc,lan9221","smsc,lan9115";
 		bank-width = <2>;
 
-		gpmc,mux-add-data;
+		gpmc,mux-add-data = <0>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <42>;
 		gpmc,cs-wr-off-ns = <36>;
diff --git a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
index e5da3bc6f105..218a10c0d815 100644
--- a/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-tobiduo-common.dtsi
@@ -22,7 +22,7 @@
 		compatible = "smsc,lan9221","smsc,lan9115";
 		bank-width = <2>;
 
-		gpmc,mux-add-data;
+		gpmc,mux-add-data = <0>;
 		gpmc,cs-on-ns = <0>;
 		gpmc,cs-rd-off-ns = <42>;
 		gpmc,cs-wr-off-ns = <36>;
-- 
2.17.1



From matthias.schiffer at ew.tq-group.com  Thu Oct  7 05:08:11 2021
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Thu,  7 Oct 2021 14:08:11 +0200
Subject: [PATCH v2 1/2] mtd: spi-nor: micron-st: make mt25ql02g/mt25qu02g
 match more specific, add 4B opcodes
Message-ID: <a69181ccf225424a8bd11349aad0df7face9715e.1633607826.git.matthias.schiffer@ew.tq-group.com>

Change the mt25ql02g/mt25qu02g entries to include SPI_NOR_4B_OPCODES. In
addition, the SPI_NOR_DUAL_READ flag is added to mt25ql02g; this seems
to have been an accidental omission, as mt25ql02g and mt25qu02g should
support the same features.

In addition, the entries are made more specific by matching on the mt25q
extended ID, like it is already done for the smaller n25q derivatives.
It is unclear whether n25q derivatives with 2Gbit exist that do not
support 4B opcodes (like it is the case for sizes up to 512MBit), so we
do not have a match for such variants anymore (as we wouldn't even know
how to name such hypothetical models).

The changes were tested with a mt25qu01g, which should support the same
features as the mt25ql02g/mt25qu02g.

Signed-off-by: Matthias Schiffer <matthias.schiffer at ew.tq-group.com>
---

v2:
- add extended ID match
- add back NO_CHIP_ERASE

 drivers/mtd/spi-nor/micron-st.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index c224e59820a1..a000a0790ecd 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -180,12 +180,14 @@ static const struct flash_info st_parts[] = {
 	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      NO_CHIP_ERASE) },
-	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
-			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
-			      NO_CHIP_ERASE) },
-	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096,
-			      SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+	{ "mt25ql02g",   INFO6(0x20ba22, 0x104400, 64 * 1024, 4096,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+			       NO_CHIP_ERASE) },
+	{ "mt25qu02g",   INFO6(0x20bb22, 0x104400, 64 * 1024, 4096,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+			       NO_CHIP_ERASE) },
 
 	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
 	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
-- 
2.17.1



From matthias.schiffer at ew.tq-group.com  Thu Oct  7 05:08:12 2021
From: matthias.schiffer at ew.tq-group.com (Matthias Schiffer)
Date: Thu,  7 Oct 2021 14:08:12 +0200
Subject: [PATCH v2 2/2] mtd: spi-nor: micron-st: add support for mt25ql01g and
 mt25qu01g
In-Reply-To: <a69181ccf225424a8bd11349aad0df7face9715e.1633607826.git.matthias.schiffer@ew.tq-group.com>
References: <a69181ccf225424a8bd11349aad0df7face9715e.1633607826.git.matthias.schiffer@ew.tq-group.com>
Message-ID: <c347908fd453fadf673000144cdbdf63c51db303.1633607826.git.matthias.schiffer@ew.tq-group.com>

Split these mt25q models from the older n25q models by matching their
extended IDs to allow adding support for 4byte opcodes.

Signed-off-by: Matthias Schiffer <matthias.schiffer at ew.tq-group.com>
---

v2: add NO_CHIP_ERASE

 drivers/mtd/spi-nor/micron-st.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index a000a0790ecd..6593b6ebe0da 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -172,11 +172,19 @@ static const struct flash_info st_parts[] = {
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
+	{ "mt25ql01g",   INFO6(0x20ba21, 0x104400, 64 * 1024, 2048,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+			       NO_CHIP_ERASE) },
 	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6 |
 			      NO_CHIP_ERASE) },
+	{ "mt25qu01g",   INFO6(0x20bb21, 0x104400, 64 * 1024, 2048,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES |
+			       NO_CHIP_ERASE) },
 	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      NO_CHIP_ERASE) },
-- 
2.17.1



From boris.brezillon at collabora.com  Thu Oct  7 05:18:58 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Thu, 7 Oct 2021 14:18:58 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211007114351.3nafhtpefezxhanc@skn-laptop>
References: <20211004065608.3190348-1-sean@geanix.com>
 <20211004104147.579f3b01@collabora.com>
 <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
Message-ID: <20211007141858.314533f2@collabora.com>

On Thu, 7 Oct 2021 13:43:51 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Tue, Oct 05, 2021 at 10:58:36AM +0200, Boris Brezillon wrote:
> > On Tue, 5 Oct 2021 10:49:38 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > On Tue, Oct 05, 2021 at 10:23:00AM +0200, Boris Brezillon wrote:  
> > > > On Tue, 5 Oct 2021 09:09:30 +0200
> > > > Sean Nyekjaer <sean at geanix.com> wrote:    
> > > 
> > > [ ... ]
> > >   
> > > > > 
> > > > > Have you seen the reproducer script?    
> > > > 
> > > > How would I know about this script or your previous attempt (mentioned
> > > > at the end of this email) given I was not Cc-ed on the previous
> > > > discussion, and nothing mentions it in this RFC...
> > > >     
> > > 
> > > That's why I shared it here ;)
> > > Initially I thought this was a bug introduced by exec_op.
> > >   
> > > > > ---
> > > > > root at iwg26-v1:/data/root# cat /data/crash.sh
> > > > > #!/bin/sh -x
> > > > > 
> > > > > echo enabled > /sys/devices/platform/soc/2100000.bus/21f4000.serial/tty/ttymxc4/power/wakeup
> > > > > 
> > > > > rm /data/test50M
> > > > > dd if=/dev/urandom of=/tmp/test50M bs=1M count=50
> > > > > cp /tmp/test50M /data/ &
> > > > > sleep 1
> > > > > echo mem > /sys/power/state
> > > > > ---
> > > > > 
> > > > > As seen in the log above disk is synced before suspend.
> > > > > cp is continuing to copy data to ubifs.
> > > > > And then user space processes are frozen.
> > > > > At this point the kernel thread would have unwritten data.
> > > > > 
> > > > > We tried to solve this with:
> > > > > https://lkml.org/lkml/2021/9/1/280    
> > > > 
> > > > I see. It's still unclear to me when the write happens. Is it in the
> > > > suspend path (before the system is actually suspended), or in the
> > > > resume path (when the system is being resumed).
> > > > 
> > > > Anyway, let's admit writing to a storage device while it's suspended is
> > > > a valid use case and requires the storage layer to put this request on
> > > > old. This wait should not, IMHO, be handled at the NAND level, but at
> > > > the MTD level (using a waitqueue, and an atomic to make
> > > > suspended/resumed transitions safe). And abusing a mutex to implement
> > > > that is certainly not a good idea.    
> > > 
> > > I did't say this was the right solution ;) I actually asked in the RFC:
> > > "Should we introduce a new mutex? Or maybe a spin_lock?"
> > > 
> > > What are you proposing, a waitqueue in mtd_info? That gets checked in
> > > mtd_write()/mtd_read()?  
> > 
> > Yes, and replacing the suspended state by an atomic, and providing a
> > helper to wait on the device readiness. Helper you will call in every
> > path involving a communication with the HW, not just mtd_read/write()
> > (you're missing erase at least, and I fear there are other hooks that
> > might lead to commands being issued to the device). But before we get
> > there, I think it's important to understand what the kernel expects.
> > IOW, if and when threads can do a request on a suspended device, and
> > when it's acceptable to wait (vs returning -EBUSY), otherwise I fear
> > we'll end up with deadlocks in the suspend/resume path.  
> 
> I have a proposal [0] and yes I have ended up in many deadlocks during
> testing. The hardest part is the locking when going into suspend.
> I'm not sure the wait_queue is initialized the right place :)
> And I'm kinda abusing the nand_get_device() for this...
> 
> Who do you think we should add to the discussion?
> 
> /Sean
> 
> [0]:
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..735dfff18143 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c

As I said previously, I think this should be handled MTD level
(drivers/mtd/mtdcore.c) not in the raw NAND framework.

> @@ -337,11 +337,10 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
>   */
>  static int nand_get_device(struct nand_chip *chip)
>  {
> +       struct mtd_info *mtd = nand_to_mtd(chip);
> +
> +       wait_event(mtd->wait_queue, atomic_read(&chip->suspended) == 0);
>         mutex_lock(&chip->lock);
> -       if (chip->suspended) {
> -               mutex_unlock(&chip->lock);
> -               return -EBUSY;
> -       }

There's a race here: the device might enter suspend again before you're
able to acquire the lock.

>         mutex_lock(&chip->controller->lock);
> 
>         return 0;
> @@ -4562,11 +4561,15 @@ static int nand_suspend(struct mtd_info *mtd)
>         struct nand_chip *chip = mtd_to_nand(mtd);
>         int ret = 0;
> 
> +       atomic_inc(&chip->suspended);
>         mutex_lock(&chip->lock);

And it's racy here as well: you mark the device as suspended before you
even acquired the lock.

>         if (chip->ops.suspend)
>                 ret = chip->ops.suspend(chip);
> -       if (!ret)
> -               chip->suspended = 1;
> +       if (ret) {
> +               /* Wake things up again if suspend fails */
> +               atomic_dec(&chip->suspended);
> +               wake_up(&mtd->wait_queue);
> +       }
>         mutex_unlock(&chip->lock);
> 
>         return ret;
> @@ -4581,10 +4584,12 @@ static void nand_resume(struct mtd_info *mtd)
>         struct nand_chip *chip = mtd_to_nand(mtd);
> 
>         mutex_lock(&chip->lock);
> -       if (chip->suspended) {
> +       if (atomic_read(&chip->suspended)) {
>                 if (chip->ops.resume)
>                         chip->ops.resume(chip);
> -               chip->suspended = 0;
> +
> +               atomic_dec(&chip->suspended);
> +               wake_up(&mtd->wait_queue);
>         } else {
>                 pr_err("%s called for a chip which is not in suspended state\n",
>                         __func__);
> @@ -5099,6 +5104,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>         pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
>                 (int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
>                 mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
> +
> +       init_waitqueue_head(&mtd->wait_queue);
> +

It's an MTD field. It should be initialized somewhere in mtdcore.c.

>         return 0;
> 
>  free_detect_allocation:
> @@ -6264,6 +6272,8 @@ static int nand_scan_tail(struct nand_chip *chip)
>         if (chip->options & NAND_SKIP_BBTSCAN)
>                 return 0;
> 
> +       atomic_set(&chip->suspended, 0);
> +
>         /* Build bad block table */
>         ret = nand_create_bbt(chip);
>         if (ret)
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 88227044fc86..f7dcbc336170 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -360,6 +360,8 @@ struct mtd_info {
>         int (*_get_device) (struct mtd_info *mtd);
>         void (*_put_device) (struct mtd_info *mtd);
> 
> +       wait_queue_head_t wait_queue;
> +

wait_queue doesn't really describe what this waitqueue is used for
(maybe resume_wq), and the suspended state should be here as well
(actually, there's one already).

Actually, what we need is a way to prevent the device from being
suspended while accesses are still in progress, and new accesses from
being queued if a suspend is pending. So, I think you need a readwrite
lock here:

* take the lock in read mode for all IO accesses, check the
  mtd->suspended value
  - if true, release the lock, and wait (retry on wakeup)
  - if false, just do the IO

* take the lock in write mode when you want to suspend/resume the
  device and update the suspended field. Call wake_up_all() in the
  resume path


From p.yadav at ti.com  Thu Oct  7 05:36:23 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 7 Oct 2021 18:06:23 +0530
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <YVrSbyEsSLMOu1bU@lahna>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com> <YVrSbyEsSLMOu1bU@lahna>
Message-ID: <20211007123621.ld4aqasr3hlwq2c7@ti.com>

On 04/10/21 01:07PM, Mika Westerberg wrote:
> Hi,
> 
> On Mon, Oct 04, 2021 at 03:22:41PM +0530, Pratyush Yadav wrote:
> > On 30/09/21 01:07PM, Mika Westerberg wrote:
> > > The preferred way to implement SPI-NOR controller drivers is through SPI
> > > subsubsystem utilizing the SPI MEM core functions. This converts the
> > > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > > SPI MEM functions. The driver name will be changed from intel-spi to
> > > spi-intel to match the convention used in the SPI subsystem.
> > > 
> > > Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> > > ---
> > >  drivers/mtd/spi-nor/controllers/Kconfig       |  36 ---
> > >  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
> > >  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
> > >  drivers/spi/Kconfig                           |  38 +++
> > >  drivers/spi/Makefile                          |   3 +
> > >  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
> > >  .../spi-intel-platform.c}                     |  21 +-
> > >  .../intel-spi.c => spi/spi-intel.c}           | 300 +++++++++++-------
> > >  drivers/spi/spi-intel.h                       |  19 ++
> > >  include/linux/mfd/lpc_ich.h                   |   2 +-
> > >  .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
> > >  11 files changed, 252 insertions(+), 217 deletions(-)
> > >  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
> > >  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
> > >  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
> > >  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (80%)
> > >  create mode 100644 drivers/spi/spi-intel.h
> > >  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)
> > > 
> > [...]
> > > +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> > > +				      const struct spi_mem_op *op)
> > > +{
> > > +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> > >  
> > > -			offs += erase_size;
> > > -			len -= erase_size;
> > > +	if (op->cmd.dtr)
> > > +		return false;
> > > +
> > > +	if (ispi->swseq_reg && ispi->locked) {
> > > +		int i;
> > > +
> > > +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> > > +			if (ispi->opcodes[i] == op->cmd.opcode)
> > > +				return true;
> > >  		}
> > >  
> > > -		return 0;
> > > +		return false;
> > >  	}
> > >  
> > > -	/* Not needed with HW sequencer erase, make sure it is cleared */
> > > -	ispi->atomic_preopcode = 0;
> > > +	switch (op->cmd.opcode) {
> > > +	case SPINOR_OP_RDID:
> > > +	case SPINOR_OP_RDSR:
> > > +	case SPINOR_OP_WRSR:
> > > +		return true;
> > >  
> > > -	while (len > 0) {
> > > -		writel(offs, ispi->base + FADDR);
> > > +	case SPINOR_OP_READ:
> > > +	case SPINOR_OP_READ_FAST:
> > > +	case SPINOR_OP_READ_4B:
> > > +	case SPINOR_OP_READ_FAST_4B:
> > > +		return true;
> > 
> > I think the checks need to be stricter here. For example, I don't see 
> > you pass in protocol width (dual, quad, octal, etc.) to intel_spi_read() 
> > so I assume it can only do a certain protocol. You need to make sure 
> > that other protocols are rejected here.
> > 
> > Similarly, you also don't pass in dummy cycles to intel_spi_read(), so I 
> > assume it can only do a fix number of dummy cycles. Need to make sure 
> > you reject unsupported ones. Same for other opcodes/cases.
> 
> Unfortunately there is no way to tell the controller any of these. It
> simply does "read" or "write" (as we command it) and internally then
> uses whatever it got from the SFDP tables of the flash chip. That's why
> we just claim to support all these operations and let the controller do
> its thing (whatever it is).

That is not ideal. SPI NOR uses this to negotiate the best available 
protocol with the controller. Say you have a flash that is capable of 
octal mode but the controller can only support quad mode. Your driver 
will happily tell SPI NOR that it can support octal mode. I think you 
should check the SPI mode bits to make sure the protocol bus width is 
supported at least (see spi_check_buswidth_req() in spi-mem.c).

As for opcodes, is there no way to find out what opcodes the controller 
discovered via SFDP? Maybe we can't change them, but can we at least 
take a peek at them?

I think this has problems similar to the Cadence xSPI controller [0].

Sorry I only replied to this after you posted a new version. It got lost 
in the heap of emails in my inbox :-(

[0] https://patchwork.kernel.org/project/spi-devel-general/patch/1630499858-20456-1-git-send-email-pthombar at cadence.com/

> 
> Hope this clarifies.

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From sean at geanix.com  Thu Oct  7 05:39:16 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Thu, 7 Oct 2021 14:39:16 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211007141858.314533f2@collabora.com>
References: <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
Message-ID: <20211007123916.w4oaooxfbawe6yw3@skn-laptop>

On Thu, Oct 07, 2021 at 02:18:58PM +0200, Boris Brezillon wrote:
> On Thu, 7 Oct 2021 13:43:51 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 

[ ... ]

> > 
> > I have a proposal [0] and yes I have ended up in many deadlocks during
> > testing. The hardest part is the locking when going into suspend.
> > I'm not sure the wait_queue is initialized the right place :)
> > And I'm kinda abusing the nand_get_device() for this...
> > 
> > Who do you think we should add to the discussion?
> > 
> > /Sean
> > 
> > [0]:
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..735dfff18143 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> 
> As I said previously, I think this should be handled MTD level
> (drivers/mtd/mtdcore.c) not in the raw NAND framework.
> 
> > @@ -337,11 +337,10 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
> >   */
> >  static int nand_get_device(struct nand_chip *chip)
> >  {
> > +       struct mtd_info *mtd = nand_to_mtd(chip);
> > +
> > +       wait_event(mtd->wait_queue, atomic_read(&chip->suspended) == 0);
> >         mutex_lock(&chip->lock);
> > -       if (chip->suspended) {
> > -               mutex_unlock(&chip->lock);
> > -               return -EBUSY;
> > -       }
> 
> There's a race here: the device might enter suspend again before you're
> able to acquire the lock.
> 

Thought so :)

> >         mutex_lock(&chip->controller->lock);
> > 
> >         return 0;
> > @@ -4562,11 +4561,15 @@ static int nand_suspend(struct mtd_info *mtd)
> >         struct nand_chip *chip = mtd_to_nand(mtd);
> >         int ret = 0;
> > 
> > +       atomic_inc(&chip->suspended);
> >         mutex_lock(&chip->lock);
> 
> And it's racy here as well: you mark the device as suspended before you
> even acquired the lock.
> 
> >         if (chip->ops.suspend)
> >                 ret = chip->ops.suspend(chip);
> > -       if (!ret)
> > -               chip->suspended = 1;
> > +       if (ret) {
> > +               /* Wake things up again if suspend fails */
> > +               atomic_dec(&chip->suspended);
> > +               wake_up(&mtd->wait_queue);
> > +       }
> >         mutex_unlock(&chip->lock);
> > 
> >         return ret;
> > @@ -4581,10 +4584,12 @@ static void nand_resume(struct mtd_info *mtd)
> >         struct nand_chip *chip = mtd_to_nand(mtd);
> > 
> >         mutex_lock(&chip->lock);
> > -       if (chip->suspended) {
> > +       if (atomic_read(&chip->suspended)) {
> >                 if (chip->ops.resume)
> >                         chip->ops.resume(chip);
> > -               chip->suspended = 0;
> > +
> > +               atomic_dec(&chip->suspended);
> > +               wake_up(&mtd->wait_queue);
> >         } else {
> >                 pr_err("%s called for a chip which is not in suspended state\n",
> >                         __func__);
> > @@ -5099,6 +5104,9 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
> >         pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
> >                 (int)(targetsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
> >                 mtd->erasesize >> 10, mtd->writesize, mtd->oobsize);
> > +
> > +       init_waitqueue_head(&mtd->wait_queue);
> > +
> 
> It's an MTD field. It should be initialized somewhere in mtdcore.c.
> 
> >         return 0;
> > 
> >  free_detect_allocation:
> > @@ -6264,6 +6272,8 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         if (chip->options & NAND_SKIP_BBTSCAN)
> >                 return 0;
> > 
> > +       atomic_set(&chip->suspended, 0);
> > +
> >         /* Build bad block table */
> >         ret = nand_create_bbt(chip);
> >         if (ret)
> > diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> > index 88227044fc86..f7dcbc336170 100644
> > --- a/include/linux/mtd/mtd.h
> > +++ b/include/linux/mtd/mtd.h
> > @@ -360,6 +360,8 @@ struct mtd_info {
> >         int (*_get_device) (struct mtd_info *mtd);
> >         void (*_put_device) (struct mtd_info *mtd);
> > 
> > +       wait_queue_head_t wait_queue;
> > +
> 
> wait_queue doesn't really describe what this waitqueue is used for
> (maybe resume_wq), and the suspended state should be here as well
> (actually, there's one already).

I'll rename to something meaningful.
> 
> Actually, what we need is a way to prevent the device from being
> suspended while accesses are still in progress, and new accesses from
> being queued if a suspend is pending. So, I think you need a readwrite
> lock here:
> 
> * take the lock in read mode for all IO accesses, check the
>   mtd->suspended value
>   - if true, release the lock, and wait (retry on wakeup)
>   - if false, just do the IO
> 
> * take the lock in write mode when you want to suspend/resume the
>   device and update the suspended field. Call wake_up_all() in the
>   resume path

Could we use the chip->lock mutex for this? It's does kinda what you
described above?
If we introduce a new lock, do we really need to have the suspended as
an atomic?

I will test with some wait and retry added to nand_get_device().


From boris.brezillon at collabora.com  Thu Oct  7 06:14:26 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Thu, 7 Oct 2021 15:14:26 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
References: <20211004085509.iikxtdvxpt6bri5c@skn-laptop>
 <20211004115817.18739936@collabora.com>
 <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
 <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
Message-ID: <20211007151426.54db0764@collabora.com>

On Thu, 7 Oct 2021 14:39:16 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> > >         return 0;
> > > 
> > >  free_detect_allocation:
> > > @@ -6264,6 +6272,8 @@ static int nand_scan_tail(struct nand_chip *chip)
> > >         if (chip->options & NAND_SKIP_BBTSCAN)
> > >                 return 0;
> > > 
> > > +       atomic_set(&chip->suspended, 0);
> > > +
> > >         /* Build bad block table */
> > >         ret = nand_create_bbt(chip);
> > >         if (ret)
> > > diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> > > index 88227044fc86..f7dcbc336170 100644
> > > --- a/include/linux/mtd/mtd.h
> > > +++ b/include/linux/mtd/mtd.h
> > > @@ -360,6 +360,8 @@ struct mtd_info {
> > >         int (*_get_device) (struct mtd_info *mtd);
> > >         void (*_put_device) (struct mtd_info *mtd);
> > > 
> > > +       wait_queue_head_t wait_queue;
> > > +  
> > 
> > wait_queue doesn't really describe what this waitqueue is used for
> > (maybe resume_wq), and the suspended state should be here as well
> > (actually, there's one already).  
> 
> I'll rename to something meaningful.
> > 
> > Actually, what we need is a way to prevent the device from being
> > suspended while accesses are still in progress, and new accesses from
> > being queued if a suspend is pending. So, I think you need a readwrite
> > lock here:
> > 
> > * take the lock in read mode for all IO accesses, check the
> >   mtd->suspended value
> >   - if true, release the lock, and wait (retry on wakeup)
> >   - if false, just do the IO
> > 
> > * take the lock in write mode when you want to suspend/resume the
> >   device and update the suspended field. Call wake_up_all() in the
> >   resume path  
> 
> Could we use the chip->lock mutex for this? It's does kinda what you
> described above?

No you can't. Remember I suggested to move all of that logic to
mtdcore.c, which doesn't know about the nand_chip struct.

> If we introduce a new lock, do we really need to have the suspended as
> an atomic?

Nope, I thought we could do without a lock, but we actually need to
track active IO requests, not just the suspended state.

> 
> I will test with some wait and retry added to nand_get_device().

Again, I think there's a misunderstanding here: if you move it to the
mtd layer, it can't be done in nand_get_device(). But once you've
implemented it in mtdcore.c, you should be able to get rid of the
nand_chip->suspended field.


From jbglaw at lug-owl.de  Thu Oct  7 06:54:01 2021
From: jbglaw at lug-owl.de (Jan-Benedict Glaw)
Date: Thu, 7 Oct 2021 15:54:01 +0200
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
Message-ID: <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>

Hi Richard,

On Thu, 2021-10-07 09:20:05 +0200, Richard Weinberger <richard at nod.at> wrote:
> > > On Fri, 2021-10-01 21:28:36 +0200, Jan-Benedict Glaw <jbglaw at lug-owl.de> wrote:
> > > > diff --git a/fs/ubifs/key.h b/fs/ubifs/key.h
> > > > index 8142d9d6fe5d..40edcca7ba62 100644
> > > > --- a/fs/ubifs/key.h
> > > > +++ b/fs/ubifs/key.h
> > > > @@ -436,7 +436,7 @@ static inline void key_write(const struct ubifs_info *c,
> > > >  
> > > >  	t->j32[0] = cpu_to_le32(from->u32[0]);
> > > >  	t->j32[1] = cpu_to_le32(from->u32[1]);
> > > > -	memset(to + 8, 0, UBIFS_MAX_KEY_LEN - 8);
> > > > +	memset(to + 8, 0, UBIFS_SK_LEN - 8);
> > > >  }
> > > >  
> > > >  /**

> key_write() takes a ubifs_key as source and writes to a buffer.
> It assumes that the passed ubifs_key is in simple key format (being UBIFS_SK_LEN long)
> and it assumes the buffer is UBIFS_MAX_KEY_LEN long.
> So, the destination is *not* a union ubifs_key structure.

Ah. This is something I probably misunderstood. As the destination is
casted to an ubifs_key as well, my expectation was that this function
should not write outside the bounds of such an ubifs_key struct.

> We have three callers of key_write(), all in journal.c
> 
> 1. ubifs_jnl_write_data
> key_write(c, key, &data->key);
> 
> data is struct ubifs_data_node where key is of size UBIFS_MAX_KEY_LEN.
> 
> 2. ubifs_jnl_update
> 
> Same with struct ubifs_dent_node
> 
> 3. ubifs_jnl_delete_xattr
> 
> Same again.
> 
> All three objects are slab allocated, did you check, is too few memory allocated?
> In other words, how did you calculate the size of target buffer?

You're right, the code is correct somehow, but was misleading me.

  The supplied buffer (ubifs_data_node.key) is actually
UBIFS_MAX_KEY_LEN bytes long, but used as ubifs_key (which is smaller)
and then the remaining space is zeroed out, thus there's an assumption
about the buffer size.

  I actually found this due to a warning for key.h:439:

[mk all 2021-09-19 16:20:34]   arm-linux-gnueabihf-gcc -Wp,-MMD,fs/ubifs/.journal.o.d -nostdinc -isystem /var/lib/laminar/run/linux-arm-aspeed_g4_defconfig/8/toolchain/bin/../lib/gcc/arm-linux-gnueabihf/12.0.0/include -I./arch/arm/include -I./arch/arm/include/generated  -I./include -I./arch/arm/include/uapi -I./arch/arm/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ -mlittle-endian -fmacro-prefix-map=./= -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89 -fno-dwarf2-cfi-asm -fno-omit-frame-pointer -mapcs -mno-sched-prolog -fno-ipa-sra -mabi=aapcs-linux -mfpu=vfp -marm -Wa,-mno-warn-deprecated -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation -Wno-format-overflow -Wno-address-of-packed-member -O2 -fno-allow-store-data-races -Wframe-larger-than=1024 -fstack-protector-strong -Wimplicit-fallthrough=5 -Wno-main -Wno-unused-but-set-variable -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang -fno-stack-clash-protection -g -gdwarf-4 -fno-var-tracking -femit-struct-debug-baseonly -pg -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time -Werror=incompatible-pointer-types -Werror=designated-init -Wno-packed-not-aligned    -DKBUILD_MODFILE='"fs/ubifs/ubifs"' -DKBUILD_BASENAME='"journal"' -DKBUILD_MODNAME='"ubifs"' -D__KBUILD_MODNAME=kmod_ubifs -c -o fs/ubifs/journal.o fs/ubifs/journal.c
[mk all 2021-09-19 16:20:35] In file included from ./include/linux/string.h:262,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/bitmap.h:10,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/cpumask.h:12,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/smp.h:13,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/lockdep.h:14,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/spinlock.h:63,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/wait.h:9,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/wait_bit.h:8,
[mk all 2021-09-19 16:20:35]                  from ./include/linux/fs.h:6,
[mk all 2021-09-19 16:20:35]                  from fs/ubifs/ubifs.h:16,
[mk all 2021-09-19 16:20:35]                  from fs/ubifs/journal.c:49:
[mk all 2021-09-19 16:20:35] In function 'memset',
[mk all 2021-09-19 16:20:35]     inlined from 'key_write.part.0' at fs/ubifs/key.h:439:2:
[mk all 2021-09-19 16:20:35] ./include/linux/fortify-string.h:172:17: error: call to '__write_overflow' declared with attribute error: detected write beyond size of object passed as 1st parameter
[mk all 2021-09-19 16:20:35]   172 |                 __write_overflow();
[mk all 2021-09-19 16:20:35]       |                 ^~~~~~~~~~~~~~~~~~
[mk all 2021-09-19 16:20:35] make[2]: *** [scripts/Makefile.build:277: fs/ubifs/journal.o] Error 1
[mk all 2021-09-19 16:20:35] make[1]: *** [scripts/Makefile.build:540: fs/ubifs] Error 2

Maybe supply key_write() the complete target buffer length and
memset() it first, then place the properly formatted key into it?

MfG, JBG

-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211007/af659732/attachment.sig>

From richard at nod.at  Thu Oct  7 07:19:06 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 7 Oct 2021 16:19:06 +0200 (CEST)
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
 <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
Message-ID: <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
>> key_write() takes a ubifs_key as source and writes to a buffer.
>> It assumes that the passed ubifs_key is in simple key format (being UBIFS_SK_LEN
>> long)
>> and it assumes the buffer is UBIFS_MAX_KEY_LEN long.
>> So, the destination is *not* a union ubifs_key structure.
> 
> Ah. This is something I probably misunderstood. As the destination is
> casted to an ubifs_key as well, my expectation was that this function
> should not write outside the bounds of such an ubifs_key struct.
> 
>> We have three callers of key_write(), all in journal.c
>> 
>> 1. ubifs_jnl_write_data
>> key_write(c, key, &data->key);
>> 
>> data is struct ubifs_data_node where key is of size UBIFS_MAX_KEY_LEN.
>> 
>> 2. ubifs_jnl_update
>> 
>> Same with struct ubifs_dent_node
>> 
>> 3. ubifs_jnl_delete_xattr
>> 
>> Same again.
>> 
>> All three objects are slab allocated, did you check, is too few memory
>> allocated?
>> In other words, how did you calculate the size of target buffer?
> 
> You're right, the code is correct somehow, but was misleading me.
> 
>  The supplied buffer (ubifs_data_node.key) is actually
> UBIFS_MAX_KEY_LEN bytes long, but used as ubifs_key (which is smaller)
> and then the remaining space is zeroed out, thus there's an assumption
> about the buffer size.
> 
>  I actually found this due to a warning for key.h:439:
> 
> [mk all 2021-09-19 16:20:34]   arm-linux-gnueabihf-gcc
> -Wp,-MMD,fs/ubifs/.journal.o.d -nostdinc -isystem
> /var/lib/laminar/run/linux-arm-aspeed_g4_defconfig/8/toolchain/bin/../lib/gcc/arm-linux-gnueabihf/12.0.0/include
> -I./arch/arm/include -I./arch/arm/include/generated  -I./include
> -I./arch/arm/include/uapi -I./arch/arm/include/generated/uapi -I./include/uapi
> -I./include/generated/uapi -include ./include/linux/compiler-version.h -include
> ./include/linux/kconfig.h -include ./include/linux/compiler_types.h
> -D__KERNEL__ -mlittle-endian -fmacro-prefix-map=./= -Wall -Wundef
> -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common
> -fshort-wchar -fno-PIE -Werror=implicit-function-declaration
> -Werror=implicit-int -Werror=return-type -Wno-format-security -std=gnu89
> -fno-dwarf2-cfi-asm -fno-omit-frame-pointer -mapcs -mno-sched-prolog
> -fno-ipa-sra -mabi=aapcs-linux -mfpu=vfp -marm -Wa,-mno-warn-deprecated
> -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi -msoft-float -Uarm
> -fno-delete-null-pointer-checks -Wno-frame-address -Wno-format-truncation
> -Wno-format-overflow -Wno-address-of-packed-member -O2
> -fno-allow-store-data-races -Wframe-larger-than=1024 -fstack-protector-strong
> -Wimplicit-fallthrough=5 -Wno-main -Wno-unused-but-set-variable
> -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls
> -ftrivial-auto-var-init=zero
> -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang
> -fno-stack-clash-protection -g -gdwarf-4 -fno-var-tracking
> -femit-struct-debug-baseonly -pg -Wdeclaration-after-statement -Wvla
> -Wno-pointer-sign -Wno-stringop-truncation -Wno-zero-length-bounds
> -Wno-array-bounds -Wno-stringop-overflow -Wno-restrict -Wno-maybe-uninitialized
> -fno-strict-overflow -fno-stack-check -fconserve-stack -Werror=date-time
> -Werror=incompatible-pointer-types -Werror=designated-init
> -Wno-packed-not-aligned    -DKBUILD_MODFILE='"fs/ubifs/ubifs"'
> -DKBUILD_BASENAME='"journal"' -DKBUILD_MODNAME='"ubifs"'
> -D__KBUILD_MODNAME=kmod_ubifs -c -o fs/ubifs/journal.o fs/ubifs/journal.c
> [mk all 2021-09-19 16:20:35] In file included from ./include/linux/string.h:262,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/bitmap.h:10,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/cpumask.h:12,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/smp.h:13,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/lockdep.h:14,
> [mk all 2021-09-19 16:20:35]                  from
> ./include/linux/spinlock.h:63,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/wait.h:9,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/wait_bit.h:8,
> [mk all 2021-09-19 16:20:35]                  from ./include/linux/fs.h:6,
> [mk all 2021-09-19 16:20:35]                  from fs/ubifs/ubifs.h:16,
> [mk all 2021-09-19 16:20:35]                  from fs/ubifs/journal.c:49:
> [mk all 2021-09-19 16:20:35] In function 'memset',
> [mk all 2021-09-19 16:20:35]     inlined from 'key_write.part.0' at
> fs/ubifs/key.h:439:2:
> [mk all 2021-09-19 16:20:35] ./include/linux/fortify-string.h:172:17: error:
> call to '__write_overflow' declared with attribute error: detected write beyond
> size of object passed as 1st parameter
> [mk all 2021-09-19 16:20:35]   172 |                 __write_overflow();
> [mk all 2021-09-19 16:20:35]       |                 ^~~~~~~~~~~~~~~~~~
> [mk all 2021-09-19 16:20:35] make[2]: *** [scripts/Makefile.build:277:
> fs/ubifs/journal.o] Error 1
> [mk all 2021-09-19 16:20:35] make[1]: *** [scripts/Makefile.build:540: fs/ubifs]
> Error 2

Hmmm, fortify assumes that the buffer behind "to" is sizeof (union ubifs_key) just because
the function does:
union ubifs_key *t = to;
?

Even though memset() operates on "to" and not "t"...

> Maybe supply key_write() the complete target buffer length and
> memset() it first, then place the properly formatted key into it?

Well, that's the whole purpose of key_write(). It formats an in-memory key for
the disk format.
I fear this is just a matter of static analysis being not smart.

Thanks,
//richard


From jbglaw at lug-owl.de  Thu Oct  7 07:26:17 2021
From: jbglaw at lug-owl.de (Jan-Benedict Glaw)
Date: Thu, 7 Oct 2021 16:26:17 +0200
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
 <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
 <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>
Message-ID: <20211007142617.3hgjddbbvcowzgc3@lug-owl.de>

On Thu, 2021-10-07 16:19:06 +0200, Richard Weinberger <richard at nod.at> wrote:
> Hmmm, fortify assumes that the buffer behind "to" is sizeof (union ubifs_key) just because
> the function does:
> union ubifs_key *t = to;
> ?
> 
> Even though memset() operates on "to" and not "t"...
> 
> > Maybe supply key_write() the complete target buffer length and
> > memset() it first, then place the properly formatted key into it?
> 
> Well, that's the whole purpose of key_write(). It formats an in-memory key for
> the disk format.
> I fear this is just a matter of static analysis being not smart.

Guess so...

Maybe it'll get better.  At least, that's been with a very modern GCC,
so I guess this'll come up again in one way or another. (Either as a
GCC bug, or by not simply having a key[] array were the data is
"magically" written to, but some union with that array and probably a
struct like struct ubifs_key (where, for practical purposes, it's
__le32 j32 already is the on-disk representation.)

So ...  The code does _not_ overflow, that's good first of all. It's
just a bit confusing how the key bytes are written to the buffer. At
least I was easily distracted by the two different sizes.

Thanks,
  Jan-Benedict

-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211007/bc12c737/attachment.sig>

From richard at nod.at  Thu Oct  7 08:20:47 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 7 Oct 2021 17:20:47 +0200 (CEST)
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <20211007142617.3hgjddbbvcowzgc3@lug-owl.de>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
 <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
 <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>
 <20211007142617.3hgjddbbvcowzgc3@lug-owl.de>
Message-ID: <940617141.46853.1633620047008.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "Jan-Benedict Glaw" <jbglaw at lug-owl.de>
> An: "richard" <richard at nod.at>
> 
> So ...  The code does _not_ overflow, that's good first of all. It's
> just a bit confusing how the key bytes are written to the buffer. At
> least I was easily distracted by the two different sizes.

If you find a better way to write the function, I'm all open for a patch.
But please make sure the generated code is sane.

Thanks,
//richard


From mika.westerberg at linux.intel.com  Thu Oct  7 09:46:12 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Thu, 7 Oct 2021 19:46:12 +0300
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211007123621.ld4aqasr3hlwq2c7@ti.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com> <YVrSbyEsSLMOu1bU@lahna>
 <20211007123621.ld4aqasr3hlwq2c7@ti.com>
Message-ID: <YV8kVKiMShWp4g7a@lahna>

Hi,

On Thu, Oct 07, 2021 at 06:06:23PM +0530, Pratyush Yadav wrote:
> > Unfortunately there is no way to tell the controller any of these. It
> > simply does "read" or "write" (as we command it) and internally then
> > uses whatever it got from the SFDP tables of the flash chip. That's why
> > we just claim to support all these operations and let the controller do
> > its thing (whatever it is).
> 
> That is not ideal. SPI NOR uses this to negotiate the best available 
> protocol with the controller. Say you have a flash that is capable of 
> octal mode but the controller can only support quad mode. Your driver 
> will happily tell SPI NOR that it can support octal mode. I think you 
> should check the SPI mode bits to make sure the protocol bus width is 
> supported at least (see spi_check_buswidth_req() in spi-mem.c).

Okay, I'll see if I can add that check somewhere.

> As for opcodes, is there no way to find out what opcodes the controller 
> discovered via SFDP? Maybe we can't change them, but can we at least 
> take a peek at them?

AFAICT no. The controller only allows "higher" level commands like read,
write, erase but does not expose any of that to software. You can see
yourself if you want, the spec is here:
 
  https://cdrdv2.intel.com/v1/dl/getContent/636174

Page 403 has the control register.

> I think this has problems similar to the Cadence xSPI controller [0].

Probably but I would not call these "problems" - it is how the
controller is designed. This one is meant only for SPI-NOR flash access,
typically used by the BIOS. It is by no means general purpose SPI
controller (as you can see from the datasheet). The BIOS does need the
full SPI stack, it just issues these simple commands and let's the
controller figure out what actually needs to be done.

> Sorry I only replied to this after you posted a new version. It got lost 
> in the heap of emails in my inbox :-(

No worries :)


From krzysztof.kozlowski at canonical.com  Thu Oct  7 10:37:42 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Thu, 7 Oct 2021 19:37:42 +0200
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <20211007120830.17221-1-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
Message-ID: <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>

On 07/10/2021 14:08, Roger Quadros wrote:
> Hi,
> 
> This series converts ti,gpmc memory controller and ti,gpmc-nand and
> ti,gpmc-onenand MTD controller bindings to yaml.
> 
> cheers,
> -roger
> 

Hi,

Although you did not mention it here, it looks like you have some
dependencies between the patches. Maybe this shall go simply via Rob's tree?

Best regards,
Krzysztof


From jbglaw at lug-owl.de  Thu Oct  7 10:45:10 2021
From: jbglaw at lug-owl.de (Jan-Benedict Glaw)
Date: Thu, 7 Oct 2021 19:45:10 +0200
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <940617141.46853.1633620047008.JavaMail.zimbra@nod.at>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <20211005144936.xnkzugjr3oygauei@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
 <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
 <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>
 <20211007142617.3hgjddbbvcowzgc3@lug-owl.de>
 <940617141.46853.1633620047008.JavaMail.zimbra@nod.at>
Message-ID: <20211007174510.tctkyrbvks7vjzjx@lug-owl.de>

On Thu, 2021-10-07 17:20:47 +0200, Richard Weinberger <richard at nod.at> wrote:
> > So ...  The code does _not_ overflow, that's good first of all. It's
> > just a bit confusing how the key bytes are written to the buffer. At
> > least I was easily distracted by the two different sizes.
> 
> If you find a better way to write the function, I'm all open for a patch.
> But please make sure the generated code is sane.

That wouldn't be terribly complicated, but I have no way to actually
*test* that.  It's just an issue I found while doing mass-builds for
all of Linux's defconfigs.  If there's anybody around helping with
testing, I'd happily work on that.

Thanks,
  Jan-Benedict

-- 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211007/973626ea/attachment.sig>

From p.yadav at ti.com  Thu Oct  7 11:00:31 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 7 Oct 2021 23:30:31 +0530
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <YV8kVKiMShWp4g7a@lahna>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com> <YVrSbyEsSLMOu1bU@lahna>
 <20211007123621.ld4aqasr3hlwq2c7@ti.com> <YV8kVKiMShWp4g7a@lahna>
Message-ID: <20211007180029.6agt43vyiwpcgmjz@ti.com>

On 07/10/21 07:46PM, Mika Westerberg wrote:
> Hi,
> 
> On Thu, Oct 07, 2021 at 06:06:23PM +0530, Pratyush Yadav wrote:
> > > Unfortunately there is no way to tell the controller any of these. It
> > > simply does "read" or "write" (as we command it) and internally then
> > > uses whatever it got from the SFDP tables of the flash chip. That's why
> > > we just claim to support all these operations and let the controller do
> > > its thing (whatever it is).
> > 
> > That is not ideal. SPI NOR uses this to negotiate the best available 
> > protocol with the controller. Say you have a flash that is capable of 
> > octal mode but the controller can only support quad mode. Your driver 
> > will happily tell SPI NOR that it can support octal mode. I think you 
> > should check the SPI mode bits to make sure the protocol bus width is 
> > supported at least (see spi_check_buswidth_req() in spi-mem.c).
> 
> Okay, I'll see if I can add that check somewhere.
> 
> > As for opcodes, is there no way to find out what opcodes the controller 
> > discovered via SFDP? Maybe we can't change them, but can we at least 
> > take a peek at them?
> 
> AFAICT no. The controller only allows "higher" level commands like read,
> write, erase but does not expose any of that to software. You can see
> yourself if you want, the spec is here:
>  
>   https://cdrdv2.intel.com/v1/dl/getContent/636174
> 
> Page 403 has the control register.

I do see 4k and 64k erase opcode fields on the BIOS_SFDP1_VSSC1 register 
(page 428), but I am not sure what exactly it is for. Anyway, that 
doesn't really do much for us I think.

> 
> > I think this has problems similar to the Cadence xSPI controller [0].
> 
> Probably but I would not call these "problems" - it is how the
> controller is designed. This one is meant only for SPI-NOR flash access,
> typically used by the BIOS. It is by no means general purpose SPI
> controller (as you can see from the datasheet). The BIOS does need the
> full SPI stack, it just issues these simple commands and let's the
> controller figure out what actually needs to be done.

The problem is not the controller itself. It is perfectly fine piece to 
have a controller like this IMO. The problem is how do we make it fit 
into the SPI MEM model, which seems to be designed for general purpose 
controllers only. This problem is shared with this and the Cadence xSPI 
controller.

> 
> > Sorry I only replied to this after you posted a new version. It got lost 
> > in the heap of emails in my inbox :-(
> 
> No worries :)
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From richard at nod.at  Thu Oct  7 13:48:35 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 7 Oct 2021 22:48:35 +0200 (CEST)
Subject: PING: [PATCH] Don't overflow when writing a key
In-Reply-To: <20211007174510.tctkyrbvks7vjzjx@lug-owl.de>
References: <20211001192836.n6eek7rno7ewvmu7@lug-owl.de>
 <837215091.45041.1633589943979.JavaMail.zimbra@nod.at>
 <1970203009.45154.1633591205445.JavaMail.zimbra@nod.at>
 <20211007135401.4z3gcunwr2uq7fpx@lug-owl.de>
 <135911793.46658.1633616346904.JavaMail.zimbra@nod.at>
 <20211007142617.3hgjddbbvcowzgc3@lug-owl.de>
 <940617141.46853.1633620047008.JavaMail.zimbra@nod.at>
 <20211007174510.tctkyrbvks7vjzjx@lug-owl.de>
Message-ID: <1766448751.48215.1633639715945.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "Jan-Benedict Glaw" <jbglaw at lug-owl.de>
> An: "richard" <richard at nod.at>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "Artem Bityutskiy" <artem.bityutskiy at linux.intel.com>
> Gesendet: Donnerstag, 7. Oktober 2021 19:45:10
> Betreff: Re: PING: [PATCH] Don't overflow when writing a key

> On Thu, 2021-10-07 17:20:47 +0200, Richard Weinberger <richard at nod.at> wrote:
>> > So ...  The code does _not_ overflow, that's good first of all. It's
>> > just a bit confusing how the key bytes are written to the buffer. At
>> > least I was easily distracted by the two different sizes.
>> 
>> If you find a better way to write the function, I'm all open for a patch.
>> But please make sure the generated code is sane.
> 
> That wouldn't be terribly complicated, but I have no way to actually
> *test* that.  It's just an issue I found while doing mass-builds for

You can test it.

$ modprobe nandsim
$ modprobe ubi
$ modprobe ubifs
$ ubiattach -m0
$ ubimkvol -m -N test /dev/ubi0
$ mount -t ubifs /dev/ubi0_0 /mnt

Now you have a shiny ubifs on /mnt. :-)

Thanks,
//richard


From Alexander.Stein at ew.tq-group.com  Fri Oct  8 00:10:46 2021
From: Alexander.Stein at ew.tq-group.com (Alexander Stein)
Date: Fri, 8 Oct 2021 07:10:46 +0000
Subject: AW: (EXT) Re: [PATCH 1/2] dt-bindings: mtd: spi-nor: Add
 output-driver-strength property
Message-ID: <kcEE.RpXtjvjwSXyzkQ19eSpGDg.AB9KnRO81wE@vtuxmail01.tq-net.de>

On Mon, 05 Oct 2021 14:26:28 +0200, Rob Herring wrote:
> From: Rob Herring <robh at kernel.org>
> On Mon, 04 Oct 2021 13:15:28 +0200, Alexander Stein wrote:
> > From: Alexander Stein <alexander.stein at ew.tq-group.com>
> >
> > This property is for optimizing output voltage impedance and is
> > specific to each board.
> >
> > Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> > ---
> > I checked Micron and Macronix datasheets. Both have similar but not
> > identical supported values. Also the register locations are different.
> > For those reasons I decided to specify the Ohms value directly and let
> > the device specfic driver figure out if it is supported where to write
> > it to.
> > BTW: Are the Ohm values and the corresponding register bits standardized
> > somewhere?
> >
> >? Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 6 ++++++
> >? 1 file changed, 6 insertions(+)
> >
>
> Running 'make dtbs_check' with the schema in this patch gives the
> following warnings. Consider if they are expected or the schema is
> incorrect. These may not be new warnings.
>
> Note that it is not yet a requirement to have 0 warnings for dtbs_check.
> This will change in the future.
>
> Full log is available here: https://patchwork.ozlabs.org/patch/1536062

Thanks for pointing that out. I checked the amount of error messages related to
jedec,spi-nor.yaml before and after applying these patches using
> ARCH=arm64 make -j12 dtbs_check DT_SCHEMA_FILES=Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml 2>&1 > /dev/null | wc -l

with all arm64 platforms enabled. There wasn't a change in the line count,
so I assume this new binding didn't cause them.

Best regards,
Alexander



From miquel.raynal at bootlin.com  Fri Oct  8 00:27:48 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 09:27:48 +0200
Subject: [PATCH 1/1] mtd: block2mtd: add support for an optional custom
 MTD label
In-Reply-To: <20211005080359.170360-1-troglobit@gmail.com>
References: <20211005080359.170360-1-troglobit@gmail.com>
Message-ID: <20211008092748.6b47fce6@xps13>

Hi Joachim,

troglobit at gmail.com wrote on Tue,  5 Oct 2021 10:03:59 +0200:

> This patch adds support for an optional MTD label for mtd2block emulated
> MTD devices.  Useful when, e.g. testing device images using Qemu.  The
> following /etc/fstab line in can then be used to mount a file system
> regardless of the actual MTD partition number:
> 
>     mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0
> 
> Kernel command line syntax:
> 
>     block2mtd.block2mtd=/dev/sda,,Config
> 
> The ',,' is the optional erase_size, which like before this patch,
> defaults to PAGE_SIZE when omitted.
> 
> Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
> ---
>  drivers/mtd/devices/block2mtd.c | 26 +++++++++++++++++---------
>  1 file changed, 17 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
> index c08721b11642..9465b8ff48f6 100644
> --- a/drivers/mtd/devices/block2mtd.c
> +++ b/drivers/mtd/devices/block2mtd.c
> @@ -214,7 +214,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
>  
>  
>  static struct block2mtd_dev *add_device(char *devname, int erase_size,
> -		int timeout)
> +		char *label, int timeout)
>  {
>  #ifndef MODULE
>  	int i;
> @@ -278,7 +278,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
>  
>  	/* Setup the MTD structure */
>  	/* make the name contain the block device in */
> -	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
> +	if (!label)
> +		name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
> +	else
> +		name = kstrdup(label, GFP_KERNEL);
>  	if (!name)
>  		goto err_destroy_mutex;
>  
> @@ -304,7 +307,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
>  
>  	list_add(&dev->list, &blkmtd_device_list);
>  	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
> -		dev->mtd.index,
> +		dev->mtd.index, label ? label :

Can you put this on the next line?

>  		dev->mtd.name + strlen("block2mtd: "),
>  		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
>  	return dev;
> @@ -381,8 +384,8 @@ static int block2mtd_setup2(const char *val)
>  	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
>  	char buf[80 + 12 + 80 + 8];
>  	char *str = buf;
> -	char *token[2];
> -	char *name;
> +	char *token[3];

This number deserves a define and should be used later on as well.

> +	char *name, *label = NULL;
>  	size_t erase_size = PAGE_SIZE;
>  	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
>  	int i, ret;
> @@ -395,7 +398,7 @@ static int block2mtd_setup2(const char *val)
>  	strcpy(str, val);
>  	kill_final_newline(str);
>  
> -	for (i = 0; i < 2; i++)
> +	for (i = 0; i < 3; i++)
>  		token[i] = strsep(&str, ",");
>  
>  	if (str) {
> @@ -414,7 +417,7 @@ static int block2mtd_setup2(const char *val)
>  		return 0;
>  	}
>  
> -	if (token[1]) {
> +	if (token[1] && strlen(token[1])) {

This change is not related to your commit I believe, please split if
my assumption is right.

>  		ret = parse_num(&erase_size, token[1]);
>  		if (ret) {
>  			pr_err("illegal erase size\n");
> @@ -422,7 +425,12 @@ static int block2mtd_setup2(const char *val)
>  		}
>  	}
>  
> -	add_device(name, erase_size, timeout);
> +	if (token[2]) {
> +		label = token[2];
> +		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);

Not sure this qualifies as an info log message, perhaps a debug one
would be more appropriate?

> +	}
> +
> +	add_device(name, erase_size, label, timeout);
>  
>  	return 0;
>  }
> @@ -456,7 +464,7 @@ static int block2mtd_setup(const char *val, const struct kernel_param *kp)
>  
>  
>  module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
> -MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
> +MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
>  
>  static int __init block2mtd_init(void)
>  {


Thanks,
Miqu?l


From troglobit at gmail.com  Fri Oct  8 01:26:46 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Fri, 08 Oct 2021 10:26:46 +0200
Subject: [PATCH 1/1] mtd: block2mtd: add support for an optional custom
 MTD label
In-Reply-To: <20211008092748.6b47fce6@xps13>
References: <20211005080359.170360-1-troglobit@gmail.com>
 <20211008092748.6b47fce6@xps13>
Message-ID: <87wnmnrkft.fsf@gmail.com>


Hi Miqu?l!

On Fri, Oct 08, 2021 at 09:27, Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> troglobit at gmail.com wrote on Tue,  5 Oct 2021 10:03:59 +0200:
>> [snip]
>> @@ -304,7 +307,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
>>  
>>  	list_add(&dev->list, &blkmtd_device_list);
>>  	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
>> -		dev->mtd.index,
>> +		dev->mtd.index, label ? label :
> Can you put this on the next line?

Sure thing!

>> @@ -381,8 +384,8 @@ static int block2mtd_setup2(const char *val)
>>  	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
>>  	char buf[80 + 12 + 80 + 8];
>>  	char *str = buf;
>> -	char *token[2];
>> -	char *name;
>> +	char *token[3];
> This number deserves a define and should be used later on as well.

OK, I'll see what I can do, it's for the positional module arguments,
so a FOO_MAX_ARGS or sth, I guess ...

>> @@ -395,7 +398,7 @@ static int block2mtd_setup2(const char *val)
>>  	strcpy(str, val);
>>  	kill_final_newline(str);
>>  
>> -	for (i = 0; i < 2; i++)
>> +	for (i = 0; i < 3; i++)

used here as well ...

>>  		token[i] = strsep(&str, ",");

But what about each separate arg, is there any convention?  I'll see
what I can find in other modules.

>>  	if (str) {
>> @@ -414,7 +417,7 @@ static int block2mtd_setup2(const char *val)
>>  		return 0;
>>  	}
>>  
>> -	if (token[1]) {
>> +	if (token[1] && strlen(token[1])) {
>
> This change is not related to your commit I believe, please split if
> my assumption is right.

Well, it's a logical consequence of adding another module argument, but
you're right, this could be hit before as well if someone added multiple
commas without argument.  (That breaks erase_size default value.)

Maybe this and the defines fit in the same separate "cleanup" patch?

>> -	add_device(name, erase_size, timeout);
>> +	if (token[2]) {
>> +		label = token[2];
>> +		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
> Not sure this qualifies as an info log message, perhaps a debug one
> would be more appropriate?

OK!  (Just tried to follow the same log level used for erase_size.)

Thank you for the review, I'll post a v2 later today, or during the
weekend :)

Cheers
 /Joachim
 


From miquel.raynal at bootlin.com  Fri Oct  8 01:34:40 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 10:34:40 +0200
Subject: [PATCH 1/1] mtd: block2mtd: add support for an optional custom
 MTD label
In-Reply-To: <87wnmnrkft.fsf@gmail.com>
References: <20211005080359.170360-1-troglobit@gmail.com>
 <20211008092748.6b47fce6@xps13> <87wnmnrkft.fsf@gmail.com>
Message-ID: <20211008103440.4bdb4c0e@xps13>

Hi Joachim,

troglobit at gmail.com wrote on Fri, 08 Oct 2021 10:26:46 +0200:

> Hi Miqu?l!
> 
> On Fri, Oct 08, 2021 at 09:27, Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> > troglobit at gmail.com wrote on Tue,  5 Oct 2021 10:03:59 +0200:  
> >> [snip]
> >> @@ -304,7 +307,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
> >>  
> >>  	list_add(&dev->list, &blkmtd_device_list);
> >>  	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
> >> -		dev->mtd.index,
> >> +		dev->mtd.index, label ? label :  
> > Can you put this on the next line?  
> 
> Sure thing!
> 
> >> @@ -381,8 +384,8 @@ static int block2mtd_setup2(const char *val)
> >>  	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
> >>  	char buf[80 + 12 + 80 + 8];
> >>  	char *str = buf;
> >> -	char *token[2];
> >> -	char *name;
> >> +	char *token[3];  
> > This number deserves a define and should be used later on as well.  
> 
> OK, I'll see what I can do, it's for the positional module arguments,
> so a FOO_MAX_ARGS or sth, I guess ...
> 
> >> @@ -395,7 +398,7 @@ static int block2mtd_setup2(const char *val)
> >>  	strcpy(str, val);
> >>  	kill_final_newline(str);
> >>  
> >> -	for (i = 0; i < 2; i++)
> >> +	for (i = 0; i < 3; i++)  
> 
> used here as well ...
> 
> >>  		token[i] = strsep(&str, ",");  
> 
> But what about each separate arg, is there any convention?  I'll see
> what I can find in other modules.
> 
> >>  	if (str) {
> >> @@ -414,7 +417,7 @@ static int block2mtd_setup2(const char *val)
> >>  		return 0;
> >>  	}
> >>  
> >> -	if (token[1]) {
> >> +	if (token[1] && strlen(token[1])) {  
> >
> > This change is not related to your commit I believe, please split if
> > my assumption is right.  
> 
> Well, it's a logical consequence of adding another module argument, but
> you're right, this could be hit before as well if someone added multiple
> commas without argument.  (That breaks erase_size default value.)

In this case you can keep this change in the commit but you need to
explain it in the commit message.

> Maybe this and the defines fit in the same separate "cleanup" patch?
> 
> >> -	add_device(name, erase_size, timeout);
> >> +	if (token[2]) {
> >> +		label = token[2];
> >> +		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);  
> > Not sure this qualifies as an info log message, perhaps a debug one
> > would be more appropriate?  
> 
> OK!  (Just tried to follow the same log level used for erase_size.)

Ok then keep the driver consistent, it's not a bit deal and we can
lower the level later if it's too noisy.

> Thank you for the review, I'll post a v2 later today, or during the
> weekend :)
> 
> Cheers
>  /Joachim
>  


Thanks,
Miqu?l


From mika.westerberg at linux.intel.com  Fri Oct  8 02:02:28 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Fri, 8 Oct 2021 12:02:28 +0300
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211007180029.6agt43vyiwpcgmjz@ti.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com> <YVrSbyEsSLMOu1bU@lahna>
 <20211007123621.ld4aqasr3hlwq2c7@ti.com> <YV8kVKiMShWp4g7a@lahna>
 <20211007180029.6agt43vyiwpcgmjz@ti.com>
Message-ID: <YWAJJLST7KYAD6Fw@lahna>

Hi,

On Thu, Oct 07, 2021 at 11:30:31PM +0530, Pratyush Yadav wrote:
> > Probably but I would not call these "problems" - it is how the
> > controller is designed. This one is meant only for SPI-NOR flash access,
> > typically used by the BIOS. It is by no means general purpose SPI
> > controller (as you can see from the datasheet). The BIOS does need the
> > full SPI stack, it just issues these simple commands and let's the
> > controller figure out what actually needs to be done.
> 
> The problem is not the controller itself. It is perfectly fine piece to 
> have a controller like this IMO. The problem is how do we make it fit 
> into the SPI MEM model, which seems to be designed for general purpose 
> controllers only. This problem is shared with this and the Cadence xSPI 
> controller.

Fully agree. IMHO trying to shoehorn driver like this into a generic SPI
subsystem does not make much sense to me. These things can only talk to
SPI-NOR chips, nothing else.

Do you have any suggestions how to solve this "problem" so we can move
forward with the drivers?


From miquel.raynal at bootlin.com  Fri Oct  8 02:20:45 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 11:20:45 +0200
Subject: [RFC,v1 0/4] Add a driver for Mediatek SPI Nand controller
In-Reply-To: <20210927053629.17847-1-xiangsheng.hou@mediatek.com>
References: <20210927053629.17847-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211008112045.11e8d148@xps13>

Hello,

xiangsheng.hou at mediatek.com wrote on Mon, 27 Sep 2021 13:36:25 +0800:

> Add a driver for Mediatek SPI Nand controller
> 
> Mediatek SPI Nand controller cosists of two parts: on-host HW ECC and
> snfi(stand for spi nand flash interface). They can cowork with high
> performance which called ECC nfi mode. The nfi stand for nand flash
> interfacei(snfi a one part of nfi) which can support SPI Nand flash
> and raw nand flash.
> 
> However, the snfi driver in spi subsytem need to be aware of nand
> parameter(page/spare size) and ecc status(enable/disable) when work
> at ECC nfi mode. The snfi driver in spi subsystem seems difficult to
> know these.
> 
> Therefore, consider two ways to let snfi can get these information.
> The RFC patch send to review whether they are suitable and which
> solution maybe better.
> 
> RFC patch v1:
> Add nfi register base at bch(ecc) dts node and config nand parameter
> and ecc status into nfi registers in ecc driver, then parse these
> information at snfi driver to use.
> 
> RFC patch v2:
> Export some function in HW ECC driver and snfi driver.
> In HW ECC driver, export function include get nand page/spare size, HW
> ECC status(enable/disable) and fdm(oob free per sector in ooblayout) size.
> In snfi driver need export empty page status which the nfi can be aware
> when in ECC nfi mode(the spim framework can not return this information).
> 

I've looked at both versions that you provided and I thought about a
number of things that cannot be done like this:
- I believe the snfi is a regular SPI controller. I will let Mark
  confirm but I do not think we want to start writing SPI-NAND
  controllers. Instead we write SPI controllers and we provide SPI-mem
  operations (we've explained this in a previous ELC, the video is
  available on YouTube).
- You cannot add an MTK ECC algorithm. This is dedicated for sofware
  solutions only and as far as I understand your engine uses the BCH
  algorithm.
- When the ECC engine is pipelined, there is an additional complexity
  in interfacing it with a SPI controller (that's your case I believe).
  I have an example that is not yet upstream but I think worth looking
  at that I will send very soon (I will Cc: you on it).
- The DT description for those engines that has been described on the
  mailing list and will be enforced is:

// External engine

	&spi-controller {
                flash at 0 {
                        compatible = "spi-nand";
                        reg = <0>;
                        nand-ecc-engine = <&ecc_engine>;
                        spi-max-frequency = <50000000>;
                        spi-tx-bus-width = <4>;
                        spi-rx-bus-width = <4>;
                };
        };

        ecc_engine: ecc at 43c40000 {
                compatible = "mxic,nand-ecc-engine-rev3";
                reg = <0x43c40000 0x10000>;
        };
 

// Pipelined engine

	&spi-controller {
               nand-ecc-engine = <&ecc_engine>;
 
                flash at 0 {
                        compatible = "spi-nand";
                        reg = <0>;
                        nand-ecc-engine = <&spi_controller>;
                        spi-max-frequency = <50000000>;
                        spi-tx-bus-width = <4>;
                        spi-rx-bus-width = <4>;
 		};
	};

        ecc_engine: ecc at 43c40000 {
                compatible = "mxic,nand-ecc-engine-rev3";
                reg = <0x43c40000 0x10000>;
        };

Thanks,
Miqu?l


From geert at linux-m68k.org  Fri Oct  8 02:27:03 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 8 Oct 2021 11:27:03 +0200
Subject: [PATCH 4/6] mtd: hyperbus: rpc-if: Check return value of
 rpcif_sw_init()
In-Reply-To: <20210928140721.8805-5-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20210928140721.8805-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20210928140721.8805-5-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdW_X+ji9316DkKP20zgwjn+AzXTXKKJ4nox5XkeiwQQ8w@mail.gmail.com>

On Tue, Sep 28, 2021 at 4:07 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> rpcif_sw_init() can fail so make sure we check the return value
> of it and on error exit rpcif_hb_probe() callback with error code.
>
> Fixes: 5de15b610f78 ("mtd: hyperbus: add Renesas RPC-IF driver")
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From ceggers at arri.de  Fri Oct  8 02:55:56 2021
From: ceggers at arri.de (Christian Eggers)
Date: Fri, 8 Oct 2021 11:55:56 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211004160620.3guajv5vvtfjrl7c@umbrella>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211004173351.36a66ccb@xps13> <20211004160620.3guajv5vvtfjrl7c@umbrella>
Message-ID: <2091909.Mh6RI2rZIc@n95hx1g2>

+ set PHYTEC developers on (B)CC

On Monday, 4 October 2021, 18:06:20 CEST, Han Xu wrote:
> 
> Could you please try to add clock dis/enable when setting clock rate, in case
> clock glitches.
> 
> clk_disable_unprepare(r->clock[0]);
> clk_set_rate(r->clock[0], hw->clk_rate);
> clk_prepare_enable(r->clock[0]);
> 

With this change, we made over 2000 successful reboots without any GPMI DMA
timeout problems!

From PHYTEC (our BSP supplier), I got some possible background for this
problem. For older revisions of IMX6DQ there was an errata (ERR007117, [1])
in the ROM bootloader which triggers a similar / the same behavior:

> For raw NAND boot, ROM switches the source of enfc_clk_root from PLL2_PFD2
> to PLL3. The root clock is required to be gated before switching the source
> clock. If the root clock is not gated, clock glitches might be passed to
> the divider that follows the clock mux, and the divider might behave
> unpredictably.
> ...
> This problem can also occur elsewhere in application code if the root clock
> is not properly gated when the clock configuration is changed.

In my case (Linux boot on i.MX6ULL), I recognized that on the 3rd call of
gpmi_nfc_apply_timings(), the rate of r->clock[0] is changed 

- from: 22 MHz (CS2CDR::ENFC_CLK_PRED=6 and CS2CDR::ENFC_CLK_PODF=3)
- to:  100 MHz (CS2CDR::ENFC_CLK_PRED=4 and CS2CDR::ENFC_CLK_PODF=1)

The proposal from from Han Xu
> clk_disable_unprepare(r->clock[0]);
> clk_set_rate(r->clock[0], hw->clk_rate);
> clk_prepare_enable(r->clock[0]);
disables only CCGR4::CG14 [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE] during
the rate change. While this works very fine on my system, this probably doesn't
fulfill the requirements in the errata description:

> For other occurrences in application code, the following procedure should be
> followed to change the clock configuration for the enfc_clk_root:
> 1) Gate (disable) the GPMI/BCH clocks in register CCM_CCGR4.
> 2) Gate (disable) the enfc_clk_root before changing the enfc_clk_root source
>    or dividers by clearing CCM_CCGR2[CG7] to 2?b00. This disables the
>    iomux_ipt_clk_io_clk.
> 3) Configure CCM_CS2CDR for the new clock source configuration.
> 4) Enable enfc_clk_root by setting CCM_CCGR2[CG7] to 2?b11. This enables the
>    iomux_ipt_clk_io_clk.
> 5) Enable the GPMI/BCH clocks in register CCM_CCGR4

I got another solution from PHYTEC ([2], not lengthy tested yet), which
disables all GPMI/BCH clocks on CCGR4 (verified with a JTAG debugger):
- CCGR4::CG15  [RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE]
- CCGR4::CG14  [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE]
- CCGR4::CG13  [RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE]
- CCGR4::CG12  [RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE]
- CCGR4::CG6   [PL301_MX6QPER1_BCHCLK_ENABLE]

CCM_CCGR2[CG7] is used for IOMUX_IPT_CLK_IO_ENABLE on i.MX6ULL, so step 2.
seems not to apply here. Actually I don't know how to gate ENFC_CLK_ROOT.

I will cyclic test the solution from PHYTEC over the weekend.

@Han Xu: Should I prefer the solution from PHYTEC?
@Stefan Riedmueller: Are you willing to commit this upstream?

regards
Christian


[1] https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf
[2] https://git.phytec.de/linux-mainline/commit/?h=v5.10.48-phy&id=866939ea8110764d9c12af960d746e2f7f5debe3





From sean at geanix.com  Fri Oct  8 03:04:25 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri, 8 Oct 2021 12:04:25 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211007151426.54db0764@collabora.com>
References: <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
 <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
 <20211007151426.54db0764@collabora.com>
Message-ID: <20211008100425.uudzlda2n5ojqjzc@skn-laptop>

On Thu, Oct 07, 2021 at 03:14:26PM +0200, Boris Brezillon wrote:
> On Thu, 7 Oct 2021 14:39:16 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > > 
> > > wait_queue doesn't really describe what this waitqueue is used for
> > > (maybe resume_wq), and the suspended state should be here as well
> > > (actually, there's one already).  
> > 
> > I'll rename to something meaningful.
> > > 
> > > Actually, what we need is a way to prevent the device from being
> > > suspended while accesses are still in progress, and new accesses from
> > > being queued if a suspend is pending. So, I think you need a readwrite
> > > lock here:
> > > 
> > > * take the lock in read mode for all IO accesses, check the
> > >   mtd->suspended value
> > >   - if true, release the lock, and wait (retry on wakeup)
> > >   - if false, just do the IO
> > > 
> > > * take the lock in write mode when you want to suspend/resume the
> > >   device and update the suspended field. Call wake_up_all() in the
> > >   resume path  
> > 
> > Could we use the chip->lock mutex for this? It's does kinda what you
> > described above?
> 
> No you can't. Remember I suggested to move all of that logic to
> mtdcore.c, which doesn't know about the nand_chip struct.
> 
> > If we introduce a new lock, do we really need to have the suspended as
> > an atomic?
> 
> Nope, I thought we could do without a lock, but we actually need to
> track active IO requests, not just the suspended state.

I have only added wait_queue to read and write operations.
I'll have a look into where we should add further checks.

> 
> > 
> > I will test with some wait and retry added to nand_get_device().
> 
> Again, I think there's a misunderstanding here: if you move it to the
> mtd layer, it can't be done in nand_get_device(). But once you've
> implemented it in mtdcore.c, you should be able to get rid of the
> nand_chip->suspended field.

I have moved the suspended atomic and wake_queue to mtdcore.c. And kept
the suspended variable in nand_base as is fine for chip level suspend
status.

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c8fd7f758938..6492071eb4da 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -42,15 +42,24 @@ static int mtd_cls_suspend(struct device *dev)
 {
        struct mtd_info *mtd = dev_get_drvdata(dev);

-       return mtd ? mtd_suspend(mtd) : 0;
+       if (mtd) {
+               atomic_inc(&mtd->suspended);
+               return mtd_suspend(mtd);
+       }
+                                                                                                                                                                                                                                                                                                                                                                                             +       return 0;
 }

 static int mtd_cls_resume(struct device *dev)
 {
        struct mtd_info *mtd = dev_get_drvdata(dev);

-       if (mtd)
+       if (mtd) {
                mtd_resume(mtd);
+               atomic_dec(&mtd->suspended);
+               wake_up_all(&mtd->resume_wq);
+       }
+
        return 0;
 }
@@ -678,6 +687,10 @@ int add_mtd_device(struct mtd_info *mtd)
        if (error)
                goto fail_nvmem_add;

+       init_waitqueue_head(&mtd->resume_wq);
+
+       atomic_set(&mtd->suspended, 0);
+
        mtd_debugfs_populate(mtd);

        device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
@@ -1558,6 +1571,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
        struct mtd_ecc_stats old_stats = master->ecc_stats;
        int ret_code;

+       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
+
        ops->retlen = ops->oobretlen = 0;

        ret_code = mtd_check_oob_ops(mtd, from, ops);
@@ -1597,6 +1612,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
        struct mtd_info *master = mtd_get_master(mtd);
        int ret;

+       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
+
        ops->retlen = ops->oobretlen = 0;

        if (!(mtd->flags & MTD_WRITEABLE))
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..70ede36092a9 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -360,6 +360,9 @@ struct mtd_info {
        int (*_get_device) (struct mtd_info *mtd);
        void (*_put_device) (struct mtd_info *mtd);

+       atomic_t suspended;
+       wait_queue_head_t resume_wq;
+
        /*
         * flag indicates a panic write, low level drivers can take appropriate
         * action if required to ensure writes go through


From p.yadav at ti.com  Fri Oct  8 03:56:48 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 8 Oct 2021 16:26:48 +0530
Subject: [PATCH 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <YWAJJLST7KYAD6Fw@lahna>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-3-mika.westerberg@linux.intel.com>
 <20211004095239.dyowgkyq5lnfdag2@ti.com> <YVrSbyEsSLMOu1bU@lahna>
 <20211007123621.ld4aqasr3hlwq2c7@ti.com> <YV8kVKiMShWp4g7a@lahna>
 <20211007180029.6agt43vyiwpcgmjz@ti.com> <YWAJJLST7KYAD6Fw@lahna>
Message-ID: <20211008105646.ity7isvuum4yyvpj@ti.com>

On 08/10/21 12:02PM, Mika Westerberg wrote:
> Hi,
> 
> On Thu, Oct 07, 2021 at 11:30:31PM +0530, Pratyush Yadav wrote:
> > > Probably but I would not call these "problems" - it is how the
> > > controller is designed. This one is meant only for SPI-NOR flash access,
> > > typically used by the BIOS. It is by no means general purpose SPI
> > > controller (as you can see from the datasheet). The BIOS does need the
> > > full SPI stack, it just issues these simple commands and let's the
> > > controller figure out what actually needs to be done.
> > 
> > The problem is not the controller itself. It is perfectly fine piece to 
> > have a controller like this IMO. The problem is how do we make it fit 
> > into the SPI MEM model, which seems to be designed for general purpose 
> > controllers only. This problem is shared with this and the Cadence xSPI 
> > controller.
> 
> Fully agree. IMHO trying to shoehorn driver like this into a generic SPI
> subsystem does not make much sense to me. These things can only talk to
> SPI-NOR chips, nothing else.
> 
> Do you have any suggestions how to solve this "problem" so we can move
> forward with the drivers?

No, I unfortunately don't. But I suppose the same problem existed with 
the old driver as well. It ignored nor->read_opcode, etc. and did its 
own thing, so at least I don't expect things to get much worse with the 
SPI MEM model.

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From p.yadav at ti.com  Fri Oct  8 04:18:57 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 8 Oct 2021 16:48:57 +0530
Subject: [PATCH 2/2] mtd: spi-nor: micron-st: Add support for
 output-driver-strength
In-Reply-To: <20211004111529.211089-2-Alexander.Stein@tq-systems.com>
References: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
 <20211004111529.211089-2-Alexander.Stein@tq-systems.com>
Message-ID: <20211008111855.rhfs7xpsybcfclmy@ti.com>

Hi Alexander,

On 04/10/21 01:15PM, Alexander Stein wrote:
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> 
> Micron flashes support this by the Bits [2:0] in the Enhanced Volatile
> Configuration Register.
> Checked datasheets:
> - n25q_128mb_3v_65nm.pdf
> - mt25t-qljs-L512-xBA-xxT.pdf

What does changing the impedance do? Does it improve latency? If we use 
suboptimal impedance, will the flash still keep working correctly?

In other words, you need to justify why this patch is needed.

> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
>  drivers/mtd/spi-nor/micron-st.c | 109 ++++++++++++++++++++++++++++++++
>  1 file changed, 109 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index c224e59820a1..5d5e7fbc24a2 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -16,6 +16,11 @@
>  #define SPINOR_MT_OCT_DTR	0xe7	/* Enable Octal DTR. */
>  #define SPINOR_MT_EXSPI		0xff	/* Enable Extended SPI (default) */
>  
> +struct micron_drive_strength {
> +	u32 ohms;
> +	u8 val;
> +};
> +
>  static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor, bool enable)
>  {
>  	struct spi_mem_op op;
> @@ -255,8 +260,112 @@ static void micron_st_default_init(struct spi_nor *nor)
>  	nor->params->set_4byte_addr_mode = st_micron_set_4byte_addr_mode;
>  }
>  
> +
> +/*
> + * Read Micron enhanced volatile configuration register
> + * Return negative if error occurred or configuration register value
> + */
> +static int micron_read_evcr(struct spi_nor *nor)
> +{
> +	int ret;
> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op =
> +			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_EVCR, 1),
> +				   SPI_MEM_OP_NO_ADDR,
> +				   SPI_MEM_OP_NO_DUMMY,
> +				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));

Are you always guaranteed to be in 1S-1S-1S mode during register write?

I would suggest calling spi_nor_spimem_setup_op() before this so that it 
sets up all the buswidths correctly based on nor->reg_proto.

> +
> +		ret = spi_mem_exec_op(nor->spimem, &op);
> +	} else {
> +		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RD_EVCR, nor->bouncebuf, 1);

Split into 2 lines?

> +	}
> +
> +	if (ret < 0) {
> +		dev_err(nor->dev, "error %d reading EVCR\n", ret);
> +		return ret;
> +	}
> +
> +	return nor->bouncebuf[0];
> +}
> +
> +/*
> + * Write Micron enhanced volatile configuration register
> + * Return negative if error occurred or configuration register value
> + */
> +static int micron_write_evcr(struct spi_nor *nor, u8 evcr)
> +{
> +	nor->bouncebuf[0] = evcr;
> +
> +	spi_nor_write_enable(nor);

Check return code.

> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op =
> +			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WD_EVCR, 1),
> +				   SPI_MEM_OP_NO_ADDR,
> +				   SPI_MEM_OP_NO_DUMMY,
> +				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1));

Same as above.

> +
> +		return spi_mem_exec_op(nor->spimem, &op);
> +	}
> +
> +	return nor->controller_ops->write_reg(nor, SPINOR_OP_WD_EVCR, nor->bouncebuf, 1);

Same as above. Split into 2 lines?

> +}
> +
> +/*
> + * Supported values from Enahanced Volatile COnfiguration Register (Bits 2:0)
> + */
> +static const struct micron_drive_strength drive_strength_data[] = {
> +	{ .ohms = 90, .val = 1 },
> +	{ .ohms = 45, .val = 3 },
> +	{ .ohms = 20, .val = 5 },
> +	{ .ohms = 30, .val = 7 },
> +};
> +
> +static struct micron_drive_strength const *micron_st_find_drive_strength_entry(u32 ohms)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(drive_strength_data); i++) {
> +		if (ohms == drive_strength_data[i].ohms)
> +			return &drive_strength_data[i];
> +	}
> +	return NULL;
> +}
> +
> +static void micron_st_post_sfdp(struct spi_nor *nor)
> +{
> +	struct device_node *np = spi_nor_get_flash_node(nor);
> +	u32 ohms;
> +
> +	if (!np)
> +		return;
> +
> +	if (!of_property_read_u32(np, "output-driver-strength", &ohms)) {
> +		struct micron_drive_strength const *entry =
> +			micron_st_find_drive_strength_entry(ohms);
> +
> +		if (entry) {
> +			int evcrr = micron_read_evcr(nor);
> +
> +			if (evcrr >= 0) {

This is a bit confusing. Can you instead do:

if (evcrr < 0)
	return evcrr;

...

> +				u8 evcr = (u8)(evcrr & 0xf8) | entry->val;

Don't use magic numbers. Define a bitmask, preferably using GENMASK().

> +
> +				micron_write_evcr(nor, evcr);

Check return code. Do we need to abort flash probe if this fails, or can 
we live with it, despite the suboptimal impedance?

> +				dev_dbg(nor->dev, "%s: EVCR 0x%x\n", __func__,
> +					(u32)micron_read_evcr(nor));
> +			}
> +		} else {
> +			dev_warn(nor->dev,
> +				"Invalid output-driver-strength property specified: %u",
> +				ohms);
> +		}
> +	}
> +}
> +
>  static const struct spi_nor_fixups micron_st_fixups = {
>  	.default_init = micron_st_default_init,
> +	.post_sfdp = micron_st_post_sfdp,

NACK. Not every Micron flash has the EVCR register. For example, the 
Micron MT35 flash family does not have an EVCR and the output drive 
strength is programmed in a separate register. Set this only for the 
flashes that need this.

>  };
>  
>  const struct spi_nor_manufacturer spi_nor_micron = {
> -- 
> 2.25.1
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From boris.brezillon at collabora.com  Fri Oct  8 04:20:38 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Fri, 8 Oct 2021 13:20:38 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211008100425.uudzlda2n5ojqjzc@skn-laptop>
References: <20211004101246.kagtezizympxupat@skn-laptop>
 <20211004134700.26327f6f@collabora.com>
 <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
 <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
 <20211007151426.54db0764@collabora.com>
 <20211008100425.uudzlda2n5ojqjzc@skn-laptop>
Message-ID: <20211008132038.77231e2a@collabora.com>

Hi Sean,

On Fri, 8 Oct 2021 12:04:25 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Thu, Oct 07, 2021 at 03:14:26PM +0200, Boris Brezillon wrote:
> > On Thu, 7 Oct 2021 14:39:16 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > > 
> > > > wait_queue doesn't really describe what this waitqueue is used for
> > > > (maybe resume_wq), and the suspended state should be here as well
> > > > (actually, there's one already).    
> > > 
> > > I'll rename to something meaningful.  
> > > > 
> > > > Actually, what we need is a way to prevent the device from being
> > > > suspended while accesses are still in progress, and new accesses from
> > > > being queued if a suspend is pending. So, I think you need a readwrite
> > > > lock here:
> > > > 
> > > > * take the lock in read mode for all IO accesses, check the
> > > >   mtd->suspended value
> > > >   - if true, release the lock, and wait (retry on wakeup)
> > > >   - if false, just do the IO
> > > > 
> > > > * take the lock in write mode when you want to suspend/resume the
> > > >   device and update the suspended field. Call wake_up_all() in the
> > > >   resume path    
> > > 
> > > Could we use the chip->lock mutex for this? It's does kinda what you
> > > described above?  
> > 
> > No you can't. Remember I suggested to move all of that logic to
> > mtdcore.c, which doesn't know about the nand_chip struct.
> >   
> > > If we introduce a new lock, do we really need to have the suspended as
> > > an atomic?  
> > 
> > Nope, I thought we could do without a lock, but we actually need to
> > track active IO requests, not just the suspended state.  
> 
> I have only added wait_queue to read and write operations.

It's still racy (see below).

> I'll have a look into where we should add further checks.
> 
> >   
> > > 
> > > I will test with some wait and retry added to nand_get_device().  
> > 
> > Again, I think there's a misunderstanding here: if you move it to the
> > mtd layer, it can't be done in nand_get_device(). But once you've
> > implemented it in mtdcore.c, you should be able to get rid of the
> > nand_chip->suspended field.  
> 
> I have moved the suspended atomic and wake_queue to mtdcore.c.

That doesn't work (see below).

> And kept
> the suspended variable in nand_base as is fine for chip level suspend
> status.

Why? If you handle that at the MTD level you shouldn't need it at the
NAND level? BTW, would you please care to detail your reasoning when
you say you did or didn't do something. It's a bit hard to guess what
led you to this conclusion...

> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c8fd7f758938..6492071eb4da 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -42,15 +42,24 @@ static int mtd_cls_suspend(struct device *dev)
>  {
>         struct mtd_info *mtd = dev_get_drvdata(dev);
> 
> -       return mtd ? mtd_suspend(mtd) : 0;
> +       if (mtd) {
> +               atomic_inc(&mtd->suspended);
> +               return mtd_suspend(mtd);
> +       }
> +                                                                                                                                                                                                                                                                                                                                                                                             +       return 0;
>  }
> 
>  static int mtd_cls_resume(struct device *dev)
>  {
>         struct mtd_info *mtd = dev_get_drvdata(dev);
> 
> -       if (mtd)
> +       if (mtd) {
>                 mtd_resume(mtd);
> +               atomic_dec(&mtd->suspended);
> +               wake_up_all(&mtd->resume_wq);
> +       }
> +
>         return 0;
>  }
> @@ -678,6 +687,10 @@ int add_mtd_device(struct mtd_info *mtd)
>         if (error)
>                 goto fail_nvmem_add;
> 
> +       init_waitqueue_head(&mtd->resume_wq);
> +
> +       atomic_set(&mtd->suspended, 0);
> +
>         mtd_debugfs_populate(mtd);
> 
>         device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
> @@ -1558,6 +1571,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>         struct mtd_ecc_stats old_stats = master->ecc_stats;
>         int ret_code;
> 
> +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);

That's racy:

thread A			thread B
			   |
enters mtd_read()	   |
passes the !suspended test |
			   |	enters mtd_suspend()
			   |	sets suspended to 1
			   |
starts the IO		   |
			   |	suspends the device
tries to finish the IO	   |
on a suspended device	   |

			 BOOM!


Using an atomic doesn't solve any of that, you really need to make sure
nothing tries to communicate with the device while you're suspending
it, hence the suggestion to use a rw_semaphore to protect against that.

> +
>         ops->retlen = ops->oobretlen = 0;
> 
>         ret_code = mtd_check_oob_ops(mtd, from, ops);
> @@ -1597,6 +1612,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>         struct mtd_info *master = mtd_get_master(mtd);
>         int ret;
> 
> +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
> +

Please don't open-code this in every IO path, add helpers hiding all the
complexity.

To sum-up, that's more or less what I add in mind:

static void mtd_start_access(struct mtd_info *mtd)
{
	/*
	 * Don't take the suspend_lock on devices that don't
	 * implement the suspend hook. Otherwise, lockdep will
	 * complain about nested locks when trying to suspend MTD
	 * partitions or MTD devices created by gluebi which are
	 * backed by real devices.
	 */
	if (!mtd->_suspend)
		return;

	/*
	 * Wait until the device is resumed. Should we have a
	 * non-blocking mode here?
	 */
	while (1) {
		down_read(&mtd->suspend_lock);
		if (!mtd->suspended)
			return;

		up_read(&mtd->suspend_lock);
		wait_event(mtd->resume_wq, mtd->suspended == false);
	}
}

static void mtd_end_access(struct mtd_info *mtd)
{
	if (!mtd->_suspend)
		return;

	up_read(&mtd->suspend_lock);
}

static void mtd_suspend(struct mtd_info *mtd)
{
	int ret;

	if (!mtd->_suspend)
		return;

	down_write(&mtd->suspend_lock);
	if (mtd->suspended == false) {
		ret = mtd->_suspend(mtd);
		if (!ret)
			mtd->suspended = true;
	}
	up_write(&mtd->suspend_lock);
}

static void mtd_resume(struct mtd_info *mtd)
{
	if (!mtd->_suspend)
		return;

	down_write(&mtd->suspend_lock);
	if (mtd->suspended) {
		if (mtd->_resume)
			mtd->_resume(mtd);

		mtd->suspended = false;

		/* The MTD dev has been resumed, wake up all waiters. */
		wake_up_all(&mtd->resume_wq)
	}
	up_write(&mtd->suspend_lock);
}

You then need to call mtd_{start,end}_access() in all MTD IO path
(read/write/erase and maybe others too).

Regards,

Boris


From sean at geanix.com  Fri Oct  8 04:54:13 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri, 8 Oct 2021 13:54:13 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211008132038.77231e2a@collabora.com>
References: <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
 <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
 <20211007151426.54db0764@collabora.com>
 <20211008100425.uudzlda2n5ojqjzc@skn-laptop>
 <20211008132038.77231e2a@collabora.com>
Message-ID: <20211008115413.cbkdxv3mpmmkyvjx@skn-laptop>

On Fri, Oct 08, 2021 at 01:20:38PM +0200, Boris Brezillon wrote:
> Hi Sean,
> 
> On Fri, 8 Oct 2021 12:04:25 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Thu, Oct 07, 2021 at 03:14:26PM +0200, Boris Brezillon wrote:
> > > On Thu, 7 Oct 2021 14:39:16 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:
> > >   
> > > > > 
> > > > > wait_queue doesn't really describe what this waitqueue is used for
> > > > > (maybe resume_wq), and the suspended state should be here as well
> > > > > (actually, there's one already).    
> > > > 
> > > > I'll rename to something meaningful.  
> > > > > 
> > > > > Actually, what we need is a way to prevent the device from being
> > > > > suspended while accesses are still in progress, and new accesses from
> > > > > being queued if a suspend is pending. So, I think you need a readwrite
> > > > > lock here:
> > > > > 
> > > > > * take the lock in read mode for all IO accesses, check the
> > > > >   mtd->suspended value
> > > > >   - if true, release the lock, and wait (retry on wakeup)
> > > > >   - if false, just do the IO
> > > > > 
> > > > > * take the lock in write mode when you want to suspend/resume the
> > > > >   device and update the suspended field. Call wake_up_all() in the
> > > > >   resume path    
> > > > 
> > > > Could we use the chip->lock mutex for this? It's does kinda what you
> > > > described above?  
> > > 
> > > No you can't. Remember I suggested to move all of that logic to
> > > mtdcore.c, which doesn't know about the nand_chip struct.
> > >   
> > > > If we introduce a new lock, do we really need to have the suspended as
> > > > an atomic?  
> > > 
> > > Nope, I thought we could do without a lock, but we actually need to
> > > track active IO requests, not just the suspended state.  
> > 
> > I have only added wait_queue to read and write operations.
> 
> It's still racy (see below).
> 
> > I'll have a look into where we should add further checks.
> > 
> > >   
> > > > 
> > > > I will test with some wait and retry added to nand_get_device().  
> > > 
> > > Again, I think there's a misunderstanding here: if you move it to the
> > > mtd layer, it can't be done in nand_get_device(). But once you've
> > > implemented it in mtdcore.c, you should be able to get rid of the
> > > nand_chip->suspended field.  
> > 
> > I have moved the suspended atomic and wake_queue to mtdcore.c.
> 
> That doesn't work (see below).
> 
> > And kept
> > the suspended variable in nand_base as is fine for chip level suspend
> > status.
> 
> Why? If you handle that at the MTD level you shouldn't need it at the
> NAND level? BTW, would you please care to detail your reasoning when
> you say you did or didn't do something. It's a bit hard to guess what
> led you to this conclusion...
> 
> > 
> > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > index c8fd7f758938..6492071eb4da 100644
> > --- a/drivers/mtd/mtdcore.c
> > +++ b/drivers/mtd/mtdcore.c
> > @@ -42,15 +42,24 @@ static int mtd_cls_suspend(struct device *dev)
> >  {
> >         struct mtd_info *mtd = dev_get_drvdata(dev);
> > 
> > -       return mtd ? mtd_suspend(mtd) : 0;
> > +       if (mtd) {
> > +               atomic_inc(&mtd->suspended);
> > +               return mtd_suspend(mtd);
> > +       }
> > +                                                                                                                                                                                                                                                                                                                                                                                             +       return 0;
> >  }
> > 
> >  static int mtd_cls_resume(struct device *dev)
> >  {
> >         struct mtd_info *mtd = dev_get_drvdata(dev);
> > 
> > -       if (mtd)
> > +       if (mtd) {
> >                 mtd_resume(mtd);
> > +               atomic_dec(&mtd->suspended);
> > +               wake_up_all(&mtd->resume_wq);
> > +       }
> > +
> >         return 0;
> >  }
> > @@ -678,6 +687,10 @@ int add_mtd_device(struct mtd_info *mtd)
> >         if (error)
> >                 goto fail_nvmem_add;
> > 
> > +       init_waitqueue_head(&mtd->resume_wq);
> > +
> > +       atomic_set(&mtd->suspended, 0);
> > +
> >         mtd_debugfs_populate(mtd);
> > 
> >         device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
> > @@ -1558,6 +1571,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
> >         struct mtd_ecc_stats old_stats = master->ecc_stats;
> >         int ret_code;
> > 
> > +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
> 
> That's racy:
> 
> thread A			thread B
> 			   |
> enters mtd_read()	   |
> passes the !suspended test |
> 			   |	enters mtd_suspend()
> 			   |	sets suspended to 1
> 			   |
> starts the IO		   |
> 			   |	suspends the device
> tries to finish the IO	   |
> on a suspended device	   |
> 
> 			 BOOM!
> 
> 
> Using an atomic doesn't solve any of that, you really need to make sure
> nothing tries to communicate with the device while you're suspending
> it, hence the suggestion to use a rw_semaphore to protect against that.
> 
> > +
> >         ops->retlen = ops->oobretlen = 0;
> > 
> >         ret_code = mtd_check_oob_ops(mtd, from, ops);
> > @@ -1597,6 +1612,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
> >         struct mtd_info *master = mtd_get_master(mtd);
> >         int ret;
> > 
> > +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
> > +
> 
> Please don't open-code this in every IO path, add helpers hiding all the
> complexity.
> 
> To sum-up, that's more or less what I add in mind:
> 
> static void mtd_start_access(struct mtd_info *mtd)
> {
> 	/*
> 	 * Don't take the suspend_lock on devices that don't
> 	 * implement the suspend hook. Otherwise, lockdep will
> 	 * complain about nested locks when trying to suspend MTD
> 	 * partitions or MTD devices created by gluebi which are
> 	 * backed by real devices.
> 	 */
> 	if (!mtd->_suspend)
> 		return;
> 
> 	/*
> 	 * Wait until the device is resumed. Should we have a
> 	 * non-blocking mode here?
> 	 */
> 	while (1) {
> 		down_read(&mtd->suspend_lock);
> 		if (!mtd->suspended)
> 			return;
> 
> 		up_read(&mtd->suspend_lock);
> 		wait_event(mtd->resume_wq, mtd->suspended == false);
> 	}
> }
> 
> static void mtd_end_access(struct mtd_info *mtd)
> {
> 	if (!mtd->_suspend)
> 		return;
> 
> 	up_read(&mtd->suspend_lock);
> }
> 
> static void mtd_suspend(struct mtd_info *mtd)
> {
> 	int ret;
> 
> 	if (!mtd->_suspend)
> 		return;
> 
> 	down_write(&mtd->suspend_lock);
> 	if (mtd->suspended == false) {
> 		ret = mtd->_suspend(mtd);
> 		if (!ret)
> 			mtd->suspended = true;
> 	}
> 	up_write(&mtd->suspend_lock);
> }
> 
> static void mtd_resume(struct mtd_info *mtd)
> {
> 	if (!mtd->_suspend)
> 		return;
> 
> 	down_write(&mtd->suspend_lock);
> 	if (mtd->suspended) {
> 		if (mtd->_resume)
> 			mtd->_resume(mtd);
> 
> 		mtd->suspended = false;
> 
> 		/* The MTD dev has been resumed, wake up all waiters. */
> 		wake_up_all(&mtd->resume_wq)
> 	}
> 	up_write(&mtd->suspend_lock);
> }
> 
> You then need to call mtd_{start,end}_access() in all MTD IO path
> (read/write/erase and maybe others too).

Looks cool.

But you are introducing a new lock that basically does the
same as chip->lock in nand_base.c one level above ;)
You wrote that we didn't want to introduce a new lock :)

I will this code...


From S.Riedmueller at phytec.de  Fri Oct  8 05:08:01 2021
From: S.Riedmueller at phytec.de (=?utf-8?B?U3RlZmFuIFJpZWRtw7xsbGVy?=)
Date: Fri, 8 Oct 2021 12:08:01 +0000
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <2091909.Mh6RI2rZIc@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211004173351.36a66ccb@xps13> <20211004160620.3guajv5vvtfjrl7c@umbrella>
 <2091909.Mh6RI2rZIc@n95hx1g2>
Message-ID: <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>

Hi Christian,

On Fri, 2021-10-08 at 11:55 +0200, Christian Eggers wrote:
> + set PHYTEC developers on (B)CC
> 
> On Monday, 4 October 2021, 18:06:20 CEST, Han Xu wrote:
> > Could you please try to add clock dis/enable when setting clock rate, in
> > case
> > clock glitches.
> > 
> > clk_disable_unprepare(r->clock[0]);
> > clk_set_rate(r->clock[0], hw->clk_rate);
> > clk_prepare_enable(r->clock[0]);
> > 
> 
> With this change, we made over 2000 successful reboots without any GPMI DMA
> timeout problems!
> 
> From PHYTEC (our BSP supplier), I got some possible background for this
> problem. For older revisions of IMX6DQ there was an errata (ERR007117, [1])
> in the ROM bootloader which triggers a similar / the same behavior:
> 
> > For raw NAND boot, ROM switches the source of enfc_clk_root from PLL2_PFD2
> > to PLL3. The root clock is required to be gated before switching the
> > source
> > clock. If the root clock is not gated, clock glitches might be passed to
> > the divider that follows the clock mux, and the divider might behave
> > unpredictably.
> > ...
> > This problem can also occur elsewhere in application code if the root
> > clock
> > is not properly gated when the clock configuration is changed.
> 
> In my case (Linux boot on i.MX6ULL), I recognized that on the 3rd call of
> gpmi_nfc_apply_timings(), the rate of r->clock[0] is changed 
> 
> - from: 22 MHz (CS2CDR::ENFC_CLK_PRED=6 and CS2CDR::ENFC_CLK_PODF=3)
> - to:  100 MHz (CS2CDR::ENFC_CLK_PRED=4 and CS2CDR::ENFC_CLK_PODF=1)
> 
> The proposal from from Han Xu
> > clk_disable_unprepare(r->clock[0]);
> > clk_set_rate(r->clock[0], hw->clk_rate);
> > clk_prepare_enable(r->clock[0]);
> disables only CCGR4::CG14 [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE]
> during
> the rate change. While this works very fine on my system, this probably
> doesn't
> fulfill the requirements in the errata description:
> 
> > For other occurrences in application code, the following procedure should
> > be
> > followed to change the clock configuration for the enfc_clk_root:
> > 1) Gate (disable) the GPMI/BCH clocks in register CCM_CCGR4.
> > 2) Gate (disable) the enfc_clk_root before changing the enfc_clk_root
> > source
> >    or dividers by clearing CCM_CCGR2[CG7] to 2?b00. This disables the
> >    iomux_ipt_clk_io_clk.
> > 3) Configure CCM_CS2CDR for the new clock source configuration.
> > 4) Enable enfc_clk_root by setting CCM_CCGR2[CG7] to 2?b11. This enables
> > the
> >    iomux_ipt_clk_io_clk.
> > 5) Enable the GPMI/BCH clocks in register CCM_CCGR4
> 
> I got another solution from PHYTEC ([2], not lengthy tested yet), which
> disables all GPMI/BCH clocks on CCGR4 (verified with a JTAG debugger):
> - CCGR4::CG15  [RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE]
> - CCGR4::CG14  [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE]
> - CCGR4::CG13  [RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE]
> - CCGR4::CG12  [RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE]
> - CCGR4::CG6   [PL301_MX6QPER1_BCHCLK_ENABLE]
> 
> CCM_CCGR2[CG7] is used for IOMUX_IPT_CLK_IO_ENABLE on i.MX6ULL, so step 2.
> seems not to apply here. Actually I don't know how to gate ENFC_CLK_ROOT.
> 
> I will cyclic test the solution from PHYTEC over the weekend.
> 
> @Han Xu: Should I prefer the solution from PHYTEC?
> @Stefan Riedmueller: Are you willing to commit this upstream?

Yes sure, I can prepare a patch beginning of next week.
BTW, we have seen these DMA timeout issues on the i.MX6 SOCs as well. So this
fix is not only for the i.MX 6ULL.

Regards,
Stefan

> 
> regards
> Christian
> 
> 
> [1] https://www.nxp.com/docs/en/errata/IMX6DQCE.pdf
> [2] 
> https://git.phytec.de/linux-mainline/commit/?h=v5.10.48-phy&id=866939ea8110764d9c12af960d746e2f7f5debe3
> 
> 
> 

From boris.brezillon at collabora.com  Fri Oct  8 05:15:24 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Fri, 8 Oct 2021 14:15:24 +0200
Subject: [RFC PATCH] mtd: rawnand: use mutex to protect access while in
 suspend
In-Reply-To: <20211008115413.cbkdxv3mpmmkyvjx@skn-laptop>
References: <20211005070930.epgxb5qzumk4awxq@skn-laptop>
 <20211005102300.5da6d480@collabora.com>
 <20211005084938.jcbw24umhehoiirs@skn-laptop>
 <20211005105836.6c300f25@collabora.com>
 <20211007114351.3nafhtpefezxhanc@skn-laptop>
 <20211007141858.314533f2@collabora.com>
 <20211007123916.w4oaooxfbawe6yw3@skn-laptop>
 <20211007151426.54db0764@collabora.com>
 <20211008100425.uudzlda2n5ojqjzc@skn-laptop>
 <20211008132038.77231e2a@collabora.com>
 <20211008115413.cbkdxv3mpmmkyvjx@skn-laptop>
Message-ID: <20211008141524.20ca8219@collabora.com>

On Fri, 8 Oct 2021 13:54:13 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Fri, Oct 08, 2021 at 01:20:38PM +0200, Boris Brezillon wrote:
> > Hi Sean,
> > 
> > On Fri, 8 Oct 2021 12:04:25 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > On Thu, Oct 07, 2021 at 03:14:26PM +0200, Boris Brezillon wrote:  
> > > > On Thu, 7 Oct 2021 14:39:16 +0200
> > > > Sean Nyekjaer <sean at geanix.com> wrote:
> > > >     
> > > > > > 
> > > > > > wait_queue doesn't really describe what this waitqueue is used for
> > > > > > (maybe resume_wq), and the suspended state should be here as well
> > > > > > (actually, there's one already).      
> > > > > 
> > > > > I'll rename to something meaningful.    
> > > > > > 
> > > > > > Actually, what we need is a way to prevent the device from being
> > > > > > suspended while accesses are still in progress, and new accesses from
> > > > > > being queued if a suspend is pending. So, I think you need a readwrite
> > > > > > lock here:
> > > > > > 
> > > > > > * take the lock in read mode for all IO accesses, check the
> > > > > >   mtd->suspended value
> > > > > >   - if true, release the lock, and wait (retry on wakeup)
> > > > > >   - if false, just do the IO
> > > > > > 
> > > > > > * take the lock in write mode when you want to suspend/resume the
> > > > > >   device and update the suspended field. Call wake_up_all() in the
> > > > > >   resume path      
> > > > > 
> > > > > Could we use the chip->lock mutex for this? It's does kinda what you
> > > > > described above?    
> > > > 
> > > > No you can't. Remember I suggested to move all of that logic to
> > > > mtdcore.c, which doesn't know about the nand_chip struct.
> > > >     
> > > > > If we introduce a new lock, do we really need to have the suspended as
> > > > > an atomic?    
> > > > 
> > > > Nope, I thought we could do without a lock, but we actually need to
> > > > track active IO requests, not just the suspended state.    
> > > 
> > > I have only added wait_queue to read and write operations.  
> > 
> > It's still racy (see below).
> >   
> > > I'll have a look into where we should add further checks.
> > >   
> > > >     
> > > > > 
> > > > > I will test with some wait and retry added to nand_get_device().    
> > > > 
> > > > Again, I think there's a misunderstanding here: if you move it to the
> > > > mtd layer, it can't be done in nand_get_device(). But once you've
> > > > implemented it in mtdcore.c, you should be able to get rid of the
> > > > nand_chip->suspended field.    
> > > 
> > > I have moved the suspended atomic and wake_queue to mtdcore.c.  
> > 
> > That doesn't work (see below).
> >   
> > > And kept
> > > the suspended variable in nand_base as is fine for chip level suspend
> > > status.  
> > 
> > Why? If you handle that at the MTD level you shouldn't need it at the
> > NAND level? BTW, would you please care to detail your reasoning when
> > you say you did or didn't do something. It's a bit hard to guess what
> > led you to this conclusion...
> >   
> > > 
> > > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > > index c8fd7f758938..6492071eb4da 100644
> > > --- a/drivers/mtd/mtdcore.c
> > > +++ b/drivers/mtd/mtdcore.c
> > > @@ -42,15 +42,24 @@ static int mtd_cls_suspend(struct device *dev)
> > >  {
> > >         struct mtd_info *mtd = dev_get_drvdata(dev);
> > > 
> > > -       return mtd ? mtd_suspend(mtd) : 0;
> > > +       if (mtd) {
> > > +               atomic_inc(&mtd->suspended);
> > > +               return mtd_suspend(mtd);
> > > +       }
> > > +                                                                                                                                                                                                                                                                                                                                                                                             +       return 0;
> > >  }
> > > 
> > >  static int mtd_cls_resume(struct device *dev)
> > >  {
> > >         struct mtd_info *mtd = dev_get_drvdata(dev);
> > > 
> > > -       if (mtd)
> > > +       if (mtd) {
> > >                 mtd_resume(mtd);
> > > +               atomic_dec(&mtd->suspended);
> > > +               wake_up_all(&mtd->resume_wq);
> > > +       }
> > > +
> > >         return 0;
> > >  }
> > > @@ -678,6 +687,10 @@ int add_mtd_device(struct mtd_info *mtd)
> > >         if (error)
> > >                 goto fail_nvmem_add;
> > > 
> > > +       init_waitqueue_head(&mtd->resume_wq);
> > > +
> > > +       atomic_set(&mtd->suspended, 0);
> > > +
> > >         mtd_debugfs_populate(mtd);
> > > 
> > >         device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
> > > @@ -1558,6 +1571,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
> > >         struct mtd_ecc_stats old_stats = master->ecc_stats;
> > >         int ret_code;
> > > 
> > > +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);  
> > 
> > That's racy:
> > 
> > thread A			thread B
> > 			   |
> > enters mtd_read()	   |
> > passes the !suspended test |
> > 			   |	enters mtd_suspend()
> > 			   |	sets suspended to 1
> > 			   |
> > starts the IO		   |
> > 			   |	suspends the device
> > tries to finish the IO	   |
> > on a suspended device	   |
> > 
> > 			 BOOM!
> > 
> > 
> > Using an atomic doesn't solve any of that, you really need to make sure
> > nothing tries to communicate with the device while you're suspending
> > it, hence the suggestion to use a rw_semaphore to protect against that.
> >   
> > > +
> > >         ops->retlen = ops->oobretlen = 0;
> > > 
> > >         ret_code = mtd_check_oob_ops(mtd, from, ops);
> > > @@ -1597,6 +1612,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
> > >         struct mtd_info *master = mtd_get_master(mtd);
> > >         int ret;
> > > 
> > > +       wait_event(mtd->resume_wq, atomic_read(&mtd->suspended) == 0);
> > > +  
> > 
> > Please don't open-code this in every IO path, add helpers hiding all the
> > complexity.
> > 
> > To sum-up, that's more or less what I add in mind:
> > 
> > static void mtd_start_access(struct mtd_info *mtd)
> > {
> > 	/*
> > 	 * Don't take the suspend_lock on devices that don't
> > 	 * implement the suspend hook. Otherwise, lockdep will
> > 	 * complain about nested locks when trying to suspend MTD
> > 	 * partitions or MTD devices created by gluebi which are
> > 	 * backed by real devices.
> > 	 */
> > 	if (!mtd->_suspend)
> > 		return;
> > 
> > 	/*
> > 	 * Wait until the device is resumed. Should we have a
> > 	 * non-blocking mode here?
> > 	 */
> > 	while (1) {
> > 		down_read(&mtd->suspend_lock);
> > 		if (!mtd->suspended)
> > 			return;
> > 
> > 		up_read(&mtd->suspend_lock);
> > 		wait_event(mtd->resume_wq, mtd->suspended == false);
> > 	}
> > }
> > 
> > static void mtd_end_access(struct mtd_info *mtd)
> > {
> > 	if (!mtd->_suspend)
> > 		return;
> > 
> > 	up_read(&mtd->suspend_lock);
> > }
> > 
> > static void mtd_suspend(struct mtd_info *mtd)
> > {
> > 	int ret;
> > 
> > 	if (!mtd->_suspend)
> > 		return;
> > 
> > 	down_write(&mtd->suspend_lock);
> > 	if (mtd->suspended == false) {
> > 		ret = mtd->_suspend(mtd);
> > 		if (!ret)
> > 			mtd->suspended = true;
> > 	}
> > 	up_write(&mtd->suspend_lock);
> > }
> > 
> > static void mtd_resume(struct mtd_info *mtd)
> > {
> > 	if (!mtd->_suspend)
> > 		return;
> > 
> > 	down_write(&mtd->suspend_lock);
> > 	if (mtd->suspended) {
> > 		if (mtd->_resume)
> > 			mtd->_resume(mtd);
> > 
> > 		mtd->suspended = false;
> > 
> > 		/* The MTD dev has been resumed, wake up all waiters. */
> > 		wake_up_all(&mtd->resume_wq)
> > 	}
> > 	up_write(&mtd->suspend_lock);
> > }
> > 
> > You then need to call mtd_{start,end}_access() in all MTD IO path
> > (read/write/erase and maybe others too).  
> 
> Looks cool.
> 
> But you are introducing a new lock that basically does the
> same as chip->lock in nand_base.c one level above ;)

It doesn't serve the same purpose, no. This one is making sure suspend
can't happen while IOs are in-flight, and IOs can't happen while the
device is being suspended. The nand_chip->lock serializes all IO going
through a chip (the new mtd->suspend_lock doesn't guarantee that). This
being said, once you have this, you should be able to get rid of the
nand_chip->suspended field.

> You wrote that we didn't want to introduce a new lock :)

Again, that's not what I said. I said using a lock to wait on devices
going out of suspend was a bad idea, because then the lock is held when
you enter suspend, and only released when the device gets resumed.
That's quite a big/unbounded critical section, and we try to
avoid that in general (ideally locks should be taken/released in the
same function). What I do here is quite different, see how the
mtd->suspend_lock is released before calling wait_event().


From miquel.raynal at bootlin.com  Fri Oct  8 05:27:24 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 14:27:24 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211004173351.36a66ccb@xps13>
 <20211004160620.3guajv5vvtfjrl7c@umbrella>
 <2091909.Mh6RI2rZIc@n95hx1g2>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
Message-ID: <20211008142724.7fbeed6a@xps13>

Hello,

S.Riedmueller at phytec.de wrote on Fri, 8 Oct 2021 12:08:01 +0000:

> Hi Christian,
> 
> On Fri, 2021-10-08 at 11:55 +0200, Christian Eggers wrote:
> > + set PHYTEC developers on (B)CC
> > 
> > On Monday, 4 October 2021, 18:06:20 CEST, Han Xu wrote:  
> > > Could you please try to add clock dis/enable when setting clock rate, in
> > > case
> > > clock glitches.
> > > 
> > > clk_disable_unprepare(r->clock[0]);
> > > clk_set_rate(r->clock[0], hw->clk_rate);
> > > clk_prepare_enable(r->clock[0]);
> > >   
> > 
> > With this change, we made over 2000 successful reboots without any GPMI DMA
> > timeout problems!
> > 
> > From PHYTEC (our BSP supplier), I got some possible background for this
> > problem. For older revisions of IMX6DQ there was an errata (ERR007117, [1])
> > in the ROM bootloader which triggers a similar / the same behavior:
> >   
> > > For raw NAND boot, ROM switches the source of enfc_clk_root from PLL2_PFD2
> > > to PLL3. The root clock is required to be gated before switching the
> > > source
> > > clock. If the root clock is not gated, clock glitches might be passed to
> > > the divider that follows the clock mux, and the divider might behave
> > > unpredictably.
> > > ...
> > > This problem can also occur elsewhere in application code if the root
> > > clock
> > > is not properly gated when the clock configuration is changed.  
> > 
> > In my case (Linux boot on i.MX6ULL), I recognized that on the 3rd call of
> > gpmi_nfc_apply_timings(), the rate of r->clock[0] is changed 
> > 
> > - from: 22 MHz (CS2CDR::ENFC_CLK_PRED=6 and CS2CDR::ENFC_CLK_PODF=3)
> > - to:  100 MHz (CS2CDR::ENFC_CLK_PRED=4 and CS2CDR::ENFC_CLK_PODF=1)
> > 
> > The proposal from from Han Xu  
> > > clk_disable_unprepare(r->clock[0]);
> > > clk_set_rate(r->clock[0], hw->clk_rate);
> > > clk_prepare_enable(r->clock[0]);  
> > disables only CCGR4::CG14 [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE]
> > during
> > the rate change. While this works very fine on my system, this probably
> > doesn't
> > fulfill the requirements in the errata description:
> >   
> > > For other occurrences in application code, the following procedure should
> > > be
> > > followed to change the clock configuration for the enfc_clk_root:
> > > 1) Gate (disable) the GPMI/BCH clocks in register CCM_CCGR4.
> > > 2) Gate (disable) the enfc_clk_root before changing the enfc_clk_root
> > > source
> > >    or dividers by clearing CCM_CCGR2[CG7] to 2?b00. This disables the
> > >    iomux_ipt_clk_io_clk.
> > > 3) Configure CCM_CS2CDR for the new clock source configuration.
> > > 4) Enable enfc_clk_root by setting CCM_CCGR2[CG7] to 2?b11. This enables
> > > the
> > >    iomux_ipt_clk_io_clk.
> > > 5) Enable the GPMI/BCH clocks in register CCM_CCGR4  
> > 
> > I got another solution from PHYTEC ([2], not lengthy tested yet), which
> > disables all GPMI/BCH clocks on CCGR4 (verified with a JTAG debugger):
> > - CCGR4::CG15  [RAWNAND_U_GPMI_INPUT_APB_CLK_ENABLE]
> > - CCGR4::CG14  [RAWNAND_U_GPMI_BCH_INPUT_GPMI_IO_CLK_ENABLE]
> > - CCGR4::CG13  [RAWNAND_U_GPMI_BCH_INPUT_BCH_CLK_ENABLE]
> > - CCGR4::CG12  [RAWNAND_U_BCH_INPUT_APB_CLK_ENABLE]
> > - CCGR4::CG6   [PL301_MX6QPER1_BCHCLK_ENABLE]
> > 
> > CCM_CCGR2[CG7] is used for IOMUX_IPT_CLK_IO_ENABLE on i.MX6ULL, so step 2.
> > seems not to apply here. Actually I don't know how to gate ENFC_CLK_ROOT.
> > 
> > I will cyclic test the solution from PHYTEC over the weekend.
> > 
> > @Han Xu: Should I prefer the solution from PHYTEC?
> > @Stefan Riedmueller: Are you willing to commit this upstream?  
> 
> Yes sure, I can prepare a patch beginning of next week.
> BTW, we have seen these DMA timeout issues on the i.MX6 SOCs as well. So this
> fix is not only for the i.MX 6ULL.

Could it be possible to quantify the extra time spent in
disabling/re-enabling clocks just for the record? So far this driver
only supports a single chip and thus frequency changes do not happen
frequently (a couple times at boot) but if someday we introduce support
for several chips it might become very impacting. 

Thanks,
Miqu?l


From ceggers at arri.de  Fri Oct  8 06:11:59 2021
From: ceggers at arri.de (Christian Eggers)
Date: Fri, 8 Oct 2021 15:11:59 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008142724.7fbeed6a@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
 <20211008142724.7fbeed6a@xps13>
Message-ID: <13290228.RDIVbhacDa@n95hx1g2>

On Friday, 8 October 2021, 11:55:56 CEST, Christian Eggers wrote:

> I got another solution from PHYTEC ([2], not lengthy tested yet), which
> disables all GPMI/BCH clocks on CCGR4

> -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> 
>  {
>  
>  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
>  	struct resources *r = &this->resources;
>  	void __iomem *gpmi_regs = r->gpmi_regs;
>  	unsigned int dll_wait_time_us;
> 
> +	int ret;
> 
> +	ret = __gpmi_enable_clk(this, false);
> +	if (ret)
> +		return ret;
> 
>  	clk_set_rate(r->clock[0], hw->clk_rate);
> 
> +	ret = __gpmi_enable_clk(this, true);
> +	if (ret)
> +		return ret;
> 
>  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
>  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);


I think that this is also required for the first call to clk_set_rate() in
gpmi_get_clks(). From the kernel's point of view, the clocks are not enabled
yet, so no "guard" is required. Putting the same guard here will actually give
a warning at runtime that I am trying to disable a clock which is not enabled.
But on my system, all clock gates are enabled by the bootloader (barebox)
and therefore the glitch could also happen here.

If setting the clock to a "default" rate is really required (on my system, the
clock is switched from 99 MHz to 22 MHz, and back to 99 MHz on a later call...),
I suggest moving this call to gpmi_nand_probe() (below __gpmi_enable_clock())
and guard it. The result would look like:

...
	ret = acquire_resources(this);
	if (ret)
		goto exit_acquire_resources;

	ret = __gpmi_enable_clk(this, true);
	if (ret)
		goto exit_acquire_resources;

	if (GPMI_IS_MX6(this)) {
		/*
		 * Set the default value for the gpmi clock.
		 *
		 * If you want to use the ONFI nand which is in the
		 * Synchronous Mode, you should change the clock as you need.
		 */
		__gpmi_enable_clk(this, false);
		clk_set_rate(this->resources.clock[0], 22000000);
		__gpmi_enable_clk(this, true);
	}

	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
...

It looks a little bit useless to enable the clocks and immediately disable
them. But probably this is the only way to make sure that clocks enabled by
the bootloader are certainly off.

regards
Christian





From ceggers at arri.de  Fri Oct  8 06:13:17 2021
From: ceggers at arri.de (Christian Eggers)
Date: Fri, 8 Oct 2021 15:13:17 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008142724.7fbeed6a@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
 <20211008142724.7fbeed6a@xps13>
Message-ID: <2533161.k3LOHGUjKi@n95hx1g2>

On Friday, 8 October 2021, 14:27:24 CEST, Miquel Raynal wrote:
> Hello,
> 
> Could it be possible to quantify the extra time spent in
> disabling/re-enabling clocks just for the record? So far this driver
> only supports a single chip and thus frequency changes do not happen
> frequently (a couple times at boot) but if someday we introduce support
> for several chips it might become very impacting. 
> 
> Thanks,
> Miqu?l
> 


ktime_t start = ktime_get(), duration;
__gpmi_enable_clk(this, false);
clk_set_rate(r->clock[0], hw->clk_rate);
__gpmi_enable_clk(this, true);
duration = ktime_get() - start;
printk(KERN_ERR "%s() duration = %lld ns\n", __func__, ktime_to_ns(duration));

--> 

gpmi_nfc_apply_timings() duration = 39250 ns
...
nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
nand: Micron MT29F4G08ABADAH4
nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
gpmi_nfc_apply_timings() duration = 36750 ns
gpmi_nfc_apply_timings() duration = 170750 ns

On i.MX6ULL @ 792MHz this takes less than 250 us.

regards
Christian





From miquel.raynal at bootlin.com  Fri Oct  8 06:29:05 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 15:29:05 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <13290228.RDIVbhacDa@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
 <20211008142724.7fbeed6a@xps13> <13290228.RDIVbhacDa@n95hx1g2>
Message-ID: <20211008152905.2fbdcce9@xps13>

Hi Christian,

ceggers at arri.de wrote on Fri, 8 Oct 2021 15:11:59 +0200:

> On Friday, 8 October 2021, 11:55:56 CEST, Christian Eggers wrote:
> 
> > I got another solution from PHYTEC ([2], not lengthy tested yet), which
> > disables all GPMI/BCH clocks on CCGR4  
> 
> > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > 
> >  {
> >  
> >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> >  	struct resources *r = &this->resources;
> >  	void __iomem *gpmi_regs = r->gpmi_regs;
> >  	unsigned int dll_wait_time_us;
> > 
> > +	int ret;
> > 
> > +	ret = __gpmi_enable_clk(this, false);
> > +	if (ret)
> > +		return ret;
> > 
> >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > 
> > +	ret = __gpmi_enable_clk(this, true);
> > +	if (ret)
> > +		return ret;
> > 
> >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);  
> 
> 
> I think that this is also required for the first call to clk_set_rate() in
> gpmi_get_clks(). From the kernel's point of view, the clocks are not enabled
> yet, so no "guard" is required. Putting the same guard here will actually give
> a warning at runtime that I am trying to disable a clock which is not enabled.
> But on my system, all clock gates are enabled by the bootloader (barebox)
> and therefore the glitch could also happen here.
> 
> If setting the clock to a "default" rate is really required (on my system, the
> clock is switched from 99 MHz to 22 MHz, and back to 99 MHz on a later call...),
> I suggest moving this call to gpmi_nand_probe() (below __gpmi_enable_clock())
> and guard it. The result would look like:
> 
> ...
> 	ret = acquire_resources(this);
> 	if (ret)
> 		goto exit_acquire_resources;
> 
> 	ret = __gpmi_enable_clk(this, true);
> 	if (ret)
> 		goto exit_acquire_resources;
> 
> 	if (GPMI_IS_MX6(this)) {
> 		/*
> 		 * Set the default value for the gpmi clock.
> 		 *
> 		 * If you want to use the ONFI nand which is in the
> 		 * Synchronous Mode, you should change the clock as you need.
> 		 */
> 		__gpmi_enable_clk(this, false);
> 		clk_set_rate(this->resources.clock[0], 22000000);
> 		__gpmi_enable_clk(this, true);
> 	}
> 
> 	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);

If this clock (as I understand) does not prevent us to access the
registers but only feeds the external NAND bus part, then there is no
need to enable it in the probe, just acquiring it will be enough.

Then, the first call for an IO operation with ->must_apply_timings
should:

	if (imx6)
		disable_clk();

	clk_set_rate();

	if (imx6)
		enable_clk();

I believe this should cover it all.

> ...
> 
> It looks a little bit useless to enable the clocks and immediately disable
> them. But probably this is the only way to make sure that clocks enabled by
> the bootloader are certainly off.
> 
> regards
> Christian
> 
> 
> 


Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Fri Oct  8 06:30:26 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 15:30:26 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <2533161.k3LOHGUjKi@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
 <20211008142724.7fbeed6a@xps13> <2533161.k3LOHGUjKi@n95hx1g2>
Message-ID: <20211008153026.7a5d8e8b@xps13>

Hi Christian,

ceggers at arri.de wrote on Fri, 8 Oct 2021 15:13:17 +0200:

> On Friday, 8 October 2021, 14:27:24 CEST, Miquel Raynal wrote:
> > Hello,
> > 
> > Could it be possible to quantify the extra time spent in
> > disabling/re-enabling clocks just for the record? So far this driver
> > only supports a single chip and thus frequency changes do not happen
> > frequently (a couple times at boot) but if someday we introduce support
> > for several chips it might become very impacting. 
> > 
> > Thanks,
> > Miqu?l
> >   
> 
> 
> ktime_t start = ktime_get(), duration;
> __gpmi_enable_clk(this, false);
> clk_set_rate(r->clock[0], hw->clk_rate);
> __gpmi_enable_clk(this, true);
> duration = ktime_get() - start;
> printk(KERN_ERR "%s() duration = %lld ns\n", __func__, ktime_to_ns(duration));
> 
> -->   
> 
> gpmi_nfc_apply_timings() duration = 39250 ns
> ...
> nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
> nand: Micron MT29F4G08ABADAH4
> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> gpmi_nfc_apply_timings() duration = 36750 ns
> gpmi_nfc_apply_timings() duration = 170750 ns
> 
> On i.MX6ULL @ 792MHz this takes less than 250 us.

Ok thanks for the feedback. This is not negligible if we start
switching between chips with different frequencies quite regularly.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Fri Oct  8 06:36:31 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 15:36:31 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008152905.2fbdcce9@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
 <20211008142724.7fbeed6a@xps13> <13290228.RDIVbhacDa@n95hx1g2>
 <20211008152905.2fbdcce9@xps13>
Message-ID: <20211008153631.3f1a09aa@xps13>


miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:

> Hi Christian,
> 
> ceggers at arri.de wrote on Fri, 8 Oct 2021 15:11:59 +0200:
> 
> > On Friday, 8 October 2021, 11:55:56 CEST, Christian Eggers wrote:
> >   
> > > I got another solution from PHYTEC ([2], not lengthy tested yet), which
> > > disables all GPMI/BCH clocks on CCGR4    
> >   
> > > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > 
> > >  {
> > >  
> > >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > >  	struct resources *r = &this->resources;
> > >  	void __iomem *gpmi_regs = r->gpmi_regs;
> > >  	unsigned int dll_wait_time_us;
> > > 
> > > +	int ret;
> > > 
> > > +	ret = __gpmi_enable_clk(this, false);
> > > +	if (ret)
> > > +		return ret;
> > > 
> > >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > > 
> > > +	ret = __gpmi_enable_clk(this, true);
> > > +	if (ret)
> > > +		return ret;
> > > 
> > >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);    
> > 
> > 
> > I think that this is also required for the first call to clk_set_rate() in
> > gpmi_get_clks(). From the kernel's point of view, the clocks are not enabled
> > yet, so no "guard" is required. Putting the same guard here will actually give
> > a warning at runtime that I am trying to disable a clock which is not enabled.
> > But on my system, all clock gates are enabled by the bootloader (barebox)
> > and therefore the glitch could also happen here.
> > 
> > If setting the clock to a "default" rate is really required (on my system, the
> > clock is switched from 99 MHz to 22 MHz, and back to 99 MHz on a later call...),
> > I suggest moving this call to gpmi_nand_probe() (below __gpmi_enable_clock())
> > and guard it. The result would look like:
> > 
> > ...
> > 	ret = acquire_resources(this);
> > 	if (ret)
> > 		goto exit_acquire_resources;
> > 
> > 	ret = __gpmi_enable_clk(this, true);
> > 	if (ret)
> > 		goto exit_acquire_resources;
> > 
> > 	if (GPMI_IS_MX6(this)) {
> > 		/*
> > 		 * Set the default value for the gpmi clock.
> > 		 *
> > 		 * If you want to use the ONFI nand which is in the
> > 		 * Synchronous Mode, you should change the clock as you need.
> > 		 */
> > 		__gpmi_enable_clk(this, false);
> > 		clk_set_rate(this->resources.clock[0], 22000000);
> > 		__gpmi_enable_clk(this, true);
> > 	}
> > 
> > 	pm_runtime_set_autosuspend_delay(&pdev->dev, 500);  
> 
> If this clock (as I understand) does not prevent us to access the
> registers but only feeds the external NAND bus part, then there is no
> need to enable it in the probe, just acquiring it will be enough.
> Then, the first call for an IO operation with ->must_apply_timings
> should:
> 
> 	if (imx6)
> 		disable_clk();
> 
> 	clk_set_rate();
> 
> 	if (imx6)
> 		enable_clk();

Actually we should ensure clks are enabled in the !imx6 case anyway,
but this is needed only once so either we keep enabling the clock in
the probe or we check here if the clk has already been enabled or not.

Cheers,
Miqu?l


From ceggers at arri.de  Fri Oct  8 06:49:21 2021
From: ceggers at arri.de (Christian Eggers)
Date: Fri, 8 Oct 2021 15:49:21 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008153631.3f1a09aa@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211008152905.2fbdcce9@xps13> <20211008153631.3f1a09aa@xps13>
Message-ID: <6364938.4vTCxPXJkl@n95hx1g2>

On Friday, 8 October 2021, 15:36:31 CEST, Miquel Raynal wrote:
> 
> miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:
> 
> > 
> > If this clock (as I understand) does not prevent us to access the
> > registers but only feeds the external NAND bus part, then there is no
> > need to enable it in the probe, just acquiring it will be enough.

clocks[0] is "gpmi_io" which sounds more like i/o than registers. So lets
try to remove the initial call to clk_set_rate().

> > Then, the first call for an IO operation with ->must_apply_timings
> > should:
> > 
> > 	if (imx6)
> > 		disable_clk();
> > 
> > 	clk_set_rate();
> > 
> > 	if (imx6)
> > 		enable_clk();

Do you think that the need for avoiding clock glitches is i.MX6 specific?
The errata I mentioned is specific for the bootloader software, but (I think)
the requirement for switching off the clocks gates prior changing the dividers
may apply also for other series.

> Actually we should ensure clks are enabled in the !imx6 case anyway,
> but this is needed only once so either we keep enabling the clock in
> the probe or we check here if the clk has already been enabled or not.
The clocks are already enabled (and kept on) in probe. The initial call to
clk_set_rate() is just above this (but the clocks are not disabled at this
stage as all gates have been enabled by the boot loader).

regards
Christian





From troglobit at gmail.com  Fri Oct  8 07:08:35 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Fri,  8 Oct 2021 16:08:35 +0200
Subject: [PATCH v2 1/1] mtd: block2mtd: add support for an optional custom MTD
 label
Message-ID: <20211008140835.476949-1-troglobit@gmail.com>

This patch adds support for an optional MTD label for mtd2block emulated
MTD devices.  Useful when, e.g., testing device images using Qemu.

The following line in /etc/fstab can then be used to mount a file system
regardless if running on an embedded system, or emulated with block2mtd:

    mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0

Kernel command line syntax in the emulated case:

    block2mtd.block2mtd=/dev/sda,,Config

Notioce the ',,', it is the optional erase_size, which like before this
patch, defaults to PAGE_SIZE when omitted.  Hence the strlen() check.

Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
Reviewed-by: Miqu?l Raynal <miquel.raynal at bootlin.com>
---
v2:
  * Variables and arguments on their own lines
  * Add comment to explain why we need strlen()
  * Refactor hard coded constants with a define
  * Spell and grammar check commit message
---
 drivers/mtd/devices/block2mtd.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index c08721b11642..40d7211485da 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -31,6 +31,9 @@
 #include <linux/slab.h>
 #include <linux/major.h>
 
+/* Maximum number of comma-separated items in the 'block2mtd=' parameter */
+#define BLOCK2MTD_PARAM_MAX_COUNT 3
+
 /* Info for the block device */
 struct block2mtd_dev {
 	struct list_head list;
@@ -214,7 +217,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 
 
 static struct block2mtd_dev *add_device(char *devname, int erase_size,
-		int timeout)
+		char *label, int timeout)
 {
 #ifndef MODULE
 	int i;
@@ -278,7 +281,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	/* Setup the MTD structure */
 	/* make the name contain the block device in */
-	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	if (!label)
+		name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	else
+		name = kstrdup(label, GFP_KERNEL);
 	if (!name)
 		goto err_destroy_mutex;
 
@@ -305,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 	list_add(&dev->list, &blkmtd_device_list);
 	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
 		dev->mtd.index,
-		dev->mtd.name + strlen("block2mtd: "),
+		label ? label : dev->mtd.name + strlen("block2mtd: "),
 		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
 
@@ -381,8 +387,9 @@ static int block2mtd_setup2(const char *val)
 	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
 	char buf[80 + 12 + 80 + 8];
 	char *str = buf;
-	char *token[2];
+	char *token[BLOCK2MTD_PARAM_MAX_COUNT];
 	char *name;
+	char *label = NULL;
 	size_t erase_size = PAGE_SIZE;
 	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
 	int i, ret;
@@ -395,7 +402,7 @@ static int block2mtd_setup2(const char *val)
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str) {
@@ -414,7 +421,8 @@ static int block2mtd_setup2(const char *val)
 		return 0;
 	}
 
-	if (token[1]) {
+	/* Optional argument when custom label is used */
+	if (token[1] && strlen(token[1])) {
 		ret = parse_num(&erase_size, token[1]);
 		if (ret) {
 			pr_err("illegal erase size\n");
@@ -422,7 +430,12 @@ static int block2mtd_setup2(const char *val)
 		}
 	}
 
-	add_device(name, erase_size, timeout);
+	if (token[2]) {
+		label = token[2];
+		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
+	}
+
+	add_device(name, erase_size, label, timeout);
 
 	return 0;
 }
@@ -456,7 +469,7 @@ static int block2mtd_setup(const char *val, const struct kernel_param *kp)
 
 
 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
 
 static int __init block2mtd_init(void)
 {
-- 
2.25.1



From sean at geanix.com  Fri Oct  8 07:38:24 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri,  8 Oct 2021 16:38:24 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211008141524.20ca8219@collabora.com>
Message-ID: <20211008143825.3717116-1-sean@geanix.com>

This will prevent reading/writing/erasing to a suspended mtd device.
It will force mtd_write()/mtd_read()/mtd_erase() to wait for
mtd_resume() to unlock access to mtd devices.

Exec_op[0] speed things up, so we see this race when rawnand devices going
into suspend. But it's actually "mtd: rawnand: Simplify the locking" that
allows it to return errors rather than locking, before that commit it would
have waited for the rawnand device to resume.

Tested on a iMX6ULL.

[0]:
ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---

Hope I got it all :)

 drivers/mtd/mtdcore.c   | 57 ++++++++++++++++++++++++++++++++++++++++-
 include/linux/mtd/mtd.h | 36 ++++++++++++++++++--------
 2 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c8fd7f758938..3c93202e6cbb 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -36,6 +36,44 @@
 
 struct backing_dev_info *mtd_bdi;
 
+static void mtd_start_access(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+
+	/*
+	 * Don't take the suspend_lock on devices that don't
+	 * implement the suspend hook. Otherwise, lockdep will
+	 * complain about nested locks when trying to suspend MTD
+	 * partitions or MTD devices created by gluebi which are
+	 * backed by real devices.
+	 */
+	if (!master->_suspend)
+		return;
+
+	/*
+	 * Wait until the device is resumed. Should we have a
+	 * non-blocking mode here?
+	 */
+	while (1) {
+		down_read(&master->master.suspend_lock);
+		if (!master->master.suspended)
+			return;
+
+		up_read(&master->master.suspend_lock);
+		wait_event(master->master.resume_wq, master->master.suspended == 0);
+	}
+}
+
+static void mtd_end_access(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+
+	if (!master->_suspend)
+		return;
+
+	up_read(&master->master.suspend_lock);
+}
+
 #ifdef CONFIG_PM_SLEEP
 
 static int mtd_cls_suspend(struct device *dev)
@@ -1000,6 +1038,9 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
 
 	ret = mtd_otp_nvmem_add(mtd);
 
+	init_waitqueue_head(&mtd->master.resume_wq);
+	init_rwsem(&mtd->master.suspend_lock);
+
 out:
 	if (ret && device_is_registered(&mtd->dev))
 		del_mtd_device(mtd);
@@ -1241,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 	struct erase_info adjinstr;
 	int ret;
 
+	mtd_start_access(mtd);
+
 	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 	adjinstr = *instr;
 
@@ -1278,6 +1321,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 		}
 	}
 
+	mtd_end_access(mtd);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase);
@@ -1558,6 +1603,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 	struct mtd_ecc_stats old_stats = master->ecc_stats;
 	int ret_code;
 
+	mtd_start_access(mtd);
+
 	ops->retlen = ops->oobretlen = 0;
 
 	ret_code = mtd_check_oob_ops(mtd, from, ops);
@@ -1577,6 +1624,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 
 	mtd_update_ecc_stats(mtd, master, &old_stats);
 
+	mtd_end_access(mtd);
+
 	/*
 	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
 	 * similar to mtd->_read(), returning a non-negative integer
@@ -1597,6 +1646,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	struct mtd_info *master = mtd_get_master(mtd);
 	int ret;
 
+	mtd_start_access(mtd);
+
 	ops->retlen = ops->oobretlen = 0;
 
 	if (!(mtd->flags & MTD_WRITEABLE))
@@ -1615,7 +1666,11 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		return mtd_io_emulated_slc(mtd, to, false, ops);
 
-	return mtd_write_oob_std(mtd, to, ops);
+	ret = mtd_write_oob_std(mtd, to, ops);
+
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_write_oob);
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..cfab07b02dc9 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -231,6 +231,8 @@ struct mtd_master {
 	struct mutex partitions_lock;
 	struct mutex chrdev_lock;
 	unsigned int suspended : 1;
+	wait_queue_head_t resume_wq;
+	struct rw_semaphore suspend_lock;
 };
 
 struct mtd_info {
@@ -546,30 +548,42 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
-	int ret;
+	int ret = 0;
 
-	if (master->master.suspended)
-		return 0;
 
-	ret = master->_suspend ? master->_suspend(master) : 0;
-	if (ret)
+	if (!master->_suspend)
 		return ret;
 
-	master->master.suspended = 1;
-	return 0;
+	down_write(&master->master.suspend_lock);
+	if (!master->master.suspended) {
+		ret = master->_suspend(master);
+		if (!ret)
+			master->master.suspended = 1;
+	}
+	up_write(&master->master.suspend_lock);
+
+	return ret;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 
-	if (!master->master.suspended)
+	if (!master->_suspend)
 		return;
 
-	if (master->_resume)
-		master->_resume(master);
 
-	master->master.suspended = 0;
+	down_write(&master->master.suspend_lock);
+	if (master->master.suspended) {
+		if (master->_resume)
+			master->_resume(master);
+
+		master->master.suspended = 0;
+
+		/* The MTD dev has been resumed, wake up all waiters. */
+		wake_up_all(&master->master.resume_wq);
+	}
+	up_write(&master->master.suspend_lock);
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
-- 
2.33.0



From sean at geanix.com  Fri Oct  8 07:38:25 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri,  8 Oct 2021 16:38:25 +0200
Subject: [RFC PATCH 2/2] mtd: rawnand: remove suspended check
In-Reply-To: <20211008141524.20ca8219@collabora.com>
References: <20211008143825.3717116-1-sean@geanix.com>
Message-ID: <20211008143825.3717116-2-sean@geanix.com>

Rawnand access is protected in upper mtd layer when mtd devices are
suspended. So remove this obsolute check/lock

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---

Hmm what to do in nand_sync()? Fine as is?

 drivers/mtd/nand/raw/nand_base.c | 50 ++++++++------------------------
 include/linux/mtd/rawnand.h      |  5 +---
 2 files changed, 13 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..f1f85866c87a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  * @chip: NAND chip structure
  *
  * Lock the device and its controller for exclusive access
- *
- * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
 	mutex_lock(&chip->controller->lock);
-
-	return 0;
 }
 
 /**
@@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
-
+		nand_get_device(chip);
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
 	}
@@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4349,9 +4336,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 	if (nand_region_is_secured(chip, instr->addr, instr->len))
 		return -EIO;
 
-	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	/* Grab the lock */
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 	pr_debug("%s: called\n", __func__);
 
-	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	/* Grab the lock */
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
 	mutex_lock(&chip->lock);
 	if (chip->ops.suspend)
 		ret = chip->ops.suspend(chip);
-	if (!ret)
-		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
+
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		if (chip->ops.resume)
-			chip->ops.resume(chip);
-		chip->suspended = 0;
-	} else {
-		pr_err("%s called for a chip which is not in suspended state\n",
-			__func__);
-	}
+	if (chip->ops.resume)
+		chip->ops.resume(chip);
 	mutex_unlock(&chip->lock);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..1198a6548912 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1237,9 +1237,7 @@ struct nand_secure_region {
  * @pagecache.page: Page number currently in the cache. -1 means no page is
  *                  currently cached
  * @buf_align: Minimum buffer alignment required by a platform
- * @lock: Lock protecting the suspended field. Also used to serialize accesses
- *        to the NAND device
- * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @lock: Lock to serialize accesses to the NAND device
  * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
  *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
  *          NAND Controller drivers should not modify this value, but they're
@@ -1293,7 +1291,6 @@ struct nand_chip {
 
 	/* Internals */
 	struct mutex lock;
-	unsigned int suspended : 1;
 	int cur_cs;
 	int read_retries;
 	struct nand_secure_region *secure_regions;
-- 
2.33.0



From miquel.raynal at bootlin.com  Fri Oct  8 07:44:07 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 16:44:07 +0200
Subject: [PATCH v2 1/1] mtd: block2mtd: add support for an optional
 custom MTD label
In-Reply-To: <20211008140835.476949-1-troglobit@gmail.com>
References: <20211008140835.476949-1-troglobit@gmail.com>
Message-ID: <20211008164407.5dc6c20a@xps13>

Hi Joachim,

troglobit at gmail.com wrote on Fri,  8 Oct 2021 16:08:35 +0200:

> This patch adds support for an optional MTD label for mtd2block emulated
> MTD devices.  Useful when, e.g., testing device images using Qemu.
> 
> The following line in /etc/fstab can then be used to mount a file system
> regardless if running on an embedded system, or emulated with block2mtd:
> 
>     mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0
> 
> Kernel command line syntax in the emulated case:
> 
>     block2mtd.block2mtd=/dev/sda,,Config
> 
> Notioce the ',,', it is the optional erase_size, which like before this
> patch, defaults to PAGE_SIZE when omitted.  Hence the strlen() check.
> 
> Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
> Reviewed-by: Miqu?l Raynal <miquel.raynal at bootlin.com>
> ---
> v2:
>   * Variables and arguments on their own lines
>   * Add comment to explain why we need strlen()
>   * Refactor hard coded constants with a define
>   * Spell and grammar check commit message
> ---
>  drivers/mtd/devices/block2mtd.c | 29 +++++++++++++++++++++--------
>  1 file changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
> index c08721b11642..40d7211485da 100644
> --- a/drivers/mtd/devices/block2mtd.c
> +++ b/drivers/mtd/devices/block2mtd.c
> @@ -31,6 +31,9 @@
>  #include <linux/slab.h>
>  #include <linux/major.h>
>  
> +/* Maximum number of comma-separated items in the 'block2mtd=' parameter */
> +#define BLOCK2MTD_PARAM_MAX_COUNT 3
> +
>  /* Info for the block device */
>  struct block2mtd_dev {
>  	struct list_head list;
> @@ -214,7 +217,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
>  
>  
>  static struct block2mtd_dev *add_device(char *devname, int erase_size,
> -		int timeout)
> +		char *label, int timeout)
>  {
>  #ifndef MODULE
>  	int i;
> @@ -278,7 +281,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
>  
>  	/* Setup the MTD structure */
>  	/* make the name contain the block device in */
> -	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
> +	if (!label)
> +		name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
> +	else
> +		name = kstrdup(label, GFP_KERNEL);
>  	if (!name)
>  		goto err_destroy_mutex;
>  
> @@ -305,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
>  	list_add(&dev->list, &blkmtd_device_list);
>  	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
>  		dev->mtd.index,
> -		dev->mtd.name + strlen("block2mtd: "),
> +		label ? label : dev->mtd.name + strlen("block2mtd: "),
>  		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
>  	return dev;
>  
> @@ -381,8 +387,9 @@ static int block2mtd_setup2(const char *val)
>  	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
>  	char buf[80 + 12 + 80 + 8];
>  	char *str = buf;
> -	char *token[2];
> +	char *token[BLOCK2MTD_PARAM_MAX_COUNT];

I believe this change should still be kept in a separate patch.
Otherwise looks fine.

>  	char *name;
> +	char *label = NULL;
>  	size_t erase_size = PAGE_SIZE;
>  	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
>  	int i, ret;
> @@ -395,7 +402,7 @@ static int block2mtd_setup2(const char *val)
>  	strcpy(str, val);
>  	kill_final_newline(str);
>  
> -	for (i = 0; i < 2; i++)
> +	for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++)
>  		token[i] = strsep(&str, ",");
>  
>  	if (str) {
> @@ -414,7 +421,8 @@ static int block2mtd_setup2(const char *val)
>  		return 0;
>  	}
>  
> -	if (token[1]) {
> +	/* Optional argument when custom label is used */
> +	if (token[1] && strlen(token[1])) {
>  		ret = parse_num(&erase_size, token[1]);
>  		if (ret) {
>  			pr_err("illegal erase size\n");
> @@ -422,7 +430,12 @@ static int block2mtd_setup2(const char *val)
>  		}
>  	}
>  
> -	add_device(name, erase_size, timeout);
> +	if (token[2]) {
> +		label = token[2];
> +		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
> +	}
> +
> +	add_device(name, erase_size, label, timeout);
>  
>  	return 0;
>  }
> @@ -456,7 +469,7 @@ static int block2mtd_setup(const char *val, const struct kernel_param *kp)
>  
>  
>  module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
> -MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
> +MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
>  
>  static int __init block2mtd_init(void)
>  {


Thanks,
Miqu?l


From boris.brezillon at collabora.com  Fri Oct  8 08:30:43 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Fri, 8 Oct 2021 17:30:43 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while
 in suspend
In-Reply-To: <20211008143825.3717116-1-sean@geanix.com>
References: <20211008141524.20ca8219@collabora.com>
 <20211008143825.3717116-1-sean@geanix.com>
Message-ID: <20211008173043.6263ba80@collabora.com>

Hi Sean,

Can you please submit that as a separate thread, ideally with an
incremented version number, a changelog and a reference to all your
previous attempts.

On Fri,  8 Oct 2021 16:38:24 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> This will prevent reading/writing/erasing to a suspended mtd device.
> It will force mtd_write()/mtd_read()/mtd_erase() to wait for
> mtd_resume() to unlock access to mtd devices.

I think this has to be done for all the hooks except ->_reboot(),
->_get_device() and ->_put_device().

> 
> Exec_op[0] speed things up, so we see this race when rawnand devices going

Mention the commit directly:

Commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op") speed
things up, so we see this race when rawnand devices going ...

> into suspend. But it's actually "mtd: rawnand: Simplify the locking" that

But it's actually commit 013e6292aaf5 ("mtd: rawnand: Simplify the
locking") that ...

> allows it to return errors rather than locking, before that commit it would
> have waited for the rawnand device to resume.
> 
> Tested on a iMX6ULL.
> 
> [0]:
> ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>

You flagged yourself as the author even though you didn't really write
that code. I guess I'm fine with that, but I'd appreciate a

Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>

here, at least.

> ---
> 
> Hope I got it all :)
> 
>  drivers/mtd/mtdcore.c   | 57 ++++++++++++++++++++++++++++++++++++++++-
>  include/linux/mtd/mtd.h | 36 ++++++++++++++++++--------
>  2 files changed, 81 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c8fd7f758938..3c93202e6cbb 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -36,6 +36,44 @@
>  
>  struct backing_dev_info *mtd_bdi;
>  
> +static void mtd_start_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	/*
> +	 * Don't take the suspend_lock on devices that don't
> +	 * implement the suspend hook. Otherwise, lockdep will
> +	 * complain about nested locks when trying to suspend MTD
> +	 * partitions or MTD devices created by gluebi which are
> +	 * backed by real devices.
> +	 */
> +	if (!master->_suspend)
> +		return;
> +

You need to remove the ->_suspend()/->_resume() implementation in
mtd_concat.c, otherwise you'll hit the case described in the comment.

BTW, did you test this series with lockdep enabled to make sure we
don't introduce a deadlock?

> +	/*
> +	 * Wait until the device is resumed. Should we have a
> +	 * non-blocking mode here?
> +	 */
> +	while (1) {
> +		down_read(&master->master.suspend_lock);
> +		if (!master->master.suspended)
> +			return;
> +
> +		up_read(&master->master.suspend_lock);
> +		wait_event(master->master.resume_wq, master->master.suspended == 0);
> +	}
> +}
> +
> +static void mtd_end_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	if (!master->_suspend)
> +		return;
> +
> +	up_read(&master->master.suspend_lock);
> +}
> +


From miquel.raynal at bootlin.com  Fri Oct  8 08:35:26 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 17:35:26 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while
 in suspend
In-Reply-To: <20211008143825.3717116-1-sean@geanix.com>
References: <20211008141524.20ca8219@collabora.com>
 <20211008143825.3717116-1-sean@geanix.com>
Message-ID: <20211008173526.19745a10@xps13>

Hi Sean,

sean at geanix.com wrote on Fri,  8 Oct 2021 16:38:24 +0200:

> This will prevent reading/writing/erasing to a suspended mtd device.
> It will force mtd_write()/mtd_read()/mtd_erase() to wait for
> mtd_resume() to unlock access to mtd devices.

Maybe you can use the present tense, as in:
Prevent reading/...

s/mtd/MTD/

Force mtd_write/...

I would suggest something like:

	Prevent accessing the devices while in a suspended state. Also
	prevent suspending a device which is still currently in use.


> Exec_op[0] speed things up, so we see this race when rawnand devices going

I believe you can quote the commit inline, like below (please use the
12-digit hash below as well).

I am not sure ->exec_op() is to be blamed here, maybe this change
revealed the issue but I doubt it is because of its efficiency. The
problem was just laying silently IMHO.

> into suspend. But it's actually "mtd: rawnand: Simplify the locking" that
> allows it to return errors rather than locking, before that commit it would
> have waited for the rawnand device to resume.

I don't think so, I believe it was broken in the same way but was just
not returning errors.
> 
> Tested on a iMX6ULL.
> 
> [0]:
> ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> 

	Suggested-by: Boris... 

would be nice.


> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
> 
> Hope I got it all :)
> 
>  drivers/mtd/mtdcore.c   | 57 ++++++++++++++++++++++++++++++++++++++++-
>  include/linux/mtd/mtd.h | 36 ++++++++++++++++++--------
>  2 files changed, 81 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c8fd7f758938..3c93202e6cbb 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -36,6 +36,44 @@
>  
>  struct backing_dev_info *mtd_bdi;
>  
> +static void mtd_start_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	/*
> +	 * Don't take the suspend_lock on devices that don't
> +	 * implement the suspend hook. Otherwise, lockdep will
> +	 * complain about nested locks when trying to suspend MTD
> +	 * partitions or MTD devices created by gluebi which are
> +	 * backed by real devices.
> +	 */
> +	if (!master->_suspend)
> +		return;
> +
> +	/*
> +	 * Wait until the device is resumed. Should we have a
> +	 * non-blocking mode here?
> +	 */
> +	while (1) {
> +		down_read(&master->master.suspend_lock);
> +		if (!master->master.suspended)
> +			return;
> +
> +		up_read(&master->master.suspend_lock);
> +		wait_event(master->master.resume_wq, master->master.suspended == 0);

"var == 0" translates well to "!var"

> +	}
> +}
> +
> +static void mtd_end_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	if (!master->_suspend)
> +		return;
> +
> +	up_read(&master->master.suspend_lock);
> +}
> +
>  #ifdef CONFIG_PM_SLEEP
>  
>  static int mtd_cls_suspend(struct device *dev)
> @@ -1000,6 +1038,9 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
>  
>  	ret = mtd_otp_nvmem_add(mtd);
>  
> +	init_waitqueue_head(&mtd->master.resume_wq);
> +	init_rwsem(&mtd->master.suspend_lock);

what about setting this in mtd_set_dev_defaults()?

> +
>  out:
>  	if (ret && device_is_registered(&mtd->dev))
>  		del_mtd_device(mtd);
> @@ -1241,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
>  	struct erase_info adjinstr;
>  	int ret;
>  
> +	mtd_start_access(mtd);

I believe we should cover all the ioctls, even if they are not
accessing the device. I don't think it's a problem to stop
interacting when the devices are suspended?

> +
>  	instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
>  	adjinstr = *instr;
>  
> @@ -1278,6 +1321,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
>  		}
>  	}
>  
> +	mtd_end_access(mtd);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_erase);
> @@ -1558,6 +1603,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>  	struct mtd_ecc_stats old_stats = master->ecc_stats;
>  	int ret_code;
>  
> +	mtd_start_access(mtd);
> +
>  	ops->retlen = ops->oobretlen = 0;
>  
>  	ret_code = mtd_check_oob_ops(mtd, from, ops);
> @@ -1577,6 +1624,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>  
>  	mtd_update_ecc_stats(mtd, master, &old_stats);
>  
> +	mtd_end_access(mtd);
> +
>  	/*
>  	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
>  	 * similar to mtd->_read(), returning a non-negative integer
> @@ -1597,6 +1646,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>  	struct mtd_info *master = mtd_get_master(mtd);
>  	int ret;
>  
> +	mtd_start_access(mtd);
> +
>  	ops->retlen = ops->oobretlen = 0;
>  
>  	if (!(mtd->flags & MTD_WRITEABLE))
> @@ -1615,7 +1666,11 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		return mtd_io_emulated_slc(mtd, to, false, ops);
>  
> -	return mtd_write_oob_std(mtd, to, ops);
> +	ret = mtd_write_oob_std(mtd, to, ops);
> +
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_write_oob);
>  
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 88227044fc86..cfab07b02dc9 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -231,6 +231,8 @@ struct mtd_master {
>  	struct mutex partitions_lock;
>  	struct mutex chrdev_lock;
>  	unsigned int suspended : 1;
> +	wait_queue_head_t resume_wq;
> +	struct rw_semaphore suspend_lock;
>  };
>  
>  struct mtd_info {
> @@ -546,30 +548,42 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
>  static inline int mtd_suspend(struct mtd_info *mtd)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> -	int ret;
> +	int ret = 0;
>  
> -	if (master->master.suspended)
> -		return 0;
>  
> -	ret = master->_suspend ? master->_suspend(master) : 0;
> -	if (ret)
> +	if (!master->_suspend)
>  		return ret;
>  
> -	master->master.suspended = 1;
> -	return 0;
> +	down_write(&master->master.suspend_lock);
> +	if (!master->master.suspended) {
> +		ret = master->_suspend(master);
> +		if (!ret)
> +			master->master.suspended = 1;
> +	}
> +	up_write(&master->master.suspend_lock);
> +
> +	return ret;
>  }
>  
>  static inline void mtd_resume(struct mtd_info *mtd)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
>  
> -	if (!master->master.suspended)
> +	if (!master->_suspend)
>  		return;
>  
> -	if (master->_resume)
> -		master->_resume(master);
>  
> -	master->master.suspended = 0;
> +	down_write(&master->master.suspend_lock);
> +	if (master->master.suspended) {
> +		if (master->_resume)
> +			master->_resume(master);
> +
> +		master->master.suspended = 0;
> +
> +		/* The MTD dev has been resumed, wake up all waiters. */
> +		wake_up_all(&master->master.resume_wq);
> +	}
> +	up_write(&master->master.suspend_lock);
>  }
>  
>  static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)

The other patch lgtm.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Fri Oct  8 09:07:52 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 8 Oct 2021 18:07:52 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <6364938.4vTCxPXJkl@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211008152905.2fbdcce9@xps13> <20211008153631.3f1a09aa@xps13>
 <6364938.4vTCxPXJkl@n95hx1g2>
Message-ID: <20211008180752.09f33896@xps13>

Hi Christian,

ceggers at arri.de wrote on Fri, 8 Oct 2021 15:49:21 +0200:

> On Friday, 8 October 2021, 15:36:31 CEST, Miquel Raynal wrote:
> > 
> > miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:
> >   
> > > 
> > > If this clock (as I understand) does not prevent us to access the
> > > registers but only feeds the external NAND bus part, then there is no
> > > need to enable it in the probe, just acquiring it will be enough.  
> 
> clocks[0] is "gpmi_io" which sounds more like i/o than registers. So lets
> try to remove the initial call to clk_set_rate().
> 
> > > Then, the first call for an IO operation with ->must_apply_timings
> > > should:
> > > 
> > > 	if (imx6)
> > > 		disable_clk();
> > > 
> > > 	clk_set_rate();
> > > 
> > > 	if (imx6)
> > > 		enable_clk();  
> 
> Do you think that the need for avoiding clock glitches is i.MX6 specific?
> The errata I mentioned is specific for the bootloader software, but (I think)
> the requirement for switching off the clocks gates prior changing the dividers
> may apply also for other series.

I honestly don't know, perhaps Han have more details about it. If you
think it's a wider issue, then we can just do the disable/enable step
without any further checks.

> > Actually we should ensure clks are enabled in the !imx6 case anyway,
> > but this is needed only once so either we keep enabling the clock in
> > the probe or we check here if the clk has already been enabled or not.  
> The clocks are already enabled (and kept on) in probe. The initial call to
> clk_set_rate() is just above this (but the clocks are not disabled at this
> stage as all gates have been enabled by the boot loader).

The IO clock should be enabled and set to a particular rate the first
time the die is selected to perform a NAND operation, or when we switch
from one device to the other (this does not apply to the GPMI driver
for now). So we can drop the enable/set_rate call in the probe if the
assumption that this clock only feeds the external bus is right.

Thanks,
Miqu?l


From boris.brezillon at collabora.com  Fri Oct  8 09:08:11 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Fri, 8 Oct 2021 18:08:11 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while
 in suspend
In-Reply-To: <20211008173526.19745a10@xps13>
References: <20211008141524.20ca8219@collabora.com>
 <20211008143825.3717116-1-sean@geanix.com>
 <20211008173526.19745a10@xps13>
Message-ID: <20211008180811.36c371f5@collabora.com>

On Fri, 8 Oct 2021 17:35:26 +0200
Miquel Raynal <miquel.raynal at bootlin.com> wrote:

> > into suspend. But it's actually "mtd: rawnand: Simplify the locking" that
> > allows it to return errors rather than locking, before that commit it would
> > have waited for the rawnand device to resume.  
> 
> I don't think so, I believe it was broken in the same way but was just
> not returning errors.

Actually I was wrong, 013e6292aaf5 ("mtd: rawnand: Simplify the
locking") removed the blocking wait (returning -EBUSY when the device
is suspended instead of putting the thread on a waitqueue). At that
time, I assumed all threads would be paused when the device is
suspended, which appeared to be incorrect. So I guess the Fixes tag
should remain, and we might want to consider backporting a less
invasive patch to stable releases (one touching only the raw NAND
layer).


From miquel.raynal at bootlin.com  Fri Oct  8 09:22:18 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:18 +0200
Subject: [RFC PATCH 00/10] Macronix ECC engine
Message-ID: <20211008162228.1753083-1-miquel.raynal@bootlin.com>

Hello all,

This series is not 100% stable yet but I believe it should be
sent out in order to help other people trying to use the ECC framework
with a SPI controller. Basically, Macronix ECC engine can be used as an
external engine (takes the data, proceeds to the calculations, writes
back the ECC bytes) or as a pipelined engine doing on-the-fly
calculations (which is very common in the raw NAND world).

In the device tree, the ECC engine should be described as a separated DT
node. Then:
* external case: the flash node should provide a nand-ecc-engine
  property pointing to the ECC engine node.
* pipelined case: the flash node should provide a nand-ecc-engine
  property pointing to the SPI controller, itself with another
  nand-ecc-engine property pointing at the ECC engine node.

I will resubmit this later when I will be done validating the hardware
and the driver.

Cheers,
Miqu?l

Mason Yang (1):
  mtd: spinand: macronix: Use random program load

Miquel Raynal (9):
  mtd: spinand: Fix comment
  dt-bindings: vendor-prefixes: Update Macronix prefix
  dt-bindings: mtd: Describe Macronix NAND ECC engine
  mtd: nand: ecc: Add infrastructure to support hardware engines
  mtd: nand: mxic-ecc: Add Macronix external ECC engine support
  mtd: nand: mxic-ecc: Support SPI pipelined mode
  spi: mxic: Fix the transmit path
  spi: mxic: Add support for direct mapping
  spi: mxic: Add support for pipelined ECC operations

 .../bindings/mtd/mxic,nand-ecc-engine.yaml    |  78 ++
 .../devicetree/bindings/vendor-prefixes.yaml  |   3 +
 drivers/mtd/nand/Kconfig                      |   6 +
 drivers/mtd/nand/Makefile                     |   1 +
 drivers/mtd/nand/core.c                       |  10 +-
 drivers/mtd/nand/ecc-mxic.c                   | 797 ++++++++++++++++++
 drivers/mtd/nand/ecc.c                        |  89 ++
 drivers/mtd/nand/spi/core.c                   |   2 +-
 drivers/mtd/nand/spi/macronix.c               |   2 +-
 drivers/spi/spi-mxic.c                        | 309 ++++++-
 include/linux/mtd/nand-ecc-mxic.h             |  36 +
 include/linux/mtd/nand.h                      |  11 +
 12 files changed, 1296 insertions(+), 48 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml
 create mode 100644 drivers/mtd/nand/ecc-mxic.c
 create mode 100644 include/linux/mtd/nand-ecc-mxic.h

-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:19 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:19 +0200
Subject: [RFC PATCH 01/10] mtd: spinand: Fix comment
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-2-miquel.raynal@bootlin.com>

This is a copy paste error, checking the ECC status finishes a page read
here, not a page write.

Fixes: 945845b54c9c ("mtd: spinand: Instantiate a SPI-NAND on-die ECC engine")
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.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 dd903d61c7c0..9655b3ef7cc2 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -307,7 +307,7 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand,
 	if (req->type == NAND_PAGE_WRITE)
 		return 0;
 
-	/* Finish a page write: check the status, report errors/bitflips */
+	/* Finish a page read: check the status, report errors/bitflips */
 	ret = spinand_check_ecc_status(spinand, engine_conf->status);
 	if (ret == -EBADMSG)
 		mtd->ecc_stats.failed++;
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:20 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:20 +0200
Subject: [RFC PATCH 02/10] mtd: spinand: macronix: Use random program load
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-3-miquel.raynal@bootlin.com>

From: Mason Yang <masonccyang at mxic.com.tw>

Macronix SPI-NAND chips might benefit from an external ECC
engine. Such an engine might need to access random columns, thus needing
to use random commands (0x84 instead of 0x02).

Signed-off-by: Mason Yang <masonccyang at mxic.com.tw>
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/spi/macronix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index a9890350db02..a97e027bcaad 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -20,7 +20,7 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
 
 static SPINAND_OP_VARIANTS(write_cache_variants,
 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
-		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
 static SPINAND_OP_VARIANTS(update_cache_variants,
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:21 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:21 +0200
Subject: [RFC PATCH 03/10] dt-bindings: vendor-prefixes: Update Macronix prefix
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-4-miquel.raynal@bootlin.com>

When looking at compatible prefixes, Macronix is sometimes referred as
mxicy:
- mxicy,mx25r1635f
- mxicy,mx25u6435f
- mxicy,mx25v8035f
- mxicy,mx25f0a-spi
and sometimes as mxic:
- mxic,multi-itfc-v009-nand-controller
- mxic,enable-randomizer-otp

It looks like the more up-to-date way is mxic so declare this prefix and
mark the other one as deprecated.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index b868cefc7c55..013a87850cd5 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -758,8 +758,11 @@ patternProperties:
     description: Mundo Reader S.L.
   "^murata,.*":
     description: Murata Manufacturing Co., Ltd.
+  "^mxic,.*":
+    description: Macronix International Co., Ltd.
   "^mxicy,.*":
     description: Macronix International Co., Ltd.
+    deprecated: true
   "^myir,.*":
     description: MYIR Tech Limited
   "^national,.*":
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:22 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:22 +0200
Subject: [RFC PATCH 04/10] dt-bindings: mtd: Describe Macronix NAND ECC engine
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-5-miquel.raynal@bootlin.com>

Describe Macronix NAND ECC engine. This engine may be used as an
external engine or pipelined, both ways are shown in the examples.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../bindings/mtd/mxic,nand-ecc-engine.yaml    | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml

diff --git a/Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml b/Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml
new file mode 100644
index 000000000000..2f5cf1a4e826
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/mxic,nand-ecc-engine.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Macronix NAND ECC engine device tree bindings
+
+maintainers:
+  - Miquel Raynal <miquel.raynal at bootlin.com>
+
+properties:
+  compatible:
+    items:
+      - const: mxic,nand-ecc-engine-rev3
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    /* External configuration */
+    spi_controller0: spi at 43c30000 {
+        compatible = "mxicy,mx25f0a-spi";
+       	reg = <0x43c30000 0x10000>, <0xa0000000 0x4000000>;
+       	reg-names = "regs", "dirmap";
+       	clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
+       	clock-names = "send_clk", "send_dly_clk", "ps_clk";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        flash at 0 {
+            compatible = "spi-nand";
+            reg = <0>;
+            nand-ecc-engine = <&ecc_engine0>;
+        };
+    };
+
+    ecc_engine0: ecc at 43c40000 {
+        compatible = "mxic,nand-ecc-engine-rev3";
+        reg = <0x43c40000 0x10000>;
+    };
+
+  - |
+    /* Pipelined configuration */
+    spi_controller1: spi at 43c30000 {
+        compatible = "mxicy,mx25f0a-spi";
+       	reg = <0x43c30000 0x10000>, <0xa0000000 0x4000000>;
+       	reg-names = "regs", "dirmap";
+       	clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
+       	clock-names = "send_clk", "send_dly_clk", "ps_clk";
+        #address-cells = <1>;
+        #size-cells = <0>;
+        nand-ecc-engine = <&ecc_engine1>;
+
+        flash at 0 {
+            compatible = "spi-nand";
+            reg = <0>;
+            nand-ecc-engine = <&spi_controller1>;
+        };
+    };
+
+    ecc_engine1: ecc at 43c40000 {
+        compatible = "mxic,nand-ecc-engine-rev3";
+        reg = <0x43c40000 0x10000>;
+    };
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:23 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:23 +0200
Subject: [RFC PATCH 05/10] mtd: nand: ecc: Add infrastructure to support
 hardware engines
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-6-miquel.raynal@bootlin.com>

Add the necessary helpers to register/unregister hardware ECC engines
that will be called from ECC engine drivers.

Also add helpers to get the right engine from the user
perspective. Keep a reference of the in use ECC engine in order to
prevent modules to be unloaded. Put the reference when the engine gets
retired.

A static list of hardware (only) ECC engines is setup to keep track of
the registered engines.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/core.c  | 10 +++--
 drivers/mtd/nand/ecc.c   | 89 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h | 11 +++++
 3 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index df9646685c91..5628bd410f7e 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -232,7 +232,9 @@ static int nanddev_get_ecc_engine(struct nand_device *nand)
 		nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
+		if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
 		break;
 	default:
 		pr_err("Missing ECC engine type\n");
@@ -252,7 +254,7 @@ static int nanddev_put_ecc_engine(struct nand_device *nand)
 {
 	switch (nand->ecc.ctx.conf.engine_type) {
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand_ecc_put_on_host_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_NONE:
 	case NAND_ECC_ENGINE_TYPE_SOFT:
@@ -297,7 +299,9 @@ int nanddev_ecc_engine_init(struct nand_device *nand)
 	/* Look for the ECC engine to use */
 	ret = nanddev_get_ecc_engine(nand);
 	if (ret) {
-		pr_err("No ECC engine found\n");
+		if (ret != -EPROBE_DEFER)
+			pr_err("No ECC engine found\n");
+
 		return ret;
 	}
 
diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
index 6c43dfda01d4..3aa56c990d11 100644
--- a/drivers/mtd/nand/ecc.c
+++ b/drivers/mtd/nand/ecc.c
@@ -96,6 +96,12 @@
 #include <linux/module.h>
 #include <linux/mtd/nand.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+static LIST_HEAD(on_host_hw_engines);
+static DEFINE_MUTEX(on_host_hw_engines_mutex);
 
 /**
  * nand_ecc_init_ctx - Init the ECC engine context
@@ -611,6 +617,89 @@ struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand)
 }
 EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine);
 
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	struct nand_ecc_engine *item;
+
+	if (!engine)
+		return -ENOTSUPP;
+
+	/* Prevent multiple registrations of one engine */
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item == engine)
+			return 0;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_add_tail(&engine->node, &on_host_hw_engines);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_register_on_host_hw_engine);
+
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	if (!engine)
+		return -ENOTSUPP;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_del(&engine->node);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_unregister_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev)
+{
+	struct nand_ecc_engine *item;
+
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item->dev == dev)
+			return item;
+
+	return NULL;
+}
+EXPORT_SYMBOL(nand_ecc_match_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand)
+{
+	struct nand_ecc_engine *engine = NULL;
+	struct device *dev = &nand->mtd.dev;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	if (list_empty(&on_host_hw_engines))
+		return NULL;
+
+	/* Check for an explicit nand-ecc-engine property */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (np) {
+		pdev = of_find_device_by_node(np);
+		if (!pdev)
+			return ERR_PTR(-EPROBE_DEFER);
+
+		engine = nand_ecc_match_on_host_hw_engine(&pdev->dev);
+		platform_device_put(pdev);
+		of_node_put(np);
+
+		if (!engine)
+			return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	if (engine)
+		get_device(engine->dev);
+
+	return engine;
+}
+EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine);
+
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand)
+{
+	put_device(nand->ecc.engine->dev);
+}
+EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal at bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 32fc7edf65b3..5ffd3e359515 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -265,10 +265,16 @@ struct nand_ecc_engine_ops {
 
 /**
  * struct nand_ecc_engine - ECC engine abstraction for NAND devices
+ * @dev: Host device
+ * @node: Private field for registration time
  * @ops: ECC engine operations
+ * @priv: Private data
  */
 struct nand_ecc_engine {
+	struct device *dev;
+	struct list_head node;
 	struct nand_ecc_engine_ops *ops;
+	void *priv;
 };
 
 void of_get_nand_ecc_user_config(struct nand_device *nand);
@@ -279,8 +285,13 @@ 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);
 bool nand_ecc_is_strong_enough(struct nand_device *nand);
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine);
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine);
 struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
 struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev);
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand);
 
 #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING)
 struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:24 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:24 +0200
Subject: [RFC PATCH 06/10] mtd: nand: mxic-ecc: Add Macronix external ECC
 engine support
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-7-miquel.raynal@bootlin.com>

Some SPI-NAND chips do not support on-die ECC. For these chips,
correction must apply on the SPI controller end. In order to avoid
doing all the calculations by software, Macronix provides a specific
engine that can offload the intensive work.

Add Macronix ECC engine support, this engine can work in conjunction
with a SPI controller and a raw NAND controller, it can be pipelined
or external and supports linear and syndrome layouts.

Right now the simplest configuration is supported: SPI controller
external and linear ECC engine.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/Kconfig    |   6 +
 drivers/mtd/nand/Makefile   |   1 +
 drivers/mtd/nand/ecc-mxic.c | 655 ++++++++++++++++++++++++++++++++++++
 3 files changed, 662 insertions(+)
 create mode 100644 drivers/mtd/nand/ecc-mxic.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index b40455234cbd..8431292ff49d 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -46,6 +46,12 @@ config MTD_NAND_ECC_SW_BCH
 	  ECC codes. They are used with NAND devices requiring more than 1 bit
 	  of error correction.
 
+config MTD_NAND_ECC_MXIC
+	bool "Macronix external hardware ECC engine"
+	select MTD_NAND_ECC
+	help
+	  This enables support for the hardware ECC engine from Macronix.
+
 endmenu
 
 endmenu
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1c0b46960eb1..a4e6b7ae0614 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -10,3 +10,4 @@ obj-y	+= spi/
 nandcore-$(CONFIG_MTD_NAND_ECC) += ecc.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_HAMMING) += ecc-sw-hamming.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_BCH) += ecc-sw-bch.o
+nandcore-$(CONFIG_MTD_NAND_ECC_MXIC) += ecc-mxic.o
diff --git a/drivers/mtd/nand/ecc-mxic.c b/drivers/mtd/nand/ecc-mxic.c
new file mode 100644
index 000000000000..8be816381f68
--- /dev/null
+++ b/drivers/mtd/nand/ecc-mxic.c
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for Macronix external hardware ECC engine for NAND devices, also
+ * called DPE for Data Processing Engine.
+ *
+ * Copyright ? 2019 Macronix
+ * Author: Miquel Raynal <miquel.raynal at bootlin.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* DPE Configuration */
+#define DP_CONFIG 0x00
+#define   ECC_EN BIT(0)
+#define   ECC_TYP(idx) (((idx) << 3) & GENMASK(6, 3))
+/* DPE Interrupt Status */
+#define INTRPT_STS 0x04
+#define   TRANS_CMPLT BIT(0)
+#define   SDMA_MAIN BIT(1)
+#define   SDMA_SPARE BIT(2)
+#define   ECC_ERR BIT(3)
+#define   TO_SPARE BIT(4)
+#define   TO_MAIN BIT(5)
+/* DPE Interrupt Status Enable */
+#define INTRPT_STS_EN 0x08
+/* DPE Interrupt Signal Enable */
+#define INTRPT_SIG_EN 0x0C
+/* Host Controller Configuration */
+#define HC_CONFIG 0x10
+#define   MEM2MEM BIT(4) /* TRANS_TYP_IO in the spec */
+#define   ECC_PACKED 0 /* LAYOUT_TYP_INTEGRATED in the spec */
+#define   ECC_INTERLEAVED BIT(2) /* LAYOUT_TYP_DISTRIBUTED in the spec */
+#define   BURST_TYP_FIXED 0
+#define   BURST_TYP_INCREASING BIT(0)
+/* Host Controller Slave Address */
+#define HC_SLV_ADDR 0x14
+/* ECC Chunk Size */
+#define CHUNK_SIZE 0x20
+/* Main Data Size */
+#define MAIN_SIZE 0x24
+/* Spare Data Size */
+#define SPARE_SIZE 0x28
+#define   META_SZ(reg) ((reg) & GENMASK(7, 0))
+#define   PARITY_SZ(reg) (((reg) & GENMASK(15, 8)) >> 8)
+#define   RSV_SZ(reg) (((reg) & GENMASK(23, 16)) >> 16)
+#define   SPARE_SZ(reg) ((reg) >> 24)
+/* ECC Chunk Count */
+#define CHUNK_CNT 0x30
+/* SDMA Control */
+#define SDMA_CTRL 0x40
+#define   WRITE_NAND 0
+#define   READ_NAND BIT(1)
+#define   CONT_NAND BIT(29)
+#define   CONT_SYSM BIT(30) /* Continue System Memory? */
+#define   SDMA_STRT BIT(31)
+/* SDMA Address of Main Data */
+#define SDMA_MAIN_ADDR 0x44
+/* SDMA Address of Spare Data */
+#define SDMA_SPARE_ADDR 0x48
+/* DPE Version Number */
+#define DP_VER 0xD0
+#define   DP_VER_OFFSET 16
+
+/* Status bytes between each chunk of spare data */
+#define STAT_BYTES 4
+#define   NO_ERR 0x00
+#define   MAX_CORR_ERR 0x28
+#define   UNCORR_ERR 0xFE
+#define   ERASED_CHUNK 0xFF
+
+struct mxic_ecc_engine {
+	struct device *dev;
+	void __iomem *regs;
+
+	/* ECC machinery */
+	unsigned int data_step_sz;
+	unsigned int oob_step_sz;
+	unsigned int parity_sz;
+	unsigned int meta_sz;
+	u8 *status;
+	int steps;
+
+	/* Completion boilerplate */
+	int irq;
+	struct completion complete;
+
+	/* DMA boilerplate */
+	struct nand_ecc_req_tweak_ctx req_ctx;
+	u8 *oobwithstat;
+	struct scatterlist sg[2];
+	struct nand_page_io_req *req;
+};
+
+static int mxic_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (section < 0 || section >= eng->steps)
+		return -ERANGE;
+
+	oobregion->offset = (section * eng->oob_step_sz) + eng->meta_sz;
+	oobregion->length = eng->parity_sz;
+
+	return 0;
+}
+
+static int mxic_ecc_ooblayout_free(struct mtd_info *mtd, int section,
+				   struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (section < 0 || section >= eng->steps)
+		return -ERANGE;
+
+	if (!section) {
+		oobregion->offset = 2;
+		oobregion->length = eng->meta_sz - 2;
+	} else {
+		oobregion->offset = section * eng->oob_step_sz;
+		oobregion->length = eng->meta_sz;
+	}
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops mxic_ecc_ooblayout_ops = {
+	.ecc = mxic_ecc_ooblayout_ecc,
+	.free = mxic_ecc_ooblayout_free,
+};
+
+static void mxic_ecc_disable_engine(struct mxic_ecc_engine *eng)
+{
+	u32 reg;
+
+	reg = readl(eng->regs + DP_CONFIG);
+	reg &= ~ECC_EN;
+	writel(reg, eng->regs + DP_CONFIG);
+}
+
+static void mxic_ecc_enable_engine(struct mxic_ecc_engine *eng)
+{
+	u32 reg;
+
+	reg = readl(eng->regs + DP_CONFIG);
+	reg |= ECC_EN;
+	writel(reg, eng->regs + DP_CONFIG);
+}
+
+static void mxic_ecc_disable_int(struct mxic_ecc_engine *eng)
+{
+	writel(0, eng->regs + INTRPT_SIG_EN);
+}
+
+static void mxic_ecc_enable_int(struct mxic_ecc_engine *eng)
+{
+	writel(TRANS_CMPLT, eng->regs + INTRPT_SIG_EN);
+}
+
+static irqreturn_t mxic_ecc_isr(int irq, void *dev_id)
+{
+	struct mxic_ecc_engine *eng = dev_id;
+	u32 sts;
+
+	sts = readl(eng->regs + INTRPT_STS);
+	if (!sts)
+		return IRQ_NONE;
+
+	if (sts & TRANS_CMPLT)
+		complete(&eng->complete);
+
+	writel(sts, eng->regs + INTRPT_STS);
+
+	return IRQ_HANDLED;
+}
+
+static int mxic_ecc_init_ctx(struct nand_device *nand, struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	struct nand_ecc_props *reqs = &nand->ecc.requirements;
+	struct nand_ecc_props *user = &nand->ecc.user_conf;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct mxic_ecc_engine *eng;
+	int step_size = 0, strength = 0, desired_correction = 0, steps, idx;
+	int possible_strength[] = {4, 8, 40, 48};
+	int spare_size[] = {32, 32, 96, 96};
+	u32 spare_reg;
+	int ret;
+
+	eng = devm_kzalloc(dev, sizeof(*eng), GFP_KERNEL);
+	if (!eng)
+		return -ENOMEM;
+
+	nand->ecc.ctx.priv = eng;
+	nand->ecc.engine->priv = eng;
+
+	eng->dev = dev;
+
+	/*
+	 * Both memory regions for the ECC engine itself and the AXI slave
+	 * address are mandatory.
+	 */
+	eng->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(eng->regs)) {
+		dev_err(dev, "Missing memory region\n");
+		return PTR_ERR(eng->regs);
+	}
+
+	mxic_ecc_disable_engine(eng);
+	mxic_ecc_disable_int(eng);
+
+	/* IRQ is optional yet much more efficient */
+	eng->irq = platform_get_irq_byname(pdev, "ecc-engine");
+	if (eng->irq > 0) {
+		ret = devm_request_irq(dev, eng->irq, mxic_ecc_isr, 0,
+				       "mxic-ecc", eng);
+		if (ret)
+			return ret;
+	} else {
+		dev_info(dev, "No ECC engine IRQ (%d), using polling\n",
+			 eng->irq);
+		eng->irq = 0;
+	}
+
+	/* 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;
+	}
+
+	mtd_set_ooblayout(mtd, &mxic_ecc_ooblayout_ops);
+
+	/* Enable all status bits */
+	writel(TRANS_CMPLT | SDMA_MAIN | SDMA_SPARE | ECC_ERR |
+	       TO_SPARE | TO_MAIN, eng->regs + INTRPT_STS_EN);
+
+	/* Configure the correction depending on the NAND device topology */
+	if (user->step_size && user->strength) {
+		step_size = user->step_size;
+		strength = user->strength;
+	} else if (reqs->step_size && reqs->strength) {
+		step_size = reqs->step_size;
+		strength = reqs->strength;
+	}
+
+	if (step_size && strength) {
+		steps = mtd->writesize / step_size;
+		desired_correction = steps * strength;
+	}
+
+	/* Step size is fixed to 1kiB, strength may vary (4 possible values) */
+	conf->step_size = SZ_1K;
+	steps = mtd->writesize / conf->step_size;
+
+	eng->status = devm_kzalloc(dev, steps * sizeof(u8), GFP_KERNEL);
+	if (!eng->status)
+		return -ENOMEM;
+
+	if (desired_correction) {
+		strength = desired_correction / steps;
+
+		for (idx = 0; idx < ARRAY_SIZE(possible_strength); idx++)
+			if (possible_strength[idx] >= strength)
+				break;
+
+		idx = min_t(unsigned int, idx,
+			    ARRAY_SIZE(possible_strength) - 1);
+	} else {
+		/* Missing data, maximize the correction */
+		idx = ARRAY_SIZE(possible_strength) - 1;
+	}
+
+	/* Tune the selected strength until it fits in the OOB area */
+	for (; idx >= 0; idx--) {
+		if (spare_size[idx] * steps <= mtd->oobsize)
+			break;
+	}
+
+	/* This engine cannot be used with this NAND device */
+	if (idx < 0)
+		return -EINVAL;
+
+	/* Configure the engine for the desired strength */
+	writel(ECC_TYP(idx), eng->regs + DP_CONFIG);
+	conf->strength = possible_strength[idx];
+	spare_reg = readl(eng->regs + SPARE_SIZE);
+
+	eng->steps = steps;
+	eng->data_step_sz = mtd->writesize / steps;
+	eng->oob_step_sz = mtd->oobsize / steps;
+	eng->parity_sz = PARITY_SZ(spare_reg);
+	eng->meta_sz = META_SZ(spare_reg);
+
+	/* Ensure buffers will contain enough bytes to store the STAT_BYTES */
+	eng->req_ctx.oob_buffer_size = nanddev_per_page_oobsize(nand) +
+				       (eng->steps * STAT_BYTES);
+	ret = nand_ecc_init_req_tweaking(&eng->req_ctx, nand);
+	if (ret)
+		return ret;
+
+	eng->oobwithstat = kmalloc(mtd->oobsize + (eng->steps * STAT_BYTES),
+				   GFP_KERNEL);
+	if (!eng->oobwithstat) {
+		ret = -ENOMEM;
+		goto cleanup_req_tweak;
+	}
+
+	sg_init_table(eng->sg, 2);
+
+	/* Configuration dump and sanity checks */
+	dev_err(dev, "DPE version number: %d\n",
+		readl(eng->regs + DP_VER) >> DP_VER_OFFSET);
+	dev_err(dev, "Chunk size: %d\n", readl(eng->regs + CHUNK_SIZE));
+	dev_err(dev, "Main size: %d\n", readl(eng->regs + MAIN_SIZE));
+	dev_err(dev, "Spare size: %d\n", SPARE_SZ(spare_reg));
+	dev_err(dev, "Rsv size: %ld\n", RSV_SZ(spare_reg));
+	dev_err(dev, "Parity size: %d\n", eng->parity_sz);
+	dev_err(dev, "Meta size: %d\n", eng->meta_sz);
+
+	if (eng->meta_sz + eng->parity_sz + RSV_SZ(spare_reg) != SPARE_SZ(spare_reg)) {
+		dev_err(dev, "Wrong OOB configuration: %d + %d + %ld != %d\n",
+			eng->meta_sz, eng->parity_sz, RSV_SZ(spare_reg),
+			SPARE_SZ(spare_reg));
+		ret = -EINVAL;
+		goto free_oobwithstat;
+	}
+
+	if (eng->oob_step_sz != SPARE_SZ(spare_reg)) {
+		dev_err(dev, "Wrong OOB configuration: %d != %d\n",
+			eng->oob_step_sz, SPARE_SZ(spare_reg));
+		ret = -EINVAL;
+		goto free_oobwithstat;
+	}
+
+	return 0;
+
+free_oobwithstat:
+	kfree(eng->oobwithstat);
+cleanup_req_tweak:
+	nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+
+	return ret;
+}
+
+static int mxic_ecc_init_ctx_external(struct nand_device *nand)
+{
+	struct device *dev = nand->ecc.engine->dev;
+	struct mxic_ecc_engine *eng;
+	int ret;
+
+	dev_info(dev, "Macronix ECC engine in external mode\n");
+
+	ret = mxic_ecc_init_ctx(nand, dev);
+	if (ret)
+		return ret;
+
+	eng = nand->ecc.ctx.priv;
+
+	/* Trigger each step manually */
+	writel(1, eng->regs + CHUNK_CNT);
+	writel(BURST_TYP_INCREASING | ECC_PACKED | MEM2MEM,
+	       eng->regs + HC_CONFIG);
+
+	return 0;
+}
+
+static void mxic_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (eng) {
+		nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+		kfree(eng->oobwithstat);
+	}
+}
+
+static int mxic_ecc_data_xfer_wait_for_completion(struct mxic_ecc_engine *eng)
+{
+	u32 val;
+	int ret;
+
+	if (eng->irq) {
+		init_completion(&eng->complete);
+		mxic_ecc_enable_int(eng);
+		ret = wait_for_completion_timeout(&eng->complete,
+						  msecs_to_jiffies(1000));
+		mxic_ecc_disable_int(eng);
+	} else {
+		ret = readl_poll_timeout(eng->regs + INTRPT_STS, val,
+					 val & TRANS_CMPLT, 10, USEC_PER_SEC);
+		writel(val, eng->regs + INTRPT_STS);
+	}
+
+	if (ret) {
+		dev_err(eng->dev, "Timeout on data xfer completion (sts 0x%08x)\n", val);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int mxic_ecc_process_data(struct mxic_ecc_engine *eng)
+{
+	/* Retrieve the direction */
+	unsigned int dir = (eng->req->type == NAND_PAGE_READ) ?
+			   READ_NAND : WRITE_NAND;
+
+	/* Trigger processing */
+	writel(SDMA_STRT | dir, eng->regs + SDMA_CTRL);
+
+	/* Wait for completion */
+	return mxic_ecc_data_xfer_wait_for_completion(eng);
+}
+
+static void mxic_ecc_extract_status_bytes(struct mxic_ecc_engine *eng, u8 *buf)
+{
+	int next_stat_pos;
+	int step;
+
+	/* Extract the ECC status */
+	for (step = 0; step < eng->steps; step++) {
+		next_stat_pos = eng->oob_step_sz +
+				((STAT_BYTES + eng->oob_step_sz) * step);
+
+		eng->status[step] = buf[next_stat_pos];
+	}
+}
+
+static void mxic_ecc_reconstruct_oobbuf(struct mxic_ecc_engine *eng,
+					u8 *dst, const u8 *src)
+{
+	int step;
+
+	/* Reconstruct the OOB buffer linearly (without the ECC status bytes) */
+	for (step = 0; step < eng->steps; step++)
+		memcpy(dst + (step * eng->oob_step_sz),
+		       src + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->oob_step_sz);
+}
+
+static void mxic_ecc_add_room_in_oobbuf(struct mxic_ecc_engine *eng,
+					u8 *dst, const u8 *src)
+{
+	int step;
+
+	/* Add some space in the OOB buffer for the status bytes */
+	for (step = 0; step < eng->steps; step++)
+		memcpy(dst + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       src + (step * eng->oob_step_sz),
+		       eng->oob_step_sz);
+}
+
+static int mxic_ecc_count_biterrs(struct mxic_ecc_engine *eng, struct mtd_info *mtd)
+{
+	struct device *dev = eng->dev;
+	unsigned int max_bf = 0;
+	int step;
+
+	for (step = 0; step < eng->steps; step++) {
+		u8 stat = eng->status[step];
+
+		if (stat == NO_ERR) {
+			dev_dbg(dev, "ECC step %d: no error\n", step);
+		} else if (stat == ERASED_CHUNK) {
+			dev_dbg(dev, "ECC step %d: erased\n", step);
+		} else if (stat == UNCORR_ERR || stat > MAX_CORR_ERR) {
+			dev_dbg(dev, "ECC step %d: uncorrectable\n", step);
+			mtd->ecc_stats.failed++;
+		} else {
+			dev_dbg(dev, "ECC step %d: %d bits corrected\n",
+				step, stat);
+			max_bf = max_t(unsigned int, max_bf, stat);
+			mtd->ecc_stats.corrected += stat;
+		}
+	}
+
+	return max_bf;
+}
+
+/* External ECC engine helpers */
+static int mxic_ecc_prepare_io_req_external(struct nand_device *nand,
+					    struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int offset, nents, step, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	nand_ecc_tweak_req(&eng->req_ctx, req);
+	eng->req = req;
+
+	if (req->type == NAND_PAGE_READ)
+		return 0;
+
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.out);
+
+	sg_set_buf(&eng->sg[0], req->databuf.out, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	mxic_ecc_enable_engine(eng);
+
+	for (step = 0; step < eng->steps; step++) {
+		writel(sg_dma_address(&eng->sg[0]) + (step * eng->data_step_sz),
+		       eng->regs + SDMA_MAIN_ADDR);
+		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->regs + SDMA_SPARE_ADDR);
+		ret = mxic_ecc_process_data(eng);
+		if (ret)
+			break;
+	}
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	/* Retrieve the calculated ECC bytes */
+	for (step = 0; step < eng->steps; step++) {
+		offset = eng->meta_sz + (step * eng->oob_step_sz);
+		mtd_ooblayout_get_eccbytes(mtd,
+					   (u8 *)eng->req->oobbuf.out + offset,
+					   eng->oobwithstat,
+					   step * eng->parity_sz,
+					   eng->parity_sz);
+	}
+
+	return ret;
+}
+
+static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
+					   struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int nents, step, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	if (req->type == NAND_PAGE_WRITE) {
+		nand_ecc_restore_req(&eng->req_ctx, req);
+		return 0;
+	}
+
+	/* Copy the OOB buffer and add room for the ECC engine status bytes */
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.in);
+
+	sg_set_buf(&eng->sg[0], req->databuf.in, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	mxic_ecc_enable_engine(eng);
+
+	for (step = 0; step < eng->steps; step++) {
+		writel(sg_dma_address(&eng->sg[0]) + (step * eng->data_step_sz),
+		       eng->regs + SDMA_MAIN_ADDR);
+		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->regs + SDMA_SPARE_ADDR);
+		ret = mxic_ecc_process_data(eng);
+		if (ret)
+			break;
+	}
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	/* Extract the status bytes and reconstruct the buffer */
+	mxic_ecc_extract_status_bytes(eng, eng->oobwithstat);
+	mxic_ecc_reconstruct_oobbuf(eng, eng->req->oobbuf.in, eng->oobwithstat);
+
+	nand_ecc_restore_req(&eng->req_ctx, req);
+
+	return mxic_ecc_count_biterrs(eng, mtd);
+}
+
+static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
+	.init_ctx = mxic_ecc_init_ctx_external,
+	.cleanup_ctx = mxic_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_ecc_prepare_io_req_external,
+	.finish_io_req = mxic_ecc_finish_io_req_external,
+};
+
+static int mxic_ecc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nand_ecc_engine *ecceng;
+
+	ecceng = devm_kzalloc(dev, sizeof(*ecceng), GFP_KERNEL);
+	if (!ecceng)
+		return -ENOMEM;
+
+	ecceng->dev = dev;
+	ecceng->ops = &mxic_ecc_engine_external_ops;
+	nand_ecc_register_on_host_hw_engine(ecceng);
+
+	return 0;
+}
+
+static int mxic_ecc_remove(struct platform_device *pdev)
+{
+	struct nand_ecc_engine *ecceng;
+
+	ecceng = nand_ecc_match_on_host_hw_engine(&pdev->dev);
+	if (ecceng)
+		nand_ecc_unregister_on_host_hw_engine(ecceng);
+
+	return 0;
+}
+
+static const struct of_device_id mxic_ecc_of_ids[] = {
+	{
+		.compatible = "mxic,nand-ecc-engine-rev3",
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mxic_ecc_of_ids);
+
+static struct platform_driver mxic_ecc_driver = {
+	.driver	= {
+		.name = "mxic-nand-ecc-engine",
+		.of_match_table = mxic_ecc_of_ids,
+	},
+	.probe = mxic_ecc_probe,
+	.remove	= mxic_ecc_remove,
+};
+module_platform_driver(mxic_ecc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal at bootlin.com>");
+MODULE_DESCRIPTION("Macronix NAND hardware ECC controller");
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:25 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:25 +0200
Subject: [RFC PATCH 07/10] mtd: nand: mxic-ecc: Support SPI pipelined mode
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-8-miquel.raynal@bootlin.com>

Introduce the support for another possible configuration: the ECC
engine may work as DMA master (pipelined) and move itself the data
to/from the NAND chip into the buffer, applying the necessary
corrections/computations on the fly.

This driver offers an ECC engine implementation that must be
instatiated from a SPI controller driver.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/ecc-mxic.c       | 148 +++++++++++++++++++++++++++++-
 include/linux/mtd/nand-ecc-mxic.h |  36 ++++++++
 2 files changed, 181 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/mtd/nand-ecc-mxic.h

diff --git a/drivers/mtd/nand/ecc-mxic.c b/drivers/mtd/nand/ecc-mxic.c
index 8be816381f68..509e50a9136e 100644
--- a/drivers/mtd/nand/ecc-mxic.c
+++ b/drivers/mtd/nand/ecc-mxic.c
@@ -39,7 +39,9 @@
 #define INTRPT_SIG_EN 0x0C
 /* Host Controller Configuration */
 #define HC_CONFIG 0x10
+#define   DEV2MEM 0 /* TRANS_TYP_DMA in the spec */
 #define   MEM2MEM BIT(4) /* TRANS_TYP_IO in the spec */
+#define   MAPPING BIT(5) /* TRANS_TYP_MAPPING in the spec */
 #define   ECC_PACKED 0 /* LAYOUT_TYP_INTEGRATED in the spec */
 #define   ECC_INTERLEAVED BIT(2) /* LAYOUT_TYP_DISTRIBUTED in the spec */
 #define   BURST_TYP_FIXED 0
@@ -101,6 +103,7 @@ struct mxic_ecc_engine {
 	u8 *oobwithstat;
 	struct scatterlist sg[2];
 	struct nand_page_io_req *req;
+	unsigned int pageoffs;
 };
 
 static int mxic_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
@@ -188,6 +191,31 @@ static irqreturn_t mxic_ecc_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static struct device *mxic_ecc_get_engine_dev(struct device *dev)
+{
+	struct platform_device *eccpdev;
+	struct device_node *np;
+
+	/*
+	 * If the device node contains this property, it means the device does
+	 * not represent the actual ECC engine.
+	 */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (!np)
+		return dev;
+
+	eccpdev = of_find_device_by_node(np);
+	if (!eccpdev) {
+		of_node_put(np);
+		return NULL;
+	}
+
+	platform_device_put(eccpdev);
+	of_node_put(np);
+
+	return &eccpdev->dev;
+}
+
 static int mxic_ecc_init_ctx(struct nand_device *nand, struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -379,6 +407,41 @@ static int mxic_ecc_init_ctx_external(struct nand_device *nand)
 	return 0;
 }
 
+static int mxic_ecc_init_ctx_pipelined(struct nand_device *nand)
+{
+	struct mxic_ecc_engine *eng;
+	struct device *dev;
+	int ret;
+
+	/*
+	 * In the case of a pipelined engine, the device registering the ECC
+	 * engine is not the actual ECC engine device but the host controller.
+	 */
+	dev = mxic_ecc_get_engine_dev(nand->ecc.engine->dev);
+	if (!dev)
+		return -EINVAL;
+
+	dev_info(dev, "Macronix ECC engine in pipelined/mapping mode\n");
+
+	ret = mxic_ecc_init_ctx(nand, dev);
+	if (ret)
+		return ret;
+
+	eng = nand->ecc.ctx.priv;
+
+	/* All steps should be handled in one go directly by the internal DMA */
+	writel(eng->steps, eng->regs + CHUNK_CNT);
+
+	/*
+	 * Interleaved ECC scheme cannot be used otherwise factory bad block
+	 * markers would be lost. A packed layout is mandatory.
+	 */
+	writel(BURST_TYP_INCREASING | ECC_PACKED | MAPPING,
+	       eng->regs + HC_CONFIG);
+
+	return 0;
+}
+
 static void mxic_ecc_cleanup_ctx(struct nand_device *nand)
 {
 	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
@@ -414,18 +477,22 @@ static int mxic_ecc_data_xfer_wait_for_completion(struct mxic_ecc_engine *eng)
 	return 0;
 }
 
-static int mxic_ecc_process_data(struct mxic_ecc_engine *eng)
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
 {
 	/* Retrieve the direction */
 	unsigned int dir = (eng->req->type == NAND_PAGE_READ) ?
 			   READ_NAND : WRITE_NAND;
 
+	if (dirmap)
+		writel(dirmap, eng->regs + HC_SLV_ADDR);
+
 	/* Trigger processing */
 	writel(SDMA_STRT | dir, eng->regs + SDMA_CTRL);
 
 	/* Wait for completion */
 	return mxic_ecc_data_xfer_wait_for_completion(eng);
 }
+EXPORT_SYMBOL_GPL(mxic_ecc_process_data);
 
 static void mxic_ecc_extract_status_bytes(struct mxic_ecc_engine *eng, u8 *buf)
 {
@@ -526,7 +593,7 @@ static int mxic_ecc_prepare_io_req_external(struct nand_device *nand,
 		       eng->regs + SDMA_MAIN_ADDR);
 		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
 		       eng->regs + SDMA_SPARE_ADDR);
-		ret = mxic_ecc_process_data(eng);
+		ret = mxic_ecc_process_data(eng, 0);
 		if (ret)
 			break;
 	}
@@ -580,7 +647,7 @@ static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
 		       eng->regs + SDMA_MAIN_ADDR);
 		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
 		       eng->regs + SDMA_SPARE_ADDR);
-		ret = mxic_ecc_process_data(eng);
+		ret = mxic_ecc_process_data(eng, 0);
 		if (ret)
 			break;
 	}
@@ -598,6 +665,64 @@ static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
 	return mxic_ecc_count_biterrs(eng, mtd);
 }
 
+/* Pipelined ECC engine helpers */
+static int mxic_ecc_prepare_io_req_pipelined(struct nand_device *nand,
+					     struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	int nents;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	nand_ecc_tweak_req(&eng->req_ctx, req);
+	eng->req = req;
+
+	/* Copy the OOB buffer and add room for the ECC engine status bytes */
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.in);
+
+	sg_set_buf(&eng->sg[0], req->databuf.in, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	writel(sg_dma_address(&eng->sg[0]), eng->regs + SDMA_MAIN_ADDR);
+	writel(sg_dma_address(&eng->sg[1]), eng->regs + SDMA_SPARE_ADDR);
+
+	mxic_ecc_enable_engine(eng);
+
+	return 0;
+}
+
+static int mxic_ecc_finish_io_req_pipelined(struct nand_device *nand,
+					    struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int ret = 0;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	if (req->type == NAND_PAGE_READ) {
+		mxic_ecc_extract_status_bytes(eng, eng->oobwithstat);
+		mxic_ecc_reconstruct_oobbuf(eng, eng->req->oobbuf.in,
+					    eng->oobwithstat);
+		ret = mxic_ecc_count_biterrs(eng, mtd);
+	}
+
+	nand_ecc_restore_req(&eng->req_ctx, req);
+
+	return ret;
+}
+
 static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
 	.init_ctx = mxic_ecc_init_ctx_external,
 	.cleanup_ctx = mxic_ecc_cleanup_ctx,
@@ -605,6 +730,23 @@ static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
 	.finish_io_req = mxic_ecc_finish_io_req_external,
 };
 
+static struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
+	.init_ctx = mxic_ecc_init_ctx_pipelined,
+	.cleanup_ctx = mxic_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_ecc_prepare_io_req_pipelined,
+	.finish_io_req = mxic_ecc_finish_io_req_pipelined,
+};
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
+{
+	return &mxic_ecc_engine_pipelined_ops;
+}
+EXPORT_SYMBOL_GPL(mxic_ecc_get_pipelined_ops);
+
+/*
+ * Only the external ECC engine is exported as the pipelined is SoC specific, so
+ * it is registered directly by the drivers that wrap it.
+ */
 static int mxic_ecc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
diff --git a/include/linux/mtd/nand-ecc-mxic.h b/include/linux/mtd/nand-ecc-mxic.h
new file mode 100644
index 000000000000..d48b7fe05644
--- /dev/null
+++ b/include/linux/mtd/nand-ecc-mxic.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright ? 2019 Macronix
+ * Author: Miqu?l Raynal <miquel.raynal at bootlin.com>
+ *
+ * Header for the Macronix external ECC engine.
+ */
+
+#ifndef __MTD_NAND_ECC_MXIC_H__
+#define __MTD_NAND_ECC_MXIC_H__
+
+#include <linux/device.h>
+
+struct mxic_ecc_engine;
+
+#if IS_ENABLED(CONFIG_MTD_NAND_ECC_MXIC)
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void);
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap);
+
+#else /* !CONFIG_MTD_NAND_ECC_MXIC */
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
+{
+	return NULL;
+}
+
+static inline
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
+{
+	return -ENOTSUPP;
+}
+
+#endif /* CONFIG_MTD_NAND_ECC_MXIC */
+
+#endif /* __MTD_NAND_ECC_MXIC_H__ */
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:26 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:26 +0200
Subject: [RFC PATCH 08/10] spi: mxic: Fix the transmit path
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-9-miquel.raynal@bootlin.com>

By working with external hardware ECC engines, we figured out that
Under certain circumstances, it is needed for the SPI controller to
check INT_TX_EMPTY and INT_RX_NOT_EMPTY in both receive and transmit
path (not only in the receive path). The delay penalty being
negligible, move this code in the common path.

Fixes: b942d80b0a39 ("spi: Add MXIC controller driver")
Cc: stable at vger.kernel.org
Suggested-by: Mason Yang <masonccyang at mxic.com.tw>
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 96b418293bf2..4fb19e6f94b0 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -304,25 +304,21 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 
 		writel(data, mxic->regs + TXD(nbytes % 4));
 
+		ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+					 sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
+		if (ret)
+			return ret;
+
+		ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+					 sts & INT_RX_NOT_EMPTY, 0,
+					 USEC_PER_SEC);
+		if (ret)
+			return ret;
+
+		data = readl(mxic->regs + RXD);
 		if (rxbuf) {
-			ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
-						 sts & INT_TX_EMPTY, 0,
-						 USEC_PER_SEC);
-			if (ret)
-				return ret;
-
-			ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
-						 sts & INT_RX_NOT_EMPTY, 0,
-						 USEC_PER_SEC);
-			if (ret)
-				return ret;
-
-			data = readl(mxic->regs + RXD);
 			data >>= (8 * (4 - nbytes));
 			memcpy(rxbuf + pos, &data, nbytes);
-			WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
-		} else {
-			readl(mxic->regs + RXD);
 		}
 		WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
 
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:27 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:27 +0200
Subject: [RFC PATCH 09/10] spi: mxic: Add support for direct mapping
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-10-miquel.raynal@bootlin.com>

Implement the ->dirmap_create() and ->dirmap_read/write() hooks to
provide a fast path for read and write accesses.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 171 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 144 insertions(+), 27 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 4fb19e6f94b0..e10c55ee4d06 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -172,6 +172,11 @@ struct mxic_spi {
 	struct clk *send_dly_clk;
 	void __iomem *regs;
 	u32 cur_speed_hz;
+	struct {
+		void __iomem *map;
+		dma_addr_t dma;
+		size_t size;
+	} linear;
 };
 
 static int mxic_spi_clk_enable(struct mxic_spi *mxic)
@@ -280,6 +285,42 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
 	       mxic->regs + HC_CFG);
 }
 
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+{
+	u32 cfg = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
+
+	if (op->addr.nbytes)
+		cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
+		       OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
+
+	if (op->dummy.nbytes)
+		cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
+
+	if (op->data.dir != SPI_MEM_NO_DATA) {
+		cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
+		if (op->data.dir == SPI_MEM_DATA_IN)
+			cfg |= OP_READ;
+	}
+
+	return cfg;
+}
+
+static void mxic_spi_set_hc_cfg(struct spi_device *spi, u32 flags)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
+	int nio = 1;
+
+	if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
+		nio = 4;
+	else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
+		nio = 2;
+
+	writel(flags | HC_CFG_NIO(nio) |
+	       HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
+	       HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1),
+	       mxic->regs + HC_CFG);
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 			      void *rxbuf, unsigned int len)
 {
@@ -328,6 +369,77 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 	return 0;
 }
 
+static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
+					u64 offs, size_t len, void *buf)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+	int ret;
+	u32 sts;
+
+	if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
+		return -EINVAL;
+
+	mxic_spi_set_hc_cfg(desc->mem->spi, 0);
+
+	writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
+	       LMODE_SLV_ACT(desc->mem->spi->chip_select) |
+	       LMODE_EN,
+	       mxic->regs + LRD_CTRL);
+	writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl),
+	       mxic->regs + LRD_CFG);
+	writel(desc->info.offset + offs, mxic->regs + LRD_ADDR);
+	len = min_t(size_t, len, mxic->linear.size);
+	writel(len, mxic->regs + LRD_RANGE);
+
+	memcpy_fromio(buf, mxic->linear.map, len);
+
+	writel(INT_LRD_DIS, mxic->regs + INT_STS);
+	writel(0, mxic->regs + LRD_CTRL);
+
+	ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+				 sts & INT_LRD_DIS, 0, USEC_PER_SEC);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
+static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
+					 u64 offs, size_t len,
+					 const void *buf)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+	u32 sts;
+	int ret;
+
+	if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
+		return -EINVAL;
+
+	mxic_spi_set_hc_cfg(desc->mem->spi, 0);
+
+	writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
+	       LMODE_SLV_ACT(desc->mem->spi->chip_select) |
+	       LMODE_EN,
+	       mxic->regs + LWR_CTRL);
+	writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl),
+	       mxic->regs + LWR_CFG);
+	writel(desc->info.offset + offs, mxic->regs + LWR_ADDR);
+	len = min_t(size_t, len, mxic->linear.size);
+	writel(len, mxic->regs + LWR_RANGE);
+
+	memcpy_toio(mxic->linear.map, buf, len);
+
+	writel(INT_LWR_DIS, mxic->regs + INT_STS);
+	writel(0, mxic->regs + LWR_CTRL);
+
+	ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+				 sts & INT_LWR_DIS, 0, USEC_PER_SEC);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
 static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 				     const struct spi_mem_op *op)
 {
@@ -345,12 +457,27 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 	return spi_mem_default_supports_op(mem, op);
 }
 
+static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+
+	if (!mxic->linear.map)
+		return -ENOTSUPP;
+
+	if (desc->info.offset + desc->info.length > U32_MAX)
+		return -ENOTSUPP;
+
+	if (!mxic_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
+		return -ENOTSUPP;
+
+	return 0;
+}
+
 static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
 	struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
-	int nio = 1, i, ret;
-	u32 ss_ctrl;
+	int i, ret;
 	u8 addr[8];
 	u8 opcode = op->cmd.opcode;
 
@@ -358,34 +485,12 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 	if (ret)
 		return ret;
 
-	if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
-		nio = 4;
-	else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
-		nio = 2;
+	mxic_spi_set_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN);
 
-	writel(HC_CFG_NIO(nio) |
-	       HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
-	       HC_CFG_SLV_ACT(mem->spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1) |
-	       HC_CFG_MAN_CS_EN,
-	       mxic->regs + HC_CFG);
 	writel(HC_EN_BIT, mxic->regs + HC_EN);
 
-	ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
-
-	if (op->addr.nbytes)
-		ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) |
-			   OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
-
-	if (op->dummy.nbytes)
-		ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes);
-
-	if (op->data.nbytes) {
-		ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
-		if (op->data.dir == SPI_MEM_DATA_IN)
-			ss_ctrl |= OP_READ;
-	}
-
-	writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select));
+	writel(mxic_spi_mem_prep_op_cfg(op),
+	       mxic->regs + SS_CTRL(mem->spi->chip_select));
 
 	writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
 	       mxic->regs + HC_CFG);
@@ -423,6 +528,9 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
 	.supports_op = mxic_spi_mem_supports_op,
 	.exec_op = mxic_spi_mem_exec_op,
+	.dirmap_create = mxic_spi_mem_dirmap_create,
+	.dirmap_read = mxic_spi_mem_dirmap_read,
+	.dirmap_write = mxic_spi_mem_dirmap_write,
 };
 
 static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
@@ -552,6 +660,15 @@ static int mxic_spi_probe(struct platform_device *pdev)
 	if (IS_ERR(mxic->regs))
 		return PTR_ERR(mxic->regs);
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
+	mxic->linear.map = devm_ioremap_resource(&pdev->dev, res);
+	if (!IS_ERR(mxic->linear.map)) {
+		mxic->linear.dma = res->start;
+		mxic->linear.size = resource_size(res);
+	} else {
+		mxic->linear.map = NULL;
+	}
+
 	pm_runtime_enable(&pdev->dev);
 	master->auto_runtime_pm = true;
 
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:22:28 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:22:28 +0200
Subject: [RFC PATCH 10/10] spi: mxic: Add support for pipelined ECC operations
In-Reply-To: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
Message-ID: <20211008162228.1753083-11-miquel.raynal@bootlin.com>

Some SPI-NAND chips do not have a proper on-die ECC engine providing
error correction/detection. This is particularly an issue on embedded
devices with limited resources because all the computations must
happen in software, unless an external hardware engine is provided.

These external engines are new and can be of two categories: external
or pipelined. Macronix is providing both, the former being already
supported. The second, however, is very SoC implementation dependent
and must be instantiated by the SPI host controller directly.

An entire subsystem has been contributed to support these engines which
makes the insertion into another subsystem such as SPI quite
straightforward without the need for a lot of specific functions.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 114 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index e10c55ee4d06..9481d1685faf 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -12,6 +12,8 @@
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand-ecc-mxic.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
@@ -167,6 +169,7 @@
 #define HW_TEST(x)		(0xe0 + ((x) * 4))
 
 struct mxic_spi {
+	struct device *dev;
 	struct clk *ps_clk;
 	struct clk *send_clk;
 	struct clk *send_dly_clk;
@@ -177,6 +180,10 @@ struct mxic_spi {
 		dma_addr_t dma;
 		size_t size;
 	} linear;
+	struct {
+		struct nand_ecc_engine *engine;
+		bool enabled;
+	} ecc;
 };
 
 static int mxic_spi_clk_enable(struct mxic_spi *mxic)
@@ -369,6 +376,13 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 	return 0;
 }
 
+static struct mxic_ecc_engine *mxic_spi_to_ecc_engine(struct mxic_spi *mxic)
+{
+	struct nand_ecc_engine *ecc_engine = mxic->ecc.engine;
+
+	return ecc_engine->priv;
+}
+
 static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
 					u64 offs, size_t len, void *buf)
 {
@@ -391,7 +405,14 @@ static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	len = min_t(size_t, len, mxic->linear.size);
 	writel(len, mxic->regs + LRD_RANGE);
 
-	memcpy_fromio(buf, mxic->linear.map, len);
+	if (mxic->ecc.enabled) {
+		ret = mxic_ecc_process_data(mxic_spi_to_ecc_engine(mxic),
+					    mxic->linear.dma + offs);
+		if (ret)
+			return ret;
+	} else {
+		memcpy_fromio(buf, mxic->linear.map, len);
+	}
 
 	writel(INT_LRD_DIS, mxic->regs + INT_STS);
 	writel(0, mxic->regs + LRD_CTRL);
@@ -427,7 +448,14 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	len = min_t(size_t, len, mxic->linear.size);
 	writel(len, mxic->regs + LWR_RANGE);
 
-	memcpy_toio(mxic->linear.map, buf, len);
+	if (mxic->ecc.enabled) {
+		ret = mxic_ecc_process_data(mxic_spi_to_ecc_engine(mxic),
+					    mxic->linear.dma + offs);
+		if (ret)
+			return ret;
+	} else {
+		memcpy_toio(mxic->linear.map, buf, len);
+	}
 
 	writel(INT_LWR_DIS, mxic->regs + INT_STS);
 	writel(0, mxic->regs + LWR_CTRL);
@@ -595,6 +623,80 @@ static int mxic_spi_transfer_one(struct spi_master *master,
 	return 0;
 }
 
+/* ECC wrapper */
+static int mxic_spi_mem_ecc_init_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+
+	return ops->init_ctx(nand);
+}
+
+static void mxic_spi_mem_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+
+	ops->cleanup_ctx(nand);
+}
+
+static struct mxic_spi *mxic_nand_to_spi(struct nand_device *nand)
+{
+	struct device *dev = nand->ecc.engine->dev;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mxic_spi *mxic = spi_master_get_devdata(master);
+
+	return mxic;
+}
+
+static int mxic_spi_mem_ecc_prepare_io_req(struct nand_device *nand,
+					   struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+	struct mxic_spi *mxic = mxic_nand_to_spi(nand);
+
+	mxic->ecc.enabled = (req->mode != MTD_OPS_RAW);
+
+	return ops->prepare_io_req(nand, req);
+}
+
+static int mxic_spi_mem_ecc_finish_io_req(struct nand_device *nand,
+					  struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+	struct mxic_spi *mxic = mxic_nand_to_spi(nand);
+
+	mxic->ecc.enabled = false;
+
+	return ops->finish_io_req(nand, req);
+}
+
+static struct nand_ecc_engine_ops mxic_spi_mem_ecc_engine_pipelined_ops = {
+	.init_ctx = mxic_spi_mem_ecc_init_ctx,
+	.cleanup_ctx = mxic_spi_mem_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_spi_mem_ecc_prepare_io_req,
+	.finish_io_req = mxic_spi_mem_ecc_finish_io_req,
+};
+
+static int mxic_spi_mem_ecc_probe(struct platform_device *pdev,
+				  struct mxic_spi *mxic)
+{
+	struct nand_ecc_engine *ecceng;
+
+	if (!mxic_ecc_get_pipelined_ops())
+		return -EOPNOTSUPP;
+
+	ecceng = devm_kzalloc(&pdev->dev, sizeof(*ecceng), GFP_KERNEL);
+	if (!ecceng)
+		return -ENOMEM;
+
+	ecceng->dev = &pdev->dev;
+	ecceng->ops = &mxic_spi_mem_ecc_engine_pipelined_ops;
+
+	nand_ecc_register_on_host_hw_engine(ecceng);
+	mxic->ecc.engine = ecceng;
+
+	return 0;
+}
+
 static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
@@ -640,6 +742,7 @@ static int mxic_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	mxic = spi_master_get_devdata(master);
+	mxic->dev = &pdev->dev;
 
 	master->dev.of_node = pdev->dev.of_node;
 
@@ -684,6 +787,10 @@ static int mxic_spi_probe(struct platform_device *pdev)
 
 	mxic_spi_hw_init(mxic);
 
+	ret = mxic_spi_mem_ecc_probe(pdev, mxic);
+	if (ret)
+		dev_warn(&pdev->dev, "SPI-mem ECC engine not available\n");
+
 	ret = spi_register_master(master);
 	if (ret) {
 		dev_err(&pdev->dev, "spi_register_master failed\n");
@@ -696,8 +803,11 @@ static int mxic_spi_probe(struct platform_device *pdev)
 static int mxic_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
+	struct mxic_spi *mxic = spi_master_get_devdata(master);
+	struct nand_ecc_engine *ecc_engine = mxic->ecc.engine;
 
 	pm_runtime_disable(&pdev->dev);
+	nand_ecc_unregister_on_host_hw_engine(ecc_engine);
 	spi_unregister_master(master);
 
 	return 0;
-- 
2.27.0



From miquel.raynal at bootlin.com  Fri Oct  8 09:36:40 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri,  8 Oct 2021 18:36:40 +0200
Subject: [PATCH v2] mtd: rawnand: arasan: Prevent an unsupported configuration
Message-ID: <20211008163640.1753821-1-miquel.raynal@bootlin.com>

Under the following conditions:
* after rounding up by 4 the number of bytes to transfer (this is
  related to the controller's internal constraints),
* if this (rounded) amount of data is situated beyond the end of the
  device,
* and only in NV-DDR mode,
the Arasan NAND controller timeouts.

This currently can happen in a particular helper used when picking
software ECC algorithms. Let's prevent this situation by refusing to use
the NV-DDR interface with software engines.

Fixes: 4edde6031458 ("mtd: rawnand: arasan: Support NV-DDR interface")
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---

Changes in v2:
As v1 was too invasive Boris suggested to adopt a much simpler approach:
let's just avoid the situation. That's what I am doing here.

 drivers/mtd/nand/raw/arasan-nand-controller.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index 9cbcc698c64d..53bd10738418 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -973,6 +973,21 @@ static int anfc_setup_interface(struct nand_chip *chip, int target,
 		nvddr = nand_get_nvddr_timings(conf);
 		if (IS_ERR(nvddr))
 			return PTR_ERR(nvddr);
+
+		/*
+		 * The controller only supports data payload requests which are
+		 * a multiple of 4. In practice, most data accesses are 4-byte
+		 * aligned and this is not an issue. However, rounding up will
+		 * simply be refused by the controller if we reached the end of
+		 * the device *and* we are using the NV-DDR interface(!). In
+		 * this situation, unaligned data requests ending at the device
+		 * boundary will confuse the controller and cannot be performed.
+		 *
+		 * This is something that happens in nand_read_subpage() when
+		 * selecting software ECC support and must be avoided.
+		 */
+		if (chip->ecc.engine_type == NAND_ECC_ENGINE_TYPE_SOFT)
+			return -ENOTSUPP;
 	} else {
 		sdr = nand_get_sdr_timings(conf);
 		if (IS_ERR(sdr))
-- 
2.27.0



From sean at geanix.com  Fri Oct  8 10:31:14 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri, 8 Oct 2021 19:31:14 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while
 in suspend
In-Reply-To: <20211008173043.6263ba80@collabora.com>
References: <20211008141524.20ca8219@collabora.com>
 <20211008143825.3717116-1-sean@geanix.com>
 <20211008173043.6263ba80@collabora.com>
Message-ID: <20211008173114.fmwbs3j3ufjvpcqd@skn-laptop>

On Fri, Oct 08, 2021 at 05:30:43PM +0200, Boris Brezillon wrote:
> Hi Sean,
> 
> Can you please submit that as a separate thread, ideally with an
> incremented version number, a changelog and a reference to all your
> previous attempts.

Yes, I'll do that with the next one.

> 
> On Fri,  8 Oct 2021 16:38:24 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > This will prevent reading/writing/erasing to a suspended mtd device.
> > It will force mtd_write()/mtd_read()/mtd_erase() to wait for
> > mtd_resume() to unlock access to mtd devices.
> 
> I think this has to be done for all the hooks except ->_reboot(),
> ->_get_device() and ->_put_device().
> 
> > 
> > Exec_op[0] speed things up, so we see this race when rawnand devices going
> 
> Mention the commit directly:
> 
> Commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op") speed
> things up, so we see this race when rawnand devices going ...
> 
> > into suspend. But it's actually "mtd: rawnand: Simplify the locking" that
> 
> But it's actually commit 013e6292aaf5 ("mtd: rawnand: Simplify the
> locking") that ...
> 
> > allows it to return errors rather than locking, before that commit it would
> > have waited for the rawnand device to resume.
> > 
> > Tested on a iMX6ULL.
> > 
> > [0]:
> > ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> > 
> > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> 
> You flagged yourself as the author even though you didn't really write
> that code. I guess I'm fine with that, but I'd appreciate a
> 
> Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
> 
> here, at least.
> 

Of course, of course I forgot it... Still an RFC after all :)

> > ---
> > 
> > Hope I got it all :)
> > 
> >  drivers/mtd/mtdcore.c   | 57 ++++++++++++++++++++++++++++++++++++++++-
> >  include/linux/mtd/mtd.h | 36 ++++++++++++++++++--------
> >  2 files changed, 81 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> > index c8fd7f758938..3c93202e6cbb 100644
> > --- a/drivers/mtd/mtdcore.c
> > +++ b/drivers/mtd/mtdcore.c
> > @@ -36,6 +36,44 @@
> >  
> >  struct backing_dev_info *mtd_bdi;
> >  
> > +static void mtd_start_access(struct mtd_info *mtd)
> > +{
> > +	struct mtd_info *master = mtd_get_master(mtd);
> > +
> > +	/*
> > +	 * Don't take the suspend_lock on devices that don't
> > +	 * implement the suspend hook. Otherwise, lockdep will
> > +	 * complain about nested locks when trying to suspend MTD
> > +	 * partitions or MTD devices created by gluebi which are
> > +	 * backed by real devices.
> > +	 */
> > +	if (!master->_suspend)
> > +		return;
> > +
> 
> You need to remove the ->_suspend()/->_resume() implementation in
> mtd_concat.c, otherwise you'll hit the case described in the comment.

Do you mean to remove concat_suspend() and concat_resume() together
with the references to them?

> 
> BTW, did you test this series with lockdep enabled to make sure we
> don't introduce a deadlock?
> 

Good you mentioned it... I thought the kernel had LOCKDEP enabled, but I
guess it at some point got removed.

It reveals that mtd_read_oob() -> mtd_start_access() is using the suspend_lock
rw_semaphore before it's initialized...
But it's not complaining when going suspend and resuming, will continue
to test with LOCKDEP enabled.

/Sean

> > +	/*
> > +	 * Wait until the device is resumed. Should we have a
> > +	 * non-blocking mode here?
> > +	 */
> > +	while (1) {
> > +		down_read(&master->master.suspend_lock);
> > +		if (!master->master.suspended)
> > +			return;
> > +
> > +		up_read(&master->master.suspend_lock);
> > +		wait_event(master->master.resume_wq, master->master.suspended == 0);
> > +	}
> > +}
> > +
> > +static void mtd_end_access(struct mtd_info *mtd)
> > +{
> > +	struct mtd_info *master = mtd_get_master(mtd);
> > +
> > +	if (!master->_suspend)
> > +		return;
> > +
> > +	up_read(&master->master.suspend_lock);
> > +}
> > +



From sean at geanix.com  Fri Oct  8 10:50:27 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Fri, 8 Oct 2021 19:50:27 +0200
Subject: [RFC PATCH 1/2] mtd: core: protect access to mtd devices while
 in suspend
In-Reply-To: <20211008180811.36c371f5@collabora.com>
References: <20211008141524.20ca8219@collabora.com>
 <20211008143825.3717116-1-sean@geanix.com>
 <20211008173526.19745a10@xps13>
 <20211008180811.36c371f5@collabora.com>
Message-ID: <20211008175027.4eg4qsrcu7nxwplv@skn-laptop>

On Fri, Oct 08, 2021 at 06:08:11PM +0200, Boris Brezillon wrote:
> On Fri, 8 Oct 2021 17:35:26 +0200
> Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> 
> > > into suspend. But it's actually "mtd: rawnand: Simplify the locking" that
> > > allows it to return errors rather than locking, before that commit it would
> > > have waited for the rawnand device to resume.  
> > 
> > I don't think so, I believe it was broken in the same way but was just
> > not returning errors.
> 
> Actually I was wrong, 013e6292aaf5 ("mtd: rawnand: Simplify the
> locking") removed the blocking wait (returning -EBUSY when the device
> is suspended instead of putting the thread on a waitqueue). At that
> time, I assumed all threads would be paused when the device is
> suspended, which appeared to be incorrect. So I guess the Fixes tag
> should remain, and we might want to consider backporting a less
> invasive patch to stable releases (one touching only the raw NAND
> layer).

Thanks Miquel add Reviewed-By you on the second patch.

I'll remove the mentioning of commit ef347c0cfd61
("mtd: rawnand: gpmi: Implement exec_op") in this commit msg.

Is it possible to backport another(less invasive) patch to stable
releases? I thought only upstream commits could be backported.

/Sean


From rogerq at kernel.org  Fri Oct  8 12:10:15 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Fri, 8 Oct 2021 22:10:15 +0300
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
Message-ID: <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>

Krzysztof,

On 07/10/2021 20:37, Krzysztof Kozlowski wrote:
> On 07/10/2021 14:08, Roger Quadros wrote:
>> Hi,
>>
>> This series converts ti,gpmc memory controller and ti,gpmc-nand and
>> ti,gpmc-onenand MTD controller bindings to yaml.
>>
>> cheers,
>> -roger
>>
> 
> Hi,
> 
> Although you did not mention it here, it looks like you have some
> dependencies between the patches. Maybe this shall go simply via Rob's tree?
> 

Rob has acked all the DT binding patches.
So it is upto you and Miqu?l to decide the best way. MTD tree or Memory controller tree
for the dt-bindings patches.

The ARM: dts changes should go via Tony's OMAP SoC tree.

Or if Tony is OK with it then maybe all patches can go via Tony's tree? :)

cheers,
-roger



From robh at kernel.org  Fri Oct  8 12:48:56 2021
From: robh at kernel.org (Rob Herring)
Date: Fri, 08 Oct 2021 14:48:56 -0500
Subject: [RFC PATCH 04/10] dt-bindings: mtd: Describe Macronix NAND ECC
 engine
In-Reply-To: <20211008162228.1753083-5-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-5-miquel.raynal@bootlin.com>
Message-ID: <1633722536.880854.3211954.nullmailer@robh.at.kernel.org>

On Fri, 08 Oct 2021 18:22:22 +0200, Miquel Raynal wrote:
> Describe Macronix NAND ECC engine. This engine may be used as an
> external engine or pipelined, both ways are shown in the examples.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../bindings/mtd/mxic,nand-ecc-engine.yaml    | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.example.dt.yaml:0:0: /example-0/spi at 43c30000: failed to match any schema with compatible: ['mxicy,mx25f0a-spi']
Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.example.dt.yaml:0:0: /example-0/spi at 43c30000/flash at 0: failed to match any schema with compatible: ['spi-nand']
Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.example.dt.yaml:0:0: /example-1/spi at 43c30000: failed to match any schema with compatible: ['mxicy,mx25f0a-spi']
Documentation/devicetree/bindings/mtd/mxic,nand-ecc-engine.example.dt.yaml:0:0: /example-1/spi at 43c30000/flash at 0: failed to match any schema with compatible: ['spi-nand']

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1538445

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.



From robh at kernel.org  Fri Oct  8 14:47:58 2021
From: robh at kernel.org (Rob Herring)
Date: Fri, 8 Oct 2021 16:47:58 -0500
Subject: [RFC PATCH 03/10] dt-bindings: vendor-prefixes: Update Macronix
 prefix
In-Reply-To: <20211008162228.1753083-4-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-4-miquel.raynal@bootlin.com>
Message-ID: <YWC8jgI74FgTudSD@robh.at.kernel.org>

On Fri, Oct 08, 2021 at 06:22:21PM +0200, Miquel Raynal wrote:
> When looking at compatible prefixes, Macronix is sometimes referred as
> mxicy:
> - mxicy,mx25r1635f
> - mxicy,mx25u6435f
> - mxicy,mx25v8035f
> - mxicy,mx25f0a-spi
> and sometimes as mxic:
> - mxic,multi-itfc-v009-nand-controller
> - mxic,enable-randomizer-otp
> 
> It looks like the more up-to-date way is mxic so declare this prefix and
> mark the other one as deprecated.

mxicy is more widely used with flash parts. There's not a single dts 
file with 'mxic' which only seems to be some nand controller.

> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index b868cefc7c55..013a87850cd5 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -758,8 +758,11 @@ patternProperties:
>      description: Mundo Reader S.L.
>    "^murata,.*":
>      description: Murata Manufacturing Co., Ltd.
> +  "^mxic,.*":
> +    description: Macronix International Co., Ltd.
>    "^mxicy,.*":
>      description: Macronix International Co., Ltd.
> +    deprecated: true
>    "^myir,.*":
>      description: MYIR Tech Limited
>    "^national,.*":
> -- 
> 2.27.0
> 
> 


From michael at amarulasolutions.com  Fri Oct  8 22:53:26 2021
From: michael at amarulasolutions.com (Michael Nazzareno Trimarchi)
Date: Sat, 9 Oct 2021 07:53:26 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008180752.09f33896@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211008152905.2fbdcce9@xps13> <20211008153631.3f1a09aa@xps13>
 <6364938.4vTCxPXJkl@n95hx1g2> <20211008180752.09f33896@xps13>
Message-ID: <CAOf5uwkTzPtqjO0XQ7otzNKLugUzS+9MJg0GkdtvV2JY4=n5mw@mail.gmail.com>

Hi

On Fri, Oct 8, 2021 at 6:07 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
>
> Hi Christian,
>
> ceggers at arri.de wrote on Fri, 8 Oct 2021 15:49:21 +0200:
>
> > On Friday, 8 October 2021, 15:36:31 CEST, Miquel Raynal wrote:
> > >
> > > miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:
> > >
> > > >
> > > > If this clock (as I understand) does not prevent us to access the
> > > > registers but only feeds the external NAND bus part, then there is no
> > > > need to enable it in the probe, just acquiring it will be enough.
> >
> > clocks[0] is "gpmi_io" which sounds more like i/o than registers. So lets
> > try to remove the initial call to clk_set_rate().
> >
> > > > Then, the first call for an IO operation with ->must_apply_timings
> > > > should:
> > > >
> > > >   if (imx6)
> > > >           disable_clk();
> > > >
> > > >   clk_set_rate();
> > > >
> > > >   if (imx6)
> > > >           enable_clk();
> >
> > Do you think that the need for avoiding clock glitches is i.MX6 specific?
> > The errata I mentioned is specific for the bootloader software, but (I think)
> > the requirement for switching off the clocks gates prior changing the dividers
> > may apply also for other series.
>
> I honestly don't know, perhaps Han have more details about it. If you
> think it's a wider issue, then we can just do the disable/enable step
> without any further checks.
>

Still don't explain why it was working on the old driver. The glitch
was already there,
so just a delay can do the trick. For imx28 we need to reparent to a
different clock the
nand driver in order to get the frequency we want in EDO mode. I'm
still thinking that
set the frequency without without get back and understand if in that
edo mode is valid
is still a bug.

Michael

> > > Actually we should ensure clks are enabled in the !imx6 case anyway,
> > > but this is needed only once so either we keep enabling the clock in
> > > the probe or we check here if the clk has already been enabled or not.
> > The clocks are already enabled (and kept on) in probe. The initial call to
> > clk_set_rate() is just above this (but the clocks are not disabled at this
> > stage as all gates have been enabled by the boot loader).
>
> The IO clock should be enabled and set to a particular rate the first
> time the die is selected to perform a NAND operation, or when we switch
> from one device to the other (this does not apply to the GPMI driver
> for now). So we can drop the enable/set_rate call in the probe if the
> assumption that this clock only feeds the external bus is right.
>
> Thanks,
> Miqu?l



-- 
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com


From troglobit at gmail.com  Fri Oct  8 23:09:53 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Sat,  9 Oct 2021 08:09:53 +0200
Subject: [PATCH v3 0/2] mtd: block2mtd: support for custom MTD label
Message-ID: <20211009060955.552636-1-troglobit@gmail.com>

This series contains a refactor and feature extension to the block2mtd
driver.  First we factor out the hard coded constant for number of
module arguments, then we add the new label argument,

Best regards
 /Joachim

v3:
  * split v2 in two separate patches
v2:
  * Variables and arguments on their own lines
  * Add comment to explain why we need strlen()
  * Refactor hard coded constants with a define
  * Spell and grammar check commit message

Joachim Wiberg (2):
  mtd: block2mtd: minor refactor to avoid hard coded constant
  mtd: block2mtd: add support for an optional custom MTD label

 drivers/mtd/devices/block2mtd.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

-- 
2.25.1



From troglobit at gmail.com  Fri Oct  8 23:09:54 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Sat,  9 Oct 2021 08:09:54 +0200
Subject: [PATCH v3 1/2] mtd: block2mtd: minor refactor to avoid hard coded
 constant
In-Reply-To: <20211009060955.552636-1-troglobit@gmail.com>
References: <20211009060955.552636-1-troglobit@gmail.com>
Message-ID: <20211009060955.552636-2-troglobit@gmail.com>

Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
---
 drivers/mtd/devices/block2mtd.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index c08721b11642..6c2871788d59 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -31,6 +31,9 @@
 #include <linux/slab.h>
 #include <linux/major.h>
 
+/* Maximum number of comma-separated items in the 'block2mtd=' parameter */
+#define BLOCK2MTD_PARAM_MAX_COUNT 2
+
 /* Info for the block device */
 struct block2mtd_dev {
 	struct list_head list;
@@ -381,7 +384,7 @@ static int block2mtd_setup2(const char *val)
 	/* 80 for device, 12 for erase size, 80 for name, 8 for timeout */
 	char buf[80 + 12 + 80 + 8];
 	char *str = buf;
-	char *token[2];
+	char *token[BLOCK2MTD_PARAM_MAX_COUNT];
 	char *name;
 	size_t erase_size = PAGE_SIZE;
 	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
@@ -395,7 +398,7 @@ static int block2mtd_setup2(const char *val)
 	strcpy(str, val);
 	kill_final_newline(str);
 
-	for (i = 0; i < 2; i++)
+	for (i = 0; i < BLOCK2MTD_PARAM_MAX_COUNT; i++)
 		token[i] = strsep(&str, ",");
 
 	if (str) {
-- 
2.25.1



From troglobit at gmail.com  Fri Oct  8 23:09:55 2021
From: troglobit at gmail.com (Joachim Wiberg)
Date: Sat,  9 Oct 2021 08:09:55 +0200
Subject: [PATCH v3 2/2] mtd: block2mtd: add support for an optional custom MTD
 label
In-Reply-To: <20211009060955.552636-1-troglobit@gmail.com>
References: <20211009060955.552636-1-troglobit@gmail.com>
Message-ID: <20211009060955.552636-3-troglobit@gmail.com>

This patch adds support for an optional MTD label for mtd2block emulated
MTD devices.  Useful when, e.g., testing device images using Qemu.

The following line in /etc/fstab can then be used to mount a file system
regardless if running on an embedded system, or emulated with block2mtd:

    mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0

Kernel command line syntax in the emulated case:

    block2mtd.block2mtd=/dev/sda,,Config

Notice the ',,' it is the optional erase_size, which like before this
patch, defaults to PAGE_SIZE when omitted.  Hence the strlen() check.

Signed-off-by: Joachim Wiberg <troglobit at gmail.com>
---
 drivers/mtd/devices/block2mtd.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index 6c2871788d59..40d7211485da 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -32,7 +32,7 @@
 #include <linux/major.h>
 
 /* Maximum number of comma-separated items in the 'block2mtd=' parameter */
-#define BLOCK2MTD_PARAM_MAX_COUNT 2
+#define BLOCK2MTD_PARAM_MAX_COUNT 3
 
 /* Info for the block device */
 struct block2mtd_dev {
@@ -217,7 +217,7 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 
 
 static struct block2mtd_dev *add_device(char *devname, int erase_size,
-		int timeout)
+		char *label, int timeout)
 {
 #ifndef MODULE
 	int i;
@@ -281,7 +281,10 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	/* Setup the MTD structure */
 	/* make the name contain the block device in */
-	name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	if (!label)
+		name = kasprintf(GFP_KERNEL, "block2mtd: %s", devname);
+	else
+		name = kstrdup(label, GFP_KERNEL);
 	if (!name)
 		goto err_destroy_mutex;
 
@@ -308,7 +311,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 	list_add(&dev->list, &blkmtd_device_list);
 	pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
 		dev->mtd.index,
-		dev->mtd.name + strlen("block2mtd: "),
+		label ? label : dev->mtd.name + strlen("block2mtd: "),
 		dev->mtd.erasesize >> 10, dev->mtd.erasesize);
 	return dev;
 
@@ -386,6 +389,7 @@ static int block2mtd_setup2(const char *val)
 	char *str = buf;
 	char *token[BLOCK2MTD_PARAM_MAX_COUNT];
 	char *name;
+	char *label = NULL;
 	size_t erase_size = PAGE_SIZE;
 	unsigned long timeout = MTD_DEFAULT_TIMEOUT;
 	int i, ret;
@@ -417,7 +421,8 @@ static int block2mtd_setup2(const char *val)
 		return 0;
 	}
 
-	if (token[1]) {
+	/* Optional argument when custom label is used */
+	if (token[1] && strlen(token[1])) {
 		ret = parse_num(&erase_size, token[1]);
 		if (ret) {
 			pr_err("illegal erase size\n");
@@ -425,7 +430,12 @@ static int block2mtd_setup2(const char *val)
 		}
 	}
 
-	add_device(name, erase_size, timeout);
+	if (token[2]) {
+		label = token[2];
+		pr_info("Using custom MTD label '%s' for dev %s\n", label, name);
+	}
+
+	add_device(name, erase_size, label, timeout);
 
 	return 0;
 }
@@ -459,7 +469,7 @@ static int block2mtd_setup(const char *val, const struct kernel_param *kp)
 
 
 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
-MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
+MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,[<erasesize>][,<label>]]\"");
 
 static int __init block2mtd_init(void)
 {
-- 
2.25.1



From ceggers at arri.de  Fri Oct  8 23:26:36 2021
From: ceggers at arri.de (Christian Eggers)
Date: Sat, 9 Oct 2021 08:26:36 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211008180752.09f33896@xps13>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <6364938.4vTCxPXJkl@n95hx1g2> <20211008180752.09f33896@xps13>
Message-ID: <2811233.e9J7NaK4W3@n95hx1g2>

On Friday, 8 October 2021, 18:07:52 CEST, Miquel Raynal wrote:
> Hi Christian,
> 
> ceggers at arri.de wrote on Fri, 8 Oct 2021 15:49:21 +0200:
> 
> > On Friday, 8 October 2021, 15:36:31 CEST, Miquel Raynal wrote:
> > > 
> > > miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:
> > >   
> > > > 
> > > > If this clock (as I understand) does not prevent us to access the
> > > > registers but only feeds the external NAND bus part, then there is no
> > > > need to enable it in the probe, just acquiring it will be enough.  
> > 
> > clocks[0] is "gpmi_io" which sounds more like i/o than registers. So lets
> > try to remove the initial call to clk_set_rate().

>From the GPMI description (i.MX6 ULL):
> [GPMI] Registers are clocked on the HCLK domain. The I/O and pin timing are 
> clocked on a dedicated GPMICLK domain. GPMICLK can be set to maximize I/O
> performance.

Additionally, figure 17-1 in IMX6ULLRM.pdf shows that both (BCH and GPMI)
registers are connected to APBH.

I checked this with the debugger: For accessing the BCH and GPMI
registers, only CCGR0::CG2 [APBHDMA_HCLK_ENABLE] is required. This bit is
enabled in mxs_dma_alloc_chan_resources():

-000|mxs_dma_alloc_chan_resources(chan = 0xC2090154)
-001|__refcount_inc_not_zero(inline)
-001|refcount_inc_not_zero(inline)
-001|kref_get_unless_zero(inline)
-001|dma_chan_get(:chan = 0xC2090154)
-002|find_candidate(device = 0xC2090050, :mask = 0xC209BD38, :fn = 0xC0254679, :fn_param = 0xC209BD3C)
-003|__dma_request_channel(:mask = 0xC209BD38, :fn = 0xC0254679, :fn_param = 0xC209BD3C, np = 0xC7EEB0B0)
-004|mxs_dma_xlate(:dma_spec = 0xC209BD60, :ofdma = 0xC2264840)
-005|of_dma_request_slave_channel(np = 0xC7EEB2B4, name = 0xC04F923A -> "rx-tx")
-006|dma_request_chan(dev = 0xC2182410, :name = 0xC04F923A -> "rx-tx")
-007|acquire_dma_channels(inline)
-007|acquire_resources(:this = 0xC200F840)
-008|gpmi_nand_probe(:pdev = 0xC2182400)

The root clock is BCH_CLK_ROOT. It doesn't depend on ENFC_PRED or ENFC_PODF
(the dividers which are actually set in clk_set_rate(r->clock[0], 22000000)).

--> clk_set_rate(r->clock[0], 22000000) is not required for accessing the
registers. I removed the call entirely and everything works fine.

> > 
> > > > Then, the first call for an IO operation with ->must_apply_timings
> > > > should:
> > > > 
> > > > 	if (imx6)
> > > > 		disable_clk();
> > > > 
> > > > 	clk_set_rate();
> > > > 
> > > > 	if (imx6)
> > > > 		enable_clk();  
> > 
> > Do you think that the need for avoiding clock glitches is i.MX6 specific?
> > The errata I mentioned is specific for the bootloader software, but (I think)
> > the requirement for switching off the clocks gates prior changing the dividers
> > may apply also for other series.
> 
> I honestly don't know, perhaps Han have more details about it. If you
> think it's a wider issue, then we can just do the disable/enable step
> without any further checks.
I also don't know. I can not find the required sequence in the reference manual
(only in the errata sheet), so I cannot compare with other series. For best
performance we can start with checking for GPMI_IS_MX6Q(x) and extend it later
if this issue comes up on other devices.

I sent a question for this on NXP community:
https://community.nxp.com/t5/i-MX-Processors/ERR007117-Which-i-MX-devices-require-gating-the-clocks-when/m-p/1353018

> > > Actually we should ensure clks are enabled in the !imx6 case anyway,
> > > but this is needed only once so either we keep enabling the clock in
> > > the probe or we check here if the clk has already been enabled or not.  
> > The clocks are already enabled (and kept on) in probe. The initial call to
> > clk_set_rate() is just above this (but the clocks are not disabled at this
> > stage as all gates have been enabled by the boot loader).
> 
> The IO clock should be enabled and set to a particular rate the first
> time the die is selected to perform a NAND operation, or when we switch
> from one device to the other (this does not apply to the GPMI driver
> for now). So we can drop the enable/set_rate call in the probe if the
> assumption that this clock only feeds the external bus is right.

I think that this assumption is right.

regards
Christian





From ceggers at arri.de  Fri Oct  8 23:33:20 2021
From: ceggers at arri.de (Christian Eggers)
Date: Sat, 9 Oct 2021 08:33:20 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <2091909.Mh6RI2rZIc@n95hx1g2>
 <b6cc888f8211790ddee6683204f3b8e31a9facd4.camel@phytec.de>
Message-ID: <9980438.nUPlyArG6x@n95hx1g2>

On Friday, 8 October 2021, 14:08:01 CEST, Stefan Riedm?ller wrote:
> On Fri, 2021-10-08 at 11:55 +0200, Christian Eggers wrote:
> > @Stefan Riedmueller: Are you willing to commit this upstream?
> 
> Yes sure, I can prepare a patch beginning of next week.
> BTW, we have seen these DMA timeout issues on the i.MX6 SOCs as well. So this
> fix is not only for the i.MX 6ULL.

Current status:

- If have entirely removed the following part:
	if (GPMI_IS_MX6(this))
		/*
		 * Set the default value for the gpmi clock.
		 *
		 * If you want to use the ONFI nand which is in the
		 * Synchronous Mode, you should change the clock as you need.
		 */
		clk_set_rate(r->clock[0], 22000000);

- I applied your patch:
https://git.phytec.de/linux-mainline/commit/?h=v5.10.48-phy&id=866939ea8110764d9c12af960d746e2f7f5debe3


Last night I made a cycle test with a phyCORE i.MX6ULL. Over 1700 cycles were successful!

regards
Christian





From krzysztof.kozlowski at canonical.com  Sat Oct  9 07:52:38 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Sat, 9 Oct 2021 16:52:38 +0200
Subject: [PATCH v5 3/8] dt-bindings: memory-controllers: Introduce
 ti,gpmc-child
In-Reply-To: <20211007120830.17221-4-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <20211007120830.17221-4-rogerq@kernel.org>
Message-ID: <a6478659-cea1-8c5a-287d-acc27b60a898@canonical.com>

On 07/10/2021 14:08, Roger Quadros wrote:
> This binding is meant for the child nodes of the TI GPMC node. The node
> represents any device connected to the GPMC bus. It may be a Flash chip,
> RAM chip or Ethernet controller, etc. These properties are meant for
> configuring the GPMC settings/timings and will accompany the bindings
> supported by the respective device.
> 
> Signed-off-by: Roger Quadros <rogerq at kernel.org>
> Reviewed-by: Rob Herring <robh at kernel.org>
> ---
>  .../memory-controllers/ti,gpmc-child.yaml     | 245 ++++++++++++++++++
>  1 file changed, 245 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
> 


Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com>


Best regards,
Krzysztof


From krzysztof.kozlowski at canonical.com  Sat Oct  9 07:54:03 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Sat, 9 Oct 2021 16:54:03 +0200
Subject: [PATCH v5 6/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <20211007120830.17221-7-rogerq@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <20211007120830.17221-7-rogerq@kernel.org>
Message-ID: <05368ff4-a2fa-a7d2-b87b-d8363b085148@canonical.com>

On 07/10/2021 14:08, Roger Quadros wrote:
> Convert omap-gpmc.txt to ti,gpmc.yaml.
> 
> Signed-off-by: Roger Quadros <rogerq at kernel.org>
> Reviewed-by: Rob Herring <robh at kernel.org>
> ---
>  .../bindings/memory-controllers/omap-gpmc.txt | 157 ----------------
>  .../bindings/memory-controllers/ti,gpmc.yaml  | 172 ++++++++++++++++++
>  2 files changed, 172 insertions(+), 157 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/memory-controllers/omap-gpmc.txt
>  create mode 100644 Documentation/devicetree/bindings/memory-controllers/ti,gpmc.yaml
> 

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com>

Best regards,
Krzysztof


From krzysztof.kozlowski at canonical.com  Sat Oct  9 07:55:47 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Sat, 9 Oct 2021 16:55:47 +0200
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
 <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>
Message-ID: <64b65579-7153-1e7d-9866-77ce07fd1df5@canonical.com>

On 08/10/2021 21:10, Roger Quadros wrote:
> Krzysztof,
> 
> On 07/10/2021 20:37, Krzysztof Kozlowski wrote:
>> On 07/10/2021 14:08, Roger Quadros wrote:
>>> Hi,
>>>
>>> This series converts ti,gpmc memory controller and ti,gpmc-nand and
>>> ti,gpmc-onenand MTD controller bindings to yaml.
>>>
>>> cheers,
>>> -roger
>>>
>>
>> Hi,
>>
>> Although you did not mention it here, it looks like you have some
>> dependencies between the patches. Maybe this shall go simply via Rob's tree?
>>
> 
> Rob has acked all the DT binding patches.
> So it is upto you and Miqu?l to decide the best way. MTD tree or Memory controller tree
> for the dt-bindings patches.
> 
> The ARM: dts changes should go via Tony's OMAP SoC tree.
> 
> Or if Tony is OK with it then maybe all patches can go via Tony's tree? :)
> 


I reviewed the two memory-controller patches, so feel free to take them
via MTD or OMAP SoC.


Best regards,
Krzysztof


From paul at crapouillou.net  Sat Oct  9 11:49:49 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat,  9 Oct 2021 20:49:49 +0200
Subject: [PATCH 0/3] mtd: Ingenic NAND fix for JZ4740
Message-ID: <20211009184952.24591-1-paul@crapouillou.net>

Hi,

Looks like NAND support has been broken on the JZ4740 SoC for a while;
it looks like it comes from the fact that the "hw_oob_first" mechanism
was dropped from the NAND core and moved to the Davinci driver.

It turns out the JZ4740 SoC needs it too; I didn't notice it when
writing the new ingenic-nand driver (to replace the old jz4740-nand
driver) most likely because my Device Tree had the "nand-ecc-mode" set
to "hw_oob_first".

I am not very sure about patch [1/3]; to me the original code does not
make sense, and it didn't work out-of-the-box on the JZ4740 without it.
By applying patch [1/3] the function nand_read_page_hwecc_oob_first()
can be reused for the JZ4740 SoC as well. But I did not test patch [1/3]
on Davinci.

Cheers,
-Paul

Paul Cercueil (3):
  mtd: rawnand/davinci: Don't calculate ECC when reading page
  mtd: rawnand: Export nand_read_page_hwecc_oob_first()
  mtd: rawnand/ingenic: JZ4740 needs 'oob_first' read page function

 drivers/mtd/nand/raw/davinci_nand.c           | 73 +------------------
 .../mtd/nand/raw/ingenic/ingenic_nand_drv.c   |  5 ++
 drivers/mtd/nand/raw/nand_base.c              | 69 ++++++++++++++++++
 include/linux/mtd/rawnand.h                   |  2 +
 4 files changed, 77 insertions(+), 72 deletions(-)

-- 
2.33.0



From paul at crapouillou.net  Sat Oct  9 11:49:50 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat,  9 Oct 2021 20:49:50 +0200
Subject: [PATCH 1/3] mtd: rawnand/davinci: Don't calculate ECC when reading
 page
In-Reply-To: <20211009184952.24591-1-paul@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
Message-ID: <20211009184952.24591-2-paul@crapouillou.net>

The function nand_davinci_read_page_hwecc_oob_first() does read the ECC
data from the OOB area. Therefore it does not need to calculate the ECC
as it is already available.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 118da9944e3b..89de24d3bb7a 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -394,7 +394,6 @@ static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 	int eccsteps = chip->ecc.steps;
 	uint8_t *p = buf;
 	uint8_t *ecc_code = chip->ecc.code_buf;
-	uint8_t *ecc_calc = chip->ecc.calc_buf;
 	unsigned int max_bitflips = 0;
 
 	/* Read the OOB area first */
@@ -420,8 +419,6 @@ static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 		if (ret)
 			return ret;
 
-		chip->ecc.calculate(chip, p, &ecc_calc[i]);
-
 		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
 		if (stat == -EBADMSG &&
 		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
-- 
2.33.0



From paul at crapouillou.net  Sat Oct  9 11:49:51 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat,  9 Oct 2021 20:49:51 +0200
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211009184952.24591-1-paul@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
Message-ID: <20211009184952.24591-3-paul@crapouillou.net>

Move the function nand_read_page_hwecc_oob_first() (previously
nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and export it
as a GPL symbol, so that it can be used by more modules.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 70 +----------------------------
 drivers/mtd/nand/raw/nand_base.c    | 69 ++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h         |  2 +
 3 files changed, 72 insertions(+), 69 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 89de24d3bb7a..45fec8c192ab 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -371,74 +371,6 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
 	return corrected;
 }
 
-/**
- * nand_read_page_hwecc_oob_first - hw ecc, read oob first
- * @chip: nand chip info structure
- * @buf: buffer to store read data
- * @oob_required: caller requires OOB data read to chip->oob_poi
- * @page: page number to read
- *
- * Hardware ECC for large page chips, require OOB to be read first. For this
- * ECC mode, the write_page method is re-used from ECC_HW. These methods
- * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
- * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
- * the data area, by overwriting the NAND manufacturer bad block markings.
- */
-static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
-						  uint8_t *buf,
-						  int oob_required, int page)
-{
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	int i, eccsize = chip->ecc.size, ret;
-	int eccbytes = chip->ecc.bytes;
-	int eccsteps = chip->ecc.steps;
-	uint8_t *p = buf;
-	uint8_t *ecc_code = chip->ecc.code_buf;
-	unsigned int max_bitflips = 0;
-
-	/* Read the OOB area first */
-	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
-	if (ret)
-		return ret;
-
-	ret = nand_read_page_op(chip, page, 0, NULL, 0);
-	if (ret)
-		return ret;
-
-	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
-					 chip->ecc.total);
-	if (ret)
-		return ret;
-
-	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		int stat;
-
-		chip->ecc.hwctl(chip, NAND_ECC_READ);
-
-		ret = nand_read_data_op(chip, p, eccsize, false, false);
-		if (ret)
-			return ret;
-
-		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
-		if (stat == -EBADMSG &&
-		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
-			/* check for empty pages with bitflips */
-			stat = nand_check_erased_ecc_chunk(p, eccsize,
-							   &ecc_code[i],
-							   eccbytes, NULL, 0,
-							   chip->ecc.strength);
-		}
-
-		if (stat < 0) {
-			mtd->ecc_stats.failed++;
-		} else {
-			mtd->ecc_stats.corrected += stat;
-			max_bitflips = max_t(unsigned int, max_bitflips, stat);
-		}
-	}
-	return max_bitflips;
-}
-
 /*----------------------------------------------------------------------*/
 
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
 			} else if (chunks == 4 || chunks == 8) {
 				mtd_set_ooblayout(mtd,
 						  nand_get_large_page_ooblayout());
-				chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
+				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
 			} else {
 				return -EIO;
 			}
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..cb5f343b9fa2 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
 	return max_bitflips;
 }
 
+/**
+ * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC
+ *                                  data read from OOB area
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
+ * @page: page number to read
+ *
+ * Hardware ECC for large page chips, require OOB to be read first. For this
+ * ECC mode, the write_page method is re-used from ECC_HW. These methods
+ * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
+ * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
+ * the data area, by overwriting the NAND manufacturer bad block markings.
+ */
+int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
+				   int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int i, eccsize = chip->ecc.size, ret;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *ecc_code = chip->ecc.code_buf;
+	unsigned int max_bitflips = 0;
+
+	/* Read the OOB area first */
+	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
+	if (ret)
+		return ret;
+
+	ret = nand_read_page_op(chip, page, 0, NULL, 0);
+	if (ret)
+		return ret;
+
+	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
+					 chip->ecc.total);
+	if (ret)
+		return ret;
+
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
+
+		chip->ecc.hwctl(chip, NAND_ECC_READ);
+
+		ret = nand_read_data_op(chip, p, eccsize, false, false);
+		if (ret)
+			return ret;
+
+		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, eccsize,
+							   &ecc_code[i],
+							   eccbytes, NULL, 0,
+							   chip->ecc.strength);
+		}
+
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+	return max_bitflips;
+}
+EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
+
 /**
  * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
  * @chip: nand chip info structure
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..5b88cd51fadb 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
 		      bool force_8bit, bool check_only);
 int nand_write_data_op(struct nand_chip *chip, const void *buf,
 		       unsigned int len, bool force_8bit);
+int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
+				   int oob_required, int page);
 
 /* Scan and identify a NAND device */
 int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,
-- 
2.33.0



From paul at crapouillou.net  Sat Oct  9 11:49:52 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat,  9 Oct 2021 20:49:52 +0200
Subject: [PATCH 3/3] mtd: rawnand/ingenic: JZ4740 needs 'oob_first' read page
 function
In-Reply-To: <20211009184952.24591-1-paul@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
Message-ID: <20211009184952.24591-4-paul@crapouillou.net>

The ECC engine on the JZ4740 SoC requires the ECC data to be read before
the page; using the default page reading function does not work. Indeed,
the old JZ4740 NAND driver (removed in 5.4) did use the 'OOB first' flag
that existed back then.

Use the newly created nand_read_page_hwecc_oob_first() to address this
issue.

This issue was not found when the new ingenic-nand driver was developed,
most likely because the Device Tree used had the nand-ecc-mode set to
"hw_oob_first", which seems to not be supported anymore.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
index 0e9d426fe4f2..b18861bdcdc8 100644
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
@@ -32,6 +32,7 @@ struct jz_soc_info {
 	unsigned long addr_offset;
 	unsigned long cmd_offset;
 	const struct mtd_ooblayout_ops *oob_layout;
+	bool oob_first;
 };
 
 struct ingenic_nand_cs {
@@ -240,6 +241,9 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
+	if (nfc->soc_info->oob_first)
+		chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+
 	/* For legacy reasons we use a different layout on the qi,lb60 board. */
 	if (of_machine_is_compatible("qi,lb60"))
 		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
@@ -534,6 +538,7 @@ static const struct jz_soc_info jz4740_soc_info = {
 	.data_offset = 0x00000000,
 	.cmd_offset = 0x00008000,
 	.addr_offset = 0x00010000,
+	.oob_first = true,
 };
 
 static const struct jz_soc_info jz4725b_soc_info = {
-- 
2.33.0



From richard at nod.at  Sat Oct  9 13:48:53 2021
From: richard at nod.at (Richard Weinberger)
Date: Sat, 9 Oct 2021 22:48:53 +0200 (CEST)
Subject: [PATCH 1/1] ubifs: ubifs to export filesystem error counters
In-Reply-To: <20211004055758.C52AD899CC4@corona.crabdance.com>
References: <20210907214034.11676-1-schaecsn@gmx.net>
 <20210907214034.11676-2-schaecsn@gmx.net>
 <1815586081.32955.1633291105033.JavaMail.zimbra@nod.at>
 <20211004055758.C52AD899CC4@corona.crabdance.com>
Message-ID: <67641638.55077.1633812533457.JavaMail.zimbra@nod.at>

Stefan,

----- Urspr?ngliche Mail -----
> Von: "schaecsn" <schaecsn at gmx.net>
> An: "richard" <richard at nod.at>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel" <linux-kernel at vger.kernel.org>, "Stefan Schaeckeler"
> <sschaeck at cisco.com>
> Gesendet: Montag, 4. Oktober 2021 07:57:58
> Betreff: Re: [PATCH 1/1] ubifs: ubifs to export filesystem error counters

> Hello Richard,
> 
>> > Not all ubifs filesystem errors are propagated to userspace.
>> >
>> > Export bad magic, bad node and crc errors via sysfs. This allows userspace
>> > to notice filesystem errors:
>> >
>> > /sys/fs/ubifs/ubiX_Y/errors_magic
>> > /sys/fs/ubifs/ubiX_Y/errors_node
>> > /sys/fs/ubifs/ubiX_Y/errors_crc
>> >
>> > The counters are reset to 0 with a remount. Writing anything into the
>> > counters also clears them.
>>
>> I think this is a nice feature. Thanks for implementing it.
>> Please see some minor nits below.
>>
>> Is there a specific reason why you didn't implement it via UBIFS's debugfs
>> interface?
> 
> These error counters are not meant for aiding debugging but for userspace to
> monitor the sanity of the filesystem. Also ext4 exports error counters via
> sysfs - it's probably a good idea to be consistent with them.
> 
> $ dir /sys/fs/ext4/sdb2/*error*
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/errors_count
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_block
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_errcode
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_func
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_ino
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_line
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/first_error_time
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_block
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_errcode
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_func
> -r--r--r-- 1 root root 4096 Oct  3 13:47 /sys/fs/ext4/sdb2/last_error_ino
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_line
> -r--r--r-- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/last_error_time
> --w------- 1 root root 4096 Oct  3 13:46 /sys/fs/ext4/sdb2/trigger_fs_error

ext4 is not the reference design for filesystems in Linux.
e.g. btrfs has an ioctl for such stats.

> 
>> sysfs is ABI, so we cannot change much anymore.
> 
> Judging by the filesystem permissions above, ext4 does not seem to allow
> resetting error counters. If you worry about unchangable ABIs then we could
> play it safe and don't support write callbacks for resetting the error counters
> in an initial version of the ubifs sysfs. What do you think?

Ack.

> When we are at it, in the current code, writing anything into a sysfs node
> resets the corresponding counter. One could fine-tune that to set the counter
> to whatever non-negative integer is passed.
> 
> 
>> > +		if (c->stats)
>> > +			c->stats->magic_errors++;
>>
>> Please wrap this into a helper function.
> 
> Ack.
> 
> 
>> > +		if (c->stats)
>> > +			c->stats->node_errors++;
>>
>> Same.
> 
> Ack.
> 
> 
>> > +		if (c->stats)
>> > +			c->stats->crc_errors++;
>>
>> Same.
> 
> Ack.
> 
> 
>> > +#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
>> > +
>> > +UBIFS_ATTR_FUNC(errors_magic, 0644);
>> > +UBIFS_ATTR_FUNC(errors_crc, 0644);
>> > +UBIFS_ATTR_FUNC(errors_node, 0644);
>>
>> I'm not sure whether everyone should be allowed to read these stats.
>> dmesg is also restricted these days. An unprivileged user should not see the
>> errors he can indirectly trigger.
> 
> I don't mind 600, but having error counters world-readable is consistent with
> ext4 (see dir above) and so I suggest to keep 644.
> 

Ok.
 
>> > +	case attr_errors_crc:
>> > +		return snprintf(buf, PAGE_SIZE, "%u\n",
>> > +				sbi->stats->crc_errors);
>>
>> Please use sysfs_emit().
> 
> Ack.
> 
> 
>> > +	if (n == UBIFS_DFS_DIR_LEN) {
>> > +		/* The array size is too small */
>> > +		ret = -EINVAL;
>> > +		goto out_last;
>>
>> Where is c->stats released in case of an error?
> 
> My fault. Will be fixed.
> 
> 
>> > diff --git a/fs/ubifs/sysfs.h b/fs/ubifs/sysfs.h
>> > new file mode 100644
>> > index 000000000000..a10a82585af8
>> > --- /dev/null
>> > +++ b/fs/ubifs/sysfs.h
>>
>> Do we really need a new header file?
>> Usually most run-time stuff of UBIFS is part of ubifs.h.
> 
> I wanted to be consistent with debugfs where fs/ubifs/debug.c comes with its
> own header fs/ubifs/debug.h.

debug.h is not just about debugfs. It is about debugging/developing UBIFS.
That's why it is kind of special.

> 
> I'll send out a new patch once we agree on all changes. To recap:
> 
> - write callbacks: do we remove them? If not, do we keep them as is or do we
>  fine-tine them by letting a non-negative integer set the counter?

I'd go for read-only first.

> - 644 (world-readable) counters to be consistent with ext4?

Ack.

> - keep sysfs.h to be consistent with debugfs?

Please remove sysfs.h.

Thanks,
//richard


From schaecsn at gmx.net  Sat Oct  9 21:22:39 2021
From: schaecsn at gmx.net (Stefan Schaeckeler)
Date: Sat,  9 Oct 2021 21:22:39 -0700
Subject: [PATCH v2] ubifs: ubifs to export filesystem error counters
Message-ID: <20211010042239.2888-1-schaecsn@gmx.net>

Not all ubifs filesystem errors are propagated to userspace.

Export bad magic, bad node and crc errors via sysfs. This allows userspace
to notice filesystem errors:

 /sys/fs/ubifs/ubiX_Y/errors_magic
 /sys/fs/ubifs/ubiX_Y/errors_node
 /sys/fs/ubifs/ubiX_Y/errors_crc

The counters are reset to 0 with a remount.

Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
---
Changes in v2:
  - merged sysfs.h header into ubifs.h.
  - io.c: wrapped incrementing error counters into new functions
    record_*_error().
  - sysfs.c: removed sysfs write callback for clearing stats.
  - sysfs.c: ubifs_sysfs_register(): free c->stats on error.
  - sysfs.c: ubifs_attr_show(): use sysfs_emit().

 fs/ubifs/Makefile |   2 +-
 fs/ubifs/io.c     |  21 +++++++
 fs/ubifs/super.c  |  16 ++++-
 fs/ubifs/sysfs.c  | 153 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/ubifs.h  |  35 +++++++++++
 5 files changed, 225 insertions(+), 2 deletions(-)
 create mode 100644 fs/ubifs/sysfs.c

diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 5c4b845754a7..314c80b24a76 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -5,7 +5,7 @@ ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
 ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
 ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
 ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
-ubifs-y += misc.o
+ubifs-y += misc.o sysfs.o
 ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
 ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
 ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 00b61dba62b7..789a7813f3fa 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -194,6 +194,24 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
 	return err;
 }

+static void record_magic_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->magic_errors++;
+}
+
+static void record_node_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->node_errors++;
+}
+
+static void record_crc_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->crc_errors++;
+}
+
 /**
  * ubifs_check_node - check node.
  * @c: UBIFS file-system description object
@@ -238,6 +256,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 		if (!quiet)
 			ubifs_err(c, "bad magic %#08x, expected %#08x",
 				  magic, UBIFS_NODE_MAGIC);
+		record_magic_error(c->stats);
 		err = -EUCLEAN;
 		goto out;
 	}
@@ -246,6 +265,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 	if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
 		if (!quiet)
 			ubifs_err(c, "bad node type %d", type);
+		record_node_error(c->stats);
 		goto out;
 	}

@@ -270,6 +290,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 		if (!quiet)
 			ubifs_err(c, "bad CRC: calculated %#08x, read %#08x",
 				  crc, node_crc);
+		record_crc_error(c->stats);
 		err = -EUCLEAN;
 		goto out;
 	}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f0fb25727d96..a4e3a143fb1b 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1264,6 +1264,10 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		return err;

+	err = ubifs_sysfs_register(c);
+	if (err)
+		goto out_debugging;
+
 	err = check_volume_empty(c);
 	if (err)
 		goto out_free;
@@ -1641,6 +1645,8 @@ static int mount_ubifs(struct ubifs_info *c)
 	vfree(c->sbuf);
 	kfree(c->bottom_up_buf);
 	kfree(c->sup_node);
+	ubifs_sysfs_unregister(c);
+out_debugging:
 	ubifs_debugging_exit(c);
 	return err;
 }
@@ -1684,6 +1690,7 @@ static void ubifs_umount(struct ubifs_info *c)
 	kfree(c->bottom_up_buf);
 	kfree(c->sup_node);
 	ubifs_debugging_exit(c);
+	ubifs_sysfs_unregister(c);
 }

 /**
@@ -2436,14 +2443,20 @@ static int __init ubifs_init(void)

 	dbg_debugfs_init();

+	err = ubifs_sysfs_init();
+	if (err)
+		goto out_dbg;
+
 	err = register_filesystem(&ubifs_fs_type);
 	if (err) {
 		pr_err("UBIFS error (pid %d): cannot register file system, error %d",
 		       current->pid, err);
-		goto out_dbg;
+		goto out_sysfs;
 	}
 	return 0;

+out_sysfs:
+	ubifs_sysfs_exit();
 out_dbg:
 	dbg_debugfs_exit();
 	ubifs_compressors_exit();
@@ -2462,6 +2475,7 @@ static void __exit ubifs_exit(void)
 	WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) != 0);

 	dbg_debugfs_exit();
+	ubifs_sysfs_exit();
 	ubifs_compressors_exit();
 	unregister_shrinker(&ubifs_shrinker_info);

diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
new file mode 100644
index 000000000000..0b6f79b6e2e8
--- /dev/null
+++ b/fs/ubifs/sysfs.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2021 Cisco Systems
+ *
+ * Author: Stefan Schaeckeler
+ */
+
+
+#include <linux/fs.h>
+#include "ubifs.h"
+
+enum attr_id_t {
+	attr_errors_magic,
+	attr_errors_node,
+	attr_errors_crc,
+};
+
+struct ubifs_attr {
+	struct attribute attr;
+	enum attr_id_t attr_id;
+};
+
+#define UBIFS_ATTR(_name, _mode, _id)					\
+static struct ubifs_attr ubifs_attr_##_name = {				\
+	.attr = {.name = __stringify(_name), .mode = _mode },		\
+	.attr_id = attr_##_id,						\
+}
+
+#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
+
+UBIFS_ATTR_FUNC(errors_magic, 0444);
+UBIFS_ATTR_FUNC(errors_crc, 0444);
+UBIFS_ATTR_FUNC(errors_node, 0444);
+
+#define ATTR_LIST(name) (&ubifs_attr_##name.attr)
+
+static struct attribute *ubifs_attrs[] = {
+	ATTR_LIST(errors_magic),
+	ATTR_LIST(errors_node),
+	ATTR_LIST(errors_crc),
+	NULL,
+};
+
+static ssize_t ubifs_attr_show(struct kobject *kobj,
+			       struct attribute *attr, char *buf)
+{
+	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
+					      kobj);
+
+	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
+
+	switch (a->attr_id) {
+	case attr_errors_magic:
+		return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
+	case attr_errors_node:
+		return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
+	case attr_errors_crc:
+		return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
+	}
+	return 0;
+};
+
+static void ubifs_sb_release(struct kobject *kobj)
+{
+	struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
+
+	complete(&c->kobj_unregister);
+}
+
+static const struct sysfs_ops ubifs_attr_ops = {
+	.show	= ubifs_attr_show,
+};
+
+static struct kobj_type ubifs_sb_ktype = {
+	.default_attrs	= ubifs_attrs,
+	.sysfs_ops	= &ubifs_attr_ops,
+	.release	= ubifs_sb_release,
+};
+
+static struct kobj_type ubifs_ktype = {
+	.sysfs_ops	= &ubifs_attr_ops,
+};
+
+static struct kset ubifs_kset = {
+	.kobj	= {.ktype = &ubifs_ktype},
+};
+
+int ubifs_sysfs_register(struct ubifs_info *c)
+{
+	int ret, n;
+	char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];
+
+	c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
+	if (!c->stats) {
+		ret = -ENOMEM;
+		goto out_last;
+	}
+	n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
+		     c->vi.ubi_num, c->vi.vol_id);
+
+	if (n == UBIFS_DFS_DIR_LEN) {
+		/* The array size is too small */
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	c->kobj.kset = &ubifs_kset;
+	init_completion(&c->kobj_unregister);
+
+	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
+				   "%s", dfs_dir_name);
+	if (ret)
+		goto out_put;
+
+	return 0;
+
+out_put:
+	kobject_put(&c->kobj);
+	wait_for_completion(&c->kobj_unregister);
+out_free:
+	kfree(c->stats);
+out_last:
+	ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
+		  c->vi.ubi_num, c->vi.vol_id, ret);
+	return ret;
+}
+
+void ubifs_sysfs_unregister(struct ubifs_info *c)
+{
+	kobject_del(&c->kobj);
+	kobject_put(&c->kobj);
+	wait_for_completion(&c->kobj_unregister);
+
+	kfree(c->stats);
+}
+
+int __init ubifs_sysfs_init(void)
+{
+	int ret;
+
+	kobject_set_name(&ubifs_kset.kobj, "ubifs");
+	ubifs_kset.kobj.parent = fs_kobj;
+	ret = kset_register(&ubifs_kset);
+
+	return ret;
+}
+
+void ubifs_sysfs_exit(void)
+{
+	kset_unregister(&ubifs_kset);
+}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index c38066ce9ab0..f55828c0a300 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -27,6 +27,8 @@
 #include <linux/security.h>
 #include <linux/xattr.h>
 #include <linux/random.h>
+#include <linux/sysfs.h>
+#include <linux/completion.h>
 #include <crypto/hash_info.h>
 #include <crypto/hash.h>
 #include <crypto/algapi.h>
@@ -155,6 +157,13 @@
 #define UBIFS_HMAC_ARR_SZ 0
 #endif

+/*
+ * The UBIFS sysfs directory name pattern and maximum name length (3 for "ubi"
+ * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
+ */
+#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
+#define UBIFS_DFS_DIR_LEN  (3 + 1 + 2*2 + 1)
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
@@ -990,6 +999,18 @@ struct ubifs_budg_info {
 	int dent_budget;
 };

+/**
+ * ubifs_stats_info - per-FS statistics information.
+ * @magic_errors: number of bad magic numbers (will be reset with a new mount).
+ * @node_errors: number of bad nodes (will be reset with a new mount).
+ * @crc_errors: number of bad crcs (will be reset with a new mount).
+ */
+struct ubifs_stats_info {
+	unsigned int magic_errors;
+	unsigned int node_errors;
+	unsigned int crc_errors;
+};
+
 struct ubifs_debug_info;

 /**
@@ -1251,6 +1272,10 @@ struct ubifs_debug_info;
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg: debugging-related information
+ * @stats: statistics exported over sysfs
+ *
+ * @kobj: kobject for /sys/fs/ubifs/
+ * @kobj_unregister: completion to unregister sysfs kobject
  */
 struct ubifs_info {
 	struct super_block *vfs_sb;
@@ -1286,6 +1311,9 @@ struct ubifs_info {
 	spinlock_t cs_lock;
 	wait_queue_head_t cmt_wq;

+	struct kobject kobj;
+	struct completion kobj_unregister;
+
 	unsigned int big_lpt:1;
 	unsigned int space_fixup:1;
 	unsigned int double_hash:1;
@@ -1493,6 +1521,7 @@ struct ubifs_info {
 	struct ubifs_mount_opts mount_opts;

 	struct ubifs_debug_info *dbg;
+	struct ubifs_stats_info *stats;
 };

 extern struct list_head ubifs_infos;
@@ -2072,6 +2101,12 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len,
 int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
 		     void *out, int *out_len, int compr_type);

+/* sysfs.c */
+int ubifs_sysfs_init(void);
+void ubifs_sysfs_exit(void);
+int ubifs_sysfs_register(struct ubifs_info *c);
+void ubifs_sysfs_unregister(struct ubifs_info *c);
+
 #include "debug.h"
 #include "misc.h"
 #include "key.h"
--
2.33.0



From sven at narfation.org  Sun Oct 10 05:53:13 2021
From: sven at narfation.org (Sven Eckelmann)
Date: Sun, 10 Oct 2021 14:53:13 +0200
Subject: nvmem: Defining cells on mtd created by mtdparts
Message-ID: <18728084.NGlc0Rocea@sven-desktop>

Hi,

OpenWrt switched [1] their MAC address (from flash) retrieval code from their 
mtd-mac-address based solution [2] to nvmem-cells. The mtd-mac-address based 
solution had the benefit that it could find the correct partition by using 
get_mtd_device_nm - which was label based. So a lookup for a partition which 
was defined via mtdparts was absolutely no problem. This doesn't seem to be
the case for nvmem - at least not how it is integrated at the moment in
OpenWrt.

This means that the performed switch broke the vendor defined MAC addresses 
when the u-boot must dynamically define the partitions via mtdpart - and where 
fixed-partitions are not possible in the DT. The bootloaders used by the ath79 
usually have no devicetree support and cannot modify the device tree (beside 
the problem to get the sources for these bootloaders). These devices will now 
only have random mac addresses.

Since there are most likely more devices out there which use mtdparts, I would 
guess that there might already be a strategy out there which can be used to 
define the nvmem-provider for mtdparts defined partitions. At least I saw that 
Bartosz Golaszewski added all the mtd devices automatically as nvmem provider 
in c4dfa25ab307 ("mtd: add support for reading MTD devices via the nvmem 
API"). So there might also be something for nvmem-cells to find the correct 
mtd instead of relying on the fixed-partitions registration + of_node (which 
doesn't exist because it comes from mtdparts and not devicetree).

Right now nvmem_cell_get (actually __nvmem_device_get) in 
nvmem_get_mac_address just return -517 (EPROBE_DEFER). So the nvmem_device is 
not yet registered - which absolutely makes sense when mtdparts is used. 
of_nvmem_find will just not be able to find the of_node for this partition
via bus_find_device_by_of_node because there is no such of_node for mtdparts 
partitions.

Kind regards,
	Sven

[1] https://github.com/openwrt/openwrt/pull/4041
[2] https://github.com/openwrt/openwrt/commit/5ae2e786395c7f9db0167ebe875be5df9502d8d8
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211010/cae054f8/attachment-0001.sig>

From tony at atomide.com  Sun Oct 10 22:53:50 2021
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 11 Oct 2021 08:53:50 +0300
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <64b65579-7153-1e7d-9866-77ce07fd1df5@canonical.com>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
 <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>
 <64b65579-7153-1e7d-9866-77ce07fd1df5@canonical.com>
Message-ID: <YWPRbmaJQN85wRIO@atomide.com>

* Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> [211009 14:56]:
> On 08/10/2021 21:10, Roger Quadros wrote:
> > Krzysztof,
> > 
> > On 07/10/2021 20:37, Krzysztof Kozlowski wrote:
> >> On 07/10/2021 14:08, Roger Quadros wrote:
> >>> Hi,
> >>>
> >>> This series converts ti,gpmc memory controller and ti,gpmc-nand and
> >>> ti,gpmc-onenand MTD controller bindings to yaml.
> >>>
> >>> cheers,
> >>> -roger
> >>>
> >>
> >> Hi,
> >>
> >> Although you did not mention it here, it looks like you have some
> >> dependencies between the patches. Maybe this shall go simply via Rob's tree?
> >>
> > 
> > Rob has acked all the DT binding patches.
> > So it is upto you and Miqu?l to decide the best way. MTD tree or Memory controller tree
> > for the dt-bindings patches.
> > 
> > The ARM: dts changes should go via Tony's OMAP SoC tree.
> > 
> > Or if Tony is OK with it then maybe all patches can go via Tony's tree? :)
> > 
> 
> 
> I reviewed the two memory-controller patches, so feel free to take them
> via MTD or OMAP SoC.

Sounds like I should pick up these because of the dts changes.

Thanks,

Tony


From p.yadav at ti.com  Sun Oct 10 23:15:57 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Mon, 11 Oct 2021 11:45:57 +0530
Subject: [PATCH v2 19/35] mtd: spi-nor: Get rid of
 SPI_NOR_IO_MODE_EN_VOLATILE flag
In-Reply-To: <490dc958-1033-5807-5a67-8e7f6d064fd7@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-20-tudor.ambarus@microchip.com>
 <20210817122108.nr2elnkiyatdp2hz@ti.com>
 <490dc958-1033-5807-5a67-8e7f6d064fd7@microchip.com>
Message-ID: <20211011061555.6sxmpuvpq7awkyke@ti.com>

On 04/10/21 03:52AM, Tudor.Ambarus at microchip.com wrote:
> On 8/17/21 3:21 PM, Pratyush Yadav wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 27/07/21 07:52AM, Tudor Ambarus wrote:
> >> Get rid of flash_info flags that indicate settings which can be
> >> discovered when parsing SFDP. It will be clearer who sets what,
> >> and we'll restrict the flash settings that a developer can choose to
> >> only settings that are not SFDP discoverable.
> >>
> >> SNOR_F_IO_MODE_EN_VOLATILE is discoverable when parsing the optional
> >> SCCR Map SFDP table. Flashes that do not define this table should set
> >> the flag in the late_init() call. Flashes that define the SFDP optional
> >> table but get the value wrong, should fix it in a post_sfdp fixup hook.
> >>
> >> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> >> ---
> >>  drivers/mtd/spi-nor/core.c      |  3 ---
> >>  drivers/mtd/spi-nor/core.h      |  9 ++-------
> >>  drivers/mtd/spi-nor/micron-st.c | 11 ++++++++---
> >>  3 files changed, 10 insertions(+), 13 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >> index 240d5c31af88..9885d434ea83 100644
> >> --- a/drivers/mtd/spi-nor/core.c
> >> +++ b/drivers/mtd/spi-nor/core.c
> >> @@ -3204,9 +3204,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> >>       if (ret)
> >>               return ret;
> >>
> >> -     if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
> >> -             nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
> >> -
> >>       ret = spi_nor_set_addr_width(nor);
> >>       if (ret)
> >>               return ret;
> >> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> >> index dfdc51a26cad..987797a789c8 100644
> >> --- a/drivers/mtd/spi-nor/core.h
> >> +++ b/drivers/mtd/spi-nor/core.h
> >> @@ -367,17 +367,12 @@ struct flash_info {
> >>                                        */
> >>  #define SPI_NOR_OCTAL_DTR_READ       BIT(18) /* Flash supports octal DTR Read. */
> >>  #define SPI_NOR_OCTAL_DTR_PP BIT(19) /* Flash supports Octal DTR Page Program */
> >> -#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(20) /*
> >> -                                              * Flash enables the best
> >> -                                              * available I/O mode via a
> >> -                                              * volatile bit.
> > 
> > We are losing the information contained in the comment. I think you
> > should move it to SNOR_F_IO_MODE_EN_VOLATILE's declaration.
> 
> ok
> 
> > 
> >> -                                              */
> >> -#define SPI_NOR_SWP_IS_VOLATILE      BIT(21) /*
> >> +#define SPI_NOR_SWP_IS_VOLATILE      BIT(20) /*
> >>                                        * Flash has volatile software write
> >>                                        * protection bits. Usually these will
> >>                                        * power-up in a write-protected state.
> >>                                        */
> >> -#define SPI_NOR_PARSE_SFDP   BIT(22) /*
> >> +#define SPI_NOR_PARSE_SFDP   BIT(21) /*
> >>                                        * Flash initialized based on the SFDP
> >>                                        * tables.
> >>                                        */
> >> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> >> index 72cc4673bf88..31ebd4c9b431 100644
> >> --- a/drivers/mtd/spi-nor/micron-st.c
> >> +++ b/drivers/mtd/spi-nor/micron-st.c
> >> @@ -118,13 +118,18 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
> >>       .post_sfdp = mt35xu512aba_post_sfdp_fixup,
> >>  };
> >>
> >> +static void mt35xu512aba_late_init(struct spi_nor *nor)
> >> +{
> >> +     nor->flags |= SNOR_F_4B_OPCODES;
> > 
> > Like I mentioned in the previous email, you can drop this since the
> > flash populates the 4BAIT table.
> 
> ok
> 
> > 
> >> +     nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
> >> +}
> >> +
> >>  static const struct flash_info micron_parts[] = {
> >>       { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
> >>                              SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
> >> -                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP |
> >> -                            SPI_NOR_IO_MODE_EN_VOLATILE)
> >> +                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
> >>         .fixups = &mt35xu512aba_fixups,
> >> -       .late_init = snor_f_4b_opcodes, },
> >> +       .late_init = mt35xu512aba_late_init, },
> >>       { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
> >>                           SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ)
> >>         .late_init = snor_f_4b_opcodes, },
> > 
> > I forgot to say this in the previous email, but since this flash is the
> > same family as the one above, it should also have the 4BAIT table, and
> > should not need this late_init. But I don't have access to this part so
> > I can't say with 100% certainty.
> > 
> 
> yeah, we don't update flash entries solely by datasheet, we can't update it without
> testing it.

Sounds fair to me. I didn't add Octal DTR support for this flash either, 
since I couldn't actually test it.

> 
> Cheers,
> ta

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From p.yadav at ti.com  Sun Oct 10 23:27:07 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Mon, 11 Oct 2021 11:57:07 +0530
Subject: [PATCH v2 09/35] mtd: spi-nor: atmel: Use flash late_init() for
 locking
In-Reply-To: <88abe817-9d2f-35f6-746c-1640b166aab8@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-10-tudor.ambarus@microchip.com>
 <20210816190629.3kg4cbf5d7h7gyk5@ti.com>
 <a9d41aa96a8749b599d4479f18479c5d@walle.cc>
 <88abe817-9d2f-35f6-746c-1640b166aab8@microchip.com>
Message-ID: <20211011062705.4vgew3efp5vvqwni@ti.com>

On 01/10/21 11:40AM, Tudor.Ambarus at microchip.com wrote:
> On 9/10/21 12:44 AM, Michael Walle wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Am 2021-08-16 21:06, schrieb Pratyush Yadav:
> >> On 27/07/21 07:51AM, Tudor Ambarus wrote:
> >>> Locking is not described in JESD216 SFDP standard, place the locking
> >>> init in late_init().
> > 
> > Btw, we should differentiate between the block protection
> > bits and individual block locking. At least the latter is described
> > in the SFDP (I've seen it in the XTX SFDP, haven't checked the
> > standard yet).
> 
> that's probably a vendor specific table, not something standardized by SFDP.
> 
> > 
> >> You are chaning the order of setting the locking ops here. Earlier,
> >> they
> >> were set before we parsed SFDP. Now they are set after we parse SFDP.
> >> Though I don't see it making much of a difference.
> 
> Right, as the locking is not covered by SFDP, we should place it after
> parsing SFDP.
> 
> >>
> >>>
> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> >>> ---
> >>> ?drivers/mtd/spi-nor/atmel.c | 30 +++++++++++-------------------
> >>> ?1 file changed, 11 insertions(+), 19 deletions(-)
> >>>
> >>> diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
> >>> index 1fea5cab492c..b937ef734e55 100644
> >>> --- a/drivers/mtd/spi-nor/atmel.c
> >>> +++ b/drivers/mtd/spi-nor/atmel.c
> >>> @@ -48,15 +48,11 @@ static const struct spi_nor_locking_ops
> >>> atmel_at25fs_locking_ops = {
> >>> ???? .is_locked = atmel_at25fs_is_locked,
> >>> ?};
> >>>
> >>> -static void atmel_at25fs_default_init(struct spi_nor *nor)
> >>> +static void atmel_at25fs_late_init(struct spi_nor *nor)
> >>> ?{
> >>> ???? nor->params->locking_ops = &atmel_at25fs_locking_ops;
> >>> ?}
> >>>
> >>> -static const struct spi_nor_fixups atmel_at25fs_fixups = {
> >>> -??? .default_init = atmel_at25fs_default_init,
> >>> -};
> >>> -
> >>> ?/**
> >>> ? * atmel_set_global_protection - Do a Global Protect or Unprotect
> >>> command
> >>> ? * @nor:??? pointer to 'struct spi_nor'
> >>> @@ -146,34 +142,30 @@ static const struct spi_nor_locking_ops
> >>> atmel_global_protection_ops = {
> >>> ???? .is_locked = atmel_is_global_protected,
> >>> ?};
> >>>
> >>> -static void atmel_global_protection_default_init(struct spi_nor *nor)
> >>> +static void atmel_global_protection_late_init(struct spi_nor *nor)
> >>> ?{
> >>> ???? nor->params->locking_ops = &atmel_global_protection_ops;
> >>> ?}
> >>>
> >>> -static const struct spi_nor_fixups atmel_global_protection_fixups = {
> >>> -??? .default_init = atmel_global_protection_default_init,
> >>> -};
> >>> -
> >>> ?static const struct flash_info atmel_parts[] = {
> >>> ???? /* Atmel -- some are (confusingly) marketed as "DataFlash" */
> >>> ???? { "at25fs010",? INFO(0x1f6601, 0, 32 * 1024,?? 4, SECT_4K |
> >>> SPI_NOR_HAS_LOCK)
> >>> -??????????? .fixups = &atmel_at25fs_fixups },
> >>> +??????????? .late_init = atmel_at25fs_late_init },
> >>> ???? { "at25fs040",? INFO(0x1f6604, 0, 64 * 1024,?? 8, SECT_4K |
> >>> SPI_NOR_HAS_LOCK)
> >>> -??????????? .fixups = &atmel_at25fs_fixups },
> >>> +??????????? .late_init = atmel_at25fs_late_init },
> >>>
> >>> ???? { "at25df041a", INFO(0x1f4401, 0, 64 * 1024,?? 8,
> >>> ????????????????????????? SECT_4K | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
> >>> -??????????????????? .fixups = &atmel_global_protection_fixups },
> >>> +??????????? .late_init = atmel_global_protection_late_init },
> >>
> >> Won't you be better off setting this in the manufacturer late_init()?
> >> It
> >> seems common for most atmel flashes.
> >>
> >> Of course, this would cause a problem for atmel flashes that don't have
> >> this at all, since we would set locking for those as well. But I think
> >> we can avoid that by checking for SNOR_F_HAS_LOCK in
> >> spi_nor_register_locking_ops().
> > 
> > +1
> > 
> 
> we also have the atmel_at25fs_late_init() method. setting it per manufacturer will result
> in setting the manufacturer locking ops for at25fs as well, which will be overwritten by the
> at25fs locking ops. For those that don't support locking at all, we should clear the locking
> ops as you said. This will make the code a little difficult to follow and we return a bit
> to spaghetti. defining late_init() takes only a line anyway. I would keep the code as it is
> if you don't mind. We can ask ourselves about scalability when we have lots of entries,
> we can reevaluate this in the future. Tell me if you have strong opinions on this.

Okay, this should be fine I think. Looking at the Micron output driver 
strength patch has make me rethink manufacturer-wide settings in 
general. If we add manufacturer-wide settings, and then the manufacturer 
later change their minds and start using different settings for their 
newer flashes, we could easily run into a situation where half the 
flashes are just overwriting the manufacturer-wide default.

> 
> Cheers,
> ta
> 
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From caihuoqing at baidu.com  Sun Oct 10 23:44:46 2021
From: caihuoqing at baidu.com (Cai,Huoqing)
Date: Mon, 11 Oct 2021 06:44:46 +0000
Subject: [PATCH] MAINTAINERS: Update the devicetree documentation path of
 hyperbus
In-Reply-To: <20211009062740.833-1-caihuoqing@baidu.com>
References: <20211009062740.833-1-caihuoqing@baidu.com>
Message-ID: <5d496515614a468881a896c2494add37@baidu.com>

Hello,
+Cc vigneshr at ti.com, linux-mtd at lists.infradead.org

> -----Original Message-----
> From: Cai,Huoqing <caihuoqing at baidu.com>
> Sent: 2021?10?9? 14:28
> To: Cai,Huoqing
> Cc: linux-kernel at vger.kernel.org
> Subject: [PATCH] MAINTAINERS: Update the devicetree documentation path of
> hyperbus
> 
> Change the devicetree documentation path
> to "Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml"
> since 'cypress,hyperflash.txt' and 'ti,am654-hbmc.txt' have
> been converted to 'ti,am654-hbmc.yaml'.
> 
> Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>
> ---
>  MAINTAINERS | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 9b255cf4fca8..48949cd7f898 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8783,8 +8783,7 @@ S:	Supported
>  Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/
>  C:	irc://irc.oftc.net/mtd
>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git cfi/next
> -F:	Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt
> -F:	Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt
> +F:	Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
>  F:	drivers/mtd/hyperbus/
>  F:	include/linux/mtd/hyperbus.h
> 
> --
> 2.25.1


From miquel.raynal at bootlin.com  Sun Oct 10 23:46:07 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 11 Oct 2021 08:46:07 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <CAOf5uwkTzPtqjO0XQ7otzNKLugUzS+9MJg0GkdtvV2JY4=n5mw@mail.gmail.com>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211008152905.2fbdcce9@xps13> <20211008153631.3f1a09aa@xps13>
 <6364938.4vTCxPXJkl@n95hx1g2> <20211008180752.09f33896@xps13>
 <CAOf5uwkTzPtqjO0XQ7otzNKLugUzS+9MJg0GkdtvV2JY4=n5mw@mail.gmail.com>
Message-ID: <20211011084607.27a840e0@xps13>

Hi Michael,

michael at amarulasolutions.com wrote on Sat, 9 Oct 2021 07:53:26 +0200:

> Hi
> 
> On Fri, Oct 8, 2021 at 6:07 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> >
> > Hi Christian,
> >
> > ceggers at arri.de wrote on Fri, 8 Oct 2021 15:49:21 +0200:
> >  
> > > On Friday, 8 October 2021, 15:36:31 CEST, Miquel Raynal wrote:  
> > > >
> > > > miquel.raynal at bootlin.com wrote on Fri, 8 Oct 2021 15:29:05 +0200:
> > > >  
> > > > >
> > > > > If this clock (as I understand) does not prevent us to access the
> > > > > registers but only feeds the external NAND bus part, then there is no
> > > > > need to enable it in the probe, just acquiring it will be enough.  
> > >
> > > clocks[0] is "gpmi_io" which sounds more like i/o than registers. So lets
> > > try to remove the initial call to clk_set_rate().
> > >  
> > > > > Then, the first call for an IO operation with ->must_apply_timings
> > > > > should:
> > > > >
> > > > >   if (imx6)
> > > > >           disable_clk();
> > > > >
> > > > >   clk_set_rate();
> > > > >
> > > > >   if (imx6)
> > > > >           enable_clk();  
> > >
> > > Do you think that the need for avoiding clock glitches is i.MX6 specific?
> > > The errata I mentioned is specific for the bootloader software, but (I think)
> > > the requirement for switching off the clocks gates prior changing the dividers
> > > may apply also for other series.  
> >
> > I honestly don't know, perhaps Han have more details about it. If you
> > think it's a wider issue, then we can just do the disable/enable step
> > without any further checks.
> >  
> 
> Still don't explain why it was working on the old driver. The glitch
> was already there,
> so just a delay can do the trick. For imx28 we need to reparent to a
> different clock the
> nand driver in order to get the frequency we want in EDO mode. I'm
> still thinking that
> set the frequency without without get back and understand if in that
> edo mode is valid
> is still a bug.

There are possibly two bugs here, I am also in favor of checking
that the received frequencies match what we expect, so please provide a
patch to also cover that situation.

Thanks,
Miqu?l


From p.yadav at ti.com  Sun Oct 10 23:54:55 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Mon, 11 Oct 2021 12:24:55 +0530
Subject: [PATCH v2 11/35] mtd: spi-nor: winbond: Use manufacturer
 late_init() for OTP ops
In-Reply-To: <aaab30e5-9ea0-c103-0791-e565470ebbc0@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-12-tudor.ambarus@microchip.com>
 <20210816191744.k6ufbgrrwh6whhnc@ti.com>
 <aaab30e5-9ea0-c103-0791-e565470ebbc0@microchip.com>
Message-ID: <20211011065453.h7mnxpm4ywbaubbe@ti.com>

On 01/10/21 11:54AM, Tudor.Ambarus at microchip.com wrote:
> On 8/16/21 10:17 PM, Pratyush Yadav wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 27/07/21 07:51AM, Tudor Ambarus wrote:
> >> OTP info is not yet discoverable via SFDP, use late_init() to init
> >> the OTP ops.
> > 
> > What do you mean by the "yet"? Does it mean that OTP info is planned to
> > be added to the next SFDP version? Or does it mean that it is possible
> > to discover it via SFDP but we just don't support it yet?
> > 
> > If it is neither and it just means "SFDP does not mention OTP at all",
> > like it is for locking, then you should just drop the "yet". I know this
> > is very nitpicky but it just caught my eye.
> 
> I will update according to your suggestion.
> 
> > 
> >>
> >> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> >> ---
> >>  drivers/mtd/spi-nor/winbond.c | 9 +++++++--
> >>  1 file changed, 7 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
> >> index 96573f61caf5..6be45d2291c6 100644
> >> --- a/drivers/mtd/spi-nor/winbond.c
> >> +++ b/drivers/mtd/spi-nor/winbond.c
> >> @@ -147,17 +147,22 @@ static const struct spi_nor_otp_ops winbond_otp_ops = {
> >>  static void winbond_default_init(struct spi_nor *nor)
> >>  {
> >>       nor->params->set_4byte_addr_mode = winbond_set_4byte_addr_mode;
> > 
> > Why not move this to late_init() as well?
> 
> 4byte mode is SFDP discoverable. Ideally we would get rid of the default_init()
> hook. Flashes that define SFDP will get the 4byte mode from SFDP, the others
> by explicitly setting the late_init() hook. All these should be done at flash
> level, not manufacturer level, otherwise it will be hard to guess who sets what,
> and we can end up with fixups for fixups.

Ok, makes sense.

> 
> I'll parse the 4byte mode from SFDP soon, I think I have some patches somewhere.
> But the series is getting big, so maybe I'll keep it after this patch set.

Which table has that information? BFPT DWORD 16? Anyway, I agree with 
keeping it after this patch set.

> 
> > 
> >> -     if (nor->params->otp.org->n_regions)
> >> -             nor->params->otp.ops = &winbond_otp_ops;
> >>  }
> >>
> >>  static const struct spi_nor_fixups winbond_fixups = {
> >>       .default_init = winbond_default_init,
> >>  };
> >>
> >> +static void winbond_late_init(struct spi_nor *nor)
> >> +{
> >> +     if (nor->params->otp.org->n_regions)
> >> +             nor->params->otp.ops = &winbond_otp_ops;
> >> +}
> >> +
> >>  const struct spi_nor_manufacturer spi_nor_winbond = {
> >>       .name = "winbond",
> >>       .parts = winbond_parts,
> >>       .nparts = ARRAY_SIZE(winbond_parts),
> >>       .fixups = &winbond_fixups,
> >> +     .late_init = winbond_late_init,
> >>  };
> >> --
> >> 2.25.1
> >>
> > 
> > --
> > Regards,
> > Pratyush Yadav
> > Texas Instruments Inc.
> > 
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From rogerq at kernel.org  Mon Oct 11 00:03:48 2021
From: rogerq at kernel.org (Roger Quadros)
Date: Mon, 11 Oct 2021 10:03:48 +0300
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <YWPRbmaJQN85wRIO@atomide.com>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
 <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>
 <64b65579-7153-1e7d-9866-77ce07fd1df5@canonical.com>
 <YWPRbmaJQN85wRIO@atomide.com>
Message-ID: <f2125e81-07da-92ea-899a-d06ecae1919f@kernel.org>

Hi Tony,

On 11/10/2021 08:53, Tony Lindgren wrote:
> * Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> [211009 14:56]:
>> On 08/10/2021 21:10, Roger Quadros wrote:
>>> Krzysztof,
>>>
>>> On 07/10/2021 20:37, Krzysztof Kozlowski wrote:
>>>> On 07/10/2021 14:08, Roger Quadros wrote:
>>>>> Hi,
>>>>>
>>>>> This series converts ti,gpmc memory controller and ti,gpmc-nand and
>>>>> ti,gpmc-onenand MTD controller bindings to yaml.
>>>>>
>>>>> cheers,
>>>>> -roger
>>>>>
>>>>
>>>> Hi,
>>>>
>>>> Although you did not mention it here, it looks like you have some
>>>> dependencies between the patches. Maybe this shall go simply via Rob's tree?
>>>>
>>>
>>> Rob has acked all the DT binding patches.
>>> So it is upto you and Miqu?l to decide the best way. MTD tree or Memory controller tree
>>> for the dt-bindings patches.
>>>
>>> The ARM: dts changes should go via Tony's OMAP SoC tree.
>>>
>>> Or if Tony is OK with it then maybe all patches can go via Tony's tree? :)
>>>
>>
>>
>> I reviewed the two memory-controller patches, so feel free to take them
>> via MTD or OMAP SoC.
> 
> Sounds like I should pick up these because of the dts changes.

There is no dependency with the dts patches but it would be great if you can pick them all up.
Thanks!

cheers,
-roger


From sven at narfation.org  Mon Oct 11 00:06:56 2021
From: sven at narfation.org (Sven Eckelmann)
Date: Mon, 11 Oct 2021 09:06:56 +0200
Subject: nvmem: Defining cells on mtd created by mtdparts
In-Reply-To: <18728084.NGlc0Rocea@sven-desktop>
References: <18728084.NGlc0Rocea@sven-desktop>
Message-ID: <14722734.oMan5NXi5u@sven-desktop>

On Sunday, 10 October 2021 14:53:13 CEST Sven Eckelmann wrote:
[...]
> Since there are most likely more devices out there which use mtdparts, I would 
> guess that there might already be a strategy out there which can be used to 
> define the nvmem-provider for mtdparts defined partitions. At least I saw that 
> Bartosz Golaszewski added all the mtd devices automatically as nvmem provider 
> in c4dfa25ab307 ("mtd: add support for reading MTD devices via the nvmem 
> API"). So there might also be something for nvmem-cells to find the correct 
> mtd instead of relying on the fixed-partitions registration + of_node (which 
> doesn't exist because it comes from mtdparts and not devicetree).

Ansuel Smith just proposed in OpenWrt [1] a workaround. It basically adds a 
minimal fixed-partitions parser to the mtd cmdlinepart parser (responsible for 
the mtdparts=) that tries to find the matching (size + offset) fixed-partition 
from the devicetree. The code in mtd_device_parse_register
(add_mtd_partitions -> add_mtd_device -> mtd_nvmem_add) will then 
automatically take care of the rest.

Kind regards,
	Sven

[1] https://github.com/openwrt/openwrt/pull/4664#issuecomment-939567963
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211011/da5556f6/attachment.sig>

From tony at atomide.com  Mon Oct 11 03:31:36 2021
From: tony at atomide.com (Tony Lindgren)
Date: Mon, 11 Oct 2021 13:31:36 +0300
Subject: [PATCH v5 0/8] dt-bindings: memory-controllers: ti, gpmc: Convert
 to yaml
In-Reply-To: <f2125e81-07da-92ea-899a-d06ecae1919f@kernel.org>
References: <20211007120830.17221-1-rogerq@kernel.org>
 <6b90a6fd-001f-a41a-b69f-2bd3ec8a8e26@canonical.com>
 <e165b6ee-91d3-3a50-3b9d-3f15fa82a101@kernel.org>
 <64b65579-7153-1e7d-9866-77ce07fd1df5@canonical.com>
 <YWPRbmaJQN85wRIO@atomide.com>
 <f2125e81-07da-92ea-899a-d06ecae1919f@kernel.org>
Message-ID: <YWQSiNX/bBKcdTl2@atomide.com>

* Roger Quadros <rogerq at kernel.org> [211011 07:04]:
> Hi Tony,
> 
> On 11/10/2021 08:53, Tony Lindgren wrote:
> > * Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> [211009 14:56]:
> >> On 08/10/2021 21:10, Roger Quadros wrote:
> >>> Krzysztof,
> >>>
> >>> On 07/10/2021 20:37, Krzysztof Kozlowski wrote:
> >>>> On 07/10/2021 14:08, Roger Quadros wrote:
> >>>>> Hi,
> >>>>>
> >>>>> This series converts ti,gpmc memory controller and ti,gpmc-nand and
> >>>>> ti,gpmc-onenand MTD controller bindings to yaml.
> >>>>>
> >>>>> cheers,
> >>>>> -roger
> >>>>>
> >>>>
> >>>> Hi,
> >>>>
> >>>> Although you did not mention it here, it looks like you have some
> >>>> dependencies between the patches. Maybe this shall go simply via Rob's tree?
> >>>>
> >>>
> >>> Rob has acked all the DT binding patches.
> >>> So it is upto you and Miqu?l to decide the best way. MTD tree or Memory controller tree
> >>> for the dt-bindings patches.
> >>>
> >>> The ARM: dts changes should go via Tony's OMAP SoC tree.
> >>>
> >>> Or if Tony is OK with it then maybe all patches can go via Tony's tree? :)
> >>>
> >>
> >>
> >> I reviewed the two memory-controller patches, so feel free to take them
> >> via MTD or OMAP SoC.
> > 
> > Sounds like I should pick up these because of the dts changes.
> 
> There is no dependency with the dts patches but it would be great if you can pick them all up.

OK all pushed out now to omap-for-v5.16/gpmc.

Thanks,

Tony


From xiangsheng.hou at mediatek.com  Mon Oct 11 04:31:28 2021
From: xiangsheng.hou at mediatek.com (xiangsheng.hou)
Date: Mon, 11 Oct 2021 19:31:28 +0800
Subject: [RFC,v1 0/4] Add a driver for Mediatek SPI Nand controller
In-Reply-To: <20211008112045.11e8d148@xps13>
References: <20210927053629.17847-1-xiangsheng.hou@mediatek.com>
 <20211008112045.11e8d148@xps13>
Message-ID: <cb200da61b942d93a272f3391f756c493cb5a342.camel@mediatek.com>

Hi Miquel,

On Fri, 2021-10-08 at 11:20 +0200, Miquel Raynal wrote:
> Hello,
> 
> xiangsheng.hou at mediatek.com wrote on Mon, 27 Sep 2021 13:36:25 +0800:
> 
> > Add a driver for Mediatek SPI Nand controller
> > 
> > Mediatek SPI Nand controller cosists of two parts: on-host HW ECC
> > and
> > snfi(stand for spi nand flash interface). They can cowork with high
> > performance which called ECC nfi mode. The nfi stand for nand flash
> > interfacei(snfi a one part of nfi) which can support SPI Nand flash
> > and raw nand flash.
> > 
> > However, the snfi driver in spi subsytem need to be aware of nand
> > parameter(page/spare size) and ecc status(enable/disable) when work
> > at ECC nfi mode. The snfi driver in spi subsystem seems difficult
> > to
> > know these.
> > 
> > Therefore, consider two ways to let snfi can get these information.
> > The RFC patch send to review whether they are suitable and which
> > solution maybe better.
> > 
> 
> I've looked at both versions that you provided and I thought about a
> number of things that cannot be done like this:
> - I believe the snfi is a regular SPI controller. I will let Mark
>   confirm but I do not think we want to start writing SPI-NAND
>   controllers. Instead we write SPI controllers and we provide SPI-
> mem
>   operations (we've explained this in a previous ELC, the video is
>   available on YouTube).

The snfi controller can support multiple SPI protocols, which can
support other SPI device in theory. However, the snfi need to know nand
parameter and ecc status(enable/disable) when work with MTK on-host HW
BCH ECC engine for nand flash.

Therefore, the RFC patch v1/v2 is try the way to get these information.

> - You cannot add an MTK ECC algorithm. This is dedicated for sofware
>   solutions only and as far as I understand your engine uses the BCH
>   algorithm.
> - When the ECC engine is pipelined, there is an additional complexity
>   in interfacing it with a SPI controller (that's your case I
> believe).
>   I have an example tintendhat is not yet upstream but I think worth
> looking
>   at that I will send very soon (I will Cc: you on it).

Thanks for your patch.

MTK HW ECC(bch) algorithm can work in pipelined and external.
However, the performance worse when work at ecternal which realize and
verify in local. Therefore, try the pipelined in RFC patch v1/v2.

And also realize the mtd/nand info can be get in spi driver which the
spi-mxic driver in your patch. This may solve most of difficulty that
encountered in the snfi driver that the RFC patch v1/v2 try to resolve.

I will prepare the RFC patch v3 with correct pipelined ecc engine
realization for your review.

Thanks
Xiangsheng Hou

From sean at geanix.com  Mon Oct 11 04:52:50 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 11 Oct 2021 13:52:50 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in suspend
Message-ID: <20211011115253.38497-1-sean@geanix.com>

Follow-up on discussion in https://lkml.org/lkml/2021/10/4/41

Changes since from rfc v1/v2:
 - added access protection for all device access hooks in mtd_info.
 - added Suggested-by to [1/3] patch.
 - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
   from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
   to be blamed.
 - tested on a kernel with LOCKDEP enabled.

@Miquel: I havn't covered every ioctl, to me it looks like they havn't
direct device access.

One (small) issue still present. gpmi_nand.c uses the rwsem before it's
initialized. Seems cumbersome to have every mtd/nand driver to call
init_waitqueue_head() and init_rwsem(). Could we somehow move the call
to mtd_set_dev_defaults() before nand_create_bbt()?

---
nand: device found, Manufacturer ID: 0x98, Chip ID: 0xdc
nand: Toshiba NAND 512MiB 3,3V 8-bit
nand: 512 MiB, SLC, erase size: 256 KiB, page size: 4096, OOB size: 128
------------[ cut here ]------------
WARNING: CPU: 0 PID: 1 at kernel/locking/rwsem.c:1240 down_read+0x160/0x184
DEBUG_RWSEMS_WARN_ON(sem->magic != sem): count = 0x0, magic = 0x0, owner = 0x0, curr 0xc40b0000, list not empty 
Modules linked in:
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc3-00002-g7eab985fa8cd-dirty #163 
Hardware name: Freescale i.MX6 Ultralite (Device Tree)
[<c010fa90>] (unwind_backtrace) from [<c010b8fc>] (show_stack+0x10/0x14)
[<c010b8fc>] (show_stack) from [<c0b34998>] (dump_stack_lvl+0x58/0x70)
[<c0b34998>] (dump_stack_lvl) from [<c0123884>] (__warn+0xd4/0x154) 
[<c0123884>] (__warn) from [<c0b2e9ac>] (warn_slowpath_fmt+0x94/0xbc)
[<c0b2e9ac>] (warn_slowpath_fmt) from [<c0b428c8>] (down_read+0x160/0x184)
[<c0b428c8>] (down_read) from [<c06df42c>] (mtd_read_oob+0xc8/0x284)
[<c06df42c>] (mtd_read_oob) from [<c06f28cc>] (scan_block_fast+0x78/0xf4) 
[<c06f28cc>] (scan_block_fast) from [<c06f3c14>] (search_bbt+0x268/0x304) 
[<c06f3c14>] (search_bbt) from [<c06f3ef0>] (nand_create_bbt+0x240/0x6dc) 
[<c06f3ef0>] (nand_create_bbt) from [<c06fa758>] (gpmi_nand_probe+0x568/0x6d0)
[<c06fa758>] (gpmi_nand_probe) from [<c068731c>] (platform_probe+0x58/0xb8)
[<c068731c>] (platform_probe) from [<c0684a48>] (really_probe.part.0+0x9c/0x32c)
[<c0684a48>] (really_probe.part.0) from [<c0684d78>] (__driver_probe_device+0xa0/0x138) 
[<c0684d78>] (__driver_probe_device) from [<c0684e40>] (driver_probe_device+0x30/0x10c) 
[<c0684e40>] (driver_probe_device) from [<c0685510>] (__driver_attach+0xb4/0x174) 
[<c0685510>] (__driver_attach) from [<c0682b84>] (bus_for_each_dev+0x78/0xb8) 
[<c0682b84>] (bus_for_each_dev) from [<c0683ea4>] (bus_add_driver+0xf0/0x1d8) 
[<c0683ea4>] (bus_add_driver) from [<c0686270>] (driver_register+0x88/0x118)
[<c0686270>] (driver_register) from [<c0102108>] (do_one_initcall+0x74/0x378) 
[<c0102108>] (do_one_initcall) from [<c1001304>] (kernel_init_freeable+0x2a4/0x348) 
[<c1001304>] (kernel_init_freeable) from [<c0b3bc34>] (kernel_init+0x10/0x124)
[<c0b3bc34>] (kernel_init) from [<c010011c>] (ret_from_fork+0x14/0x38)
Exception stack(0xc40a7fb0 to 0xc40a7ff8) 
7fa0: ???????? ???????? ???????? ???????? 
7fc0: ???????? ???????? ???????? ???????? ???????? ???????? ???????? ???????? 
7fe0: ???????? ???????? ???????? ???????? ???????? ???????? 
irq event stamp: 110936 
hardirqs lastenabled at (110935): [<c0100b04>] __irq_svc+0x64/0x80
hardirqs last disabled at (110936): [<c0100af0>] __irq_svc+0x50/0x80
softirqs lastenabled at (110906): [<c093818c>] netlink_insert+0x60/0x8a4
softirqs last disabled at (110904): [<c08ac6d4>] release_sock+0x18/0x98 
---[ end trace c70a1a8da23b619d ]---
Bad block table found at page 131008, version 0x01
Bad block table found at page 130944, version 0x01
---

Sean Nyekjaer (3):
  mtd: core: protect access to MTD devices while in suspend
  mtd: rawnand: remove suspended check
  mtd: mtdconcat: add suspend lock handling

 drivers/mtd/mtdconcat.c          |  11 ++-
 drivers/mtd/mtdcore.c            | 133 +++++++++++++++++++++++++++----
 drivers/mtd/nand/raw/nand_base.c |  52 +++---------
 include/linux/mtd/mtd.h          | 109 +++++++++++++++++++++----
 include/linux/mtd/rawnand.h      |   5 +-
 5 files changed, 234 insertions(+), 76 deletions(-)

-- 
2.33.0



From sean at geanix.com  Mon Oct 11 04:52:51 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 11 Oct 2021 13:52:51 +0200
Subject: [PATCH 1/3] mtd: core: protect access to MTD devices while in suspend
In-Reply-To: <20211011115253.38497-1-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
Message-ID: <20211011115253.38497-2-sean@geanix.com>

Prevent accessing the devices while in a suspended state. Also
prevent suspending a device which is still currently in use.

Commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") allows the
rawnand layer to return errors rather than waiting in a blocking wait.

Tested on a iMX6ULL.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdcore.c   | 133 +++++++++++++++++++++++++++++++++++-----
 include/linux/mtd/mtd.h | 109 +++++++++++++++++++++++++++-----
 2 files changed, 211 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c8fd7f758938..51be9b46ef54 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -777,6 +777,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
 	INIT_LIST_HEAD(&mtd->partitions);
 	mutex_init(&mtd->master.partitions_lock);
 	mutex_init(&mtd->master.chrdev_lock);
+	init_waitqueue_head(&mtd->master.resume_wq);
+	init_rwsem(&mtd->master.suspend_lock);
 }
 
 static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
@@ -1257,6 +1259,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	ledtrig_mtd_activity();
 
+	mtd_start_access(mtd);
+
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) {
 		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
 				master->erasesize;
@@ -1278,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 		}
 	}
 
+	mtd_end_access(mtd);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase);
@@ -1289,6 +1295,7 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	      void **virt, resource_size_t *phys)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	*virt = NULL;
@@ -1301,8 +1308,12 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	if (!len)
 		return 0;
 
+	mtd_start_access(mtd);
 	from = mtd_get_master_ofs(mtd, from);
-	return master->_point(master, from, len, retlen, virt, phys);
+	ret = master->_point(master, from, len, retlen, virt, phys);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_point);
 
@@ -1310,6 +1321,7 @@ EXPORT_SYMBOL_GPL(mtd_point);
 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unpoint)
 		return -EOPNOTSUPP;
@@ -1317,7 +1329,12 @@ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
-	return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+
+	mtd_start_access(mtd);
+	ret =  master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unpoint);
 
@@ -1372,6 +1389,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_read_oob handles mtd access protection */
 	ret = mtd_read_oob(mtd, from, &ops);
 	*retlen = ops.retlen;
 
@@ -1388,6 +1406,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_write_oob handles mtd access protection */
 	ret = mtd_write_oob(mtd, to, &ops);
 	*retlen = ops.retlen;
 
@@ -1406,6 +1425,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 		    const u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_panic_write)
@@ -1419,8 +1439,12 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	if (!master->oops_panic_write)
 		master->oops_panic_write = true;
 
-	return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
-				    retlen, buf);
+	mtd_start_access(mtd);
+	ret = master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
+				   retlen, buf);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
@@ -1566,6 +1590,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 
 	ledtrig_mtd_activity();
 
+	mtd_start_access(mtd);
+
 	/* Check the validity of a potential fallback on mtd->_read */
 	if (!master->_read_oob && (!master->_read || ops->oobbuf))
 		return -EOPNOTSUPP;
@@ -1576,7 +1602,7 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 		ret_code = mtd_read_oob_std(mtd, from, ops);
 
 	mtd_update_ecc_stats(mtd, master, &old_stats);
-
+	mtd_end_access(mtd);
 	/*
 	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
 	 * similar to mtd->_read(), returning a non-negative integer
@@ -1597,6 +1623,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	struct mtd_info *master = mtd_get_master(mtd);
 	int ret;
 
+	mtd_start_access(mtd);
+
 	ops->retlen = ops->oobretlen = 0;
 
 	if (!(mtd->flags & MTD_WRITEABLE))
@@ -1615,7 +1643,10 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		return mtd_io_emulated_slc(mtd, to, false, ops);
 
-	return mtd_write_oob_std(mtd, to, ops);
+	ret = mtd_write_oob_std(mtd, to, ops);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_write_oob);
 
@@ -1992,12 +2023,18 @@ int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_fact_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_fact_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(mtd);
+	ret = master->_get_fact_prot_info(master, len, retlen, buf);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
 
@@ -2005,13 +2042,19 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_fact_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_fact_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(mtd);
+	ret = master->_read_fact_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
 
@@ -2019,12 +2062,18 @@ int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_user_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_user_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(mtd);
+	ret =  master->_get_user_prot_info(master, len, retlen, buf);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
 
@@ -2032,13 +2081,19 @@ int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_user_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(mtd);
+	ret = master->_read_user_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
 
@@ -2053,7 +2108,11 @@ int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
+
+	mtd_start_access(mtd);
 	ret = master->_write_user_prot_reg(master, to, len, retlen, buf);
+	mtd_end_access(mtd);
+
 	if (ret)
 		return ret;
 
@@ -2068,24 +2127,36 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_lock_user_prot_reg(master, from, len);
+
+	mtd_start_access(mtd);
+	ret = master->_lock_user_prot_reg(master, from, len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
 
 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_erase_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_erase_user_prot_reg(master, from, len);
+
+	mtd_start_access(mtd);
+	ret = master->_erase_user_prot_reg(master, from, len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 
@@ -2093,6 +2164,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock)
 		return -EOPNOTSUPP;
@@ -2106,13 +2178,18 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(mtd);
+	ret = master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock);
 
 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unlock)
 		return -EOPNOTSUPP;
@@ -2126,13 +2203,18 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(mtd);
+	ret = master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unlock);
 
 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_is_locked)
 		return -EOPNOTSUPP;
@@ -2146,13 +2228,18 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(mtd);
+	ret = master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
 
 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2162,13 +2249,18 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(mtd);
+	ret = master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isreserved);
 
 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2178,7 +2270,11 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(mtd);
+	ret = master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(mtd);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
 
@@ -2197,7 +2293,10 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
+	mtd_start_access(mtd);
 	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(mtd);
+
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..7765d1fcfc8b 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -231,6 +231,8 @@ struct mtd_master {
 	struct mutex partitions_lock;
 	struct mutex chrdev_lock;
 	unsigned int suspended : 1;
+	wait_queue_head_t resume_wq;
+	struct rw_semaphore suspend_lock;
 };
 
 struct mtd_info {
@@ -476,10 +478,49 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
 }
 
+static inline void mtd_start_access(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+
+	/*
+	 * Don't take the suspend_lock on devices that don't
+	 * implement the suspend hook. Otherwise, lockdep will
+	 * complain about nested locks when trying to suspend MTD
+	 * partitions or MTD devices created by gluebi which are
+	 * backed by real devices.
+	 */
+	if (!master->_suspend)
+		return;
+
+	/*
+	 * Wait until the device is resumed. Should we have a
+	 * non-blocking mode here?
+	 */
+	while (1) {
+		down_read(&master->master.suspend_lock);
+		if (!master->master.suspended)
+			return;
+
+		up_read(&master->master.suspend_lock);
+		wait_event(master->master.resume_wq, master->master.suspended == 0);
+	}
+}
+
+static inline void mtd_end_access(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+
+	if (!master->_suspend)
+		return;
+
+	up_read(&master->master.suspend_lock);
+}
+
 static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 				     loff_t ofs, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_max_bad_blocks)
 		return -ENOTSUPP;
@@ -487,8 +528,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 	if (mtd->size < (len + ofs) || ofs < 0)
 		return -EINVAL;
 
-	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
-				       len);
+	mtd_start_access(mtd);
+	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
+				      len);
+	mtd_end_access(mtd);
+
+	return ret;
 }
 
 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
@@ -543,33 +588,69 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
 
+static inline int __mtd_suspend(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+	int ret = 0;
+
+	if (!master->_suspend)
+		return ret;
+
+	if (!master->master.suspended) {
+		ret = master->_suspend(master);
+		if (!ret)
+			master->master.suspended = 1;
+	}
+
+	return ret;
+}
+
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
-	int ret;
+	int ret = 0;
 
-	if (master->master.suspended)
-		return 0;
+	if (!master->_suspend)
+		return ret;
 
-	ret = master->_suspend ? master->_suspend(master) : 0;
-	if (ret)
+	down_write(&master->master.suspend_lock);
+	ret = __mtd_suspend(mtd);
+	up_write(&master->master.suspend_lock);
+
+	return ret;
+}
+
+static inline int __mtd_resume(struct mtd_info *mtd)
+{
+	struct mtd_info *master = mtd_get_master(mtd);
+	int ret = 0;
+
+	if (!master->_suspend)
 		return ret;
 
-	master->master.suspended = 1;
-	return 0;
+	if (master->master.suspended) {
+		if (master->_resume)
+			master->_resume(master);
+
+		master->master.suspended = 0;
+		ret = 1;
+	}
+
+	return ret;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 
-	if (!master->master.suspended)
+	if (!master->_suspend)
 		return;
 
-	if (master->_resume)
-		master->_resume(master);
-
-	master->master.suspended = 0;
+	down_write(&master->master.suspend_lock);
+	/* If MTD dev has been resumed, wake up all waiters. */
+	if (__mtd_resume(mtd))
+		wake_up_all(&master->master.resume_wq);
+	up_write(&master->master.suspend_lock);
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
-- 
2.33.0



From sean at geanix.com  Mon Oct 11 04:52:53 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 11 Oct 2021 13:52:53 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011115253.38497-1-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
Message-ID: <20211011115253.38497-4-sean@geanix.com>

Use new suspend lock handling for this special case for concatenated
MTD devices.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdconcat.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index f685a581df48..c497c851481f 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
 
 static int concat_suspend(struct mtd_info *mtd)
 {
+	struct mtd_info *master = mtd_get_master(mtd);
 	struct mtd_concat *concat = CONCAT(mtd);
 	int i, rc = 0;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		if ((rc = mtd_suspend(subdev)) < 0)
+
+		down_write(&master->master.suspend_lock);
+		if ((rc = __mtd_suspend(subdev)) < 0)
 			return rc;
+		up_write(&master->master.suspend_lock);
 	}
 	return rc;
 }
 
 static void concat_resume(struct mtd_info *mtd)
 {
+	struct mtd_info *master = mtd_get_master(mtd);
 	struct mtd_concat *concat = CONCAT(mtd);
 	int i;
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		mtd_resume(subdev);
+		down_write(&master->master.suspend_lock);
+		__mtd_resume(subdev);
+		up_write(&master->master.suspend_lock);
 	}
 }
 
-- 
2.33.0



From sean at geanix.com  Mon Oct 11 04:52:52 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 11 Oct 2021 13:52:52 +0200
Subject: [PATCH 2/3] mtd: rawnand: remove suspended check
In-Reply-To: <20211011115253.38497-1-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
Message-ID: <20211011115253.38497-3-sean@geanix.com>

Access is protected in upper MTD layer when MTD devices are suspended.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_base.c | 52 ++++++++------------------------
 include/linux/mtd/rawnand.h      |  5 +--
 2 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..aa2874ae3c4a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  * @chip: NAND chip structure
  *
  * Lock the device and its controller for exclusive access
- *
- * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
 	mutex_lock(&chip->controller->lock);
-
-	return 0;
 }
 
 /**
@@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
-
+		nand_get_device(chip);
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
 	}
@@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4345,13 +4332,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	int ret = 0;
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 	if (nand_region_is_secured(chip, instr->addr, instr->len))
 		return -EIO;
 
-	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	/* Grab the lock */
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 	pr_debug("%s: called\n", __func__);
 
-	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	/* Grab the lock */
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
 	mutex_lock(&chip->lock);
 	if (chip->ops.suspend)
 		ret = chip->ops.suspend(chip);
-	if (!ret)
-		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
+
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		if (chip->ops.resume)
-			chip->ops.resume(chip);
-		chip->suspended = 0;
-	} else {
-		pr_err("%s called for a chip which is not in suspended state\n",
-			__func__);
-	}
+	if (chip->ops.resume)
+		chip->ops.resume(chip);
 	mutex_unlock(&chip->lock);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..1198a6548912 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1237,9 +1237,7 @@ struct nand_secure_region {
  * @pagecache.page: Page number currently in the cache. -1 means no page is
  *                  currently cached
  * @buf_align: Minimum buffer alignment required by a platform
- * @lock: Lock protecting the suspended field. Also used to serialize accesses
- *        to the NAND device
- * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @lock: Lock to serialize accesses to the NAND device
  * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
  *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
  *          NAND Controller drivers should not modify this value, but they're
@@ -1293,7 +1291,6 @@ struct nand_chip {
 
 	/* Internals */
 	struct mutex lock;
-	unsigned int suspended : 1;
 	int cur_cs;
 	int read_retries;
 	struct nand_secure_region *secure_regions;
-- 
2.33.0



From boris.brezillon at collabora.com  Mon Oct 11 06:15:01 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 15:15:01 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011115253.38497-4-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-4-sean@geanix.com>
Message-ID: <20211011151501.48cc9289@collabora.com>

On Mon, 11 Oct 2021 13:52:53 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Use new suspend lock handling for this special case for concatenated
> MTD devices.
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
>  drivers/mtd/mtdconcat.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> index f685a581df48..c497c851481f 100644
> --- a/drivers/mtd/mtdconcat.c
> +++ b/drivers/mtd/mtdconcat.c
> @@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
>  
>  static int concat_suspend(struct mtd_info *mtd)
>  {
> +	struct mtd_info *master = mtd_get_master(mtd);
>  	struct mtd_concat *concat = CONCAT(mtd);
>  	int i, rc = 0;
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		if ((rc = mtd_suspend(subdev)) < 0)
> +
> +		down_write(&master->master.suspend_lock);
> +		if ((rc = __mtd_suspend(subdev)) < 0)
>  			return rc;
> +		up_write(&master->master.suspend_lock);
>  	}
>  	return rc;
>  }
>  
>  static void concat_resume(struct mtd_info *mtd)
>  {
> +	struct mtd_info *master = mtd_get_master(mtd);
>  	struct mtd_concat *concat = CONCAT(mtd);
>  	int i;
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		mtd_resume(subdev);
> +		down_write(&master->master.suspend_lock);
> +		__mtd_resume(subdev);
> +		up_write(&master->master.suspend_lock);
>  	}
>  }
>  

Why do we need to implement the _suspend/_resume() hooks here? The
underlying MTD devices should be suspended at some point (when the
class ->suspend() method is called on those device), and there's
nothing mtdconcat-specific to do here. Looks like implementing this
suspend-all-subdevs loop results in calling mtd->_suspend()/_resume()
twice, which is useless. The only issue I see is if the subdevices
haven't been registered to the device model, but that happens, I
believe we have bigger issues (those devices won't be suspended when
mtdconcat is not used).


From boris.brezillon at collabora.com  Mon Oct 11 06:27:03 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 15:27:03 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011151501.48cc9289@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-4-sean@geanix.com>
 <20211011151501.48cc9289@collabora.com>
Message-ID: <20211011152703.0086d990@collabora.com>

On Mon, 11 Oct 2021 15:15:01 +0200
Boris Brezillon <boris.brezillon at collabora.com> wrote:

> On Mon, 11 Oct 2021 13:52:53 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > Use new suspend lock handling for this special case for concatenated
> > MTD devices.
> > 
> > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> > ---
> >  drivers/mtd/mtdconcat.c | 11 +++++++++--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> > index f685a581df48..c497c851481f 100644
> > --- a/drivers/mtd/mtdconcat.c
> > +++ b/drivers/mtd/mtdconcat.c
> > @@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
> >  
> >  static int concat_suspend(struct mtd_info *mtd)
> >  {
> > +	struct mtd_info *master = mtd_get_master(mtd);
> >  	struct mtd_concat *concat = CONCAT(mtd);
> >  	int i, rc = 0;
> >  
> >  	for (i = 0; i < concat->num_subdev; i++) {
> >  		struct mtd_info *subdev = concat->subdev[i];
> > -		if ((rc = mtd_suspend(subdev)) < 0)
> > +
> > +		down_write(&master->master.suspend_lock);
> > +		if ((rc = __mtd_suspend(subdev)) < 0)
> >  			return rc;
> > +		up_write(&master->master.suspend_lock);
> >  	}
> >  	return rc;
> >  }
> >  
> >  static void concat_resume(struct mtd_info *mtd)
> >  {
> > +	struct mtd_info *master = mtd_get_master(mtd);
> >  	struct mtd_concat *concat = CONCAT(mtd);
> >  	int i;
> >  
> >  	for (i = 0; i < concat->num_subdev; i++) {
> >  		struct mtd_info *subdev = concat->subdev[i];
> > -		mtd_resume(subdev);
> > +		down_write(&master->master.suspend_lock);
> > +		__mtd_resume(subdev);
> > +		up_write(&master->master.suspend_lock);
> >  	}
> >  }
> >    
> 
> Why do we need to implement the _suspend/_resume() hooks here? The
> underlying MTD devices should be suspended at some point (when the
> class ->suspend() method is called on those device), and there's
> nothing mtdconcat-specific to do here. Looks like implementing this
> suspend-all-subdevs loop results in calling mtd->_suspend()/_resume()
> twice, which is useless. The only issue I see is if the subdevices
> haven't been registered to the device model, but that happens, I
> believe we have bigger issues (those devices won't be suspended when
> mtdconcat is not used).


Uh, just had a look at mtd_concat_create() callers, and they indeed
don't register the subdevices, so I guess the suspend-all-subdevs loop
is needed. I really thought mtdconcat was something more generic
aggregating already registered devices...


From sean at geanix.com  Mon Oct 11 06:35:56 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 11 Oct 2021 15:35:56 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011152703.0086d990@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-4-sean@geanix.com>
 <20211011151501.48cc9289@collabora.com>
 <20211011152703.0086d990@collabora.com>
Message-ID: <20211011133556.probhbuowxkumpzb@skn-laptop>

On Mon, Oct 11, 2021 at 03:27:03PM +0200, Boris Brezillon wrote:
> On Mon, 11 Oct 2021 15:15:01 +0200
> Boris Brezillon <boris.brezillon at collabora.com> wrote:
> 
> > On Mon, 11 Oct 2021 13:52:53 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> > 
> > > Use new suspend lock handling for this special case for concatenated
> > > MTD devices.
> > > 
> > > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > > Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> > > ---
> > >  drivers/mtd/mtdconcat.c | 11 +++++++++--
> > >  1 file changed, 9 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> > > index f685a581df48..c497c851481f 100644
> > > --- a/drivers/mtd/mtdconcat.c
> > > +++ b/drivers/mtd/mtdconcat.c
> > > @@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
> > >  
> > >  static int concat_suspend(struct mtd_info *mtd)
> > >  {
> > > +	struct mtd_info *master = mtd_get_master(mtd);
> > >  	struct mtd_concat *concat = CONCAT(mtd);
> > >  	int i, rc = 0;
> > >  
> > >  	for (i = 0; i < concat->num_subdev; i++) {
> > >  		struct mtd_info *subdev = concat->subdev[i];
> > > -		if ((rc = mtd_suspend(subdev)) < 0)
> > > +
> > > +		down_write(&master->master.suspend_lock);
> > > +		if ((rc = __mtd_suspend(subdev)) < 0)
> > >  			return rc;
> > > +		up_write(&master->master.suspend_lock);
> > >  	}
> > >  	return rc;
> > >  }
> > >  
> > >  static void concat_resume(struct mtd_info *mtd)
> > >  {
> > > +	struct mtd_info *master = mtd_get_master(mtd);
> > >  	struct mtd_concat *concat = CONCAT(mtd);
> > >  	int i;
> > >  
> > >  	for (i = 0; i < concat->num_subdev; i++) {
> > >  		struct mtd_info *subdev = concat->subdev[i];
> > > -		mtd_resume(subdev);
> > > +		down_write(&master->master.suspend_lock);
> > > +		__mtd_resume(subdev);
> > > +		up_write(&master->master.suspend_lock);
> > >  	}
> > >  }
> > >    
> > 
> > Why do we need to implement the _suspend/_resume() hooks here? The
> > underlying MTD devices should be suspended at some point (when the
> > class ->suspend() method is called on those device), and there's
> > nothing mtdconcat-specific to do here. Looks like implementing this
> > suspend-all-subdevs loop results in calling mtd->_suspend()/_resume()
> > twice, which is useless. The only issue I see is if the subdevices
> > haven't been registered to the device model, but that happens, I
> > believe we have bigger issues (those devices won't be suspended when
> > mtdconcat is not used).
> 
> 
> Uh, just had a look at mtd_concat_create() callers, and they indeed
> don't register the subdevices, so I guess the suspend-all-subdevs loop
> is needed. I really thought mtdconcat was something more generic
> aggregating already registered devices...

Hi Boris,

Cool, mtd_concat should be seen as mtd devices concatenated? Could be
spi-nors and rawnand. So _suspend() needs to be called for every device
layer?

>From what I see here, mtd_suspend()/mtd_resume() is called for every mtd
device. Before this patch mtd_suspend() would only have effect on the
first device as master->master.suspended is set and then calls to
device specific _suspend() is skipped.

Correct?

/Sean


From boris.brezillon at collabora.com  Mon Oct 11 06:37:04 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 15:37:04 +0200
Subject: [PATCH 1/3] mtd: core: protect access to MTD devices while in
 suspend
In-Reply-To: <20211011115253.38497-2-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-2-sean@geanix.com>
Message-ID: <20211011153704.3465be1c@collabora.com>

On Mon, 11 Oct 2021 13:52:51 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Prevent accessing the devices while in a suspended state. Also
> prevent suspending a device which is still currently in use.
> 
> Commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") allows the
> rawnand layer to return errors rather than waiting in a blocking wait.
> 
> Tested on a iMX6ULL.
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
>  drivers/mtd/mtdcore.c   | 133 +++++++++++++++++++++++++++++++++++-----
>  include/linux/mtd/mtd.h | 109 +++++++++++++++++++++++++++-----
>  2 files changed, 211 insertions(+), 31 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c8fd7f758938..51be9b46ef54 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -777,6 +777,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
>  	INIT_LIST_HEAD(&mtd->partitions);
>  	mutex_init(&mtd->master.partitions_lock);
>  	mutex_init(&mtd->master.chrdev_lock);
> +	init_waitqueue_head(&mtd->master.resume_wq);
> +	init_rwsem(&mtd->master.suspend_lock);
>  }
>  
>  static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
> @@ -1257,6 +1259,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
>  
>  	ledtrig_mtd_activity();
>  
> +	mtd_start_access(mtd);
> +
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) {
>  		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
>  				master->erasesize;
> @@ -1278,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
>  		}
>  	}
>  
> +	mtd_end_access(mtd);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_erase);
> @@ -1289,6 +1295,7 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
>  	      void **virt, resource_size_t *phys)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	*retlen = 0;
>  	*virt = NULL;
> @@ -1301,8 +1308,12 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
>  	if (!len)
>  		return 0;
>  
> +	mtd_start_access(mtd);
>  	from = mtd_get_master_ofs(mtd, from);
> -	return master->_point(master, from, len, retlen, virt, phys);
> +	ret = master->_point(master, from, len, retlen, virt, phys);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_point);
>  
> @@ -1310,6 +1321,7 @@ EXPORT_SYMBOL_GPL(mtd_point);
>  int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_unpoint)
>  		return -EOPNOTSUPP;
> @@ -1317,7 +1329,12 @@ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
>  		return -EINVAL;
>  	if (!len)
>  		return 0;
> -	return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
> +
> +	mtd_start_access(mtd);
> +	ret =  master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_unpoint);
>  
> @@ -1372,6 +1389,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
>  	};
>  	int ret;
>  
> +	/* mtd_read_oob handles mtd access protection */
>  	ret = mtd_read_oob(mtd, from, &ops);
>  	*retlen = ops.retlen;
>  
> @@ -1388,6 +1406,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
>  	};
>  	int ret;
>  
> +	/* mtd_write_oob handles mtd access protection */
>  	ret = mtd_write_oob(mtd, to, &ops);
>  	*retlen = ops.retlen;
>  
> @@ -1406,6 +1425,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
>  		    const u_char *buf)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	*retlen = 0;
>  	if (!master->_panic_write)
> @@ -1419,8 +1439,12 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
>  	if (!master->oops_panic_write)
>  		master->oops_panic_write = true;
>  
> -	return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
> -				    retlen, buf);
> +	mtd_start_access(mtd);
> +	ret = master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
> +				   retlen, buf);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_panic_write);
>  
> @@ -1566,6 +1590,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>  
>  	ledtrig_mtd_activity();
>  
> +	mtd_start_access(mtd);
> +
>  	/* Check the validity of a potential fallback on mtd->_read */
>  	if (!master->_read_oob && (!master->_read || ops->oobbuf))
>  		return -EOPNOTSUPP;
> @@ -1576,7 +1602,7 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>  		ret_code = mtd_read_oob_std(mtd, from, ops);
>  
>  	mtd_update_ecc_stats(mtd, master, &old_stats);
> -
> +	mtd_end_access(mtd);
>  	/*
>  	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
>  	 * similar to mtd->_read(), returning a non-negative integer
> @@ -1597,6 +1623,8 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>  	struct mtd_info *master = mtd_get_master(mtd);
>  	int ret;
>  
> +	mtd_start_access(mtd);
> +
>  	ops->retlen = ops->oobretlen = 0;
>  
>  	if (!(mtd->flags & MTD_WRITEABLE))
> @@ -1615,7 +1643,10 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		return mtd_io_emulated_slc(mtd, to, false, ops);
>  
> -	return mtd_write_oob_std(mtd, to, ops);
> +	ret = mtd_write_oob_std(mtd, to, ops);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_write_oob);
>  
> @@ -1992,12 +2023,18 @@ int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
>  			   struct otp_info *buf)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_get_fact_prot_info)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_get_fact_prot_info(master, len, retlen, buf);
> +
> +	mtd_start_access(mtd);
> +	ret = master->_get_fact_prot_info(master, len, retlen, buf);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
>  
> @@ -2005,13 +2042,19 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
>  			   size_t *retlen, u_char *buf)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	*retlen = 0;
>  	if (!master->_read_fact_prot_reg)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_read_fact_prot_reg(master, from, len, retlen, buf);
> +
> +	mtd_start_access(mtd);
> +	ret = master->_read_fact_prot_reg(master, from, len, retlen, buf);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
>  
> @@ -2019,12 +2062,18 @@ int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
>  			   struct otp_info *buf)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_get_user_prot_info)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_get_user_prot_info(master, len, retlen, buf);
> +
> +	mtd_start_access(mtd);
> +	ret =  master->_get_user_prot_info(master, len, retlen, buf);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
>  
> @@ -2032,13 +2081,19 @@ int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
>  			   size_t *retlen, u_char *buf)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	*retlen = 0;
>  	if (!master->_read_user_prot_reg)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_read_user_prot_reg(master, from, len, retlen, buf);
> +
> +	mtd_start_access(mtd);
> +	ret = master->_read_user_prot_reg(master, from, len, retlen, buf);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
>  
> @@ -2053,7 +2108,11 @@ int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> +
> +	mtd_start_access(mtd);
>  	ret = master->_write_user_prot_reg(master, to, len, retlen, buf);
> +	mtd_end_access(mtd);
> +
>  	if (ret)
>  		return ret;
>  
> @@ -2068,24 +2127,36 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
>  int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_lock_user_prot_reg)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_lock_user_prot_reg(master, from, len);
> +
> +	mtd_start_access(mtd);
> +	ret = master->_lock_user_prot_reg(master, from, len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
>  
>  int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_erase_user_prot_reg)
>  		return -EOPNOTSUPP;
>  	if (!len)
>  		return 0;
> -	return master->_erase_user_prot_reg(master, from, len);
> +
> +	mtd_start_access(mtd);
> +	ret = master->_erase_user_prot_reg(master, from, len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
>  
> @@ -2093,6 +2164,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
>  int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_lock)
>  		return -EOPNOTSUPP;
> @@ -2106,13 +2178,18 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
>  	}
>  
> -	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_start_access(mtd);
> +	ret = master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_lock);
>  
>  int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_unlock)
>  		return -EOPNOTSUPP;
> @@ -2126,13 +2203,18 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
>  	}
>  
> -	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_start_access(mtd);
> +	ret = master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_unlock);
>  
>  int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_is_locked)
>  		return -EOPNOTSUPP;
> @@ -2146,13 +2228,18 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
>  	}
>  
> -	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_start_access(mtd);
> +	ret = master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_is_locked);
>  
>  int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (ofs < 0 || ofs >= mtd->size)
>  		return -EINVAL;
> @@ -2162,13 +2249,18 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
>  
> -	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
> +	mtd_start_access(mtd);
> +	ret = master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_block_isreserved);
>  
>  int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (ofs < 0 || ofs >= mtd->size)
>  		return -EINVAL;
> @@ -2178,7 +2270,11 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
>  
> -	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
> +	mtd_start_access(mtd);
> +	ret = master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(mtd_block_isbad);
>  
> @@ -2197,7 +2293,10 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
>  
> +	mtd_start_access(mtd);
>  	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
> +	mtd_end_access(mtd);
> +
>  	if (ret)
>  		return ret;
>  
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 88227044fc86..7765d1fcfc8b 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -231,6 +231,8 @@ struct mtd_master {
>  	struct mutex partitions_lock;
>  	struct mutex chrdev_lock;
>  	unsigned int suspended : 1;
> +	wait_queue_head_t resume_wq;
> +	struct rw_semaphore suspend_lock;
>  };
>  
>  struct mtd_info {
> @@ -476,10 +478,49 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
>  	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
>  }
>  
> +static inline void mtd_start_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	/*
> +	 * Don't take the suspend_lock on devices that don't
> +	 * implement the suspend hook. Otherwise, lockdep will
> +	 * complain about nested locks when trying to suspend MTD
> +	 * partitions or MTD devices created by gluebi which are
> +	 * backed by real devices.
> +	 */
> +	if (!master->_suspend)
> +		return;
> +
> +	/*
> +	 * Wait until the device is resumed. Should we have a
> +	 * non-blocking mode here?
> +	 */
> +	while (1) {
> +		down_read(&master->master.suspend_lock);
> +		if (!master->master.suspended)
> +			return;
> +
> +		up_read(&master->master.suspend_lock);
> +		wait_event(master->master.resume_wq, master->master.suspended == 0);
> +	}
> +}
> +
> +static inline void mtd_end_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	if (!master->_suspend)
> +		return;
> +
> +	up_read(&master->master.suspend_lock);
> +}
> +
>  static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
>  				     loff_t ofs, size_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_max_bad_blocks)
>  		return -ENOTSUPP;
> @@ -487,8 +528,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
>  	if (mtd->size < (len + ofs) || ofs < 0)
>  		return -EINVAL;
>  
> -	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
> -				       len);
> +	mtd_start_access(mtd);
> +	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
> +				      len);
> +	mtd_end_access(mtd);
> +
> +	return ret;
>  }
>  
>  int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
> @@ -543,33 +588,69 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs);
>  int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
>  int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
>  
> +static inline int __mtd_suspend(struct mtd_info *mtd)

Please give it a proper name, like mtd_suspend_locked().

I'm really not found of this solution where we let mtdconcat grab the
lock and call the mtd_{suspend,resume}_locked() variant on its
subdevices, but fixing it in a sane way would require registering the
subdevices, which is likely to mess up with the MTD dev numbering and
cause even more pain. But please add comment explaining why you need to
expose those _locked() variants, with a big 'DON'T USE UNLESS YOU'RE
MTDCONCAT' disclaimer. Or maybe even better, open-code the _locked()
variants in mtdconcat so others don't get tempted to use it.

> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret = 0;
> +
> +	if (!master->_suspend)
> +		return ret;
> +
> +	if (!master->master.suspended) {
> +		ret = master->_suspend(master);
> +		if (!ret)
> +			master->master.suspended = 1;
> +	}
> +
> +	return ret;
> +}
> +
>  static inline int mtd_suspend(struct mtd_info *mtd)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> -	int ret;
> +	int ret = 0;
>  
> -	if (master->master.suspended)
> -		return 0;
> +	if (!master->_suspend)
> +		return ret;
>  
> -	ret = master->_suspend ? master->_suspend(master) : 0;
> -	if (ret)
> +	down_write(&master->master.suspend_lock);
> +	ret = __mtd_suspend(mtd);
> +	up_write(&master->master.suspend_lock);
> +
> +	return ret;
> +}
> +
> +static inline int __mtd_resume(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret = 0;
> +
> +	if (!master->_suspend)
>  		return ret;
>  
> -	master->master.suspended = 1;
> -	return 0;
> +	if (master->master.suspended) {
> +		if (master->_resume)
> +			master->_resume(master);
> +
> +		master->master.suspended = 0;
> +		ret = 1;
> +	}
> +
> +	return ret;
>  }
>  
>  static inline void mtd_resume(struct mtd_info *mtd)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
>  
> -	if (!master->master.suspended)
> +	if (!master->_suspend)
>  		return;
>  
> -	if (master->_resume)
> -		master->_resume(master);
> -
> -	master->master.suspended = 0;
> +	down_write(&master->master.suspend_lock);
> +	/* If MTD dev has been resumed, wake up all waiters. */
> +	if (__mtd_resume(mtd))
> +		wake_up_all(&master->master.resume_wq);
> +	up_write(&master->master.suspend_lock);
>  }
>  
>  static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)



From boris.brezillon at collabora.com  Mon Oct 11 06:49:13 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 15:49:13 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011133556.probhbuowxkumpzb@skn-laptop>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-4-sean@geanix.com>
 <20211011151501.48cc9289@collabora.com>
 <20211011152703.0086d990@collabora.com>
 <20211011133556.probhbuowxkumpzb@skn-laptop>
Message-ID: <20211011154913.5d67c7ef@collabora.com>

On Mon, 11 Oct 2021 15:35:56 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Mon, Oct 11, 2021 at 03:27:03PM +0200, Boris Brezillon wrote:
> > On Mon, 11 Oct 2021 15:15:01 +0200
> > Boris Brezillon <boris.brezillon at collabora.com> wrote:
> >   
> > > On Mon, 11 Oct 2021 13:52:53 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:
> > >   
> > > > Use new suspend lock handling for this special case for concatenated
> > > > MTD devices.
> > > > 
> > > > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > > > Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> > > > ---
> > > >  drivers/mtd/mtdconcat.c | 11 +++++++++--
> > > >  1 file changed, 9 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> > > > index f685a581df48..c497c851481f 100644
> > > > --- a/drivers/mtd/mtdconcat.c
> > > > +++ b/drivers/mtd/mtdconcat.c
> > > > @@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
> > > >  
> > > >  static int concat_suspend(struct mtd_info *mtd)
> > > >  {
> > > > +	struct mtd_info *master = mtd_get_master(mtd);
> > > >  	struct mtd_concat *concat = CONCAT(mtd);
> > > >  	int i, rc = 0;
> > > >  
> > > >  	for (i = 0; i < concat->num_subdev; i++) {
> > > >  		struct mtd_info *subdev = concat->subdev[i];
> > > > -		if ((rc = mtd_suspend(subdev)) < 0)
> > > > +
> > > > +		down_write(&master->master.suspend_lock);
> > > > +		if ((rc = __mtd_suspend(subdev)) < 0)
> > > >  			return rc;
> > > > +		up_write(&master->master.suspend_lock);
> > > >  	}
> > > >  	return rc;
> > > >  }
> > > >  
> > > >  static void concat_resume(struct mtd_info *mtd)
> > > >  {
> > > > +	struct mtd_info *master = mtd_get_master(mtd);
> > > >  	struct mtd_concat *concat = CONCAT(mtd);
> > > >  	int i;
> > > >  
> > > >  	for (i = 0; i < concat->num_subdev; i++) {
> > > >  		struct mtd_info *subdev = concat->subdev[i];
> > > > -		mtd_resume(subdev);
> > > > +		down_write(&master->master.suspend_lock);
> > > > +		__mtd_resume(subdev);
> > > > +		up_write(&master->master.suspend_lock);
> > > >  	}
> > > >  }
> > > >      
> > > 
> > > Why do we need to implement the _suspend/_resume() hooks here? The
> > > underlying MTD devices should be suspended at some point (when the
> > > class ->suspend() method is called on those device), and there's
> > > nothing mtdconcat-specific to do here. Looks like implementing this
> > > suspend-all-subdevs loop results in calling mtd->_suspend()/_resume()
> > > twice, which is useless. The only issue I see is if the subdevices
> > > haven't been registered to the device model, but that happens, I
> > > believe we have bigger issues (those devices won't be suspended when
> > > mtdconcat is not used).  
> > 
> > 
> > Uh, just had a look at mtd_concat_create() callers, and they indeed
> > don't register the subdevices, so I guess the suspend-all-subdevs loop
> > is needed. I really thought mtdconcat was something more generic
> > aggregating already registered devices...  
> 
> Hi Boris,
> 
> Cool, mtd_concat should be seen as mtd devices concatenated? Could be
> spi-nors and rawnand. So _suspend() needs to be called for every device
> layer?

If those subdevices were registered as MTD devices too, you wouldn't
have to call ->_suspend()/_resume() on the subdevices (the core does it
for you for every registered 'struct device' object).

> 
> From what I see here, mtd_suspend()/mtd_resume() is called for every mtd
> device. Before this patch mtd_suspend() would only have effect on the
> first device as master->master.suspended is set and then calls to
> device specific _suspend() is skipped.

Unfortunately, subdevices are not exposed to the MTD framework, only the
aggregate is, so suspend is called once in that case, and the mtdconcat
layer has to propagate it to all its subdevices. This makes mtdconcat
unsuitable for a generic MTD aggregation layer BTW (which I remember
discussing with someone on the MTD ML in the past).



From boris.brezillon at collabora.com  Mon Oct 11 06:58:05 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 15:58:05 +0200
Subject: [PATCH 3/3] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211011115253.38497-4-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-4-sean@geanix.com>
Message-ID: <20211011155805.7793ad21@collabora.com>

On Mon, 11 Oct 2021 13:52:53 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Use new suspend lock handling for this special case for concatenated
> MTD devices.
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
>  drivers/mtd/mtdconcat.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> index f685a581df48..c497c851481f 100644
> --- a/drivers/mtd/mtdconcat.c
> +++ b/drivers/mtd/mtdconcat.c
> @@ -561,25 +561,32 @@ static void concat_sync(struct mtd_info *mtd)
>  
>  static int concat_suspend(struct mtd_info *mtd)
>  {
> +	struct mtd_info *master = mtd_get_master(mtd);
>  	struct mtd_concat *concat = CONCAT(mtd);
>  	int i, rc = 0;
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		if ((rc = mtd_suspend(subdev)) < 0)
> +
> +		down_write(&master->master.suspend_lock);

You should definitely not take the concat lock here, the framework does
it for you, so all you'll get is a deadlock.

> +		if ((rc = __mtd_suspend(subdev)) < 0)
>  			return rc;

You're returning with the lock held => DEADLOCK next time you try to
acquire it.

Anyway, as mentioned in my review of patch 1, I'd go for this ad-hoc
solution:


	for (i = 0; i < concat->num_subdev; i++) {
		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
		if (rc < 0)
			return rc;
	}

	return 0;

> +		up_write(&master->master.suspend_lock);
>  	}
>  	return rc;
>  }
>  
>  static void concat_resume(struct mtd_info *mtd)
>  {
> +	struct mtd_info *master = mtd_get_master(mtd);
>  	struct mtd_concat *concat = CONCAT(mtd);
>  	int i;
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		mtd_resume(subdev);
> +		down_write(&master->master.suspend_lock);
> +		__mtd_resume(subdev);
> +		up_write(&master->master.suspend_lock);
>  	}

No down/up_write() needed:

  	for (i = 0; i < concat->num_subdev; i++) {
  		struct mtd_info *subdev = concat->subdev[i];
		if (subdev->_resume)
			subdev->_resume(subdev);

	}
>  }
>  



From boris.brezillon at collabora.com  Mon Oct 11 07:05:46 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 11 Oct 2021 16:05:46 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211011115253.38497-1-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
Message-ID: <20211011160546.707b737b@collabora.com>

On Mon, 11 Oct 2021 13:52:50 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Follow-up on discussion in https://lkml.org/lkml/2021/10/4/41
> 
> Changes since from rfc v1/v2:
>  - added access protection for all device access hooks in mtd_info.
>  - added Suggested-by to [1/3] patch.
>  - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
>    from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
>    to be blamed.
>  - tested on a kernel with LOCKDEP enabled.
> 
> @Miquel: I havn't covered every ioctl, to me it looks like they havn't
> direct device access.
> 
> One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> initialized. Seems cumbersome to have every mtd/nand driver to call
> init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> to mtd_set_dev_defaults() before nand_create_bbt()?

I have a nasty trick for that one, but I'm not sure Miquel will like it
(actually, I don't like it either, but it's so simple compared to the
other options we have that I'm tempted to go for this approach until
someone has time to invest in a cleaner solution :-)):

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..a9ac2d528a4d 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
        mtd->_sync = nand_sync;
        mtd->_lock = nand_lock;
        mtd->_unlock = nand_unlock;
-       mtd->_suspend = nand_suspend;
-       mtd->_resume = nand_resume;
        mtd->_reboot = nand_shutdown;
        mtd->_block_isreserved = nand_block_isreserved;
        mtd->_block_isbad = nand_block_isbad;
@@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
        if (ret)
                goto err_free_secure_regions;
 
+       /*
+        * Populate the suspend/resume hooks after the BBT has been scanned to
+        * avoid using the suspend lock and resume waitqueue which are only
+        * initialized when mtd_device_register() is called.
+        */
+       mtd->_suspend = nand_suspend;
+       mtd->_resume = nand_resume;
        return 0;
 
 err_free_secure_regions:



> 
> ---
> nand: device found, Manufacturer ID: 0x98, Chip ID: 0xdc
> nand: Toshiba NAND 512MiB 3,3V 8-bit
> nand: 512 MiB, SLC, erase size: 256 KiB, page size: 4096, OOB size: 128
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 1 at kernel/locking/rwsem.c:1240 down_read+0x160/0x184
> DEBUG_RWSEMS_WARN_ON(sem->magic != sem): count = 0x0, magic = 0x0, owner = 0x0, curr 0xc40b0000, list not empty 
> Modules linked in:
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc3-00002-g7eab985fa8cd-dirty #163 
> Hardware name: Freescale i.MX6 Ultralite (Device Tree)
> [<c010fa90>] (unwind_backtrace) from [<c010b8fc>] (show_stack+0x10/0x14)
> [<c010b8fc>] (show_stack) from [<c0b34998>] (dump_stack_lvl+0x58/0x70)
> [<c0b34998>] (dump_stack_lvl) from [<c0123884>] (__warn+0xd4/0x154) 
> [<c0123884>] (__warn) from [<c0b2e9ac>] (warn_slowpath_fmt+0x94/0xbc)
> [<c0b2e9ac>] (warn_slowpath_fmt) from [<c0b428c8>] (down_read+0x160/0x184)
> [<c0b428c8>] (down_read) from [<c06df42c>] (mtd_read_oob+0xc8/0x284)
> [<c06df42c>] (mtd_read_oob) from [<c06f28cc>] (scan_block_fast+0x78/0xf4) 
> [<c06f28cc>] (scan_block_fast) from [<c06f3c14>] (search_bbt+0x268/0x304) 
> [<c06f3c14>] (search_bbt) from [<c06f3ef0>] (nand_create_bbt+0x240/0x6dc) 
> [<c06f3ef0>] (nand_create_bbt) from [<c06fa758>] (gpmi_nand_probe+0x568/0x6d0)
> [<c06fa758>] (gpmi_nand_probe) from [<c068731c>] (platform_probe+0x58/0xb8)
> [<c068731c>] (platform_probe) from [<c0684a48>] (really_probe.part.0+0x9c/0x32c)
> [<c0684a48>] (really_probe.part.0) from [<c0684d78>] (__driver_probe_device+0xa0/0x138) 
> [<c0684d78>] (__driver_probe_device) from [<c0684e40>] (driver_probe_device+0x30/0x10c) 
> [<c0684e40>] (driver_probe_device) from [<c0685510>] (__driver_attach+0xb4/0x174) 
> [<c0685510>] (__driver_attach) from [<c0682b84>] (bus_for_each_dev+0x78/0xb8) 
> [<c0682b84>] (bus_for_each_dev) from [<c0683ea4>] (bus_add_driver+0xf0/0x1d8) 
> [<c0683ea4>] (bus_add_driver) from [<c0686270>] (driver_register+0x88/0x118)
> [<c0686270>] (driver_register) from [<c0102108>] (do_one_initcall+0x74/0x378) 
> [<c0102108>] (do_one_initcall) from [<c1001304>] (kernel_init_freeable+0x2a4/0x348) 
> [<c1001304>] (kernel_init_freeable) from [<c0b3bc34>] (kernel_init+0x10/0x124)
> [<c0b3bc34>] (kernel_init) from [<c010011c>] (ret_from_fork+0x14/0x38)
> Exception stack(0xc40a7fb0 to 0xc40a7ff8) 
> 7fa0: ???????? ???????? ???????? ???????? 
> 7fc0: ???????? ???????? ???????? ???????? ???????? ???????? ???????? ???????? 
> 7fe0: ???????? ???????? ???????? ???????? ???????? ???????? 
> irq event stamp: 110936 
> hardirqs lastenabled at (110935): [<c0100b04>] __irq_svc+0x64/0x80
> hardirqs last disabled at (110936): [<c0100af0>] __irq_svc+0x50/0x80
> softirqs lastenabled at (110906): [<c093818c>] netlink_insert+0x60/0x8a4
> softirqs last disabled at (110904): [<c08ac6d4>] release_sock+0x18/0x98 
> ---[ end trace c70a1a8da23b619d ]---
> Bad block table found at page 131008, version 0x01
> Bad block table found at page 130944, version 0x01
> ---
> 
> Sean Nyekjaer (3):
>   mtd: core: protect access to MTD devices while in suspend
>   mtd: rawnand: remove suspended check
>   mtd: mtdconcat: add suspend lock handling

Patch 3 (with the suggested changes) should be moved at the beginning of
the series to keep things bisectable.

> 
>  drivers/mtd/mtdconcat.c          |  11 ++-
>  drivers/mtd/mtdcore.c            | 133 +++++++++++++++++++++++++++----
>  drivers/mtd/nand/raw/nand_base.c |  52 +++---------
>  include/linux/mtd/mtd.h          | 109 +++++++++++++++++++++----
>  include/linux/mtd/rawnand.h      |   5 +-
>  5 files changed, 234 insertions(+), 76 deletions(-)
> 



From Alexander.Stein at ew.tq-group.com  Mon Oct 11 07:22:21 2021
From: Alexander.Stein at ew.tq-group.com (Alexander Stein)
Date: Mon, 11 Oct 2021 14:22:21 +0000
Subject: AW: (EXT) Re: [PATCH 2/2] mtd: spi-nor: micron-st: Add support for
 output-driver-strength
Message-ID: <kcEE.K51pswPLSRK1NpSyVG7WYA.gMwmZ6u+1wE@vtuxmail01.tq-net.de>

Hello Pratyush,

> On 08/10/21 01:18PM, Pratyush Yadav wrote:
> From: Pratyush Yadav <p.yadav at ti.com>
> > 
> > Micron flashes support this by the Bits [2:0] in the Enhanced Volatile
> > Configuration Register.
> > Checked datasheets:
> > - n25q_128mb_3v_65nm.pdf
> > - mt25t-qljs-L512-xBA-xxT.pdf
> 
> What does changing the impedance do? Does it improve latency? If we use 
> suboptimal impedance, will the flash still keep working correctly?
> 
> In other words, you need to justify why this patch is needed.

Hardware guys told me this will affect the signal qualitiy when the flash is
sending data. This depends among others on line length. If set incorrectly
voltage overshoots upon 0->1 or 1-> switch might occur. To answer to your
question if the flash will work with incorrect settings: It depends. It might
working the short term, but might fail in the long term.
Also this is completly unrelated to latency.

> > +static int micron_read_evcr(struct spi_nor *nor)
> > +{
> > +	int ret;
> > +
> > +	if (nor->spimem) {
> > +		struct spi_mem_op op =
> > +			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_EVCR, 1),
> > +				   SPI_MEM_OP_NO_ADDR,
> > +				   SPI_MEM_OP_NO_DUMMY,
> > +				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
> 
> Are you always guaranteed to be in 1S-1S-1S mode during register write?
> 
> I would suggest calling spi_nor_spimem_setup_op() before this so that it 
> sets up all the buswidths correctly based on nor->reg_proto.

Thanks, I wasn't aware of that. I'll do that.

> > +
> > +		ret = spi_mem_exec_op(nor->spimem, &op);
> > +	} else {
> > +		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RD_EVCR, nor->bouncebuf,
> 1);
> 
> Split into 2 lines?

Will do.

> > +	}
> > +
> > +	if (ret < 0) {
> > +		dev_err(nor->dev, "error %d reading EVCR\n", ret);
> > +		return ret;
> > +	}
> > +
> > +	return nor->bouncebuf[0];
> > +}
> > +
> > +/*
> > + * Write Micron enhanced volatile configuration register
> > + * Return negative if error occurred or configuration register value
> > + */
> > +static int micron_write_evcr(struct spi_nor *nor, u8 evcr)
> > +{
> > +	nor->bouncebuf[0] = evcr;
> > +
> > +	spi_nor_write_enable(nor);
> 
> Check return code.

Will do.

> > +
> > +	if (nor->spimem) {
> > +		struct spi_mem_op op =
> > +			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WD_EVCR, 1),
> > +				   SPI_MEM_OP_NO_ADDR,
> > +				   SPI_MEM_OP_NO_DUMMY,
> > +				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1));
> 
> Same as above.

Will do.

> > +
> > +		return spi_mem_exec_op(nor->spimem, &op);
> > +	}
> > +
> > +	return nor->controller_ops->write_reg(nor, SPINOR_OP_WD_EVCR, nor->bouncebuf,
> 1);
> 
> Same as above. Split into 2 lines?

Will do.

> > +}
> > +
> > +/*
> > + * Supported values from Enahanced Volatile COnfiguration Register (Bits
> 2:0)
> > + */
> > +static const struct micron_drive_strength drive_strength_data[] = {
> > +	{ .ohms = 90, .val = 1 },
> > +	{ .ohms = 45, .val = 3 },
> > +	{ .ohms = 20, .val = 5 },
> > +	{ .ohms = 30, .val = 7 },
> > +};
> > +
> > +static struct micron_drive_strength const *micron_st_find_drive_strength_entry(u32
> ohms)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(drive_strength_data); i++) {
> > +		if (ohms == drive_strength_data[i].ohms)
> > +			return &drive_strength_data[i];
> > +	}
> > +	return NULL;
> > +}
> > +
> > +static void micron_st_post_sfdp(struct spi_nor *nor)
> > +{
> > +	struct device_node *np = spi_nor_get_flash_node(nor);
> > +	u32 ohms;
> > +
> > +	if (!np)
> > +		return;
> > +
> > +	if (!of_property_read_u32(np, "output-driver-strength", &ohms)) {
> > +		struct micron_drive_strength const *entry =
> > +			micron_st_find_drive_strength_entry(ohms);
> > +
> > +		if (entry) {
> > +			int evcrr = micron_read_evcr(nor);
> > +
> > +			if (evcrr >= 0) {
> 
> This is a bit confusing. Can you instead do:
> 
> if (evcrr < 0)
> 	return evcrr;
> 
> ...

Will do.

> > +				u8 evcr = (u8)(evcrr & 0xf8) | entry->val;
> 
> Don't use magic numbers. Define a bitmask, preferably using GENMASK().

Will do.

> > +
> > +				micron_write_evcr(nor, evcr);
> 
> Check return code. Do we need to abort flash probe if this fails, or can 
> we live with it, despite the suboptimal impedance?

Well, it's hard to say. It might work, see above. At least this should raise a warning
if setting the driver strength for some reason.

> > +				dev_dbg(nor->dev, "%s: EVCR 0x%x\n", __func__,
> > +					(u32)micron_read_evcr(nor));
> > +			}
> > +		} else {
> > +			dev_warn(nor->dev,
> > +				"Invalid output-driver-strength property specified: %u",
> > +				ohms);
> > +		}
> > +	}
> > +}
> > +
> >  static const struct spi_nor_fixups micron_st_fixups = {
> >  	.default_init = micron_st_default_init,
> > +	.post_sfdp = micron_st_post_sfdp,
> 
> NACK. Not every Micron flash has the EVCR register. For example, the 
> Micron MT35 flash family does not have an EVCR and the output drive 
> strength is programmed in a separate register. Set this only for the 
> flashes that need this.

Thanks for that information. I do not have the MT35 datasheet, so I wasn't aware of it.
I'll stick to MT25Q for now, which is the part number my datasheet is for.

Thanks for your feedback.

Best regards,
Alexander



From miquel.raynal at bootlin.com  Mon Oct 11 07:31:08 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 11 Oct 2021 16:31:08 +0200
Subject: [RFC,v1 0/4] Add a driver for Mediatek SPI Nand controller
In-Reply-To: <cb200da61b942d93a272f3391f756c493cb5a342.camel@mediatek.com>
References: <20210927053629.17847-1-xiangsheng.hou@mediatek.com>
 <20211008112045.11e8d148@xps13>
 <cb200da61b942d93a272f3391f756c493cb5a342.camel@mediatek.com>
Message-ID: <20211011163108.256752eb@xps13>

Hello,

xiangsheng.hou at mediatek.com wrote on Mon, 11 Oct 2021 19:31:28 +0800:

> Hi Miquel,
> 
> On Fri, 2021-10-08 at 11:20 +0200, Miquel Raynal wrote:
> > Hello,
> > 
> > xiangsheng.hou at mediatek.com wrote on Mon, 27 Sep 2021 13:36:25 +0800:
> >   
> > > Add a driver for Mediatek SPI Nand controller
> > > 
> > > Mediatek SPI Nand controller cosists of two parts: on-host HW ECC
> > > and
> > > snfi(stand for spi nand flash interface). They can cowork with high
> > > performance which called ECC nfi mode. The nfi stand for nand flash
> > > interfacei(snfi a one part of nfi) which can support SPI Nand flash
> > > and raw nand flash.
> > > 
> > > However, the snfi driver in spi subsytem need to be aware of nand
> > > parameter(page/spare size) and ecc status(enable/disable) when work
> > > at ECC nfi mode. The snfi driver in spi subsystem seems difficult
> > > to
> > > know these.
> > > 
> > > Therefore, consider two ways to let snfi can get these information.
> > > The RFC patch send to review whether they are suitable and which
> > > solution maybe better.
> > >   
> > 
> > I've looked at both versions that you provided and I thought about a
> > number of things that cannot be done like this:
> > - I believe the snfi is a regular SPI controller. I will let Mark
> >   confirm but I do not think we want to start writing SPI-NAND
> >   controllers. Instead we write SPI controllers and we provide SPI-
> > mem
> >   operations (we've explained this in a previous ELC, the video is
> >   available on YouTube).  
> 
> The snfi controller can support multiple SPI protocols, which can
> support other SPI device in theory. However, the snfi need to know nand
> parameter and ecc status(enable/disable) when work with MTK on-host HW
> BCH ECC engine for nand flash.
> 
> Therefore, the RFC patch v1/v2 is try the way to get these information.
> 
> > - You cannot add an MTK ECC algorithm. This is dedicated for sofware
> >   solutions only and as far as I understand your engine uses the BCH
> >   algorithm.
> > - When the ECC engine is pipelined, there is an additional complexity
> >   in interfacing it with a SPI controller (that's your case I
> > believe).
> >   I have an example tintendhat is not yet upstream but I think worth
> > looking
> >   at that I will send very soon (I will Cc: you on it).  
> 
> Thanks for your patch.
> 
> MTK HW ECC(bch) algorithm can work in pipelined and external.
> However, the performance worse when work at ecternal which realize and
> verify in local. Therefore, try the pipelined in RFC patch v1/v2.

Yes this is completely expected as the data must be moved twice instead
of once. I believe pipelined mode is harder to implement in software but
brings better performances.

> And also realize the mtd/nand info can be get in spi driver which the
> spi-mxic driver in your patch. This may solve most of difficulty that
> encountered in the snfi driver that the RFC patch v1/v2 try to resolve.

Great, that was indeed the goal.

> I will prepare the RFC patch v3 with correct pipelined ecc engine
> realization for your review.

Thanks,
Miqu?l


From havasiefr at gmail.com  Mon Oct 11 10:16:01 2021
From: havasiefr at gmail.com (Kristof Havasi)
Date: Mon, 11 Oct 2021 19:16:01 +0200
Subject: UBIFS panic during brown-out
Message-ID: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>

Dear Richard,

we have been in contact regarding another (similar) kernel panic a year ago:
http://lists.infradead.org/pipermail/linux-mtd/2020-September/082175.html

Now we are stress testing our board for brown-out stability, and we can
see reproducible file system corruptions.
The culprit was narrowed down to a pending SQLite operation during brown-out,
in the business-logic.

As far as I understood, UBIFS is extremely robust in such cases, so I would
expect a corrupted file as the worst case scenario, not an unbootable system.

Am I too "optimistic" about UBIFS's brown-out stability?

Does the Auth+Encryption combo increase the chances for corrupting the FS
during brown-out, due to the extra operations?

Would you suggest turning on any of the chk_* knobs in the debugfs?
I am not sure that they are helpful, or will just modify the behaviour of the
timings of the system too much.

Would it be a last resort in case the brown-out is detected to switch the FS
into ro mode? Is there any API/ABI apart from the debugfs's ro_error knob to
switch the FS into read-only mode and so trying to prevent file-system
corruption?

Any pointers are welcomed!

We are on Kernel v5.4.150
We use _both_ UBIFS Authentication and Encryption.
The board is a SAMA5D3 powered embedded device with 1GB NAND flash,
which is not even nearly full (10% used).

Kernel panic after the last brown-out:
ubi0: scanning is finished
ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
sequence number: 921361235
>ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for bad PEB handling: 67
ubi0: background thread "ubi_bgt0d" started, PID 617
UBIFS (ubi0:4): Mounting in authenticated mode
UBIFS (ubi0:4): recovery needed
>VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on ubi0:rootfs
CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.109-00033-ga88943c1e68 #1
Hardware name: Atmel SAMA5
[<c010babc>] (unwind_backtrace) from [<c010a8d0>] (show_stack+0x10/0x14)
[<c010a8d0>] (show_stack) from [<c0569970>] (panic+0xfc/0x2e8)
[<c0569970>] (panic) from [<c0801598>] (mount_block_root+0x268/0x2a4)
[<c0801598>] (mount_block_root) from [<c0801674>] (prepare_namespace+0x9c/0x184)
[<c0801674>] (prepare_namespace) from [<c056b774>] (kernel_init+0x8/0x108)
[<c056b774>] (kernel_init) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
Exception stack(0xc7829fb0 to 0xc7829ff8)
9fa0:                                     00000000 00000000 00000000 00000000
9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on
ubi0:rootfs ]---

Best regards,
Krist?f Havasi


From richard at nod.at  Mon Oct 11 12:02:46 2021
From: richard at nod.at (Richard Weinberger)
Date: Mon, 11 Oct 2021 21:02:46 +0200 (CEST)
Subject: UBIFS panic during brown-out
In-Reply-To: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
Message-ID: <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>

Krist?f,

----- Urspr?ngliche Mail -----
> Von: "Kristof Havasi" <havasiefr at gmail.com>
> An: "richard" <richard at nod.at>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>
> Gesendet: Montag, 11. Oktober 2021 19:16:01
> Betreff: UBIFS panic during brown-out

> Dear Richard,
> 
> we have been in contact regarding another (similar) kernel panic a year ago:
> http://lists.infradead.org/pipermail/linux-mtd/2020-September/082175.html
> 
> Now we are stress testing our board for brown-out stability, and we can
> see reproducible file system corruptions.
> The culprit was narrowed down to a pending SQLite operation during brown-out,
> in the business-logic.
> 
> As far as I understood, UBIFS is extremely robust in such cases, so I would
> expect a corrupted file as the worst case scenario, not an unbootable system.
> 
> Am I too "optimistic" about UBIFS's brown-out stability?

A brown-out is something very bad. Electronic components show undefined behavior
in this phase. UBIFS (and Linux) can nothing do there.
But both UBI and UBIFS try to be robust against sudden power loss (power-cut).
E.g. an interrupted erase or program operation. 

So, are you really talking about brown-out? If so, better talk to you hardware guys.

> Does the Auth+Encryption combo increase the chances for corrupting the FS
> during brown-out, due to the extra operations?

Assuming you actually meant power-cut.
Both features are rather new, so there can be still bugs.
 
> Would you suggest turning on any of the chk_* knobs in the debugfs?
> I am not sure that they are helpful, or will just modify the behaviour of the
> timings of the system too much.

Let's start with logs first.
 
> Would it be a last resort in case the brown-out is detected to switch the FS
> into ro mode? Is there any API/ABI apart from the debugfs's ro_error knob to
> switch the FS into read-only mode and so trying to prevent file-system
> corruption?

Not really. You need to make sure that the current NAND command is finished
and no new one will be scheduled. Depending on your hardware design this can
be a challenge.

> Any pointers are welcomed!
> 
> We are on Kernel v5.4.150
> We use _both_ UBIFS Authentication and Encryption.
> The board is a SAMA5D3 powered embedded device with 1GB NAND flash,
> which is not even nearly full (10% used).
> 
> Kernel panic after the last brown-out:
> ubi0: scanning is finished
> ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
> ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
> sequence number: 921361235
>>ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for bad PEB
>>handling: 67
> ubi0: background thread "ubi_bgt0d" started, PID 617
> UBIFS (ubi0:4): Mounting in authenticated mode
> UBIFS (ubi0:4): recovery needed
>>VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1

There is a lot of context missing. Can you please share the full logs?
Usually UBIFS prints in detail what went wrong.

> Please append a correct "root=" boot option; here are the available partitions:
> Kernel panic - not syncing: VFS: Unable to mount root fs on ubi0:rootfs
> CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.109-00033-ga88943c1e68 #1

5.4 is not fresh. Can you use a more recent kernel?

Thanks,
//richard


From a-nandan at ti.com  Mon Oct 11 13:46:05 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:05 +0530
Subject: [PATCH v2 00/14] mtd: spinand: Add Octal DTR SPI (8D-8D-8D) mode
 support
Message-ID: <20211011204619.81893-1-a-nandan@ti.com>

Hi,
This series proposes patches for adding the following functionality
in SPI NAND core:

- Octal DTR SPI (8D-8D-8D) mode support

- Winbond W35N01JW SPI NAND chip support

- Power-on-Reset instruction support

This series has been tested on TI J721e EVM with the Winbond W35N01JW
flash with following test utilities:

- nandtest
  Test log: https://textbin.net/raw/fhypoz63f9

- mtd_stresstest
  Test log: https://textbin.net/raw/0xqjmqntj7

- UBIFS LTP stress test (NAND_XL_STRESS_DD_RW_UBIFS).
  Test log: https://textbin.net/raw/pyokws7wku

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

---
Changes in v2:

- Removed *_ALL_ARGS() macros from spi-mem.h, and redefined DTR macros.

- Renamed spinand_setup_op() to spinand_patch_op(). Reduced one
  conditional check from this function. Had to keep tweaking in hot-path
  to avoid complicated implementation "hacks".

- Changes in commit messages and added comments.

- Dropped "Reject 8D-8D-8D op_templates if octal_dtr_enale() is
  missing in manufacturer_op" patch.

- Reduced PoR reset delay.

- Splitted "mtd: spinand: Add support for Winbond W35N01JW SPI NAND
  flash" into 3 independent patches.

Apurva Nandan (14):
  spi: spi-mem: Add DTR templates for cmd, address, dummy and data phase
  mtd: spinand: Add enum spinand_proto to indicate current SPI IO mode
  mtd: spinand: Patch spi_mem_op for the SPI IO protocol using reg_proto
  mtd: spinand: Fix odd byte addr and data phase in read and write reg
    op for Octal DTR mode
  mtd: spinand: Add adjust_op() in manufacturer_ops to modify the ops
    for manufacturer specific changes
  mtd: spinand: Add macros for Octal DTR page read and write operations
  mtd: spinand: Allow enabling Octal DTR mode in the core
  mtd: spinand: winbond: Add support for write volatile configuration
    register op
  mtd: spinand: winbond: Add octal_dtr_enable() for manufacturer_ops
  mtd: spinand: Add support for Power-on-Reset (PoR) instruction
  mtd: spinand: Perform Power-on-Reset on the flash in mtd_suspend()
  mtd: spinand: Add adjust_op() in Winbond manufacturer_ops
  mtd: spinand: winbond: Rename cache op_variants struct variable
  mtd: spinand: winbond: Add support for Winbond W35N01JW SPI NAND flash

 drivers/mtd/nand/spi/core.c    | 187 +++++++++++++++++++++++++++++-
 drivers/mtd/nand/spi/winbond.c | 200 +++++++++++++++++++++++++++++++--
 include/linux/mtd/spinand.h    |  67 +++++++++++
 include/linux/spi/spi-mem.h    |  41 +++++++
 4 files changed, 484 insertions(+), 11 deletions(-)

-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:06 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:06 +0530
Subject: [PATCH v2 01/14] spi: spi-mem: Add DTR templates for cmd, address,
 dummy and data phase
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-2-a-nandan@ti.com>

Setting dtr field of spi_mem_op is useful when creating templates
for DTR ops in spinand.h. Also, 2 bytes cmd phases are required when
operating in Octal DTR SPI mode.

Create new templates for dtr mode cmd, address, dummy and data phase
in spi_mem_op, which set the dtr field to 1 and also allow passing
the nbytes for the cmd phase.

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 include/linux/spi/spi-mem.h | 41 +++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
index 85e2ff7b840d..4a99e26aa0b6 100644
--- a/include/linux/spi/spi-mem.h
+++ b/include/linux/spi/spi-mem.h
@@ -20,6 +20,14 @@
 		.nbytes = 1,					\
 	}
 
+#define SPI_MEM_OP_CMD_DTR(__nbytes, __opcode, __buswidth)	\
+	{							\
+		.buswidth = __buswidth,				\
+		.opcode = __opcode,				\
+		.nbytes = __nbytes,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth)		\
 	{							\
 		.nbytes = __nbytes,				\
@@ -27,6 +35,14 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_ADDR_DTR(__nbytes, __val, __buswidth)	\
+	{							\
+		.nbytes = __nbytes,				\
+		.val = __val,					\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_ADDR	{ }
 
 #define SPI_MEM_OP_DUMMY(__nbytes, __buswidth)			\
@@ -35,6 +51,13 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DUMMY_DTR(__nbytes, __buswidth)		\
+	{							\
+		.nbytes = __nbytes,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_DUMMY	{ }
 
 #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth)		\
@@ -45,6 +68,15 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DATA_IN_DTR(__nbytes, __buf, __buswidth)	\
+	{							\
+		.dir = SPI_MEM_DATA_IN,				\
+		.nbytes = __nbytes,				\
+		.buf.in = __buf,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth)	\
 	{							\
 		.dir = SPI_MEM_DATA_OUT,			\
@@ -53,6 +85,15 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DATA_OUT_DTR(__nbytes, __buf, __buswidth)	\
+	{							\
+		.dir = SPI_MEM_DATA_OUT,			\
+		.nbytes = __nbytes,				\
+		.buf.out = __buf,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_DATA	{ }
 
 /**
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:07 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:07 +0530
Subject: [PATCH v2 02/14] mtd: spinand: Add enum spinand_proto to indicate
 current SPI IO mode
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-3-a-nandan@ti.com>

Unlike Dual and Quad SPI modes flashes, Octal DTR SPI NAND flashes
require all instructions to be made in 8D-8D-8D protocol when the
flash is in Octal DTR mode. Hence, storing the current SPI IO mode
becomes necessary for correctly generating non-array access operations.

Store the current SPI IO mode in the spinand struct using a reg_proto
enum. This would act as a flag, denoting that the core should use
the given SPI protocol for non-page access operations.

Also provide basic macros for extracting buswidth and dtr mode
information from the spinand_proto enum.

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c |  2 ++
 include/linux/mtd/spinand.h | 30 ++++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 2c8685f1f2fa..d82a3e6d9bb5 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1155,6 +1155,7 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
 	struct spinand_device *spinand = mtd_to_spinand(mtd);
 	int ret;
 
+	spinand->reg_proto = SPINAND_SINGLE_STR;
 	ret = spinand_reset_op(spinand);
 	if (ret)
 		return;
@@ -1181,6 +1182,7 @@ static int spinand_init(struct spinand_device *spinand)
 	if (!spinand->scratchbuf)
 		return -ENOMEM;
 
+	spinand->reg_proto = SPINAND_SINGLE_STR;
 	ret = spinand_detect(spinand);
 	if (ret)
 		goto err_free_bufs;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 6988956b8492..f6093cd98d7b 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -140,6 +140,31 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(len, buf, 4))
 
+#define SPINAND_PROTO_BUSWIDTH_MASK	GENMASK(6, 0)
+#define SPINAND_PROTO_DTR_BIT		BIT(7)
+
+#define SPINAND_PROTO_STR(__buswidth)	\
+	((u8)(((__buswidth) - 1) & SPINAND_PROTO_BUSWIDTH_MASK))
+#define SPINAND_PROTO_DTR(__buswidth)	\
+	(SPINAND_PROTO_DTR_BIT | SPINAND_PROTO_STR(__buswidth))
+
+#define SPINAND_PROTO_BUSWIDTH(__proto)	\
+	((u8)(((__proto) & SPINAND_PROTO_BUSWIDTH_MASK) + 1))
+#define SPINAND_PROTO_IS_DTR(__proto)	(!!((__proto) & SPINAND_PROTO_DTR_BIT))
+
+/**
+ * enum spinand_proto - List allowable SPI protocol variants for read reg,
+ *			write reg, blk erase, write enable/disable, page read
+ *			and program exec operations.
+ */
+enum spinand_proto {
+	SPINAND_SINGLE_STR = SPINAND_PROTO_STR(1),
+	SPINAND_DUAL_STR = SPINAND_PROTO_STR(2),
+	SPINAND_QUAD_STR = SPINAND_PROTO_STR(4),
+	SPINAND_OCTAL_STR = SPINAND_PROTO_STR(8),
+	SPINAND_OCTAL_DTR = SPINAND_PROTO_DTR(8),
+};
+
 /**
  * Standard SPI NAND flash commands
  */
@@ -407,6 +432,9 @@ struct spinand_dirmap {
  *		   this die. Only required if your chip exposes several dies
  * @cur_target: currently selected target/die
  * @eccinfo: on-die ECC information
+ * @reg_proto: select a variant of SPI IO protocol (single, quad, octal or
+ *	       octal DTR) for read_reg/write_reg/erase operations. Update on
+ *	       successful transition into a different SPI IO protocol.
  * @cfg_cache: config register cache. One entry per die
  * @databuf: bounce buffer for data
  * @oobbuf: bounce buffer for OOB data
@@ -438,6 +466,8 @@ struct spinand_device {
 
 	struct spinand_ecc_info eccinfo;
 
+	enum spinand_proto reg_proto;
+
 	u8 *cfg_cache;
 	u8 *databuf;
 	u8 *oobbuf;
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:08 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:08 +0530
Subject: [PATCH v2 03/14] mtd: spinand: Patch spi_mem_op for the SPI IO
 protocol using reg_proto
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-4-a-nandan@ti.com>

Currently, the op macros in spinand.h don't give the option to setup
any non-array access instructions for Dual/Quad/Octal DTR SPI bus.
Having a function that patches the op based on reg_proto would be
better than trying to write all the setup logic in op macros.

Create a spimem_patch_op() that would patch cmd, addr, dummy and data
phase of the spi_mem op, for the given spinand->reg_proto. And hence,
call the spimem_patch_op() before executing any spi_mem op.

Note: In this commit, spimem_patch_op() isn't called in the
read_reg_op(), write_reg_op() and wait() functions, as they need
modifications in address value and data nbytes when in Octal DTR mode.
This will be fixed in a later commit.

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 49 +++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index d82a3e6d9bb5..11746d858f87 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -20,6 +20,49 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-mem.h>
 
+/**
+ * spinand_patch_op() - Helper function to patch the spi_mem op based on the
+ *			spinand->reg_proto
+ * @spinand: the spinand device
+ * @op: the spi_mem op to patch
+ *
+ * Set up buswidth and dtr fields for cmd, addr, dummy and data phase. Also
+ * adjust cmd opcode and dummy nbytes. This function doesn't make any changes
+ * to addr val or data buf.
+ */
+static void spinand_patch_op(const struct spinand_device *spinand,
+			     struct spi_mem_op *op)
+{
+	u8 op_buswidth = SPINAND_PROTO_BUSWIDTH(spinand->reg_proto);
+	u8 op_is_dtr = SPINAND_PROTO_IS_DTR(spinand->reg_proto);
+
+	if (spinand->reg_proto == SPINAND_SINGLE_STR)
+		return;
+
+	op->cmd.buswidth = op_buswidth;
+	op->cmd.dtr = op_is_dtr;
+	if (spinand->reg_proto == SPINAND_OCTAL_DTR) {
+		op->cmd.opcode = (op->cmd.opcode << 8) | op->cmd.opcode;
+		op->cmd.nbytes = 2;
+	}
+
+	if (op->addr.nbytes) {
+		op->addr.buswidth = op_buswidth;
+		op->addr.dtr = op_is_dtr;
+	}
+
+	if (op->dummy.nbytes) {
+		op->dummy.buswidth = op_buswidth;
+		op->dummy.dtr = op_is_dtr;
+		op->dummy.nbytes <<= op_is_dtr;
+	}
+
+	if (op->data.nbytes) {
+		op->data.buswidth = op_buswidth;
+		op->data.dtr = op_is_dtr;
+	}
+}
+
 static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
 {
 	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
@@ -343,6 +386,7 @@ static int spinand_write_enable_op(struct spinand_device *spinand)
 {
 	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
 
+	spinand_patch_op(spinand, &op);
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -353,6 +397,7 @@ static int spinand_load_page_op(struct spinand_device *spinand,
 	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
 	struct spi_mem_op op = SPINAND_PAGE_READ_OP(row);
 
+	spinand_patch_op(spinand, &op);
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -477,6 +522,7 @@ static int spinand_program_op(struct spinand_device *spinand,
 	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
 	struct spi_mem_op op = SPINAND_PROG_EXEC_OP(row);
 
+	spinand_patch_op(spinand, &op);
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -487,6 +533,7 @@ static int spinand_erase_op(struct spinand_device *spinand,
 	unsigned int row = nanddev_pos_to_row(nand, pos);
 	struct spi_mem_op op = SPINAND_BLK_ERASE_OP(row);
 
+	spinand_patch_op(spinand, &op);
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -533,6 +580,7 @@ static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr,
 		naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
 	int ret;
 
+	spinand_patch_op(spinand, &op);
 	ret = spi_mem_exec_op(spinand->spimem, &op);
 	if (!ret)
 		memcpy(buf, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
@@ -545,6 +593,7 @@ static int spinand_reset_op(struct spinand_device *spinand)
 	struct spi_mem_op op = SPINAND_RESET_OP;
 	int ret;
 
+	spinand_patch_op(spinand, &op);
 	ret = spi_mem_exec_op(spinand->spimem, &op);
 	if (ret)
 		return ret;
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:09 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:09 +0530
Subject: [PATCH v2 04/14] mtd: spinand: Fix odd byte addr and data phase in
 read and write reg op for Octal DTR mode
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-5-a-nandan@ti.com>

In Octal DTR SPI mode, 2 bytes of data gets transmitted over one clock
cycle, and half-cycle instruction phases aren't supported yet. So,
every DTR spi_mem_op needs to have even nbytes in all phases for
non-erratic behaviour from the SPI controller.

The odd length cmd and dummy phases get handled by spimem_patch_op()
but the odd length address and data phases need to be handled according
to the use case. For example in Octal DTR mode, read register operation
has one byte long address and data phase. So it needs to extend it
by adding a suitable extra byte in addr and reading 2 bytes of data,
discarding the second byte.

Handle address and data phases for Octal DTR mode in read and write
register operations by adding a suitable extra byte in the address and
data phase.

Create spimem_patch_reg_op() helper function to ease setting up
read/write register operations in other functions, e.g. wait().

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 11746d858f87..4da794ae728d 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -63,12 +63,29 @@ static void spinand_patch_op(const struct spinand_device *spinand,
 	}
 }
 
+static void spinand_patch_reg_op(const struct spinand_device *spinand,
+				 struct spi_mem_op *op)
+{
+	if (spinand->reg_proto == SPINAND_OCTAL_DTR) {
+		/*
+		 * Assigning same first and second byte will result in constant
+		 * bits on the SPI bus between positive and negative clock edges
+		 */
+		op->addr.val = (op->addr.val << 8) | op->addr.val;
+		op->addr.nbytes = 2;
+		op->data.nbytes = 2;
+	}
+
+	spinand_patch_op(spinand, op);
+}
+
 static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
 {
 	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
 						      spinand->scratchbuf);
 	int ret;
 
+	spinand_patch_reg_op(spinand, &op);
 	ret = spi_mem_exec_op(spinand->spimem, &op);
 	if (ret)
 		return ret;
@@ -82,7 +99,8 @@ static int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val)
 	struct spi_mem_op op = SPINAND_SET_FEATURE_OP(reg,
 						      spinand->scratchbuf);
 
-	*spinand->scratchbuf = val;
+	spinand_patch_reg_op(spinand, &op);
+	memset(spinand->scratchbuf, val, op.data.nbytes);
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -547,6 +565,7 @@ static int spinand_wait(struct spinand_device *spinand,
 	u8 status;
 	int ret;
 
+	spinand_patch_reg_op(spinand, &op);
 	ret = spi_mem_poll_status(spinand->spimem, &op, STATUS_BUSY, 0,
 				  initial_delay_us,
 				  poll_delay_us,
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:10 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:10 +0530
Subject: [PATCH v2 05/14] mtd: spinand: Add adjust_op() in manufacturer_ops to
 modify the ops for manufacturer specific changes
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-6-a-nandan@ti.com>

Manufacturers might use a variation of standard SPI NAND flash
instructions, e.g. Winbond W35N01JW changes the dummy cycle length for
read register commands when in Octal DTR mode.

Add new function in manufacturer_ops: adjust_op(), which can be called
to correct the spi_mem op for any alteration in the instruction made by
the manufacturers. And hence, this function can also be used for
incorporating variations of SPI instructions in Octal DTR mode.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 3 +++
 include/linux/mtd/spinand.h | 4 ++++
 2 files changed, 7 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 4da794ae728d..8e6cf7941a0f 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -61,6 +61,9 @@ static void spinand_patch_op(const struct spinand_device *spinand,
 		op->data.buswidth = op_buswidth;
 		op->data.dtr = op_is_dtr;
 	}
+
+	if (spinand->manufacturer->ops->adjust_op)
+		spinand->manufacturer->ops->adjust_op(op, spinand->reg_proto);
 }
 
 static void spinand_patch_reg_op(const struct spinand_device *spinand,
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index f6093cd98d7b..ebb19b2cec84 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -257,6 +257,8 @@ struct spinand_devid {
 /**
  * struct manufacurer_ops - SPI NAND manufacturer specific operations
  * @init: initialize a SPI NAND device
+ * @adjust_op: modify the ops for any variation in their cmd, address, dummy or
+ *	       data phase by the manufacturer
  * @cleanup: cleanup a SPI NAND device
  *
  * Each SPI NAND manufacturer driver should implement this interface so that
@@ -264,6 +266,8 @@ struct spinand_devid {
  */
 struct spinand_manufacturer_ops {
 	int (*init)(struct spinand_device *spinand);
+	void (*adjust_op)(struct spi_mem_op *op,
+			  const enum spinand_proto reg_proto);
 	void (*cleanup)(struct spinand_device *spinand);
 };
 
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:11 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:11 +0530
Subject: [PATCH v2 06/14] mtd: spinand: Add macros for Octal DTR page read and
 write operations
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-7-a-nandan@ti.com>

Define new PAGE_READ_FROM_CACHE and PROG_LOAD op templates for Octal
DTR SPI mode. These templates will be used in op_variants and
op_templates for defining Octal DTR read from cache and write to
cache operations.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 include/linux/mtd/spinand.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index ebb19b2cec84..35816b8cfe81 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -122,6 +122,12 @@
 		   SPI_MEM_OP_DUMMY(ndummy, 4),				\
 		   SPI_MEM_OP_DATA_IN(len, buf, 4))
 
+#define SPINAND_PAGE_READ_FROM_CACHE_OCTALIO_DTR_OP(addr, ndummy, buf, len) \
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x9d9d, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_DUMMY_DTR(ndummy, 8),			\
+		   SPI_MEM_OP_DATA_IN_DTR(len, buf, 8))
+
 #define SPINAND_PROG_EXEC_OP(addr)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1),				\
 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
@@ -140,6 +146,12 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(len, buf, 4))
 
+#define SPINAND_PROG_LOAD_OCTALIO_DTR(reset, addr, buf, len)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, reset ? 0x0202 : 0x8484, 8),	\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT_DTR(len, buf, 8))
+
 #define SPINAND_PROTO_BUSWIDTH_MASK	GENMASK(6, 0)
 #define SPINAND_PROTO_DTR_BIT		BIT(7)
 
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:12 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:12 +0530
Subject: [PATCH v2 07/14] mtd: spinand: Allow enabling Octal DTR mode in the
 core
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-8-a-nandan@ti.com>

Enable Octal DTR SPI mode, i.e. 8D-8D-8D mode, if the SPI NAND flash
device supports it. Mixed OSPI (1S-1S-8S & 1S-8S-8S), mixed DTR modes
(1S-1D-8D), etc. aren't supported yet.

The method to switch to Octal DTR SPI mode may vary across
manufacturers. For example, for Winbond, it is enabled by writing
values to the volatile configuration register. So, let the
manufacturer's code have their own implementation for switching to
Octal DTR SPI mode.

Check for the SPI NAND device's support for Octal DTR mode using
spinand flags, and if the op_templates allows 8D-8D-8D, call
octal_dtr_enable() manufacturer op. If the SPI controller doesn't
supports these modes, the selected op_templates will prevent switching
to the Octal DTR mode. And finally update the spinand reg_proto
on success.

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 46 +++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h |  3 +++
 2 files changed, 49 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 8e6cf7941a0f..1210946f8447 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -257,6 +257,48 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
 			       enable ? CFG_QUAD_ENABLE : 0);
 }
 
+static bool spinand_op_is_octal_dtr(const struct spi_mem_op *op)
+{
+	return  op->cmd.buswidth == 8 && op->cmd.dtr &&
+		op->addr.buswidth == 8 && op->addr.dtr &&
+		op->data.buswidth == 8 && op->data.dtr;
+}
+
+static int spinand_init_octal_dtr_enable(struct spinand_device *spinand)
+{
+	struct device *dev = &spinand->spimem->spi->dev;
+	int ret;
+
+	if (!(spinand->flags & SPINAND_HAS_OCTAL_DTR_BIT))
+		return 0;
+
+	if (!(spinand_op_is_octal_dtr(spinand->op_templates.read_cache) &&
+	      spinand_op_is_octal_dtr(spinand->op_templates.write_cache) &&
+	      spinand_op_is_octal_dtr(spinand->op_templates.update_cache)))
+		return 0;
+
+	if (!spinand->manufacturer->ops->octal_dtr_enable) {
+		dev_dbg(dev,
+			"Missing ->octal_dtr_enable(), unable to switch mode\n");
+		return -EINVAL;
+	}
+
+	ret = spinand->manufacturer->ops->octal_dtr_enable(spinand);
+	if (ret) {
+		dev_err(dev,
+			"Failed to enable Octal DTR SPI mode (err = %d)\n",
+			ret);
+		return ret;
+	}
+
+	spinand->reg_proto = SPINAND_OCTAL_DTR;
+
+	dev_dbg(dev,
+		"%s SPI NAND switched to Octal DTR SPI (8D-8D-8D) mode\n",
+		spinand->manufacturer->name);
+	return 0;
+}
+
 static int spinand_ecc_enable(struct spinand_device *spinand,
 			      bool enable)
 {
@@ -1192,6 +1234,10 @@ static int spinand_init_flash(struct spinand_device *spinand)
 	if (ret)
 		return ret;
 
+	ret = spinand_init_octal_dtr_enable(spinand);
+	if (ret)
+		return ret;
+
 	ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0);
 	if (ret)
 		return ret;
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 35816b8cfe81..daa2ac5c3110 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -271,6 +271,7 @@ struct spinand_devid {
  * @init: initialize a SPI NAND device
  * @adjust_op: modify the ops for any variation in their cmd, address, dummy or
  *	       data phase by the manufacturer
+ * @octal_dtr_enable: switch the SPI NAND flash into Octal DTR SPI mode
  * @cleanup: cleanup a SPI NAND device
  *
  * Each SPI NAND manufacturer driver should implement this interface so that
@@ -280,6 +281,7 @@ struct spinand_manufacturer_ops {
 	int (*init)(struct spinand_device *spinand);
 	void (*adjust_op)(struct spi_mem_op *op,
 			  const enum spinand_proto reg_proto);
+	int (*octal_dtr_enable)(struct spinand_device *spinand);
 	void (*cleanup)(struct spinand_device *spinand);
 };
 
@@ -348,6 +350,7 @@ struct spinand_ecc_info {
 
 #define SPINAND_HAS_QE_BIT		BIT(0)
 #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+#define SPINAND_HAS_OCTAL_DTR_BIT	BIT(2)
 
 /**
  * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:13 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:13 +0530
Subject: [PATCH v2 08/14] mtd: spinand: winbond: Add support for write
 volatile configuration register op
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-9-a-nandan@ti.com>

Volatile configuration register are a different set of configuration
registers, i.e. they differ from the status registers. A different
SPI instruction is required to write to these registers. Any changes
to the Volatile Configuration Register get transferred directly to
the Internal Configuration Register and instantly reflect on the
device operation.

In Winbond W35N01JW, these volatile configuration register must be
configured in order to switch to Octal DTR SPI mode.

Add support for writing to volatile configuration registers using a
new WRITE_VCR_OP template.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c    |  2 +-
 drivers/mtd/nand/spi/winbond.c | 42 ++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h    |  1 +
 3 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 1210946f8447..2bea21bd9747 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -445,7 +445,7 @@ static void spinand_ondie_ecc_save_status(struct nand_device *nand, u8 status)
 		engine_conf->status = status;
 }
 
-static int spinand_write_enable_op(struct spinand_device *spinand)
+int spinand_write_enable_op(struct spinand_device *spinand)
 {
 	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
 
diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 76684428354e..89d8ee801f56 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -7,6 +7,7 @@
  *	Boris Brezillon <boris.brezillon at bootlin.com>
  */
 
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/mtd/spinand.h>
@@ -114,6 +115,47 @@ static int winbond_spinand_init(struct spinand_device *spinand)
 	return 0;
 }
 
+/**
+ * winbond_write_vcr_op() - write values onto the volatile configuration
+ *			    registers (VCR)
+ * @spinand: the spinand device
+ * @reg: the address of the particular reg in the VCR to be written on
+ * @val: the value to be written on the reg in the VCR
+ *
+ * Volatile configuration registers are a separate set of configuration
+ * registers, i.e. they differ from the status registers SR-1/2/3. A different
+ * SPI instruction is required to write to these registers. Any changes
+ * to the Volatile Configuration Register get transferred directly to
+ * the Internal Configuration Register and instantly reflect on the
+ * device operation.
+ */
+static int winbond_write_vcr_op(struct spinand_device *spinand, u8 reg, u8 val)
+{
+	int ret;
+	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(0x81, 1),
+					  SPI_MEM_OP_ADDR(3, reg, 1),
+					  SPI_MEM_OP_NO_DUMMY,
+					  SPI_MEM_OP_DATA_OUT(1, spinand->scratchbuf, 1));
+
+	*spinand->scratchbuf = val;
+
+	ret = spinand_write_enable_op(spinand);
+	if (ret)
+		return ret;
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	/*
+	 * Write VCR operation doesn't set the busy bit in SR, so can't perform
+	 * a status poll. Minimum time of 50ns is needed to complete the write.
+	 * So, give thrice the minimum required delay.
+	 */
+	ndelay(150);
+	return 0;
+}
+
 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
 	.init = winbond_spinand_init,
 };
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index daa2ac5c3110..21a4e5adcd59 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -560,5 +560,6 @@ int spinand_match_and_init(struct spinand_device *spinand,
 
 int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
 int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+int spinand_write_enable_op(struct spinand_device *spinand);
 
 #endif /* __LINUX_MTD_SPINAND_H */
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:14 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:14 +0530
Subject: [PATCH v2 09/14] mtd: spinand: winbond: Add octal_dtr_enable() for
 manufacturer_ops
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-10-a-nandan@ti.com>

Add implementation of octal_dtr_enable() manufacturer_ops for Winbond.
To switch to Ocatl DTR mode, setting programmable dummy cycles and
SPI IO mode using the volatile configuration register is required. To
function at max 120MHz SPI clock in Octal DTR mode, 12 programmable
dummy clock cycle setting is required. (Default number of dummy cycle
are 8 clocks)

Set the programmable dummy cycle to 12 clocks, and SPI IO mode to
Octal DTR with Data Strobe in the VCR. Also, perform a READ ID
operation in Octal DTR SPI mode to ensure the switch was successful.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/winbond.c | 42 ++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 89d8ee801f56..e2cb82d68f96 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -16,6 +16,14 @@
 
 #define WINBOND_CFG_BUF_READ		BIT(3)
 
+/* Octal DTR SPI mode (8D-8D-8D) with Data Strobe output*/
+#define WINBOND_IO_MODE_VCR_OCTAL_DTR	0xE7
+#define WINBOND_IO_MODE_VCR_ADDR	0x00
+
+/* Use 12 dummy clk cycles for using Octal DTR SPI at max 120MHZ */
+#define WINBOND_DUMMY_CLK_COUNT		12
+#define WINBOND_DUMMY_CLK_VCR_ADDR	0x01
+
 static SPINAND_OP_VARIANTS(read_cache_variants,
 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
@@ -156,8 +164,42 @@ static int winbond_write_vcr_op(struct spinand_device *spinand, u8 reg, u8 val)
 	return 0;
 }
 
+static int winbond_spinand_octal_dtr_enable(struct spinand_device *spinand)
+{
+	int ret;
+	struct spi_mem_op op;
+
+	ret = winbond_write_vcr_op(spinand, WINBOND_DUMMY_CLK_VCR_ADDR,
+				   WINBOND_DUMMY_CLK_COUNT);
+	if (ret)
+		return ret;
+
+	ret = winbond_write_vcr_op(spinand, WINBOND_IO_MODE_VCR_ADDR,
+				   WINBOND_IO_MODE_VCR_OCTAL_DTR);
+	if (ret)
+		return ret;
+
+	/* Read flash ID to make sure the switch was successful. */
+	op = (struct spi_mem_op)
+		SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x9f9f, 8),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_DUMMY_DTR(16, 8),
+			   SPI_MEM_OP_DATA_IN_DTR(SPINAND_MAX_ID_LEN,
+						  spinand->scratchbuf, 8));
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	if (memcmp(spinand->scratchbuf, spinand->id.data, SPINAND_MAX_ID_LEN))
+		return -EINVAL;
+
+	return 0;
+}
+
 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
 	.init = winbond_spinand_init,
+	.octal_dtr_enable = winbond_spinand_octal_dtr_enable,
 };
 
 const struct spinand_manufacturer winbond_spinand_manufacturer = {
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:15 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:15 +0530
Subject: [PATCH v2 10/14] mtd: spinand: Add support for Power-on-Reset (PoR)
 instruction
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-11-a-nandan@ti.com>

Manufacturers like Gigadevice and Winbond are adding Power-on-Reset
functionality in their SPI NAND flash chips. PoR instruction consists
of a 66h command followed by 99h command, and is different from the FFh
reset. The reset command FFh just clears the status only registers,
while the PoR command erases all the configurations written to the
flash and is equivalent to a power-down -> power-up cycle.

Add support for the Power-on-Reset command for any flash that provides
this feature.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 43 +++++++++++++++++++++++++++++++++++++
 include/linux/mtd/spinand.h | 17 +++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 2bea21bd9747..9b570570ee81 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -9,6 +9,7 @@
 
 #define pr_fmt(fmt)	"spi-nand: " fmt
 
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
@@ -668,6 +669,48 @@ static int spinand_reset_op(struct spinand_device *spinand)
 			    NULL);
 }
 
+static int spinand_power_on_rst_op(struct spinand_device *spinand)
+{
+	struct spi_mem_op op;
+	int ret;
+
+	if (!(spinand->flags & SPINAND_HAS_POR_CMD_BIT))
+		return -EOPNOTSUPP;
+
+	/*
+	 * If flash is in a busy state, wait for it to finish the operation.
+	 * As the operation is unknown, use reset poll delays here.
+	 */
+	ret = spinand_wait(spinand,
+			   SPINAND_RESET_INITIAL_DELAY_US,
+			   SPINAND_RESET_POLL_DELAY_US,
+			   NULL);
+	if (ret)
+		return ret;
+
+	op = (struct spi_mem_op)SPINAND_EN_POWER_ON_RST_OP;
+
+	spinand_patch_op(spinand, &op);
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	op = (struct spi_mem_op)SPINAND_POWER_ON_RST_OP;
+
+	spinand_patch_op(spinand, &op);
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	/* PoR can take max 500 us to complete, so sleep for 600 to 700 us*/
+	usleep_range(SPINAND_POR_MIN_DELAY_US, SPINAND_POR_MAX_DELAY_US);
+
+	dev_dbg(&spinand->spimem->spi->dev,
+		"%s SPI NAND reset to Power-On-Reset state.\n",
+		spinand->manufacturer->name);
+	return 0;
+}
+
 static int spinand_lock_block(struct spinand_device *spinand, u8 lock)
 {
 	return spinand_write_reg_op(spinand, REG_BLOCK_LOCK, lock);
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index 21a4e5adcd59..baaf8e94f301 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -26,6 +26,18 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_EN_POWER_ON_RST_OP					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(0x66, 1),				\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPINAND_POWER_ON_RST_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(0x99, 1),				\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_WR_EN_DIS_OP(enable)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD((enable) ? 0x06 : 0x04, 1),		\
 		   SPI_MEM_OP_NO_ADDR,					\
@@ -218,6 +230,8 @@ struct spinand_device;
  * reading/programming/erasing when the RESET occurs. Since we always
  * issue a RESET when the device is IDLE, 5us is selected for both initial
  * and poll delay.
+ * Power on Reset can take upto 500 us to complete, so sleep for 600 us
+ * to 700 us safely.
  */
 #define SPINAND_READ_INITIAL_DELAY_US	6
 #define SPINAND_READ_POLL_DELAY_US	5
@@ -227,6 +241,8 @@ struct spinand_device;
 #define SPINAND_WRITE_POLL_DELAY_US	15
 #define SPINAND_ERASE_INITIAL_DELAY_US	250
 #define SPINAND_ERASE_POLL_DELAY_US	50
+#define SPINAND_POR_MIN_DELAY_US	600
+#define SPINAND_POR_MAX_DELAY_US	700
 
 #define SPINAND_WAITRDY_TIMEOUT_MS	400
 
@@ -351,6 +367,7 @@ struct spinand_ecc_info {
 #define SPINAND_HAS_QE_BIT		BIT(0)
 #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
 #define SPINAND_HAS_OCTAL_DTR_BIT	BIT(2)
+#define SPINAND_HAS_POR_CMD_BIT		BIT(3)
 
 /**
  * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:16 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:16 +0530
Subject: [PATCH v2 11/14] mtd: spinand: Perform Power-on-Reset on the flash in
 mtd_suspend()
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-12-a-nandan@ti.com>

A soft reset using FFh command doesn't erase the flash's configuration
and doesn't reset the SPI IO mode also. This can result in the flash
being in a different SPI IO mode, e.g. Octal DTR, when resuming from
sleep. This could put the flash in an unrecognized SPI IO mode, making
it unusable.

Perform a Power-on-Reset (PoR), if available in the flash, when
performing mtd_suspend(). This would set the flash to clean
state for reinitialization during resume and would also ensure that it
is in standard SPI IO mode (1S-1S-1S) before the resume begins.

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/core.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 9b570570ee81..60408531979a 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1316,6 +1316,11 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
 	int ret;
 
 	spinand->reg_proto = SPINAND_SINGLE_STR;
+	/*
+	 * PoR Reset (if available by the manufacturer) is performed at the suspend
+	 * time. Hence, those flashes remain in power-on-state at this point, in a
+	 * standard SPI IO mode. So, now the core unanimously performs a soft reset.
+	 */
 	ret = spinand_reset_op(spinand);
 	if (ret)
 		return;
@@ -1327,6 +1332,21 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
 	spinand_ecc_enable(spinand, false);
 }
 
+static int spinand_mtd_suspend(struct mtd_info *mtd)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+	int ret;
+
+	if (!(spinand->flags & SPINAND_HAS_POR_CMD_BIT))
+		return 0;
+
+	ret = spinand_power_on_rst_op(spinand);
+	if (ret)
+		dev_err(&spinand->spimem->spi->dev, "suspend() failed\n");
+
+	return ret;
+}
+
 static int spinand_init(struct spinand_device *spinand)
 {
 	struct device *dev = &spinand->spimem->spi->dev;
@@ -1399,6 +1419,7 @@ static int spinand_init(struct spinand_device *spinand)
 	mtd->_erase = spinand_mtd_erase;
 	mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
 	mtd->_resume = spinand_mtd_resume;
+	mtd->_suspend = spinand_mtd_suspend;
 
 	if (nand->ecc.engine) {
 		ret = mtd_ooblayout_count_freebytes(mtd);
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:17 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:17 +0530
Subject: [PATCH v2 12/14] mtd: spinand: Add adjust_op() in Winbond
 manufacturer_ops
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-13-a-nandan@ti.com>

Add implementation of adjust_op() manufacturer_ops for Winbond. This
handles the variations introduced in read register, read vcr, blk
erase, page read and program exec ops when operating in Octal DTR mode.
Read register operation requires 7 dummy cycles and read VCR operation
requires 8 dummy cycles in Octal DTR mode instead of default 0 dummy
cycle. Block erase, page read and program exec operations require
2 byte address in Octal DTR mode instead of default 3 bytes.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/winbond.c | 45 ++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index e2cb82d68f96..d962221d4082 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -16,6 +16,13 @@
 
 #define WINBOND_CFG_BUF_READ		BIT(3)
 
+#define WINBOND_BLK_ERASE_OPCODE	0xD8
+#define WINBOND_PAGE_READ_OPCODE	0x13
+#define WINBOND_PROG_EXEC_OPCODE	0x10
+#define WINBOND_READ_REG_OPCODE_1	0x05
+#define WINBOND_READ_REG_OPCODE_2	0x0F
+#define WINBOND_READ_VCR_OPCODE		0x85
+
 /* Octal DTR SPI mode (8D-8D-8D) with Data Strobe output*/
 #define WINBOND_IO_MODE_VCR_OCTAL_DTR	0xE7
 #define WINBOND_IO_MODE_VCR_ADDR	0x00
@@ -197,9 +204,47 @@ static int winbond_spinand_octal_dtr_enable(struct spinand_device *spinand)
 	return 0;
 }
 
+static void winbond_spinand_adjust_op(struct spi_mem_op *op,
+				      const enum spinand_proto reg_proto)
+{
+	/*
+	 * To support both 1 byte opcode and 2 byte opcodes, extract the MSB
+	 * byte from the opcode as the LSB byte in 2 byte opcode is treated as
+	 * don't care.
+	 */
+	u8 opcode = op->cmd.opcode >> (8 * (op->cmd.nbytes - 1));
+
+	if (reg_proto == SPINAND_OCTAL_DTR) {
+		switch (opcode) {
+		case WINBOND_READ_REG_OPCODE_1:
+		case WINBOND_READ_REG_OPCODE_2:
+			op->dummy.nbytes = 14;
+			op->dummy.buswidth = 8;
+			op->dummy.dtr = true;
+			return;
+
+		case WINBOND_READ_VCR_OPCODE:
+			op->dummy.nbytes = 16;
+			op->dummy.buswidth = 8;
+			op->dummy.dtr = true;
+			return;
+
+		case WINBOND_BLK_ERASE_OPCODE:
+		case WINBOND_PAGE_READ_OPCODE:
+		case WINBOND_PROG_EXEC_OPCODE:
+			op->addr.nbytes = 2;
+			return;
+
+		default:
+			return;
+		}
+	}
+}
+
 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
 	.init = winbond_spinand_init,
 	.octal_dtr_enable = winbond_spinand_octal_dtr_enable,
+	.adjust_op = winbond_spinand_adjust_op,
 };
 
 const struct spinand_manufacturer winbond_spinand_manufacturer = {
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:18 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:18 +0530
Subject: [PATCH v2 13/14] mtd: spinand: winbond: Rename cache op_variants
 struct variable
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-14-a-nandan@ti.com>

Till now, supported Winbond SPI NAND flashes had same supported
op_variants. W35N01JW introduces Octal DTR SPI IO mode, so now
different op_variants struct variables are required for different
Winbond flashes. Hence, rename and append the flash name in the
op_variants struct variable.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/winbond.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index d962221d4082..1857836f19d0 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -31,7 +31,7 @@
 #define WINBOND_DUMMY_CLK_COUNT		12
 #define WINBOND_DUMMY_CLK_VCR_ADDR	0x01
 
-static SPINAND_OP_VARIANTS(read_cache_variants,
+static SPINAND_OP_VARIANTS(read_cache_variants_w25xxgv,
 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
@@ -39,11 +39,11 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
 
-static SPINAND_OP_VARIANTS(write_cache_variants,
+static SPINAND_OP_VARIANTS(write_cache_variants_w25xxgv,
 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
 
-static SPINAND_OP_VARIANTS(update_cache_variants,
+static SPINAND_OP_VARIANTS(update_cache_variants_w25xxgv,
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
@@ -95,9 +95,9 @@ static const struct spinand_info winbond_spinand_table[] = {
 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
 		     NAND_ECCREQ(1, 512),
-		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-					      &write_cache_variants,
-					      &update_cache_variants),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w25xxgv,
+					      &write_cache_variants_w25xxgv,
+					      &update_cache_variants_w25xxgv),
 		     0,
 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
 		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
@@ -105,9 +105,9 @@ static const struct spinand_info winbond_spinand_table[] = {
 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
 		     NAND_ECCREQ(1, 512),
-		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-					      &write_cache_variants,
-					      &update_cache_variants),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w25xxgv,
+					      &write_cache_variants_w25xxgv,
+					      &update_cache_variants_w25xxgv),
 		     0,
 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
 };
-- 
2.25.1



From a-nandan at ti.com  Mon Oct 11 13:46:19 2021
From: a-nandan at ti.com (Apurva Nandan)
Date: Tue, 12 Oct 2021 02:16:19 +0530
Subject: [PATCH v2 14/14] mtd: spinand: winbond: Add support for Winbond
 W35N01JW SPI NAND flash
In-Reply-To: <20211011204619.81893-1-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
Message-ID: <20211011204619.81893-15-a-nandan@ti.com>

Winbond W35N01JW is a SPI NAND flash supporting Octal DTR SPI protocol.
Add op_variants for W35N01JW, which include the Octal DTR read/write
page ops as well. Add W35N01JW's OOB layout functions for the
mtd_ooblayout_ops. Finally, add an entry for W35N01JW in spinand_info
table.

Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf

Signed-off-by: Apurva Nandan <a-nandan at ti.com>
---
 drivers/mtd/nand/spi/winbond.c | 53 ++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
index 1857836f19d0..8f687b6a6697 100644
--- a/drivers/mtd/nand/spi/winbond.c
+++ b/drivers/mtd/nand/spi/winbond.c
@@ -47,6 +47,19 @@ static SPINAND_OP_VARIANTS(update_cache_variants_w25xxgv,
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
+static SPINAND_OP_VARIANTS(read_cache_variants_w35n01jw,
+		SPINAND_PAGE_READ_FROM_CACHE_OCTALIO_DTR_OP(0, 24, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants_w35n01jw,
+		SPINAND_PROG_LOAD_OCTALIO_DTR(true, 0, NULL, 0),
+		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants_w35n01jw,
+		SPINAND_PROG_LOAD_OCTALIO_DTR(false, 0, NULL, 0),
+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *region)
 {
@@ -71,11 +84,40 @@ static int w25m02gv_ooblayout_free(struct mtd_info *mtd, int section,
 	return 0;
 }
 
+static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *region)
+{
+	if (section > 7)
+		return -ERANGE;
+
+	region->offset = (16 * section) + 12;
+	region->length = 4;
+
+	return 0;
+}
+
+static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
+				   struct mtd_oob_region *region)
+{
+	if (section > 7)
+		return -ERANGE;
+
+	region->offset = (16 * section) + 2;
+	region->length = 10;
+
+	return 0;
+}
+
 static const struct mtd_ooblayout_ops w25m02gv_ooblayout = {
 	.ecc = w25m02gv_ooblayout_ecc,
 	.free = w25m02gv_ooblayout_free,
 };
 
+static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
+	.ecc = w35n01jw_ooblayout_ecc,
+	.free = w35n01jw_ooblayout_free,
+};
+
 static int w25m02gv_select_target(struct spinand_device *spinand,
 				  unsigned int target)
 {
@@ -110,6 +152,17 @@ static const struct spinand_info winbond_spinand_table[] = {
 					      &update_cache_variants_w25xxgv),
 		     0,
 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+	SPINAND_INFO("W35N01JW",
+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdc),
+		     NAND_MEMORG(1, 4096, 128, 64, 512, 20, 1, 1, 1),
+		     NAND_ECCREQ(1, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w35n01jw,
+					      &write_cache_variants_w35n01jw,
+					      &update_cache_variants_w35n01jw),
+		     SPINAND_HAS_OCTAL_DTR_BIT | SPINAND_HAS_POR_CMD_BIT |
+		     SPINAND_HAS_CR_FEAT_BIT,
+		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL)),
+
 };
 
 static int winbond_spinand_init(struct spinand_device *spinand)
-- 
2.25.1



From alexander.stein at ew.tq-group.com  Mon Oct 11 23:17:03 2021
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue, 12 Oct 2021 08:17:03 +0200
Subject: [PATCH v2 1/2] dt-bindings: mtd: spi-nor: Add output-driver-strength
 property
Message-ID: <20211012061704.284214-1-alexander.stein@ew.tq-group.com>

This property is for optimizing output voltage impedance and is
specific to each board. It overwrites the default set by the flash
device. Various flash devices support different impedances.

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
Changes in v2:
* Updated the property description and the commit message accordingly

 Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
index ed590d7c6e37..4c3c506a8853 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
@@ -72,6 +72,14 @@ properties:
       be used on such systems, to denote the absence of a reliable reset
       mechanism.
 
+  output-driver-strength:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Output driver strength in ohms which optimizes the impedance at Vcc/2
+      output voltage. This property overwrites the default set by the flash
+      device. This is board specific and should be determined by the
+      manufacturer. Various flash devices support different impedances.
+
   label: true
 
   partitions:
-- 
2.25.1



From alexander.stein at ew.tq-group.com  Mon Oct 11 23:17:04 2021
From: alexander.stein at ew.tq-group.com (Alexander Stein)
Date: Tue, 12 Oct 2021 08:17:04 +0200
Subject: [PATCH v2 2/2] mtd: spi-nor: micron-st: Add support for
 output-driver-strength for MT25Q
In-Reply-To: <20211012061704.284214-1-alexander.stein@ew.tq-group.com>
References: <20211012061704.284214-1-alexander.stein@ew.tq-group.com>
Message-ID: <20211012061704.284214-2-alexander.stein@ew.tq-group.com>

MT25Q[UL] Micron flashes support this by the Bits [2:0] in the Enhanced
Volatile Configuration Register.
Checked datasheet:
- mt25t-qljs-L512-xBA-xxT.pdf

Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
---
Changes in v2:
* Various format fixes
* Apply property only to MT25Q devices (e.g. N25Q devices support a
 different set of impedances)
* Use spi_nor_spimem_setup_op() before issuing a command
* Add more return code checking
* Add a warning if setting drive strength fails at some point
* Use GENMASK()

 drivers/mtd/spi-nor/micron-st.c | 152 ++++++++++++++++++++++++++++++--
 1 file changed, 146 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index c224e59820a1..492805a5a278 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -16,6 +16,11 @@
 #define SPINOR_MT_OCT_DTR	0xe7	/* Enable Octal DTR. */
 #define SPINOR_MT_EXSPI		0xff	/* Enable Extended SPI (default) */
 
+struct micron_drive_strength {
+	u32 ohms;
+	u8 val;
+};
+
 static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor, bool enable)
 {
 	struct spi_mem_op op;
@@ -118,6 +123,135 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
 	.post_sfdp = mt35xu512aba_post_sfdp_fixup,
 };
 
+/*
+ * Read Micron enhanced volatile configuration register
+ * Return negative if error occurred or configuration register value
+ */
+static int micron_read_evcr(struct spi_nor *nor)
+{
+	int ret;
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_EVCR, 1),
+				   SPI_MEM_OP_NO_ADDR,
+				   SPI_MEM_OP_NO_DUMMY,
+				   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+
+		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RD_EVCR,
+						    nor->bouncebuf, 1);
+	}
+
+	if (ret < 0) {
+		dev_err(nor->dev, "error %d reading EVCR\n", ret);
+		return ret;
+	}
+
+	return nor->bouncebuf[0];
+}
+
+/*
+ * Write Micron enhanced volatile configuration register
+ * Return negative if error occurred or configuration register value
+ */
+static int micron_write_evcr(struct spi_nor *nor, u8 evcr)
+{
+	int ret;
+
+	nor->bouncebuf[0] = evcr;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WD_EVCR, 1),
+				   SPI_MEM_OP_NO_ADDR,
+				   SPI_MEM_OP_NO_DUMMY,
+				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 1));
+
+		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
+		return spi_mem_exec_op(nor->spimem, &op);
+	}
+
+	return nor->controller_ops->write_reg(nor, SPINOR_OP_WD_EVCR,
+					      nor->bouncebuf, 1);
+}
+
+/*
+ * Supported values from Enahanced Volatile COnfiguration Register (Bits 2:0)
+ */
+static const struct micron_drive_strength drive_strength_data[] = {
+	{ .ohms = 90, .val = 1 },
+	{ .ohms = 45, .val = 3 },
+	{ .ohms = 20, .val = 5 },
+	{ .ohms = 30, .val = 7 },
+};
+
+static const struct micron_drive_strength *micron_st_find_drive_strength_entry(u32 ohms)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(drive_strength_data); i++) {
+		if (ohms == drive_strength_data[i].ohms)
+			return &drive_strength_data[i];
+	}
+	return NULL;
+}
+
+static void mt25q_post_sfdp(struct spi_nor *nor)
+{
+	struct device_node *np = spi_nor_get_flash_node(nor);
+	u32 ohms;
+
+	if (!np)
+		return;
+
+	if (!of_property_read_u32(np, "output-driver-strength", &ohms)) {
+		struct micron_drive_strength const *entry =
+			micron_st_find_drive_strength_entry(ohms);
+
+		if (entry) {
+			int evcrr;
+			int ret;
+			u8 evcr;
+
+			evcrr = micron_read_evcr(nor);
+			if (evcrr < 0) {
+				dev_warn(nor->dev,
+					 "Reading EVCR failed: %d\n",
+					 evcrr);
+				return;
+			}
+
+			evcr = (u8)(evcrr & GENMASK(7, 3)) | entry->val;
+
+			ret = micron_write_evcr(nor, evcr);
+			if (ret)
+				dev_warn(nor->dev,
+					 "Setting EVCR failed: %d\n",
+					 ret);
+
+			dev_dbg(nor->dev, "%s: EVCR 0x%x\n", __func__,
+				(u32)micron_read_evcr(nor));
+		} else {
+			dev_warn(nor->dev,
+				"Invalid output-driver-strength property specified: %u",
+				ohms);
+		}
+	}
+}
+
+static struct spi_nor_fixups mt25q_fixups = {
+	.post_sfdp = mt25q_post_sfdp,
+};
+
 static const struct flash_info micron_parts[] = {
 	{ "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
 			       SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
@@ -149,25 +283,29 @@ static const struct flash_info st_parts[] = {
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES)
+	  .fixups = &mt25q_fixups },
 	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
 			      USE_FSR | SPI_NOR_DUAL_READ |
 			      SPI_NOR_QUAD_READ) },
 	{ "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES)
+	  .fixups = &mt25q_fixups },
 	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 	{ "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES)
+	  .fixups = &mt25q_fixups },
 	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
 	{ "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES)
+	  .fixups = &mt25q_fixups },
 	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
@@ -182,10 +320,12 @@ static const struct flash_info st_parts[] = {
 			      NO_CHIP_ERASE) },
 	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
-			      NO_CHIP_ERASE) },
+			      NO_CHIP_ERASE)
+	  .fixups = &mt25q_fixups },
 	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096,
 			      SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+			      SPI_NOR_QUAD_READ | NO_CHIP_ERASE)
+	  .fixups = &mt25q_fixups },
 
 	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
 	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
-- 
2.25.1



From boris.brezillon at collabora.com  Mon Oct 11 23:39:06 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 12 Oct 2021 08:39:06 +0200
Subject: [PATCH v2 02/14] mtd: spinand: Add enum spinand_proto to
 indicate current SPI IO mode
In-Reply-To: <20211011204619.81893-3-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
 <20211011204619.81893-3-a-nandan@ti.com>
Message-ID: <20211012083906.30c50009@collabora.com>

On Tue, 12 Oct 2021 02:16:07 +0530
Apurva Nandan <a-nandan at ti.com> wrote:

> Unlike Dual and Quad SPI modes flashes, Octal DTR SPI NAND flashes
> require all instructions to be made in 8D-8D-8D protocol when the
> flash is in Octal DTR mode. Hence, storing the current SPI IO mode
> becomes necessary for correctly generating non-array access operations.
> 
> Store the current SPI IO mode in the spinand struct using a reg_proto
> enum. This would act as a flag, denoting that the core should use
> the given SPI protocol for non-page access operations.
> 
> Also provide basic macros for extracting buswidth and dtr mode
> information from the spinand_proto enum.
> 
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> ---
>  drivers/mtd/nand/spi/core.c |  2 ++
>  include/linux/mtd/spinand.h | 30 ++++++++++++++++++++++++++++++
>  2 files changed, 32 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 2c8685f1f2fa..d82a3e6d9bb5 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -1155,6 +1155,7 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
>  	struct spinand_device *spinand = mtd_to_spinand(mtd);
>  	int ret;
>  
> +	spinand->reg_proto = SPINAND_SINGLE_STR;
>  	ret = spinand_reset_op(spinand);
>  	if (ret)
>  		return;
> @@ -1181,6 +1182,7 @@ static int spinand_init(struct spinand_device *spinand)
>  	if (!spinand->scratchbuf)
>  		return -ENOMEM;
>  
> +	spinand->reg_proto = SPINAND_SINGLE_STR;
>  	ret = spinand_detect(spinand);
>  	if (ret)
>  		goto err_free_bufs;
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index 6988956b8492..f6093cd98d7b 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -140,6 +140,31 @@
>  		   SPI_MEM_OP_NO_DUMMY,					\
>  		   SPI_MEM_OP_DATA_OUT(len, buf, 4))
>  
> +#define SPINAND_PROTO_BUSWIDTH_MASK	GENMASK(6, 0)
> +#define SPINAND_PROTO_DTR_BIT		BIT(7)
> +
> +#define SPINAND_PROTO_STR(__buswidth)	\
> +	((u8)(((__buswidth) - 1) & SPINAND_PROTO_BUSWIDTH_MASK))
> +#define SPINAND_PROTO_DTR(__buswidth)	\
> +	(SPINAND_PROTO_DTR_BIT | SPINAND_PROTO_STR(__buswidth))
> +
> +#define SPINAND_PROTO_BUSWIDTH(__proto)	\
> +	((u8)(((__proto) & SPINAND_PROTO_BUSWIDTH_MASK) + 1))
> +#define SPINAND_PROTO_IS_DTR(__proto)	(!!((__proto) & SPINAND_PROTO_DTR_BIT))
> +
> +/**
> + * enum spinand_proto - List allowable SPI protocol variants for read reg,
> + *			write reg, blk erase, write enable/disable, page read
> + *			and program exec operations.
> + */
> +enum spinand_proto {

s/spinand_proto/spinand_protocol/

> +	SPINAND_SINGLE_STR = SPINAND_PROTO_STR(1),
> +	SPINAND_DUAL_STR = SPINAND_PROTO_STR(2),
> +	SPINAND_QUAD_STR = SPINAND_PROTO_STR(4),
> +	SPINAND_OCTAL_STR = SPINAND_PROTO_STR(8),
> +	SPINAND_OCTAL_DTR = SPINAND_PROTO_DTR(8),

Why not have a contiguous enum listing all the modes? Are you extracting
the buswidth from these values?

> +};
> +
>  /**
>   * Standard SPI NAND flash commands
>   */
> @@ -407,6 +432,9 @@ struct spinand_dirmap {
>   *		   this die. Only required if your chip exposes several dies
>   * @cur_target: currently selected target/die
>   * @eccinfo: on-die ECC information
> + * @reg_proto: select a variant of SPI IO protocol (single, quad, octal or
> + *	       octal DTR) for read_reg/write_reg/erase operations. Update on
> + *	       successful transition into a different SPI IO protocol.
>   * @cfg_cache: config register cache. One entry per die
>   * @databuf: bounce buffer for data
>   * @oobbuf: bounce buffer for OOB data
> @@ -438,6 +466,8 @@ struct spinand_device {
>  
>  	struct spinand_ecc_info eccinfo;
>  
> +	enum spinand_proto reg_proto;
> +

I guess this mode will apply to all sort of commands, not just reg
accesses, so why not name it protocol or mode?

>  	u8 *cfg_cache;
>  	u8 *databuf;
>  	u8 *oobbuf;



From boris.brezillon at collabora.com  Mon Oct 11 23:40:47 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 12 Oct 2021 08:40:47 +0200
Subject: [PATCH v2 03/14] mtd: spinand: Patch spi_mem_op for the SPI IO
 protocol using reg_proto
In-Reply-To: <20211011204619.81893-4-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
 <20211011204619.81893-4-a-nandan@ti.com>
Message-ID: <20211012084047.6381ddce@collabora.com>

On Tue, 12 Oct 2021 02:16:08 +0530
Apurva Nandan <a-nandan at ti.com> wrote:

> Currently, the op macros in spinand.h don't give the option to setup
> any non-array access instructions for Dual/Quad/Octal DTR SPI bus.
> Having a function that patches the op based on reg_proto would be
> better than trying to write all the setup logic in op macros.
> 
> Create a spimem_patch_op() that would patch cmd, addr, dummy and data
> phase of the spi_mem op, for the given spinand->reg_proto. And hence,
> call the spimem_patch_op() before executing any spi_mem op.

I'm honestly not sure this rule will stand over time, and patching
operations at submission time has a cost (ok, it's negligible compared
to the IO duration, but still), so I'd rather see this done statically
with all relevant macros taking an extra dtr argument.

> 
> Note: In this commit, spimem_patch_op() isn't called in the
> read_reg_op(), write_reg_op() and wait() functions, as they need
> modifications in address value and data nbytes when in Octal DTR mode.
> This will be fixed in a later commit.

See, that's what I'm talking about.

> 
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> ---
>  drivers/mtd/nand/spi/core.c | 49 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 49 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index d82a3e6d9bb5..11746d858f87 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -20,6 +20,49 @@
>  #include <linux/spi/spi.h>
>  #include <linux/spi/spi-mem.h>
>  
> +/**
> + * spinand_patch_op() - Helper function to patch the spi_mem op based on the
> + *			spinand->reg_proto
> + * @spinand: the spinand device
> + * @op: the spi_mem op to patch
> + *
> + * Set up buswidth and dtr fields for cmd, addr, dummy and data phase. Also
> + * adjust cmd opcode and dummy nbytes. This function doesn't make any changes
> + * to addr val or data buf.
> + */
> +static void spinand_patch_op(const struct spinand_device *spinand,
> +			     struct spi_mem_op *op)
> +{
> +	u8 op_buswidth = SPINAND_PROTO_BUSWIDTH(spinand->reg_proto);
> +	u8 op_is_dtr = SPINAND_PROTO_IS_DTR(spinand->reg_proto);
> +
> +	if (spinand->reg_proto == SPINAND_SINGLE_STR)
> +		return;
> +
> +	op->cmd.buswidth = op_buswidth;
> +	op->cmd.dtr = op_is_dtr;
> +	if (spinand->reg_proto == SPINAND_OCTAL_DTR) {
> +		op->cmd.opcode = (op->cmd.opcode << 8) | op->cmd.opcode;
> +		op->cmd.nbytes = 2;
> +	}
> +
> +	if (op->addr.nbytes) {
> +		op->addr.buswidth = op_buswidth;
> +		op->addr.dtr = op_is_dtr;
> +	}
> +
> +	if (op->dummy.nbytes) {
> +		op->dummy.buswidth = op_buswidth;
> +		op->dummy.dtr = op_is_dtr;
> +		op->dummy.nbytes <<= op_is_dtr;
> +	}
> +
> +	if (op->data.nbytes) {
> +		op->data.buswidth = op_buswidth;
> +		op->data.dtr = op_is_dtr;
> +	}
> +}
> +
>  static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
>  {
>  	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
> @@ -343,6 +386,7 @@ static int spinand_write_enable_op(struct spinand_device *spinand)
>  {
>  	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
>  
> +	spinand_patch_op(spinand, &op);
>  	return spi_mem_exec_op(spinand->spimem, &op);
>  }
>  
> @@ -353,6 +397,7 @@ static int spinand_load_page_op(struct spinand_device *spinand,
>  	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
>  	struct spi_mem_op op = SPINAND_PAGE_READ_OP(row);
>  
> +	spinand_patch_op(spinand, &op);
>  	return spi_mem_exec_op(spinand->spimem, &op);
>  }
>  
> @@ -477,6 +522,7 @@ static int spinand_program_op(struct spinand_device *spinand,
>  	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
>  	struct spi_mem_op op = SPINAND_PROG_EXEC_OP(row);
>  
> +	spinand_patch_op(spinand, &op);
>  	return spi_mem_exec_op(spinand->spimem, &op);
>  }
>  
> @@ -487,6 +533,7 @@ static int spinand_erase_op(struct spinand_device *spinand,
>  	unsigned int row = nanddev_pos_to_row(nand, pos);
>  	struct spi_mem_op op = SPINAND_BLK_ERASE_OP(row);
>  
> +	spinand_patch_op(spinand, &op);
>  	return spi_mem_exec_op(spinand->spimem, &op);
>  }
>  
> @@ -533,6 +580,7 @@ static int spinand_read_id_op(struct spinand_device *spinand, u8 naddr,
>  		naddr, ndummy, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
>  	int ret;
>  
> +	spinand_patch_op(spinand, &op);
>  	ret = spi_mem_exec_op(spinand->spimem, &op);
>  	if (!ret)
>  		memcpy(buf, spinand->scratchbuf, SPINAND_MAX_ID_LEN);
> @@ -545,6 +593,7 @@ static int spinand_reset_op(struct spinand_device *spinand)
>  	struct spi_mem_op op = SPINAND_RESET_OP;
>  	int ret;
>  
> +	spinand_patch_op(spinand, &op);
>  	ret = spi_mem_exec_op(spinand->spimem, &op);
>  	if (ret)
>  		return ret;



From boris.brezillon at collabora.com  Mon Oct 11 23:54:35 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 12 Oct 2021 08:54:35 +0200
Subject: [PATCH v2 05/14] mtd: spinand: Add adjust_op() in
 manufacturer_ops to modify the ops for manufacturer specific changes
In-Reply-To: <20211011204619.81893-6-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
 <20211011204619.81893-6-a-nandan@ti.com>
Message-ID: <20211012085435.1aedfb7f@collabora.com>

On Tue, 12 Oct 2021 02:16:10 +0530
Apurva Nandan <a-nandan at ti.com> wrote:

> Manufacturers might use a variation of standard SPI NAND flash
> instructions, e.g. Winbond W35N01JW changes the dummy cycle length for
> read register commands when in Octal DTR mode.
> 
> Add new function in manufacturer_ops: adjust_op(), which can be called
> to correct the spi_mem op for any alteration in the instruction made by
> the manufacturers. And hence, this function can also be used for
> incorporating variations of SPI instructions in Octal DTR mode.

Okay, so now we have reg accesses differing between vendors in DTR.
Looks like we should have an OP-table for non-IO commands too (similar
to the op_variants mechanism we have for IO commands), at least when
operating in DTR. The reg access path would just end up doing:

	struct spi_mem_op op =
		spinand->templates[spinand->protocol][cmd];

This way you get rid of all this live-patching/vendor-specific
adjustment (which is likely to get more and more complex since flash
vendors have a tendency of diverging from the common behavior), and
everything gets initialized at probe time.

> 
> Datasheet: https://www.winbond.com/export/sites/winbond/datasheet/W35N01JW_Datasheet_Brief.pdf
> 
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> ---
>  drivers/mtd/nand/spi/core.c | 3 +++
>  include/linux/mtd/spinand.h | 4 ++++
>  2 files changed, 7 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 4da794ae728d..8e6cf7941a0f 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -61,6 +61,9 @@ static void spinand_patch_op(const struct spinand_device *spinand,
>  		op->data.buswidth = op_buswidth;
>  		op->data.dtr = op_is_dtr;
>  	}
> +
> +	if (spinand->manufacturer->ops->adjust_op)
> +		spinand->manufacturer->ops->adjust_op(op, spinand->reg_proto);
>  }
>  
>  static void spinand_patch_reg_op(const struct spinand_device *spinand,
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index f6093cd98d7b..ebb19b2cec84 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -257,6 +257,8 @@ struct spinand_devid {
>  /**
>   * struct manufacurer_ops - SPI NAND manufacturer specific operations
>   * @init: initialize a SPI NAND device
> + * @adjust_op: modify the ops for any variation in their cmd, address, dummy or
> + *	       data phase by the manufacturer
>   * @cleanup: cleanup a SPI NAND device
>   *
>   * Each SPI NAND manufacturer driver should implement this interface so that
> @@ -264,6 +266,8 @@ struct spinand_devid {
>   */
>  struct spinand_manufacturer_ops {
>  	int (*init)(struct spinand_device *spinand);
> +	void (*adjust_op)(struct spi_mem_op *op,
> +			  const enum spinand_proto reg_proto);
>  	void (*cleanup)(struct spinand_device *spinand);
>  };
>  



From boris.brezillon at collabora.com  Tue Oct 12 00:14:15 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 12 Oct 2021 09:14:15 +0200
Subject: [PATCH v2 07/14] mtd: spinand: Allow enabling Octal DTR mode in
 the core
In-Reply-To: <20211011204619.81893-8-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
 <20211011204619.81893-8-a-nandan@ti.com>
Message-ID: <20211012091415.4fa0ce7c@collabora.com>

On Tue, 12 Oct 2021 02:16:12 +0530
Apurva Nandan <a-nandan at ti.com> wrote:

> Enable Octal DTR SPI mode, i.e. 8D-8D-8D mode, if the SPI NAND flash
> device supports it. Mixed OSPI (1S-1S-8S & 1S-8S-8S), mixed DTR modes
> (1S-1D-8D), etc. aren't supported yet.
> 
> The method to switch to Octal DTR SPI mode may vary across
> manufacturers. For example, for Winbond, it is enabled by writing
> values to the volatile configuration register. So, let the
> manufacturer's code have their own implementation for switching to
> Octal DTR SPI mode.
> 
> Check for the SPI NAND device's support for Octal DTR mode using
> spinand flags, and if the op_templates allows 8D-8D-8D, call
> octal_dtr_enable() manufacturer op. If the SPI controller doesn't
> supports these modes, the selected op_templates will prevent switching
> to the Octal DTR mode. And finally update the spinand reg_proto
> on success.
> 
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> ---
>  drivers/mtd/nand/spi/core.c | 46 +++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/spinand.h |  3 +++
>  2 files changed, 49 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 8e6cf7941a0f..1210946f8447 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -257,6 +257,48 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
>  			       enable ? CFG_QUAD_ENABLE : 0);
>  }
>  
> +static bool spinand_op_is_octal_dtr(const struct spi_mem_op *op)
> +{
> +	return  op->cmd.buswidth == 8 && op->cmd.dtr &&
> +		op->addr.buswidth == 8 && op->addr.dtr &&
> +		op->data.buswidth == 8 && op->data.dtr;
> +}
> +
> +static int spinand_init_octal_dtr_enable(struct spinand_device *spinand)

I see no spinand_octal_dtr_disable(), and I feel like we'll want to get
back to single-STR mode just before rebooting/kexec-ing, or if/when
we need to execute other maintenance operations. Actually, I think we
should have something more generic to enter a new mode (see below
for a detailed explanation).

> +{
> +	struct device *dev = &spinand->spimem->spi->dev;
> +	int ret;
> +
> +	if (!(spinand->flags & SPINAND_HAS_OCTAL_DTR_BIT))
> +		return 0;
> +
> +	if (!(spinand_op_is_octal_dtr(spinand->op_templates.read_cache) &&
> +	      spinand_op_is_octal_dtr(spinand->op_templates.write_cache) &&
> +	      spinand_op_is_octal_dtr(spinand->op_templates.update_cache)))
> +		return 0;

Ok, so you check the controller-side octal-DTR capability when selecting
the read/write/update_cache variants, but what if other commands (reg
access, erase, ...) can't be issued in this mode? I really think all
the commands you might use should be tested at probe time, not just
these 3 operations.

> +
> +	if (!spinand->manufacturer->ops->octal_dtr_enable) {
> +		dev_dbg(dev,
> +			"Missing ->octal_dtr_enable(), unable to switch mode\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = spinand->manufacturer->ops->octal_dtr_enable(spinand);
> +	if (ret) {
> +		dev_err(dev,
> +			"Failed to enable Octal DTR SPI mode (err = %d)\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	spinand->reg_proto = SPINAND_OCTAL_DTR;
> +
> +	dev_dbg(dev,
> +		"%s SPI NAND switched to Octal DTR SPI (8D-8D-8D) mode\n",
> +		spinand->manufacturer->name);
> +	return 0;
> +}
> +
>  static int spinand_ecc_enable(struct spinand_device *spinand,
>  			      bool enable)
>  {
> @@ -1192,6 +1234,10 @@ static int spinand_init_flash(struct spinand_device *spinand)
>  	if (ret)
>  		return ret;
>  
> +	ret = spinand_init_octal_dtr_enable(spinand);
> +	if (ret)
> +		return ret;
> +

Why not delaying the 'enter fastest available mode' at the end of this
initialization? I fear some flashes won't support some of the
maintenance commands in 8-8-8-DTR, so it's probably safer to enter it
once you've initialized everything else.

>  	ret = spinand_upd_cfg(spinand, CFG_OTP_ENABLE, 0);
>  	if (ret)
>  		return ret;
> diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
> index 35816b8cfe81..daa2ac5c3110 100644
> --- a/include/linux/mtd/spinand.h
> +++ b/include/linux/mtd/spinand.h
> @@ -271,6 +271,7 @@ struct spinand_devid {
>   * @init: initialize a SPI NAND device
>   * @adjust_op: modify the ops for any variation in their cmd, address, dummy or
>   *	       data phase by the manufacturer
> + * @octal_dtr_enable: switch the SPI NAND flash into Octal DTR SPI mode
>   * @cleanup: cleanup a SPI NAND device
>   *
>   * Each SPI NAND manufacturer driver should implement this interface so that
> @@ -280,6 +281,7 @@ struct spinand_manufacturer_ops {
>  	int (*init)(struct spinand_device *spinand);
>  	void (*adjust_op)(struct spi_mem_op *op,
>  			  const enum spinand_proto reg_proto);
> +	int (*octal_dtr_enable)(struct spinand_device *spinand);

I'd probably opt for a more generic name and pass the spinand_protocol
you want to enter in:

	int (*change_mode)(struct spinand_device *spinand,
			   enum spinand_protocol proto);

This way we can get back to 1-1-1-STR if we have to, and we can also
easily extend the logic to support 4-4-4-STR and 8-8-8-STR, which,
IIRC, are a thing (at least they exist on SPI NORs).

>  	void (*cleanup)(struct spinand_device *spinand);
>  };
>  
> @@ -348,6 +350,7 @@ struct spinand_ecc_info {
>  
>  #define SPINAND_HAS_QE_BIT		BIT(0)
>  #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
> +#define SPINAND_HAS_OCTAL_DTR_BIT	BIT(2)
>  
>  /**
>   * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure



From jaimeliao at mxic.com.tw  Tue Oct 12 00:14:56 2021
From: jaimeliao at mxic.com.tw (jaimeliao at mxic.com.tw)
Date: Tue, 12 Oct 2021 15:14:56 +0800
Subject: =?Big5?B?pl6rSDogW1JGQyBQQVRDSCAwOS8xMF0gc3BpOiBteGljOiBBZGQgc3VwcG9ydA==?=
 =?Big5?B?IGZvciBkaXJlY3QgbWFwcGluZw==?=
In-Reply-To: <20211008162228.1753083-10-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-10-miquel.raynal@bootlin.com>
Message-ID: <OF032BE161.2014BA23-ON4825876C.0027CC4D-4825876C.0027D1E7@mxic.com.tw>


Hi Miquel

ZhengxunLi have patch new mxic spi host controller before.
The patch name as below
spi: mxic: patch for octal DTR mode support
Please patch mxic ECC engine base on latest version.

Thanks
Jaime

> [RFC PATCH 09/10] spi: mxic: Add support for direct mapping
> 
> Implement the ->dirmap_create() and ->dirmap_read/write() hooks to
> provide a fast path for read and write accesses.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  drivers/spi/spi-mxic.c | 171 ++++++++++++++++++++++++++++++++++-------
>  1 file changed, 144 insertions(+), 27 deletions(-)
> 
> diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
> index 4fb19e6f94b0..e10c55ee4d06 100644
> --- a/drivers/spi/spi-mxic.c
> +++ b/drivers/spi/spi-mxic.c
> @@ -172,6 +172,11 @@ struct mxic_spi {
>     struct clk *send_dly_clk;
>     void __iomem *regs;
>     u32 cur_speed_hz;
> +   struct {
> +      void __iomem *map;
> +      dma_addr_t dma;
> +      size_t size;
> +   } linear;
>  };
> 
>  static int mxic_spi_clk_enable(struct mxic_spi *mxic)
> @@ -280,6 +285,42 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
>            mxic->regs + HC_CFG);
>  }
> 
> +static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
> +{
> +   u32 cfg = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
> +
> +   if (op->addr.nbytes)
> +      cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
> +             OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
> +
> +   if (op->dummy.nbytes)
> +      cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
> +
> +   if (op->data.dir != SPI_MEM_NO_DATA) {
> +      cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
> +      if (op->data.dir == SPI_MEM_DATA_IN)
> +         cfg |= OP_READ;
> +   }
> +
> +   return cfg;
> +}
> +
> +static void mxic_spi_set_hc_cfg(struct spi_device *spi, u32 flags)
> +{
> +   struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
> +   int nio = 1;
> +
> +   if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
> +      nio = 4;
> +   else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
> +      nio = 2;
> +
> +   writel(flags | HC_CFG_NIO(nio) |
> +          HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
> +          HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1),
> +          mxic->regs + HC_CFG);
> +}
> +
>  static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
>                 void *rxbuf, unsigned int len)
>  {
> @@ -328,6 +369,77 @@ static int mxic_spi_data_xfer(struct mxic_spi 
> *mxic, const void *txbuf,
>     return 0;
>  }
> 
> +static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc 
*desc,
> +               u64 offs, size_t len, void *buf)
> +{
> +   struct mxic_spi *mxic = 
spi_master_get_devdata(desc->mem->spi->master);
> +   int ret;
> +   u32 sts;
> +
> +   if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
> +      return -EINVAL;
> +
> +   mxic_spi_set_hc_cfg(desc->mem->spi, 0);
> +
> +   writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
> +          LMODE_SLV_ACT(desc->mem->spi->chip_select) |
> +          LMODE_EN,
> +          mxic->regs + LRD_CTRL);
> +   writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl),
> +          mxic->regs + LRD_CFG);
> +   writel(desc->info.offset + offs, mxic->regs + LRD_ADDR);
> +   len = min_t(size_t, len, mxic->linear.size);
> +   writel(len, mxic->regs + LRD_RANGE);
> +
> +   memcpy_fromio(buf, mxic->linear.map, len);
> +
> +   writel(INT_LRD_DIS, mxic->regs + INT_STS);
> +   writel(0, mxic->regs + LRD_CTRL);
> +
> +   ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> +             sts & INT_LRD_DIS, 0, USEC_PER_SEC);
> +   if (ret)
> +      return ret;
> +
> +   return len;
> +}
> +
> +static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc 
*desc,
> +                u64 offs, size_t len,
> +                const void *buf)
> +{
> +   struct mxic_spi *mxic = 
spi_master_get_devdata(desc->mem->spi->master);
> +   u32 sts;
> +   int ret;
> +
> +   if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
> +      return -EINVAL;
> +
> +   mxic_spi_set_hc_cfg(desc->mem->spi, 0);
> +
> +   writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
> +          LMODE_SLV_ACT(desc->mem->spi->chip_select) |
> +          LMODE_EN,
> +          mxic->regs + LWR_CTRL);
> +   writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl),
> +          mxic->regs + LWR_CFG);
> +   writel(desc->info.offset + offs, mxic->regs + LWR_ADDR);
> +   len = min_t(size_t, len, mxic->linear.size);
> +   writel(len, mxic->regs + LWR_RANGE);
> +
> +   memcpy_toio(mxic->linear.map, buf, len);
> +
> +   writel(INT_LWR_DIS, mxic->regs + INT_STS);
> +   writel(0, mxic->regs + LWR_CTRL);
> +
> +   ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> +             sts & INT_LWR_DIS, 0, USEC_PER_SEC);
> +   if (ret)
> +      return ret;
> +
> +   return len;
> +}
> +
>  static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
>                   const struct spi_mem_op *op)
>  {
> @@ -345,12 +457,27 @@ static bool mxic_spi_mem_supports_op(struct 
> spi_mem *mem,
>     return spi_mem_default_supports_op(mem, op);
>  }
> 
> +static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
> +{
> +   struct mxic_spi *mxic = 
spi_master_get_devdata(desc->mem->spi->master);
> +
> +   if (!mxic->linear.map)
> +      return -ENOTSUPP;
> +
> +   if (desc->info.offset + desc->info.length > U32_MAX)
> +      return -ENOTSUPP;
> +
> +   if (!mxic_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
> +      return -ENOTSUPP;
> +
> +   return 0;
> +}
> +
>  static int mxic_spi_mem_exec_op(struct spi_mem *mem,
>              const struct spi_mem_op *op)
>  {
>     struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
> -   int nio = 1, i, ret;
> -   u32 ss_ctrl;
> +   int i, ret;
>     u8 addr[8];
>     u8 opcode = op->cmd.opcode;
> 
> @@ -358,34 +485,12 @@ static int mxic_spi_mem_exec_op(struct spi_mem 
*mem,
>     if (ret)
>        return ret;
> 
> -   if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
> -      nio = 4;
> -   else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
> -      nio = 2;
> +   mxic_spi_set_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN);
> 
> -   writel(HC_CFG_NIO(nio) |
> -          HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
> -          HC_CFG_SLV_ACT(mem->spi->chip_select) | 
HC_CFG_IDLE_SIO_LVL(1) |
> -          HC_CFG_MAN_CS_EN,
> -          mxic->regs + HC_CFG);
>     writel(HC_EN_BIT, mxic->regs + HC_EN);
> 
> -   ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
> -
> -   if (op->addr.nbytes)
> -      ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) |
> -            OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
> -
> -   if (op->dummy.nbytes)
> -      ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes);
> -
> -   if (op->data.nbytes) {
> -      ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
> -      if (op->data.dir == SPI_MEM_DATA_IN)
> -         ss_ctrl |= OP_READ;
> -   }
> -
> -   writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select));
> +   writel(mxic_spi_mem_prep_op_cfg(op),
> +          mxic->regs + SS_CTRL(mem->spi->chip_select));
> 
>     writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
>            mxic->regs + HC_CFG);
> @@ -423,6 +528,9 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
>  static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
>     .supports_op = mxic_spi_mem_supports_op,
>     .exec_op = mxic_spi_mem_exec_op,
> +   .dirmap_create = mxic_spi_mem_dirmap_create,
> +   .dirmap_read = mxic_spi_mem_dirmap_read,
> +   .dirmap_write = mxic_spi_mem_dirmap_write,
>  };
> 
>  static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
> @@ -552,6 +660,15 @@ static int mxic_spi_probe(struct platform_device 
*pdev)
>     if (IS_ERR(mxic->regs))
>        return PTR_ERR(mxic->regs);
> 
> +   res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
> +   mxic->linear.map = devm_ioremap_resource(&pdev->dev, res);
> +   if (!IS_ERR(mxic->linear.map)) {
> +      mxic->linear.dma = res->start;
> +      mxic->linear.size = resource_size(res);
> +   } else {
> +      mxic->linear.map = NULL;
> +   }
> +
>     pm_runtime_enable(&pdev->dev);
>     master->auto_runtime_pm = true;
> 
> -- 
> 2.27.0
> 


CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information 
and/or personal data, which is protected by applicable laws. Please be 
reminded that duplication, disclosure, distribution, or use of this e-mail 
(and/or its attachments) or any part thereof is prohibited. If you receive 
this e-mail in error, please notify us immediately and delete this mail as 
well as its attachment(s) from your system. In addition, please be 
informed that collection, processing, and/or use of personal data is 
prohibited unless expressly permitted by personal data protection laws. 
Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



============================================================================

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



From boris.brezillon at collabora.com  Tue Oct 12 00:25:08 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Tue, 12 Oct 2021 09:25:08 +0200
Subject: [PATCH v2 11/14] mtd: spinand: Perform Power-on-Reset on the
 flash in mtd_suspend()
In-Reply-To: <20211011204619.81893-12-a-nandan@ti.com>
References: <20211011204619.81893-1-a-nandan@ti.com>
 <20211011204619.81893-12-a-nandan@ti.com>
Message-ID: <20211012092508.1647047b@collabora.com>

On Tue, 12 Oct 2021 02:16:16 +0530
Apurva Nandan <a-nandan at ti.com> wrote:

> A soft reset using FFh command doesn't erase the flash's configuration
> and doesn't reset the SPI IO mode also. This can result in the flash
> being in a different SPI IO mode, e.g. Octal DTR, when resuming from
> sleep. This could put the flash in an unrecognized SPI IO mode, making
> it unusable.
> 
> Perform a Power-on-Reset (PoR), if available in the flash, when
> performing mtd_suspend(). This would set the flash to clean
> state for reinitialization during resume and would also ensure that it
> is in standard SPI IO mode (1S-1S-1S) before the resume begins.
> 
> Signed-off-by: Apurva Nandan <a-nandan at ti.com>
> ---
>  drivers/mtd/nand/spi/core.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
> index 9b570570ee81..60408531979a 100644
> --- a/drivers/mtd/nand/spi/core.c
> +++ b/drivers/mtd/nand/spi/core.c
> @@ -1316,6 +1316,11 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
>  	int ret;
>  
>  	spinand->reg_proto = SPINAND_SINGLE_STR;
> +	/*
> +	 * PoR Reset (if available by the manufacturer) is performed at the suspend
> +	 * time. Hence, those flashes remain in power-on-state at this point, in a
> +	 * standard SPI IO mode. So, now the core unanimously performs a soft reset.
> +	 */
>  	ret = spinand_reset_op(spinand);
>  	if (ret)
>  		return;
> @@ -1327,6 +1332,21 @@ static void spinand_mtd_resume(struct mtd_info *mtd)
>  	spinand_ecc_enable(spinand, false);
>  }
>  
> +static int spinand_mtd_suspend(struct mtd_info *mtd)
> +{
> +	struct spinand_device *spinand = mtd_to_spinand(mtd);
> +	int ret;
> +
> +	if (!(spinand->flags & SPINAND_HAS_POR_CMD_BIT))
> +		return 0;
> +
> +	ret = spinand_power_on_rst_op(spinand);
> +	if (ret)
> +		dev_err(&spinand->spimem->spi->dev, "suspend() failed\n");
> +
> +	return ret;
> +}

I suspect you need to implement the spi_mem_driver.shutdown() method
and do a PoR in that case too. If the device doesn't support the PoR
command, we should at least switch back to the 1-1-1-STR mode manually.

> +
>  static int spinand_init(struct spinand_device *spinand)
>  {
>  	struct device *dev = &spinand->spimem->spi->dev;
> @@ -1399,6 +1419,7 @@ static int spinand_init(struct spinand_device *spinand)
>  	mtd->_erase = spinand_mtd_erase;
>  	mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
>  	mtd->_resume = spinand_mtd_resume;
> +	mtd->_suspend = spinand_mtd_suspend;
>  
>  	if (nand->ecc.engine) {
>  		ret = mtd_ooblayout_count_freebytes(mtd);



From michael at walle.cc  Tue Oct 12 00:48:46 2021
From: michael at walle.cc (Michael Walle)
Date: Tue, 12 Oct 2021 09:48:46 +0200
Subject: [PATCH v2 1/2] dt-bindings: mtd: spi-nor: Add
 output-driver-strength property
In-Reply-To: <20211012061704.284214-1-alexander.stein@ew.tq-group.com>
References: <20211012061704.284214-1-alexander.stein@ew.tq-group.com>
Message-ID: <a347541ba3f8c76912d4afdb6dc64d4d@walle.cc>

Am 2021-10-12 08:17, schrieb Alexander Stein:
> This property is for optimizing output voltage impedance and is
> specific to each board. It overwrites the default set by the flash
> device. Various flash devices support different impedances.
> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
> Changes in v2:
> * Updated the property description and the commit message accordingly
> 
>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> index ed590d7c6e37..4c3c506a8853 100644
> --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> @@ -72,6 +72,14 @@ properties:
>        be used on such systems, to denote the absence of a reliable 
> reset
>        mechanism.
> 
> +  output-driver-strength:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Output driver strength in ohms which optimizes the impedance at 
> Vcc/2
> +      output voltage. This property overwrites the default set by the 
> flash
> +      device. This is board specific and should be determined by the
> +      manufacturer. Various flash devices support different 
> impedances.

Mh, this seems to be very tailored to this flash chip. Eg. the "Vcc/2", 
is
this something specific to this flash or is this some kind of common 
usage?
For example, Winbond flashes specifies the output driver strength in 
percent.
Settings are 25%, 50%, 75%, 100% there.

I'd have to ask a hardware guy, if one could convert between these two
representations of the driver strength.

Rob, do you know how is this case ususally handled? Can there be 
different
properties, like:

output-driver-strength-ohms
output-driver-strength-percent

or similar.

-michael


From s.riedmueller at phytec.de  Tue Oct 12 02:02:23 2021
From: s.riedmueller at phytec.de (Stefan Riedmueller)
Date: Tue, 12 Oct 2021 11:02:23 +0200
Subject: [RFC PATCH 1/2] mtd: rawnand: gpmi: Remove explicit default gpmi
 clock setting for i.MX6
In-Reply-To: <20211011084607.27a840e0@xps13>
References: <20211011084607.27a840e0@xps13>
Message-ID: <20211012090224.4101984-1-s.riedmueller@phytec.de>

There is no need to explicitly set the default gpmi clock rate during
boot for the i.MX 6 since this is done during nand_detect anyway.

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
---
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 4d08e4ab5c1b..a1f7000f033e 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -1034,15 +1034,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
 		r->clock[i] = clk;
 	}
 
-	if (GPMI_IS_MX6(this))
-		/*
-		 * Set the default value for the gpmi clock.
-		 *
-		 * If you want to use the ONFI nand which is in the
-		 * Synchronous Mode, you should change the clock as you need.
-		 */
-		clk_set_rate(r->clock[0], 22000000);
-
 	return 0;
 
 err_clock:
-- 
2.25.1



From s.riedmueller at phytec.de  Tue Oct 12 02:02:24 2021
From: s.riedmueller at phytec.de (Stefan Riedmueller)
Date: Tue, 12 Oct 2021 11:02:24 +0200
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211012090224.4101984-1-s.riedmueller@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
Message-ID: <20211012090224.4101984-2-s.riedmueller@phytec.de>

According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
when doing a gpmi_io clk rate change. So gate the clocks off before
the rate change in nfc_apply_timings and ungate them again after the
change.

Otherwise this rate change can lead to an unresponsive GPMI core which
results in DMA timeouts and failed driver probe:

[    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
...
[    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
...
[    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
[    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
[    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
[    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
...

Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
---
Hi,

I'm not sure about the error handling here, if it is actually neccessary.
So some feedback would be nice here.

Thanks,
Stefan
---
 drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index a1f7000f033e..326c8a895f1f 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
 			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
 }
 
-static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
+static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
 {
 	struct gpmi_nfc_hardware_timing *hw = &this->hw;
 	struct resources *r = &this->resources;
 	void __iomem *gpmi_regs = r->gpmi_regs;
 	unsigned int dll_wait_time_us;
+	int ret;
+
+	if (GPMI_IS_MX6Q(this)) {
+		ret = __gpmi_enable_clk(this, false);
+		if (ret)
+			return ret;
+	}
 
 	clk_set_rate(r->clock[0], hw->clk_rate);
 
+	if (GPMI_IS_MX6Q(this)) {
+		ret = __gpmi_enable_clk(this, true);
+		if (ret)
+			return ret;
+	}
+
 	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
 	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
 
@@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
 
 	/* Wait for the DLL to settle. */
 	udelay(dll_wait_time_us);
+
+	return 0;
 }
 
 static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
@@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
 	 */
 	if (this->hw.must_apply_timings) {
 		this->hw.must_apply_timings = false;
-		gpmi_nfc_apply_timings(this);
+		ret = gpmi_nfc_apply_timings(this);
+		if (ret)
+			return ret;
 	}
 
 	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
-- 
2.25.1



From sean at geanix.com  Tue Oct 12 02:15:27 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 12 Oct 2021 11:15:27 +0200
Subject: [PATCH 1/2] mtd: nand: raw: gpmi: new bch geometry settings
In-Reply-To: <20210706025001.bqvrdye4v3cidm5v@umbrella>
References: <20210522205136.19465-1-han.xu@nxp.com>
 <13c975bc-b37b-8708-9ac7-acdc62ef7108@geanix.com>
 <20210525191308.jlxqvy7khptbuj4z@umbrella> <20210526094136.279976a6@xps13>
 <20210526141700.5gygssig4rnzn6mj@umbrella> <20210526173123.1787713b@xps13>
 <20210705104654.gko7ettkilrrosi7@skn-laptop>
 <20210706025001.bqvrdye4v3cidm5v@umbrella>
Message-ID: <9f4ed2c6-7b3d-4933-2247-541855b800ba@geanix.com>


On 06/07/2021 04.50, Han Xu wrote:
> On 21/07/05 12:46PM, Sean Nyekjaer wrote:
>> On Wed, May 26, 2021 at 05:31:23PM +0200, Miquel Raynal wrote:
>>> Hi Han,

[ ... ]

>> 
>> Hi Han,
>> 
>> Is this something you are working on? If not I really think we need
>> to revert the changes to u-boot, to allign vanilla u-boot and
>> kernel.
> 
> I will send patches for both kernel and u-boot to use legacy bch
> scheme by default, and add some code to treat few MLC nand chips as
> corner cases.
> 

Have I missed the series patches for this? :)


From robh at kernel.org  Tue Oct 12 05:52:17 2021
From: robh at kernel.org (Rob Herring)
Date: Tue, 12 Oct 2021 07:52:17 -0500
Subject: [PATCH 1/2] dt-bindings: mtd: spi-nor: Add
 output-driver-strength property
In-Reply-To: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
References: <20211004111529.211089-1-Alexander.Stein@tq-systems.com>
Message-ID: <YWWFAXeekLS80bOR@robh.at.kernel.org>

On Mon, Oct 04, 2021 at 01:15:28PM +0200, Alexander Stein wrote:
> From: Alexander Stein <alexander.stein at ew.tq-group.com>
> 
> This property is for optimizing output voltage impedance and is
> specific to each board.
> 
> Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> ---
> I checked Micron and Macronix datasheets. Both have similar but not
> identical supported values. Also the register locations are different.
> For those reasons I decided to specify the Ohms value directly and let
> the device specfic driver figure out if it is supported where to write
> it to.
> BTW: Are the Ohm values and the corresponding register bits standardized
> somewhere?
> 
>  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> index ed590d7c6e37..7d7f20a741b5 100644
> --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> @@ -72,6 +72,12 @@ properties:
>        be used on such systems, to denote the absence of a reliable reset
>        mechanism.
>  
> +  output-driver-strength:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description:
> +      Output driver strength in Ohms which optimizes the impedance at Vcc/2
> +      output voltage.

Use a standard unit suffix.

Though, specifying 'drive strength' in ohms rather than amps is a bit 
strange.


From havasiefr at gmail.com  Tue Oct 12 06:02:20 2021
From: havasiefr at gmail.com (Kristof Havasi)
Date: Tue, 12 Oct 2021 15:02:20 +0200
Subject: UBIFS panic during brown-out
In-Reply-To: <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
 <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
Message-ID: <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>

Hello Richard,

On Mon, 11 Oct 2021 at 21:02, Richard Weinberger <richard at nod.at> wrote:
>
> Krist?f,
>
> ----- Urspr?ngliche Mail -----
> > Von: "Kristof Havasi" <havasiefr at gmail.com>
> > An: "richard" <richard at nod.at>
> > CC: "linux-mtd" <linux-mtd at lists.infradead.org>
> > Gesendet: Montag, 11. Oktober 2021 19:16:01
> > Betreff: UBIFS panic during brown-out
>
> > Dear Richard,
> >
> > we have been in contact regarding another (similar) kernel panic a year ago:
> > http://lists.infradead.org/pipermail/linux-mtd/2020-September/082175.html
> >
> > Now we are stress testing our board for brown-out stability, and we can
> > see reproducible file system corruptions.
> > The culprit was narrowed down to a pending SQLite operation during brown-out,
> > in the business-logic.
> >
> > As far as I understood, UBIFS is extremely robust in such cases, so I would
> > expect a corrupted file as the worst case scenario, not an unbootable system.
> >
> > Am I too "optimistic" about UBIFS's brown-out stability?
>
> A brown-out is something very bad. Electronic components show undefined behavior
> in this phase. UBIFS (and Linux) can nothing do there.
> But both UBI and UBIFS try to be robust against sudden power loss (power-cut).
> E.g. an interrupted erase or program operation.
>
> So, are you really talking about brown-out? If so, better talk to you hardware guys.

Sorry, s/brown-out/power-cut/.

>
> > Does the Auth+Encryption combo increase the chances for corrupting the FS
> > during brown-out, due to the extra operations?
>
> Assuming you actually meant power-cut.
> Both features are rather new, so there can be still bugs.

If the logs do not reveal any pointers, we could re-test with disabled enc/auth.

>
> > Would you suggest turning on any of the chk_* knobs in the debugfs?
> > I am not sure that they are helpful, or will just modify the behaviour of the
> > timings of the system too much.
>
> Let's start with logs first.
>
> > Would it be a last resort in case the brown-out is detected to switch the FS
> > into ro mode? Is there any API/ABI apart from the debugfs's ro_error knob to
> > switch the FS into read-only mode and so trying to prevent file-system
> > corruption?
>
> Not really. You need to make sure that the current NAND command is finished
> and no new one will be scheduled. Depending on your hardware design this can
> be a challenge.

So would a "successful `sync` and ro mode switch" be a safe bet, if
during the two
actions no new data is written to the FS?

>
> > Any pointers are welcomed!
> >
> > We are on Kernel v5.4.150
> > We use _both_ UBIFS Authentication and Encryption.
> > The board is a SAMA5D3 powered embedded device with 1GB NAND flash,
> > which is not even nearly full (10% used).
> >
> > Kernel panic after the last brown-out:
> > ubi0: scanning is finished
> > ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> > ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> > ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> > ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> > ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
> > ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> > ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
> > sequence number: 921361235
> >>ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for bad PEB
> >>handling: 67
> > ubi0: background thread "ubi_bgt0d" started, PID 617
> > UBIFS (ubi0:4): Mounting in authenticated mode
> > UBIFS (ubi0:4): recovery needed
> >>VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
>
> There is a lot of context missing. Can you please share the full logs?
> Usually UBIFS prints in detail what went wrong.

I couldn't see any UBIFS logs over the serial (but the kernel log
level was also only 1)
and the application log was also redirected there...
But here is the full log from the application logs through the power-cut and the
boot-up

[Sat Oct 09 14:15:00 2021] pwr outage WARN: Power outage detected ...
[Sat Oct 09 14:15:00 2021] pwr outage INFO: Low Power mode activated
[Sat Oct 09 14:15:00 2021] event manager TRACE: Database
/data/logsystem.db opened successfully
[Sat Oct 09 14:15:00 2021] event manager TRACE: SQLite prepare :
SELECT * FROM log_sys WHERE  event_flag=2 OR event_flag=1 ORDER BY
timestamp ASC LIMIT 1;
[Sat Oct 09 14:15:00 2021] fnn logger TRACE: Database
/data/logcustomer.db opened successfully
[snip] some 10s of lines of application log related to SQL operations
[Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : SELECT
MAX(repetition_counter), MAX(record_number), MAX(parent_record_number)
FROM log_customer WHERE  timestamp > ?1 AND event_id = ?2 AND
event_sub_id = ?3 AND user_identity = ?4 AND subject_identity = ?5 AND
message_extensions = ?6 AND peer_identity = ?7;
[Sat Oct 09 14:15:00 2021] fnn logger TRACE: Stepping:
SELECT MAX(repetition_counter), MAX(record_number),
MAX(parent_record_number) FROM log_customer WHERE  timestamp >
1633695300 AND event_id = 19005 AND event_sub_id = 1 AND user_identity
= '' AND subject_identity = '01005e3180a0.eefr2000003006.sm' AND
message_extensions = '' AND peer_identity = '';
[Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQL-Step executed successfully
[Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : UPDATE
log_customer SET [snip] WHERE record_number = ?21 AND
repetition_counter = ?22;
[Sat Oct 09 14:15:01 2021] fnn logger TRACE: Stepping:
UPDATE log_customer SET repetition_counter = 372, parent_record_number
= 3031, seconds_index = 246, timestamp = 1633781700, level = 2,
version = 1, length = 0, device_typ?RomBOOT
RomBOOT

AT91Bootstrap for SMGW 3.8.12-00020-g0f08dbf (Wed Apr 14 18:46:12 CEST 2021)

NAND: ONFI flash detected
NAND: Manufacturer ID: 0x2c Chip ID: 0xd3
NAND: Page Bytes: 4096, Spare Bytes: 224
NAND: ECC Correctability Bits: 8, ECC Sector Bytes: 512
NAND: Disable On-Die ECC
NAND: Initialize PMECC params, cap: 8, sector: 512
NAND: Initialize UBI...
UBI: Loading volume-table 0 at PEB 202 with copy flag!
NAND: Loading UBI volume kernel kernel-spare to @0x22000000
(0xffffffff bytes length)...
UBI: Length of Vol-2 updated to 3128 KB
NAND: Loading UBI volume dtb dtb-spare to @0x21000000 (0xffffffff
bytes length)...
UBI: Length of Vol-0 updated to 33 KB

Booting zImage ......

Using device tree in place at 0x210001f4
DT: Injected MAC addresses
DT: Populated virtual-eprom

Starting linux kernel ..., machid: 0xffffffff

Booting Linux on physical CPU 0x0
Linux version 5.4.109-00033-ga88943c1e68
(root at runner-tzue45hw-project-205-concurrent-0) (gcc version 6.5.0
(Linaro GCC 6.5-2018.12)) #1 Wed Apr 14 18:46:17 CEST 2021
CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d
CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
OF: fdt: Machine model: SMGW
Memory policy: Data cache writeback
CPU: All CPU(s) started in SVC mode.
Built 1 zonelists, mobility grouping on.  Total pages: 32511
Kernel command line: rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs
rootflags=auth_hash_name=sha256,auth_key=ubifsauth:0000aaaaffff0000
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
mem auto-init: stack:off, heap alloc:on, heap free:on
mem auto-init: clearing system memory may take some time...
Memory: 121196K/131068K available (5120K kernel code, 197K rwdata,
956K rodata, 1024K init, 153K bss, 9872K reserved, 0K cma-reserved)
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
random: get_random_bytes called from start_kernel+0x2ec/0x41c with crng_init=0
master clk is overclocked
clocksource: pit: mask: 0xfffffff max_cycles: 0xfffffff, max_idle_ns:
14479245754 ns
Console: colour dummy device 80x30
printk: console [tty0] enabled
sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every
21474836475000000ns
Calibrating delay loop... 351.43 BogoMIPS (lpj=1757184)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
CPU: Testing write buffer coherency: ok
Setting up static identity map for 0x20100000 - 0x2010003c
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 2 part 30 variant 5 rev 1
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: -1, 3072 bytes, linear)
pinctrl core: initialized pinctrl subsystem
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
gpio-at91 fffff200.gpio: at address (ptrval)
gpio-at91 fffff400.gpio: at address (ptrval)
gpio-at91 fffff600.gpio: at address (ptrval)
gpio-at91 fffff800.gpio: at address (ptrval)
gpio-at91 fffffa00.gpio: at address (ptrval)
pinctrl-at91 ahb:apb:pinctrl at fffff200: initialized AT91 pinctrl driver
atmel_tcb f0010000.timer: IRQ index 1 not found
atmel_tcb f0010000.timer: IRQ index 2 not found
atmel_tcb f8014000.timer: IRQ index 1 not found
atmel_tcb f8014000.timer: IRQ index 2 not found
at_hdmac ffffe600.dma-controller: Atmel AHB DMA Controller ( cpy set
slave ), 8 channels
at_hdmac ffffe800.dma-controller: Atmel AHB DMA Controller ( cpy set
slave ), 8 channels
AT91: Detected SoC family: sama5d3
AT91: Detected SoC: sama5d35, revision 2
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
at91_i2c f0014000.i2c: using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
at91_i2c f0014000.i2c: AT91 i2c bus driver (hw version: 0x402).
at91_i2c f0018000.i2c: can't get DMA channel, continue without DMA support
at91_i2c f0018000.i2c: AT91 i2c bus driver (hw version: 0x402).
clocksource: Switched to clocksource pit
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
NET: Registered protocol family 1
Initialise system trusted keyrings
workingset: timestamp_bits=30 max_order=15 bucket_order=0
NET: Registered protocol family 38
Key type asymmetric registered
Asymmetric key parser 'x509' registered
atmel_usart_serial.0.auto: ttyS1 at MMIO 0xf001c000 (irq = 21,
base_baud = 4125000) is a ATMEL_SERIAL
atmel_usart_serial.1.auto: ttyS2 at MMIO 0xf0020000 (irq = 22,
base_baud = 8250000) is a ATMEL_SERIAL
atmel_usart_serial.2.auto: ttyS3 at MMIO 0xf8020000 (irq = 24,
base_baud = 4125000) is a ATMEL_SERIAL
atmel_usart_serial.3.auto: ttyS0 at MMIO 0xffffee00 (irq = 32,
base_baud = 8250000) is a ATMEL_SERIAL
printk: console [ttyS0] enabled
atmel_spi f8008000.spi: DMA TX channel not available, SPI unable to use DMA
atmel_spi f8008000.spi: Atmel SPI Controller using PIO only
ksz8863 at 0 enforce active low on chipselect handle
atmel_spi f8008000.spi: Atmel SPI Controller version 0x213 at
0xf8008000 (irq 23)
libphy: Fixed MDIO Bus: probed
macb f0028000.ethernet: invalid hw address, using random
random: fast init done
libphy: MACB_mii_bus: probed
Generic PHY fixed-0:00: attached PHY driver [Generic PHY]
(mii_bus:phy_addr=fixed-0:00, irq=POLL)
macb f0028000.ethernet eth0: Cadence GEM rev 0x00020119 at 0xf0028000
irq 40 (12:71:da:58:0b:2d)
libphy: MACB_mii_bus: probed
Micrel KSZ8081 or KSZ8091 f802c000.ethernet-ffffffff:00: attached PHY
driver [Micrel KSZ8081 or KSZ8091]
(mii_bus:phy_addr=f802c000.ethernet-ffffffff:00, irq=45)
macb f802c000.ethernet eth1: Cadence MACB rev 0x0001010c at 0xf802c000
irq 41 (d8:c4:97:1c:9a:d7)
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver cdc_ncm
usbcore: registered new interface driver cdc_mbim
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-platform: EHCI generic platform driver
ehci-atmel: EHCI Atmel driver
atmel-ehci 700000.ehci: EHCI Host Controller
atmel-ehci 700000.ehci: new USB bus registered, assigned bus number 1
atmel-ehci 700000.ehci: irq 43, io mem 0x00700000
atmel-ehci 700000.ehci: USB 2.0 started, EHCI 1.00
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 5.04
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: EHCI Host Controller
usb usb1: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ehci_hcd
usb usb1: SerialNumber: 700000.ehci
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 3 ports detected
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
ohci-platform: OHCI generic platform driver
ohci-atmel: OHCI Atmel driver
at91_ohci 600000.ohci: USB Host Controller
at91_ohci 600000.ohci: new USB bus registered, assigned bus number 2
at91_ohci 600000.ohci: irq 43, io mem 0x00600000
usb usb2: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 5.04
usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb2: Product: USB Host Controller
usb usb2: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ohci_hcd
usb usb2: SerialNumber: at91
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 3 ports detected
usbcore: registered new interface driver cdc_acm
cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
usbcore: registered new interface driver cdc_wdm
usbcore: registered new interface driver usbserial_generic
usbserial: USB Serial support registered for generic
usbcore: registered new interface driver option
usbserial: USB Serial support registered for GSM modem (1-port)
usbcore: registered new interface driver usb_serial_simple
usbserial: USB Serial support registered for carelink
usbserial: USB Serial support registered for zio
usbserial: USB Serial support registered for funsoft
usbserial: USB Serial support registered for flashloader
usbserial: USB Serial support registered for google
usbserial: USB Serial support registered for libtransistor
usbserial: USB Serial support registered for vivopay
usbserial: USB Serial support registered for moto_modem
usbserial: USB Serial support registered for motorola_tetra
usbserial: USB Serial support registered for novatel_gps
usbserial: USB Serial support registered for hp4x
usbserial: USB Serial support registered for suunto
usbserial: USB Serial support registered for siemens_mpi
rtc-rv8803 1-0032: registered as rtc0
i2c /dev entries driver
at91-reset fffffe00.rstc: Starting after wakeup
at91sam9_wdt: enabled (heartbeat=15 sec, nowayout=1)
atmel_aes f8038000.aes: version: 0x135
atmel_aes f8038000.aes: Atmel AES - Using dma1chan0, dma1chan1 for DMA transfers
atmel_sha f8034000.sha: version: 0x410
atmel_sha f8034000.sha: using dma1chan2 for DMA transfers
atmel_sha f8034000.sha: Atmel SHA1/SHA256/SHA224/SHA384/SHA512
atmel_tdes f803c000.tdes: version: 0x701
atmel_tdes f803c000.tdes: using dma1chan3, dma1chan4 for DMA transfers
atmel_tdes f803c000.tdes: Atmel DES/TDES
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xd3
nand: Micron MT29F8G08ABACAWP
nand: 1024 MiB, SLC, erase size: 256 KiB, page size: 4096, OOB size: 224
Bad block table found at page 262080, version 0x01
Bad block table found at page 262016, version 0x01
nand_read_bbt: bad block at 0x000000dc0000
nand_read_bbt: bad block at 0x00000e280000
nand_read_bbt: bad block at 0x000024f40000
nand_read_bbt: bad block at 0x000026ec0000
nand_read_bbt: bad block at 0x000027ec0000
nand_read_bbt: bad block at 0x00002f140000
nand_read_bbt: bad block at 0x000030ec0000
nand_read_bbt: bad block at 0x000033b40000
nand_read_bbt: bad block at 0x000038840000
2 fixed-partitions partitions found on MTD device atmel_nand
Creating 2 MTD partitions on "atmel_nand":
0x000000000000-0x000000040000 : "at91bootstrap"
0x000000040000-0x000040000000 : "ubivols"
NET: Registered protocol family 10
Segment Routing with IPv6
sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
NET: Registered protocol family 17
8021q: 802.1Q VLAN Support v1.8
Loading compiled-in X.509 certificates
Loaded X.509 cert 'EFR: efr.de: a54308f075327fb6c3a6fb687fdabc10ce4c51c6'
Key type ._fscrypt registered
Key type .fscrypt registered
ksz8795-switch spi0.0: active low/falling IRQ
libphy: dsa slave smi: probed
ksz8795-switch spi0.0 han (uninitialized): PHY [dsa-0.0:00] driver
[Micrel KSZ886X Switch]
ksz8795-switch spi0.0 cls (uninitialized): PHY [dsa-0.0:01] driver
[Micrel KSZ886X Switch]
ksz8795-switch spi0.0: Using legacy PHYLIB callbacks. Please migrate to PHYLINK!
DSA: tree 0 setup
ubi0: attaching mtd1
usb 2-3: new full-speed USB device number 2 using at91_ohci
usb 2-3: New USB device found, idVendor=08e6, idProduct=3437, bcdDevice= 2.01
usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 2-3: Product: USB SmartCard Reader
usb 2-3: Manufacturer: Gemalto
random: crng init done
ubi0: scanning is finished
ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
sequence number: 921361235
ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for
bad PEB handling: 67
ubi0: background thread "ubi_bgt0d" started, PID 617
rtc-rv8803 1-0032: setting system clock to 2021-10-09T12:16:01 UTC (1633781761)
UBIFS (ubi0:4): Mounting in authenticated mode
UBIFS (ubi0:4): recovery needed
VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on ubi0:rootfs
CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.109-00033-ga88943c1e68 #1
Hardware name: Atmel SAMA5
[<c010babc>] (unwind_backtrace) from [<c010a8d0>] (show_stack+0x10/0x14)
[<c010a8d0>] (show_stack) from [<c0569970>] (panic+0xfc/0x2e8)
[<c0569970>] (panic) from [<c0801598>] (mount_block_root+0x268/0x2a4)
[<c0801598>] (mount_block_root) from [<c0801674>] (prepare_namespace+0x9c/0x184)
[<c0801674>] (prepare_namespace) from [<c056b774>] (kernel_init+0x8/0x108)
[<c056b774>] (kernel_init) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
Exception stack(0xc7829fb0 to 0xc7829ff8)
9fa0:                                     00000000 00000000 00000000 00000000
9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on
ubi0:rootfs ]---
RomBOOT
RomBOOT

>
> 5.4 is not fresh. Can you use a more recent kernel?

We are tracking the latest patches on 5.4, but will try whether a
rebase to 5.10 is straight-forward or not.
Or at least port the minimal changes which are needed to re-create the crash.

But first, I will try to reproduce the crash with a stripped down
program, because with the current tests,
it can take anywhere between 20-500 iterations of power-cuts with the
full business logic to trigger the crash.
(5m ON 30s OFF)

Best Regards,
Krist?f


From richard at nod.at  Tue Oct 12 06:36:18 2021
From: richard at nod.at (Richard Weinberger)
Date: Tue, 12 Oct 2021 15:36:18 +0200 (CEST)
Subject: UBIFS panic during brown-out
In-Reply-To: <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
 <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
 <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>
Message-ID: <1040411488.65265.1634045778705.JavaMail.zimbra@nod.at>

Krist?f,

----- Urspr?ngliche Mail -----
> Von: "Kristof Havasi" <havasiefr at gmail.com>
>> So, are you really talking about brown-out? If so, better talk to you hardware
>> guys.
> 
> Sorry, s/brown-out/power-cut/.

:-)

>>
>> > Does the Auth+Encryption combo increase the chances for corrupting the FS
>> > during brown-out, due to the extra operations?
>>
>> Assuming you actually meant power-cut.
>> Both features are rather new, so there can be still bugs.
> 
> If the logs do not reveal any pointers, we could re-test with disabled enc/auth.
> 
>>
>> > Would you suggest turning on any of the chk_* knobs in the debugfs?
>> > I am not sure that they are helpful, or will just modify the behaviour of the
>> > timings of the system too much.
>>
>> Let's start with logs first.
>>
>> > Would it be a last resort in case the brown-out is detected to switch the FS
>> > into ro mode? Is there any API/ABI apart from the debugfs's ro_error knob to
>> > switch the FS into read-only mode and so trying to prevent file-system
>> > corruption?
>>
>> Not really. You need to make sure that the current NAND command is finished
>> and no new one will be scheduled. Depending on your hardware design this can
>> be a challenge.
> 
> So would a "successful `sync` and ro mode switch" be a safe bet, if
> during the two
> actions no new data is written to the FS?

Kind of. Actually UBIFS should handle this just fine.
Before we consider workarounds, let's give the problem more thought.

>>
>> > Any pointers are welcomed!
>> >
>> > We are on Kernel v5.4.150
>> > We use _both_ UBIFS Authentication and Encryption.
>> > The board is a SAMA5D3 powered embedded device with 1GB NAND flash,
>> > which is not even nearly full (10% used).
>> >
>> > Kernel panic after the last brown-out:
>> > ubi0: scanning is finished
>> > ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
>> > ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
>> > ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
>> > ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
>> > ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
>> > ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
>> > ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
>> > sequence number: 921361235
>> >>ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for bad PEB
>> >>handling: 67
>> > ubi0: background thread "ubi_bgt0d" started, PID 617
>> > UBIFS (ubi0:4): Mounting in authenticated mode
>> > UBIFS (ubi0:4): recovery needed
>> >>VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
>>
>> There is a lot of context missing. Can you please share the full logs?
>> Usually UBIFS prints in detail what went wrong.
> 
> I couldn't see any UBIFS logs over the serial (but the kernel log
> level was also only 1)
> and the application log was also redirected there...
> But here is the full log from the application logs through the power-cut and the
> boot-up
> 
> [Sat Oct 09 14:15:00 2021] pwr outage WARN: Power outage detected ...
> [Sat Oct 09 14:15:00 2021] pwr outage INFO: Low Power mode activated
> [Sat Oct 09 14:15:00 2021] event manager TRACE: Database
> /data/logsystem.db opened successfully
> [Sat Oct 09 14:15:00 2021] event manager TRACE: SQLite prepare :
> SELECT * FROM log_sys WHERE  event_flag=2 OR event_flag=1 ORDER BY
> timestamp ASC LIMIT 1;
> [Sat Oct 09 14:15:00 2021] fnn logger TRACE: Database
> /data/logcustomer.db opened successfully
> [snip] some 10s of lines of application log related to SQL operations
> [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : SELECT
> MAX(repetition_counter), MAX(record_number), MAX(parent_record_number)
> FROM log_customer WHERE  timestamp > ?1 AND event_id = ?2 AND
> event_sub_id = ?3 AND user_identity = ?4 AND subject_identity = ?5 AND
> message_extensions = ?6 AND peer_identity = ?7;
> [Sat Oct 09 14:15:00 2021] fnn logger TRACE: Stepping:
> SELECT MAX(repetition_counter), MAX(record_number),
> MAX(parent_record_number) FROM log_customer WHERE  timestamp >
> 1633695300 AND event_id = 19005 AND event_sub_id = 1 AND user_identity
> = '' AND subject_identity = '01005e3180a0.eefr2000003006.sm' AND
> message_extensions = '' AND peer_identity = '';
> [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQL-Step executed successfully
> [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : UPDATE
> log_customer SET [snip] WHERE record_number = ?21 AND
> repetition_counter = ?22;
> [Sat Oct 09 14:15:01 2021] fnn logger TRACE: Stepping:
> UPDATE log_customer SET repetition_counter = 372, parent_record_number
> = 3031, seconds_index = 246, timestamp = 1633781700, level = 2,
> version = 1, length = 0, device_typ?RomBOOT
> RomBOOT
> 
> AT91Bootstrap for SMGW 3.8.12-00020-g0f08dbf (Wed Apr 14 18:46:12 CEST 2021)
> 
> NAND: ONFI flash detected
> NAND: Manufacturer ID: 0x2c Chip ID: 0xd3
> NAND: Page Bytes: 4096, Spare Bytes: 224
> NAND: ECC Correctability Bits: 8, ECC Sector Bytes: 512
> NAND: Disable On-Die ECC
> NAND: Initialize PMECC params, cap: 8, sector: 512
> NAND: Initialize UBI...
> UBI: Loading volume-table 0 at PEB 202 with copy flag!
> NAND: Loading UBI volume kernel kernel-spare to @0x22000000
> (0xffffffff bytes length)...
> UBI: Length of Vol-2 updated to 3128 KB
> NAND: Loading UBI volume dtb dtb-spare to @0x21000000 (0xffffffff
> bytes length)...
> UBI: Length of Vol-0 updated to 33 KB
> 
> Booting zImage ......
> 
> Using device tree in place at 0x210001f4
> DT: Injected MAC addresses
> DT: Populated virtual-eprom
> 
> Starting linux kernel ..., machid: 0xffffffff
> 
> Booting Linux on physical CPU 0x0
> Linux version 5.4.109-00033-ga88943c1e68
> (root at runner-tzue45hw-project-205-concurrent-0) (gcc version 6.5.0
> (Linaro GCC 6.5-2018.12)) #1 Wed Apr 14 18:46:17 CEST 2021
> CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d
> CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
> OF: fdt: Machine model: SMGW
> Memory policy: Data cache writeback
> CPU: All CPU(s) started in SVC mode.
> Built 1 zonelists, mobility grouping on.  Total pages: 32511
> Kernel command line: rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs
> rootflags=auth_hash_name=sha256,auth_key=ubifsauth:0000aaaaffff0000
> Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
> Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
> mem auto-init: stack:off, heap alloc:on, heap free:on
> mem auto-init: clearing system memory may take some time...
> Memory: 121196K/131068K available (5120K kernel code, 197K rwdata,
> 956K rodata, 1024K init, 153K bss, 9872K reserved, 0K cma-reserved)
> NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> random: get_random_bytes called from start_kernel+0x2ec/0x41c with crng_init=0
> master clk is overclocked
> clocksource: pit: mask: 0xfffffff max_cycles: 0xfffffff, max_idle_ns:
> 14479245754 ns
> Console: colour dummy device 80x30
> printk: console [tty0] enabled
> sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every
> 21474836475000000ns
> Calibrating delay loop... 351.43 BogoMIPS (lpj=1757184)
> pid_max: default: 32768 minimum: 301
> Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> CPU: Testing write buffer coherency: ok
> Setting up static identity map for 0x20100000 - 0x2010003c
> devtmpfs: initialized
> VFP support v0.3: implementor 41 architecture 2 part 30 variant 5 rev 1
> clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
> max_idle_ns: 19112604462750000 ns
> futex hash table entries: 256 (order: -1, 3072 bytes, linear)
> pinctrl core: initialized pinctrl subsystem
> NET: Registered protocol family 16
> DMA: preallocated 256 KiB pool for atomic coherent allocations
> cpuidle: using governor ladder
> gpio-at91 fffff200.gpio: at address (ptrval)
> gpio-at91 fffff400.gpio: at address (ptrval)
> gpio-at91 fffff600.gpio: at address (ptrval)
> gpio-at91 fffff800.gpio: at address (ptrval)
> gpio-at91 fffffa00.gpio: at address (ptrval)
> pinctrl-at91 ahb:apb:pinctrl at fffff200: initialized AT91 pinctrl driver
> atmel_tcb f0010000.timer: IRQ index 1 not found
> atmel_tcb f0010000.timer: IRQ index 2 not found
> atmel_tcb f8014000.timer: IRQ index 1 not found
> atmel_tcb f8014000.timer: IRQ index 2 not found
> at_hdmac ffffe600.dma-controller: Atmel AHB DMA Controller ( cpy set
> slave ), 8 channels
> at_hdmac ffffe800.dma-controller: Atmel AHB DMA Controller ( cpy set
> slave ), 8 channels
> AT91: Detected SoC family: sama5d3
> AT91: Detected SoC: sama5d35, revision 2
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> at91_i2c f0014000.i2c: using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
> at91_i2c f0014000.i2c: AT91 i2c bus driver (hw version: 0x402).
> at91_i2c f0018000.i2c: can't get DMA channel, continue without DMA support
> at91_i2c f0018000.i2c: AT91 i2c bus driver (hw version: 0x402).
> clocksource: Switched to clocksource pit
> NET: Registered protocol family 2
> tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
> TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
> TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
> TCP: Hash tables configured (established 1024 bind 1024)
> UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
> UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
> NET: Registered protocol family 1
> Initialise system trusted keyrings
> workingset: timestamp_bits=30 max_order=15 bucket_order=0
> NET: Registered protocol family 38
> Key type asymmetric registered
> Asymmetric key parser 'x509' registered
> atmel_usart_serial.0.auto: ttyS1 at MMIO 0xf001c000 (irq = 21,
> base_baud = 4125000) is a ATMEL_SERIAL
> atmel_usart_serial.1.auto: ttyS2 at MMIO 0xf0020000 (irq = 22,
> base_baud = 8250000) is a ATMEL_SERIAL
> atmel_usart_serial.2.auto: ttyS3 at MMIO 0xf8020000 (irq = 24,
> base_baud = 4125000) is a ATMEL_SERIAL
> atmel_usart_serial.3.auto: ttyS0 at MMIO 0xffffee00 (irq = 32,
> base_baud = 8250000) is a ATMEL_SERIAL
> printk: console [ttyS0] enabled
> atmel_spi f8008000.spi: DMA TX channel not available, SPI unable to use DMA
> atmel_spi f8008000.spi: Atmel SPI Controller using PIO only
> ksz8863 at 0 enforce active low on chipselect handle
> atmel_spi f8008000.spi: Atmel SPI Controller version 0x213 at
> 0xf8008000 (irq 23)
> libphy: Fixed MDIO Bus: probed
> macb f0028000.ethernet: invalid hw address, using random
> random: fast init done
> libphy: MACB_mii_bus: probed
> Generic PHY fixed-0:00: attached PHY driver [Generic PHY]
> (mii_bus:phy_addr=fixed-0:00, irq=POLL)
> macb f0028000.ethernet eth0: Cadence GEM rev 0x00020119 at 0xf0028000
> irq 40 (12:71:da:58:0b:2d)
> libphy: MACB_mii_bus: probed
> Micrel KSZ8081 or KSZ8091 f802c000.ethernet-ffffffff:00: attached PHY
> driver [Micrel KSZ8081 or KSZ8091]
> (mii_bus:phy_addr=f802c000.ethernet-ffffffff:00, irq=45)
> macb f802c000.ethernet eth1: Cadence MACB rev 0x0001010c at 0xf802c000
> irq 41 (d8:c4:97:1c:9a:d7)
> usbcore: registered new interface driver cdc_ether
> usbcore: registered new interface driver cdc_ncm
> usbcore: registered new interface driver cdc_mbim
> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> ehci-platform: EHCI generic platform driver
> ehci-atmel: EHCI Atmel driver
> atmel-ehci 700000.ehci: EHCI Host Controller
> atmel-ehci 700000.ehci: new USB bus registered, assigned bus number 1
> atmel-ehci 700000.ehci: irq 43, io mem 0x00700000
> atmel-ehci 700000.ehci: USB 2.0 started, EHCI 1.00
> usb usb1: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 5.04
> usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb1: Product: EHCI Host Controller
> usb usb1: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ehci_hcd
> usb usb1: SerialNumber: 700000.ehci
> hub 1-0:1.0: USB hub found
> hub 1-0:1.0: 3 ports detected
> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> ohci-platform: OHCI generic platform driver
> ohci-atmel: OHCI Atmel driver
> at91_ohci 600000.ohci: USB Host Controller
> at91_ohci 600000.ohci: new USB bus registered, assigned bus number 2
> at91_ohci 600000.ohci: irq 43, io mem 0x00600000
> usb usb2: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 5.04
> usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> usb usb2: Product: USB Host Controller
> usb usb2: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ohci_hcd
> usb usb2: SerialNumber: at91
> hub 2-0:1.0: USB hub found
> hub 2-0:1.0: 3 ports detected
> usbcore: registered new interface driver cdc_acm
> cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
> usbcore: registered new interface driver cdc_wdm
> usbcore: registered new interface driver usbserial_generic
> usbserial: USB Serial support registered for generic
> usbcore: registered new interface driver option
> usbserial: USB Serial support registered for GSM modem (1-port)
> usbcore: registered new interface driver usb_serial_simple
> usbserial: USB Serial support registered for carelink
> usbserial: USB Serial support registered for zio
> usbserial: USB Serial support registered for funsoft
> usbserial: USB Serial support registered for flashloader
> usbserial: USB Serial support registered for google
> usbserial: USB Serial support registered for libtransistor
> usbserial: USB Serial support registered for vivopay
> usbserial: USB Serial support registered for moto_modem
> usbserial: USB Serial support registered for motorola_tetra
> usbserial: USB Serial support registered for novatel_gps
> usbserial: USB Serial support registered for hp4x
> usbserial: USB Serial support registered for suunto
> usbserial: USB Serial support registered for siemens_mpi
> rtc-rv8803 1-0032: registered as rtc0
> i2c /dev entries driver
> at91-reset fffffe00.rstc: Starting after wakeup
> at91sam9_wdt: enabled (heartbeat=15 sec, nowayout=1)
> atmel_aes f8038000.aes: version: 0x135
> atmel_aes f8038000.aes: Atmel AES - Using dma1chan0, dma1chan1 for DMA transfers
> atmel_sha f8034000.sha: version: 0x410
> atmel_sha f8034000.sha: using dma1chan2 for DMA transfers
> atmel_sha f8034000.sha: Atmel SHA1/SHA256/SHA224/SHA384/SHA512
> atmel_tdes f803c000.tdes: version: 0x701
> atmel_tdes f803c000.tdes: using dma1chan3, dma1chan4 for DMA transfers
> atmel_tdes f803c000.tdes: Atmel DES/TDES
> usbcore: registered new interface driver usbhid
> usbhid: USB HID core driver
> nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xd3
> nand: Micron MT29F8G08ABACAWP
> nand: 1024 MiB, SLC, erase size: 256 KiB, page size: 4096, OOB size: 224
> Bad block table found at page 262080, version 0x01
> Bad block table found at page 262016, version 0x01
> nand_read_bbt: bad block at 0x000000dc0000
> nand_read_bbt: bad block at 0x00000e280000
> nand_read_bbt: bad block at 0x000024f40000
> nand_read_bbt: bad block at 0x000026ec0000
> nand_read_bbt: bad block at 0x000027ec0000
> nand_read_bbt: bad block at 0x00002f140000
> nand_read_bbt: bad block at 0x000030ec0000
> nand_read_bbt: bad block at 0x000033b40000
> nand_read_bbt: bad block at 0x000038840000
> 2 fixed-partitions partitions found on MTD device atmel_nand
> Creating 2 MTD partitions on "atmel_nand":
> 0x000000000000-0x000000040000 : "at91bootstrap"
> 0x000000040000-0x000040000000 : "ubivols"
> NET: Registered protocol family 10
> Segment Routing with IPv6
> sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> NET: Registered protocol family 17
> 8021q: 802.1Q VLAN Support v1.8
> Loading compiled-in X.509 certificates
> Loaded X.509 cert 'EFR: efr.de: a54308f075327fb6c3a6fb687fdabc10ce4c51c6'
> Key type ._fscrypt registered
> Key type .fscrypt registered
> ksz8795-switch spi0.0: active low/falling IRQ
> libphy: dsa slave smi: probed
> ksz8795-switch spi0.0 han (uninitialized): PHY [dsa-0.0:00] driver
> [Micrel KSZ886X Switch]
> ksz8795-switch spi0.0 cls (uninitialized): PHY [dsa-0.0:01] driver
> [Micrel KSZ886X Switch]
> ksz8795-switch spi0.0: Using legacy PHYLIB callbacks. Please migrate to PHYLINK!
> DSA: tree 0 setup
> ubi0: attaching mtd1
> usb 2-3: new full-speed USB device number 2 using at91_ohci
> usb 2-3: New USB device found, idVendor=08e6, idProduct=3437, bcdDevice= 2.01
> usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
> usb 2-3: Product: USB SmartCard Reader
> usb 2-3: Manufacturer: Gemalto
> random: crng init done
> ubi0: scanning is finished
> ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
> ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
> sequence number: 921361235
> ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for
> bad PEB handling: 67
> ubi0: background thread "ubi_bgt0d" started, PID 617
> rtc-rv8803 1-0032: setting system clock to 2021-10-09T12:16:01 UTC (1633781761)
> UBIFS (ubi0:4): Mounting in authenticated mode
> UBIFS (ubi0:4): recovery needed
> VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1

Hmm. -1 is -EPERM.
So some authentification check fails.

Can you find out which -EPERM in fs/ubifs this is?
E.g. by adding a printk() before the return.
Maybe this gives us a clue.

> Please append a correct "root=" boot option; here are the available partitions:
> Kernel panic - not syncing: VFS: Unable to mount root fs on ubi0:rootfs
> CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.109-00033-ga88943c1e68 #1
> Hardware name: Atmel SAMA5
> [<c010babc>] (unwind_backtrace) from [<c010a8d0>] (show_stack+0x10/0x14)
> [<c010a8d0>] (show_stack) from [<c0569970>] (panic+0xfc/0x2e8)
> [<c0569970>] (panic) from [<c0801598>] (mount_block_root+0x268/0x2a4)
> [<c0801598>] (mount_block_root) from [<c0801674>] (prepare_namespace+0x9c/0x184)
> [<c0801674>] (prepare_namespace) from [<c056b774>] (kernel_init+0x8/0x108)
> [<c056b774>] (kernel_init) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> Exception stack(0xc7829fb0 to 0xc7829ff8)
> 9fa0:                                     00000000 00000000 00000000 00000000
> 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on
> ubi0:rootfs ]---
> RomBOOT
> RomBOOT
> 
>>
>> 5.4 is not fresh. Can you use a more recent kernel?
> 
> We are tracking the latest patches on 5.4, but will try whether a
> rebase to 5.10 is straight-forward or not.
> Or at least port the minimal changes which are needed to re-create the crash.
> 
> But first, I will try to reproduce the crash with a stripped down
> program, because with the current tests,
> it can take anywhere between 20-500 iterations of power-cuts with the
> full business logic to trigger the crash.
> (5m ON 30s OFF)

Thanks,
//richard


From u.kleine-koenig at pengutronix.de  Tue Oct 12 08:39:41 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 12 Oct 2021 17:39:41 +0200
Subject: [PATCH v2 16/20] mtd: sst25l: Warn about failure to unregister mtd
 device
In-Reply-To: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20211012153945.2651412-17-u.kleine-koenig@pengutronix.de>

When an spi driver's remove function returns a non-zero error code
nothing happens apart from emitting a generic error message. Make this
error message more device specific and return zero instead.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/devices/sst25l.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index b81c3f0b85f9..04062a1f54c1 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -401,8 +401,14 @@ static int sst25l_probe(struct spi_device *spi)
 static int sst25l_remove(struct spi_device *spi)
 {
 	struct sst25l_flash *flash = spi_get_drvdata(spi);
+	int ret;
+
+	ret = mtd_device_unregister(&flash->mtd);
+	if (ret)
+		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
+			 ERR_PTR(ret));
 
-	return mtd_device_unregister(&flash->mtd);
+	return 0;
 }
 
 static struct spi_driver sst25l_driver = {
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Tue Oct 12 08:39:39 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 12 Oct 2021 17:39:39 +0200
Subject: [PATCH v2 14/20] mtd: mchp23k256: Warn about failure to unregister
 mtd device
In-Reply-To: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20211012153945.2651412-15-u.kleine-koenig@pengutronix.de>

When an spi driver's remove function returns a non-zero error code
nothing happens apart from emitting a generic error message. Make this
error message more device specific and return zero instead.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/devices/mchp23k256.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/devices/mchp23k256.c b/drivers/mtd/devices/mchp23k256.c
index 77c872fd3d83..23213009ebf4 100644
--- a/drivers/mtd/devices/mchp23k256.c
+++ b/drivers/mtd/devices/mchp23k256.c
@@ -212,8 +212,15 @@ static int mchp23k256_probe(struct spi_device *spi)
 static int mchp23k256_remove(struct spi_device *spi)
 {
 	struct mchp23k256_flash *flash = spi_get_drvdata(spi);
+	int ret;
 
-	return mtd_device_unregister(&flash->mtd);
+	ret = mtd_device_unregister(&flash->mtd);
+	if (ret)
+		/* There is nothing we can do about this ... */
+		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
+			 ERR_PTR(ret));
+
+	return 0;
 }
 
 static const struct of_device_id mchp23k256_of_table[] = {
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Tue Oct 12 08:39:38 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 12 Oct 2021 17:39:38 +0200
Subject: [PATCH v2 13/20] mtd: dataflash: Warn about failure to unregister mtd
 device
In-Reply-To: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>

When an spi driver's remove function returns a non-zero error code
nothing happens apart from emitting a generic error message. Make this
error message more device specific and return zero instead.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/devices/mtd_dataflash.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 9802e265fca8..2691b6b79df8 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -919,7 +919,10 @@ static int dataflash_remove(struct spi_device *spi)
 	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0)
 		kfree(flash);
-	return status;
+	else
+		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
+			 ERR_PTR(status));
+	return 0;
 }
 
 static struct spi_driver dataflash_driver = {
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Tue Oct 12 08:39:40 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 12 Oct 2021 17:39:40 +0200
Subject: [PATCH v2 15/20] mtd: mchp48l640: Warn about failure to unregister
 mtd device
In-Reply-To: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20211012153945.2651412-16-u.kleine-koenig@pengutronix.de>

When an spi driver's remove function returns a non-zero error code
nothing happens apart from emitting a generic error message. Make this
error message more device specific and return zero instead.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 drivers/mtd/devices/mchp48l640.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/devices/mchp48l640.c b/drivers/mtd/devices/mchp48l640.c
index 99400d0fb8c1..b87f7eca3e64 100644
--- a/drivers/mtd/devices/mchp48l640.c
+++ b/drivers/mtd/devices/mchp48l640.c
@@ -344,8 +344,14 @@ static int mchp48l640_probe(struct spi_device *spi)
 static int mchp48l640_remove(struct spi_device *spi)
 {
 	struct mchp48l640_flash *flash = spi_get_drvdata(spi);
+	int ret;
+
+	ret = mtd_device_unregister(&flash->mtd);
+	if (ret)
+		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
+			 ERR_PTR(ret));
 
-	return mtd_device_unregister(&flash->mtd);
+	return 0;
 }
 
 static const struct of_device_id mchp48l640_of_table[] = {
-- 
2.30.2



From u.kleine-koenig at pengutronix.de  Tue Oct 12 08:39:25 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Tue, 12 Oct 2021 17:39:25 +0200
Subject: [PATCH v2 00/20] Make some spi device drivers return zero in .remove()
Message-ID: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>

Hello,

this is v2 of my quest to make spi remove callbacks return void. Today
they return an int, but the only result of returning a non-zero value is
a warning message. So it's a bad idea to return an error code in the
expectation that not freeing some resources is ok then. The same holds
true for i2c and platform devices which benefit en passant for a few
drivers.

The patches in this series address some of the spi drivers that might
return non-zero and adapt them accordingly to return zero instead. For
most drivers it's just about not hiding the fact that they already
return zero.

Given that there are quite some more patches of this type to create
before I can change the spi remove callback, I suggest the respective
subsystem maintainers pick up these patches. There are no
interdependencies in this series.

Compared to (implicit) v1

 - I fixed a few compiler issues (this series it build tested with an
   allmoddefconfig on arm64, m68k, powerpc, riscv, s390, sparc64 and
   x86_64).
 - A few new patches (2x gpio, 2x misc, 4x mtd)
 - One patch already landed in next, this one I dropped. The drm/panel
   patch as claimed to applied, too, but not yet in next. It's included
   here, but I assume I was just too impatient and this one should be
   ignored.

Full range-diff below.

Best regards
Uwe

Uwe Kleine-K?nig (20):
  drm/panel: s6e63m0: Make s6e63m0_remove() return void
  gpio: max730x: Make __max730x_remove() return void
  gpio: mc33880: Drop if with an always false condition
  hwmon: max31722: Warn about failure to put device in stand-by in
    .remove()
  input: adxl34xx: Make adxl34x_remove() return void
  input: touchscreen: tsc200x: Make tsc200x_remove() return void
  media: cxd2880: Eliminate dead code
  mfd: mc13xxx: Make mc13xxx_common_exit() return void
  mfd: stmpe: Make stmpe_remove() return void
  mfd: tps65912: Make tps65912_device_exit() return void
  misc: ad525x_dpot: Make ad_dpot_remove() return void
  misc: lis3lv02d: Make lis3lv02d_remove_fs() return void
  mtd: dataflash: Warn about failure to unregister mtd device
  mtd: mchp23k256: Warn about failure to unregister mtd device
  mtd: mchp48l640: Warn about failure to unregister mtd device
  mtd: sst25l: Warn about failure to unregister mtd device
  serial: max310x: Make max310x_remove() return void
  serial: sc16is7xx: Make sc16is7xx_remove() return void
  staging: fbtft: Make fbtft_remove_common() return void
  tpm: st33zp24: Make st33zp24_remove() return void

 drivers/char/tpm/st33zp24/i2c.c                   |  5 +----
 drivers/char/tpm/st33zp24/spi.c                   |  5 +----
 drivers/char/tpm/st33zp24/st33zp24.c              |  3 +--
 drivers/char/tpm/st33zp24/st33zp24.h              |  2 +-
 drivers/gpio/gpio-max7300.c                       |  4 +++-
 drivers/gpio/gpio-max7301.c                       |  4 +++-
 drivers/gpio/gpio-max730x.c                       |  6 +-----
 drivers/gpio/gpio-mc33880.c                       |  2 --
 drivers/gpu/drm/panel/panel-samsung-s6e63m0-dsi.c |  3 ++-
 drivers/gpu/drm/panel/panel-samsung-s6e63m0-spi.c |  3 ++-
 drivers/gpu/drm/panel/panel-samsung-s6e63m0.c     |  4 +---
 drivers/gpu/drm/panel/panel-samsung-s6e63m0.h     |  2 +-
 drivers/hwmon/max31722.c                          |  8 +++++++-
 drivers/input/misc/adxl34x-i2c.c                  |  4 +++-
 drivers/input/misc/adxl34x-spi.c                  |  4 +++-
 drivers/input/misc/adxl34x.c                      |  4 +---
 drivers/input/misc/adxl34x.h                      |  2 +-
 drivers/input/touchscreen/tsc2004.c               |  4 +++-
 drivers/input/touchscreen/tsc2005.c               |  4 +++-
 drivers/input/touchscreen/tsc200x-core.c          |  4 +---
 drivers/input/touchscreen/tsc200x-core.h          |  2 +-
 drivers/media/spi/cxd2880-spi.c                   | 13 +------------
 drivers/mfd/mc13xxx-core.c                        |  4 +---
 drivers/mfd/mc13xxx-i2c.c                         |  3 ++-
 drivers/mfd/mc13xxx-spi.c                         |  3 ++-
 drivers/mfd/mc13xxx.h                             |  2 +-
 drivers/mfd/stmpe-i2c.c                           |  4 +++-
 drivers/mfd/stmpe-spi.c                           |  4 +++-
 drivers/mfd/stmpe.c                               |  4 +---
 drivers/mfd/stmpe.h                               |  2 +-
 drivers/mfd/tps65912-core.c                       |  4 +---
 drivers/mfd/tps65912-i2c.c                        |  4 +++-
 drivers/mfd/tps65912-spi.c                        |  4 +++-
 drivers/misc/ad525x_dpot-i2c.c                    |  3 ++-
 drivers/misc/ad525x_dpot-spi.c                    |  3 ++-
 drivers/misc/ad525x_dpot.c                        |  4 +---
 drivers/misc/ad525x_dpot.h                        |  2 +-
 drivers/misc/lis3lv02d/lis3lv02d.c                |  3 +--
 drivers/misc/lis3lv02d/lis3lv02d.h                |  2 +-
 drivers/misc/lis3lv02d/lis3lv02d_spi.c            |  4 +++-
 drivers/mtd/devices/mchp23k256.c                  |  9 ++++++++-
 drivers/mtd/devices/mchp48l640.c                  |  8 +++++++-
 drivers/mtd/devices/mtd_dataflash.c               |  5 ++++-
 drivers/mtd/devices/sst25l.c                      |  8 +++++++-
 drivers/platform/x86/hp_accel.c                   |  3 ++-
 drivers/staging/fbtft/fbtft-core.c                |  8 +-------
 drivers/staging/fbtft/fbtft.h                     |  8 +++++---
 drivers/tty/serial/max310x.c                      |  7 +++----
 drivers/tty/serial/sc16is7xx.c                    | 12 +++++++-----
 include/linux/mfd/tps65912.h                      |  2 +-
 include/linux/spi/max7301.h                       |  2 +-
 51 files changed, 119 insertions(+), 104 deletions(-)

Range-diff against v1:
 1:  73a1a54d9ea0 =  1:  87fd7940fbfd drm/panel: s6e63m0: Make s6e63m0_remove() return void
 2:  3bcc8e8bd1a3 <  -:  ------------ hwmon: adt7x10: Make adt7x10_remove() return void
 -:  ------------ >  2:  305311d63bbb gpio: max730x: Make __max730x_remove() return void
 -:  ------------ >  3:  0cafc31ea5c5 gpio: mc33880: Drop if with an always false condition
 3:  07f067732aa9 !  4:  f39467b50f06 hwmon: max31722: Warn about failure to put device in stand-by in .remove()
    @@ Commit message
         nothing happens apart from emitting a generic error message. Make this
         error message more device specific and return zero instead.
     
    -    Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
         Acked-by: Michael Hennerich <michael.hennerich at analog.com>
    +    Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
     
      ## drivers/hwmon/max31722.c ##
     @@ drivers/hwmon/max31722.c: static int max31722_probe(struct spi_device *spi)
 4:  0b0a5497d105 =  5:  de3a78214008 input: adxl34xx: Make adxl34x_remove() return void
 5:  0d4f14bc2dd6 !  6:  9629ac3f9e13 input: touchscreen: tsc200x: Make tsc200x_remove() return void
    @@ drivers/input/touchscreen/tsc2005.c: static int tsc2005_probe(struct spi_device
     -	return tsc200x_remove(&spi->dev);
     +	tsc200x_remove(&spi->dev);
     +
    -+	return 0
    ++	return 0;
      }
      
      #ifdef CONFIG_OF
 6:  a68bbd23223b =  7:  1aab41df9262 media: cxd2880: Eliminate dead code
 7:  3801b37ac18f !  8:  745d1a5f840e mfd: mc13xxx: Make mc13xxx_common_exit() return void
    @@ drivers/mfd/mc13xxx-spi.c: static int mc13xxx_spi_probe(struct spi_device *spi)
      {
     -	return mc13xxx_common_exit(&spi->dev);
     +	mc13xxx_common_exit(&spi->dev);
    -+	return 0
    ++	return 0;
      }
      
      static struct spi_driver mc13xxx_spi_driver = {
 8:  22159093ce71 =  9:  7ee04277db66 mfd: stmpe: Make stmpe_remove() return void
 9:  f91da216c752 = 10:  4a21c90a57f8 mfd: tps65912: Make tps65912_device_exit() return void
 -:  ------------ > 11:  f92aa824fd1c misc: ad525x_dpot: Make ad_dpot_remove() return void
 -:  ------------ > 12:  5b2fccd09a24 misc: lis3lv02d: Make lis3lv02d_remove_fs() return void
 -:  ------------ > 13:  609ab18323fc mtd: dataflash: Warn about failure to unregister mtd device
 -:  ------------ > 14:  3b220d5fa547 mtd: mchp23k256: Warn about failure to unregister mtd device
 -:  ------------ > 15:  baf6f4b3a8c7 mtd: mchp48l640: Warn about failure to unregister mtd device
 -:  ------------ > 16:  edf3788a30b0 mtd: sst25l: Warn about failure to unregister mtd device
10:  f2def77b74d1 ! 17:  614f7c001377 serial: max310x: Make max310x_remove() return void
    @@ drivers/tty/serial/max310x.c: static int max310x_spi_probe(struct spi_device *sp
      {
     -	return max310x_remove(&spi->dev);
     +	max310x_remove(&spi->dev);
    -+	return 0
    ++	return 0;
      }
      
      static const struct spi_device_id max310x_id_table[] = {
11:  283e4bbeff38 ! 18:  35d1f5b36de5 serial: sc16is7xx: Make sc16is7xx_remove() return void
    @@ drivers/tty/serial/sc16is7xx.c: static int sc16is7xx_probe(struct device *dev,
      {
      	struct sc16is7xx_port *s = dev_get_drvdata(dev);
      	int i;
    +@@ drivers/tty/serial/sc16is7xx.c: static int sc16is7xx_remove(struct device *dev)
    + 	kthread_stop(s->kworker_task);
    + 
    + 	clk_disable_unprepare(s->clk);
    +-
    +-	return 0;
    + }
    + 
    + static const struct of_device_id __maybe_unused sc16is7xx_dt_ids[] = {
     @@ drivers/tty/serial/sc16is7xx.c: static int sc16is7xx_spi_probe(struct spi_device *spi)
      
      static int sc16is7xx_spi_remove(struct spi_device *spi)
12:  5093fbdceee5 ! 19:  d9ec9a96fbb8 staging: fbtft: Make fbtft_remove_common() return void
    @@ drivers/staging/fbtft/fbtft-core.c: EXPORT_SYMBOL(fbtft_probe_common);
      
     
      ## drivers/staging/fbtft/fbtft.h ##
    +@@ drivers/staging/fbtft/fbtft.h: void fbtft_unregister_backlight(struct fbtft_par *par);
    + int fbtft_init_display(struct fbtft_par *par);
    + int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
    + 		       struct platform_device *pdev);
    +-int fbtft_remove_common(struct device *dev, struct fb_info *info);
    ++void fbtft_remove_common(struct device *dev, struct fb_info *info);
    + 
    + /* fbtft-io.c */
    + int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
     @@ drivers/staging/fbtft/fbtft.h: static int fbtft_driver_remove_spi(struct spi_device *spi)                 \
      {                                                                          \
      	struct fb_info *info = spi_get_drvdata(spi);                       \
13:  9156e6380a5e = 20:  89d0b85968a9 tpm: st33zp24: Make st33zp24_remove() return void

base-commit: 9e1ff307c779ce1f0f810c7ecce3d95bbae40896
-- 
2.30.2



From p.yadav at ti.com  Tue Oct 12 11:24:46 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Tue, 12 Oct 2021 23:54:46 +0530
Subject: nvmem: Defining cells on mtd created by mtdparts
In-Reply-To: <14722734.oMan5NXi5u@sven-desktop>
References: <18728084.NGlc0Rocea@sven-desktop>
 <14722734.oMan5NXi5u@sven-desktop>
Message-ID: <20211012182444.qrn3lzp7vukklwlx@ti.com>

Hi Sven,

On 11/10/21 09:06AM, Sven Eckelmann wrote:
> On Sunday, 10 October 2021 14:53:13 CEST Sven Eckelmann wrote:
> [...]
> > Since there are most likely more devices out there which use mtdparts, I would 
> > guess that there might already be a strategy out there which can be used to 
> > define the nvmem-provider for mtdparts defined partitions. At least I saw that 
> > Bartosz Golaszewski added all the mtd devices automatically as nvmem provider 
> > in c4dfa25ab307 ("mtd: add support for reading MTD devices via the nvmem 
> > API"). So there might also be something for nvmem-cells to find the correct 
> > mtd instead of relying on the fixed-partitions registration + of_node (which 
> > doesn't exist because it comes from mtdparts and not devicetree).

I have been wanting to fix this problem for a while but just never got 
around to it. I was thinking about either extending the mtdparts syntax 
to maybe add nvmem cell information in there or adding a separate 
cmdline argument that complements mtdparts with nvmem cell info. Dunno 
if either of these would work well though...

> 
> Ansuel Smith just proposed in OpenWrt [1] a workaround. It basically adds a 
> minimal fixed-partitions parser to the mtd cmdlinepart parser (responsible for 
> the mtdparts=) that tries to find the matching (size + offset) fixed-partition 
> from the devicetree. The code in mtd_device_parse_register
> (add_mtd_partitions -> add_mtd_device -> mtd_nvmem_add) will then 
> automatically take care of the rest.

I don't quite see how this helps. You say that some devices don't have a 
device tree at all so how would you even match the fixed partition? And 
this of course doesn't solve the problem where you might want nvmem 
cells with a partition layout that is different from the one in device 
tree.

I unfortunately don't really have any answers for this at this point, 
but maybe I can figure something out in the future...

> 
> Kind regards,
> 	Sven
> 
> [1] https://github.com/openwrt/openwrt/pull/4664#issuecomment-939567963



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


-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From mauro.lima at eclypsium.com  Tue Oct 12 11:49:22 2021
From: mauro.lima at eclypsium.com (Mauro Lima)
Date: Tue, 12 Oct 2021 15:49:22 -0300
Subject: [PATCH 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <YVqOjF/xjqFV+Dl3@lahna>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-2-mika.westerberg@linux.intel.com>
 <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>
 <YVqOjF/xjqFV+Dl3@lahna>
Message-ID: <CAArk9MPY+rCQse+JXtvb4KqunN9FZ=toK_v=PV-ro4cO6=5s7Q@mail.gmail.com>

Hi Mika

On Mon, Oct 4, 2021 at 2:18 AM Mika Westerberg
<mika.westerberg at linux.intel.com> wrote:
>
> Hi,
>
> On Fri, Oct 01, 2021 at 05:23:23PM -0300, Mauro Lima wrote:
> > Question for maintainers: With these changes is it safe to remove the
> > *(DANGEROUS)* tag from menuconfig?
>
> I don't think we want to remove that. This driver is not for regular
> users, at least in its current form.
Do we know why this is still dangerous for the user?
My plan is to make a sys/class driver to query write protection status
of the SPI, this will be
used by fwupd to gather information about vendors, also should be easy
for the user to use
'cat' and see the information from userspace. For this to be possible
we need kernel engineers
to compile the kernel with this driver enabled, but the (DANGEROUS)
tag is a no go for most
of them.
Is there anything I can do to make this possible?
Thanks


From sven at narfation.org  Tue Oct 12 11:59:29 2021
From: sven at narfation.org (Sven Eckelmann)
Date: Tue, 12 Oct 2021 20:59:29 +0200
Subject: nvmem: Defining cells on mtd created by mtdparts
In-Reply-To: <20211012182444.qrn3lzp7vukklwlx@ti.com>
References: <18728084.NGlc0Rocea@sven-desktop>
 <14722734.oMan5NXi5u@sven-desktop> <20211012182444.qrn3lzp7vukklwlx@ti.com>
Message-ID: <51067395.yQmhhqxHrA@sven-l14>

On Tuesday, 12 October 2021 20:24:46 CEST Pratyush Yadav wrote:
[...]
> I have been wanting to fix this problem for a while but just never got 
> around to it. I was thinking about either extending the mtdparts syntax 
> to maybe add nvmem cell information in there or adding a separate 
> cmdline argument that complements mtdparts with nvmem cell info. Dunno 
> if either of these would work well though...

At least for the devices I have in mind, this doesn't seem to be a good 
solution. The devices are shipped since years and the bootloader isn't updated 
with firmware updates. So changing to a different mtdparts might sometimes not 
be easily possible.

But this might help in situations which don't have this limitation.

> > Ansuel Smith just proposed in OpenWrt [1] a workaround. It basically adds a 
> > minimal fixed-partitions parser to the mtd cmdlinepart parser (responsible for 
> > the mtdparts=) that tries to find the matching (size + offset) fixed-partition 
> > from the devicetree. The code in mtd_device_parse_register
> > (add_mtd_partitions -> add_mtd_device -> mtd_nvmem_add) will then 
> > automatically take care of the rest.
> 
> I don't quite see how this helps. You say that some devices don't have a 
> device tree at all so how would you even match the fixed partition? And 
> this of course doesn't solve the problem where you might want nvmem 
> cells with a partition layout that is different from the one in device 
> tree.

I personally had a different thing in mind. The situation for OpenWrt's ath79 
target (and Linux's ath79) is that they use DTs and some of these devices are 
still using some information which are not part of the device tree. But the
DT partitions for the nvmem-cells MUST match the ones in mtdparts

But you are right, this will definitely not solve situations when there is no 
DT used. And didn't say that I needed a solution for this - I was (hopefully) 
always referring to devices which use mtdparts (which can also be used with 
devices which are using DTs)

Kind regards,
	Sven
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211012/77510863/attachment.sig>

From andriy.shevchenko at linux.intel.com  Tue Oct 12 12:07:45 2021
From: andriy.shevchenko at linux.intel.com (Andy Shevchenko)
Date: Tue, 12 Oct 2021 22:07:45 +0300
Subject: [PATCH v2 0/3] mtd: spi-nor / spi / MFD: Convert intel-spi to
 SPI MEM
In-Reply-To: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
Message-ID: <YWXdAc/rzyhqxl0b@smile.fi.intel.com>

On Thu, Oct 07, 2021 at 02:21:29PM +0300, Mika Westerberg wrote:
> Hi all,
> 
> Based on discussion on the patch I sent some time ago here:
> 
>   http://lists.infradead.org/pipermail/linux-mtd/2021-June/086867.html
> 
> it turns out that the preferred way to deal with the SPI flash controller
> drivers is through SPI MEM which is part of Linux SPI subsystem.
> 
> This series does that for the intel-spi driver. This also renames the
> driver to follow the convention used in the SPI subsystem. The first patch
> improves the write protection handling to be slightly more safer. The
> following two patches do the conversion itself. Note the Intel SPI flash
> controller only allows commands such as read, write and so on and it
> internally uses whatever addressing etc. it figured from the SFDP on the
> flash device.
> 
> Previous version of the patch series can be found here:
> 
>   https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/
> 
> Changes from the previous version:
> 
>   * Arrange dependencies in Kconfig entries the same way in both glue
>     drivers.
>   * Added empty lines between different subsystem includes.
>   * dev_err() to single line
>   * Return intel_spi_sw_cycle() directly in intel_spi_erase().
>   * Drop redundant elses.
>   * Fixed typo in the commit message of the patch 3/3.

FWIW,
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>

> Mika Westerberg (3):
>   mtd: spi-nor: intel-spi: Disable write protection only if asked
>   mtd: spi-nor: intel-spi: Convert to SPI MEM
>   Documentation / MTD: Rename the intel-spi driver
> 
>  Documentation/driver-api/mtd/index.rst        |   2 +-
>  .../mtd/{intel-spi.rst => spi-intel.rst}      |   8 +-
>  drivers/mfd/lpc_ich.c                         |  59 ++-
>  drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
>  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
>  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
>  drivers/spi/Kconfig                           |  39 ++
>  drivers/spi/Makefile                          |   3 +
>  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  49 ++-
>  .../spi-intel-platform.c}                     |  21 +-
>  .../intel-spi.c => spi/spi-intel.c}           | 345 ++++++++++--------
>  drivers/spi/spi-intel.h                       |  19 +
>  include/linux/mfd/lpc_ich.h                   |   2 +-
>  .../x86/{intel-spi.h => spi-intel.h}          |  12 +-
>  14 files changed, 355 insertions(+), 264 deletions(-)
>  rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)
>  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (84%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (78%)
>  create mode 100644 drivers/spi/spi-intel.h
>  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (64%)
> 
> -- 
> 2.33.0
> 

-- 
With Best Regards,
Andy Shevchenko




From han.xu at nxp.com  Tue Oct 12 22:01:48 2021
From: han.xu at nxp.com (Han Xu)
Date: Wed, 13 Oct 2021 00:01:48 -0500
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211012090224.4101984-2-s.riedmueller@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
Message-ID: <20211013050148.2w373kpbfaeuxbwm@umbrella>

On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> when doing a gpmi_io clk rate change. So gate the clocks off before
> the rate change in nfc_apply_timings and ungate them again after the
> change.
> 
> Otherwise this rate change can lead to an unresponsive GPMI core which
> results in DMA timeouts and failed driver probe:
> 
> [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> ...
> [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> ...
> [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
> [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> ...
> 
> Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> ---
> Hi,
> 
> I'm not sure about the error handling here, if it is actually neccessary.
> So some feedback would be nice here.
> 
> Thanks,
> Stefan
> ---
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index a1f7000f033e..326c8a895f1f 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>  			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
>  }
>  
> -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
>  {
>  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
>  	struct resources *r = &this->resources;
>  	void __iomem *gpmi_regs = r->gpmi_regs;
>  	unsigned int dll_wait_time_us;
> +	int ret;
> +
> +	if (GPMI_IS_MX6Q(this)) {

Not only for 6Q but for GPMI_IS_MX6

> +		ret = __gpmi_enable_clk(this, false);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	clk_set_rate(r->clock[0], hw->clk_rate);
>  
> +	if (GPMI_IS_MX6Q(this)) {
> +		ret = __gpmi_enable_clk(this, true);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
>  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
>  
> @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
>  
>  	/* Wait for the DLL to settle. */
>  	udelay(dll_wait_time_us);
> +
> +	return 0;
>  }
>  
>  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
>  	 */
>  	if (this->hw.must_apply_timings) {
>  		this->hw.must_apply_timings = false;
> -		gpmi_nfc_apply_timings(this);
> +		ret = gpmi_nfc_apply_timings(this);
> +		if (ret)
> +			return ret;
>  	}
>  
>  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
> -- 
> 2.25.1
> 


From hch at lst.de  Tue Oct 12 22:10:13 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:13 +0200
Subject: don't use ->bd_inode to access the block device size
Message-ID: <20211013051042.1065752-1-hch@lst.de>

Hi Jens,

various drivers currently poke directy at the block device inode, which
is a bit of a mess.  This series cleans up the places that read the
block device size to use the proper helpers.  I have separate patches
for many of the other bd_inode uses, but this series is already big
enough as-is,

I wondered about adding a helper for looking at the size in byte units
to avoid the SECTOR_SHIFT shifts in various places.  But given that
I could not come up with a good name and block devices fundamentally
work in sector size granularity I decided against that.

Diffstat:
 block/fops.c                        |    2 +-
 drivers/block/drbd/drbd_int.h       |    3 +--
 drivers/md/bcache/super.c           |    2 +-
 drivers/md/bcache/util.h            |    4 ----
 drivers/md/bcache/writeback.c       |    2 +-
 drivers/md/dm-bufio.c               |    2 +-
 drivers/md/dm-cache-metadata.c      |    2 +-
 drivers/md/dm-cache-target.c        |    2 +-
 drivers/md/dm-clone-target.c        |    2 +-
 drivers/md/dm-dust.c                |    5 ++---
 drivers/md/dm-ebs-target.c          |    2 +-
 drivers/md/dm-era-target.c          |    2 +-
 drivers/md/dm-exception-store.h     |    2 +-
 drivers/md/dm-flakey.c              |    3 +--
 drivers/md/dm-integrity.c           |    6 +++---
 drivers/md/dm-linear.c              |    3 +--
 drivers/md/dm-log-writes.c          |    4 ++--
 drivers/md/dm-log.c                 |    2 +-
 drivers/md/dm-mpath.c               |    2 +-
 drivers/md/dm-raid.c                |    6 +++---
 drivers/md/dm-switch.c              |    2 +-
 drivers/md/dm-table.c               |    3 +--
 drivers/md/dm-thin-metadata.c       |    2 +-
 drivers/md/dm-thin.c                |    2 +-
 drivers/md/dm-verity-target.c       |    3 +--
 drivers/md/dm-writecache.c          |    2 +-
 drivers/md/dm-zoned-target.c        |    2 +-
 drivers/md/md.c                     |   26 +++++++++++---------------
 drivers/mtd/devices/block2mtd.c     |    5 +++--
 drivers/nvme/target/io-cmd-bdev.c   |    4 ++--
 drivers/target/target_core_iblock.c |    5 +++--
 fs/affs/super.c                     |    2 +-
 fs/btrfs/dev-replace.c              |    2 +-
 fs/btrfs/disk-io.c                  |    3 ++-
 fs/btrfs/ioctl.c                    |    4 ++--
 fs/btrfs/volumes.c                  |    7 ++++---
 fs/buffer.c                         |    4 ++--
 fs/cramfs/inode.c                   |    2 +-
 fs/ext4/super.c                     |    2 +-
 fs/fat/inode.c                      |    5 +----
 fs/hfs/mdb.c                        |    2 +-
 fs/hfsplus/wrapper.c                |    2 +-
 fs/jfs/resize.c                     |    5 ++---
 fs/jfs/super.c                      |    5 ++---
 fs/nfs/blocklayout/dev.c            |    4 ++--
 fs/nilfs2/ioctl.c                   |    2 +-
 fs/nilfs2/super.c                   |    2 +-
 fs/nilfs2/the_nilfs.c               |    3 ++-
 fs/ntfs/super.c                     |    8 +++-----
 fs/ntfs3/super.c                    |    3 +--
 fs/pstore/blk.c                     |    4 ++--
 fs/reiserfs/super.c                 |    7 ++-----
 fs/squashfs/super.c                 |    5 +++--
 fs/udf/lowlevel.c                   |    5 ++---
 fs/udf/super.c                      |    9 +++------
 include/linux/genhd.h               |    6 ++++++
 56 files changed, 100 insertions(+), 117 deletions(-)


From hch at lst.de  Tue Oct 12 22:10:14 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:14 +0200
Subject: [PATCH 01/29] bcache: remove bdev_sectors
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-2-hch@lst.de>

Use the equivalent block layer helper instead.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/md/bcache/super.c     | 2 +-
 drivers/md/bcache/util.h      | 4 ----
 drivers/md/bcache/writeback.c | 2 +-
 3 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index f2874c77ff797..4f89985abe4b7 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1002,7 +1002,7 @@ static void calc_cached_dev_sectors(struct cache_set *c)
 	struct cached_dev *dc;
 
 	list_for_each_entry(dc, &c->cached_devs, list)
-		sectors += bdev_sectors(dc->bdev);
+		sectors += bdev_nr_sectors(dc->bdev);
 
 	c->cached_dev_sectors = sectors;
 }
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index b64460a762677..a7da7930a7fda 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -584,8 +584,4 @@ static inline unsigned int fract_exp_two(unsigned int x,
 void bch_bio_map(struct bio *bio, void *base);
 int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask);
 
-static inline sector_t bdev_sectors(struct block_device *bdev)
-{
-	return bdev->bd_inode->i_size >> 9;
-}
 #endif /* _BCACHE_UTIL_H */
diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
index 8120da278161e..c7560f66dca88 100644
--- a/drivers/md/bcache/writeback.c
+++ b/drivers/md/bcache/writeback.c
@@ -45,7 +45,7 @@ static uint64_t __calc_target_rate(struct cached_dev *dc)
 	 * backing volume uses about 2% of the cache for dirty data.
 	 */
 	uint32_t bdev_share =
-		div64_u64(bdev_sectors(dc->bdev) << WRITEBACK_SHARE_SHIFT,
+		div64_u64(bdev_nr_sectors(dc->bdev) << WRITEBACK_SHARE_SHIFT,
 				c->cached_dev_sectors);
 
 	uint64_t cache_dirty_target =
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:15 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:15 +0200
Subject: [PATCH 02/29] drbd: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-3-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/block/drbd/drbd_int.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 5d9181382ce19..75fda53eed8cf 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1826,8 +1826,7 @@ static inline sector_t drbd_md_last_sector(struct drbd_backing_dev *bdev)
 /* Returns the number of 512 byte sectors of the device */
 static inline sector_t drbd_get_capacity(struct block_device *bdev)
 {
-	/* return bdev ? get_capacity(bdev->bd_disk) : 0; */
-	return bdev ? i_size_read(bdev->bd_inode) >> 9 : 0;
+	return bdev ? bdev_nr_sectors(bdev) : 0;
 }
 
 /**
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:16 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:16 +0200
Subject: [PATCH 03/29] dm: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-4-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/md/dm-bufio.c           | 2 +-
 drivers/md/dm-cache-metadata.c  | 2 +-
 drivers/md/dm-cache-target.c    | 2 +-
 drivers/md/dm-clone-target.c    | 2 +-
 drivers/md/dm-dust.c            | 5 ++---
 drivers/md/dm-ebs-target.c      | 2 +-
 drivers/md/dm-era-target.c      | 2 +-
 drivers/md/dm-exception-store.h | 2 +-
 drivers/md/dm-flakey.c          | 3 +--
 drivers/md/dm-integrity.c       | 6 +++---
 drivers/md/dm-linear.c          | 3 +--
 drivers/md/dm-log-writes.c      | 4 ++--
 drivers/md/dm-log.c             | 2 +-
 drivers/md/dm-mpath.c           | 2 +-
 drivers/md/dm-raid.c            | 6 +++---
 drivers/md/dm-switch.c          | 2 +-
 drivers/md/dm-table.c           | 3 +--
 drivers/md/dm-thin-metadata.c   | 2 +-
 drivers/md/dm-thin.c            | 2 +-
 drivers/md/dm-verity-target.c   | 3 +--
 drivers/md/dm-writecache.c      | 2 +-
 drivers/md/dm-zoned-target.c    | 2 +-
 22 files changed, 28 insertions(+), 33 deletions(-)

diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 50f3e673729c3..104ebc1f08dcc 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -1525,7 +1525,7 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_size);
 
 sector_t dm_bufio_get_device_size(struct dm_bufio_client *c)
 {
-	sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT;
+	sector_t s = bdev_nr_sectors(c->bdev);
 	if (s >= c->start)
 		s -= c->start;
 	else
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c
index 89a73204dbf47..2874f222c3138 100644
--- a/drivers/md/dm-cache-metadata.c
+++ b/drivers/md/dm-cache-metadata.c
@@ -334,7 +334,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
 	int r;
 	struct dm_block *sblock;
 	struct cache_disk_superblock *disk_super;
-	sector_t bdev_size = i_size_read(cmd->bdev->bd_inode) >> SECTOR_SHIFT;
+	sector_t bdev_size = bdev_nr_sectors(cmd->bdev);
 
 	/* FIXME: see if we can lose the max sectors limit */
 	if (bdev_size > DM_CACHE_METADATA_MAX_SECTORS)
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index bdd500447dea2..447d030036d18 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -1940,7 +1940,7 @@ static void cache_dtr(struct dm_target *ti)
 
 static sector_t get_dev_size(struct dm_dev *dev)
 {
-	return i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(dev->bdev);
 }
 
 /*----------------------------------------------------------------*/
diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c
index 84dbe08ad2053..e4bb2fde1b54f 100644
--- a/drivers/md/dm-clone-target.c
+++ b/drivers/md/dm-clone-target.c
@@ -1514,7 +1514,7 @@ static void clone_status(struct dm_target *ti, status_type_t type,
 
 static sector_t get_dev_size(struct dm_dev *dev)
 {
-	return i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(dev->bdev);
 }
 
 /*---------------------------------------------------------------------------*/
diff --git a/drivers/md/dm-dust.c b/drivers/md/dm-dust.c
index 3163e2b1418e7..03672204b0e38 100644
--- a/drivers/md/dm-dust.c
+++ b/drivers/md/dm-dust.c
@@ -415,7 +415,7 @@ static int dust_message(struct dm_target *ti, unsigned int argc, char **argv,
 			char *result, unsigned int maxlen)
 {
 	struct dust_device *dd = ti->private;
-	sector_t size = i_size_read(dd->dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	sector_t size = bdev_nr_sectors(dd->dev->bdev);
 	bool invalid_msg = false;
 	int r = -EINVAL;
 	unsigned long long tmp, block;
@@ -544,8 +544,7 @@ static int dust_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (dd->start ||
-	    ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+	if (dd->start || ti->len != bdev_nr_sectors(dev->bdev))
 		return 1;
 
 	return 0;
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index d25989660a768..7ce5d509b9403 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -416,7 +416,7 @@ static int ebs_prepare_ioctl(struct dm_target *ti, struct block_device **bdev)
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
 	*bdev = dev->bdev;
-	return !!(ec->start || ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT);
+	return !!(ec->start || ti->len != bdev_nr_sectors(dev->bdev));
 }
 
 static void ebs_io_hints(struct dm_target *ti, struct queue_limits *limits)
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 2a78f68741431..1f6bf152b3c74 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -1681,7 +1681,7 @@ static int era_message(struct dm_target *ti, unsigned argc, char **argv,
 
 static sector_t get_dev_size(struct dm_dev *dev)
 {
-	return i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(dev->bdev);
 }
 
 static int era_iterate_devices(struct dm_target *ti,
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index 3f4139ac1f602..b5f20eba36415 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -168,7 +168,7 @@ static inline void dm_consecutive_chunk_count_dec(struct dm_exception *e)
  */
 static inline sector_t get_dev_size(struct block_device *bdev)
 {
-	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(bdev);
 }
 
 static inline chunk_t sector_to_chunk(struct dm_exception_store *store,
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 4b94ffe6f2d4f..345229d7e59c1 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -456,8 +456,7 @@ static int flakey_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (fc->start ||
-	    ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+	if (fc->start || ti->len != bdev_nr_sectors((*bdev)))
 		return 1;
 	return 0;
 }
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index dc03b70f6e65c..d0f788e72abf9 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -4113,11 +4113,11 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 		}
 	}
 
-	ic->data_device_sectors = i_size_read(ic->dev->bdev->bd_inode) >> SECTOR_SHIFT;
+	ic->data_device_sectors = bdev_nr_sectors(ic->dev->bdev);
 	if (!ic->meta_dev)
 		ic->meta_device_sectors = ic->data_device_sectors;
 	else
-		ic->meta_device_sectors = i_size_read(ic->meta_dev->bdev->bd_inode) >> SECTOR_SHIFT;
+		ic->meta_device_sectors = bdev_nr_sectors(ic->meta_dev->bdev);
 
 	if (!journal_sectors) {
 		journal_sectors = min((sector_t)DEFAULT_MAX_JOURNAL_SECTORS,
@@ -4367,7 +4367,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 	DEBUG_print("	journal_sections %u\n", (unsigned)le32_to_cpu(ic->sb->journal_sections));
 	DEBUG_print("	journal_entries %u\n", ic->journal_entries);
 	DEBUG_print("	log2_interleave_sectors %d\n", ic->sb->log2_interleave_sectors);
-	DEBUG_print("	data_device_sectors 0x%llx\n", i_size_read(ic->dev->bdev->bd_inode) >> SECTOR_SHIFT);
+	DEBUG_print("	data_device_sectors 0x%llx\n", bdev_nr_sectors(ic->dev->bdev));
 	DEBUG_print("	initial_sectors 0x%x\n", ic->initial_sectors);
 	DEBUG_print("	metadata_run 0x%x\n", ic->metadata_run);
 	DEBUG_print("	log2_metadata_run %d\n", ic->log2_metadata_run);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 679b4c0a2eea1..66ba16713f696 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -135,8 +135,7 @@ static int linear_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (lc->start ||
-	    ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+	if (lc->start || ti->len != bdev_nr_sectors(dev->bdev))
 		return 1;
 	return 0;
 }
diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c
index d93a4db235124..46de085a96709 100644
--- a/drivers/md/dm-log-writes.c
+++ b/drivers/md/dm-log-writes.c
@@ -446,7 +446,7 @@ static int log_super(struct log_writes_c *lc)
 
 static inline sector_t logdev_last_sector(struct log_writes_c *lc)
 {
-	return i_size_read(lc->logdev->bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(lc->logdev->bdev);
 }
 
 static int log_writes_kthread(void *arg)
@@ -851,7 +851,7 @@ static int log_writes_prepare_ioctl(struct dm_target *ti,
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+	if (ti->len != bdev_nr_sectors(dev->bdev))
 		return 1;
 	return 0;
 }
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 1ecf75ef276a4..a24d87aa7f556 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -447,7 +447,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti,
 				bdev_logical_block_size(lc->header_location.
 							    bdev));
 
-		if (buf_size > i_size_read(dev->bdev->bd_inode)) {
+		if (buf_size > (bdev_nr_sectors(dev->bdev) << SECTOR_SHIFT)) {
 			DMWARN("log device %s too small: need %llu bytes",
 				dev->name, (unsigned long long)buf_size);
 			kfree(lc);
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 694aaca4eea24..5794f5415155d 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -2061,7 +2061,7 @@ static int multipath_prepare_ioctl(struct dm_target *ti,
 	/*
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
-	if (!r && ti->len != i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+	if (!r && ti->len != bdev_nr_sectors((*bdev)))
 		return 1;
 	return r;
 }
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index d9ef52159a22b..2b26435a6946e 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -1261,7 +1261,7 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as,
 			md_rdev_init(jdev);
 			jdev->mddev = &rs->md;
 			jdev->bdev = rs->journal_dev.dev->bdev;
-			jdev->sectors = to_sector(i_size_read(jdev->bdev->bd_inode));
+			jdev->sectors = bdev_nr_sectors(jdev->bdev);
 			if (jdev->sectors < MIN_RAID456_JOURNAL_SPACE) {
 				rs->ti->error = "No space for raid4/5/6 journal";
 				return -ENOSPC;
@@ -1607,7 +1607,7 @@ static int _check_data_dev_sectors(struct raid_set *rs)
 
 	rdev_for_each(rdev, &rs->md)
 		if (!test_bit(Journal, &rdev->flags) && rdev->bdev) {
-			ds = min(ds, to_sector(i_size_read(rdev->bdev->bd_inode)));
+			ds = min(ds, bdev_nr_sectors(rdev->bdev));
 			if (ds < rs->md.dev_sectors) {
 				rs->ti->error = "Component device(s) too small";
 				return -EINVAL;
@@ -2662,7 +2662,7 @@ static int rs_adjust_data_offsets(struct raid_set *rs)
 	 * Make sure we got a minimum amount of free sectors per device
 	 */
 	if (rs->data_offset &&
-	    to_sector(i_size_read(rdev->bdev->bd_inode)) - rs->md.dev_sectors < MIN_FREE_RESHAPE_SPACE) {
+	    bdev_nr_sectors(rdev->bdev) - rs->md.dev_sectors < MIN_FREE_RESHAPE_SPACE) {
 		rs->ti->error = data_offset ? "No space for forward reshape" :
 					      "No space for backward reshape";
 		return -ENOSPC;
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 028a92ff6d576..534dc2ca8bb06 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -529,7 +529,7 @@ static int switch_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 	 * Only pass ioctls through if the device sizes match exactly.
 	 */
 	if (ti->len + sctx->path_list[path_nr].start !=
-	    i_size_read((*bdev)->bd_inode) >> SECTOR_SHIFT)
+	    bdev_nr_sectors((*bdev)))
 		return 1;
 	return 0;
 }
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 1fa4d5582dca5..d95142102bd25 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -227,8 +227,7 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
 {
 	struct queue_limits *limits = data;
 	struct block_device *bdev = dev->bdev;
-	sector_t dev_size =
-		i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	sector_t dev_size = bdev_nr_sectors(bdev);
 	unsigned short logical_block_size_sectors =
 		limits->logical_block_size >> SECTOR_SHIFT;
 	char b[BDEVNAME_SIZE];
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index c88ed14d49e65..1a96a07cbf443 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -549,7 +549,7 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
 	int r;
 	struct dm_block *sblock;
 	struct thin_disk_superblock *disk_super;
-	sector_t bdev_size = i_size_read(pmd->bdev->bd_inode) >> SECTOR_SHIFT;
+	sector_t bdev_size = bdev_nr_sectors(pmd->bdev);
 
 	if (bdev_size > THIN_METADATA_MAX_SECTORS)
 		bdev_size = THIN_METADATA_MAX_SECTORS;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 4c67b77c23c1b..ec119d2422d5d 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -3212,7 +3212,7 @@ static int metadata_pre_commit_callback(void *context)
 
 static sector_t get_dev_size(struct block_device *bdev)
 {
-	return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	return bdev_nr_sectors(bdev);
 }
 
 static void warn_if_metadata_device_too_big(struct block_device *bdev)
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index 88e2702b473b0..4651859d4233b 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -825,8 +825,7 @@ static int verity_prepare_ioctl(struct dm_target *ti, struct block_device **bdev
 
 	*bdev = v->data_dev->bdev;
 
-	if (v->data_start ||
-	    ti->len != i_size_read(v->data_dev->bdev->bd_inode) >> SECTOR_SHIFT)
+	if (v->data_start || ti->len != bdev_nr_sectors(v->data_dev->bdev))
 		return 1;
 	return 0;
 }
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
index 18320444fb0a9..339f2319ae65a 100644
--- a/drivers/md/dm-writecache.c
+++ b/drivers/md/dm-writecache.c
@@ -2341,7 +2341,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
 		ti->error = "Cache data device lookup failed";
 		goto bad;
 	}
-	wc->memory_map_size = i_size_read(wc->ssd_dev->bdev->bd_inode);
+	wc->memory_map_size = bdev_nr_sectors(wc->ssd_dev->bdev) << SECTOR_SHIFT;
 
 	/*
 	 * Parse the cache block size
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index ae1bc48c0043d..8dc21c09329f2 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -733,7 +733,7 @@ static int dmz_get_zoned_device(struct dm_target *ti, char *path,
 	dev->dev_idx = idx;
 	(void)bdevname(dev->bdev, dev->name);
 
-	dev->capacity = i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
+	dev->capacity = bdev_nr_sectors(bdev);
 	if (ti->begin) {
 		ti->error = "Partial mapping is not supported";
 		goto err;
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:17 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:17 +0200
Subject: [PATCH 04/29] md: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-5-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/md/md.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/md/md.c b/drivers/md/md.c
index ec09083ff0eff..9b4f4bf349120 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -890,8 +890,7 @@ static struct md_personality *find_pers(int level, char *clevel)
 /* return the offset of the super block in 512byte sectors */
 static inline sector_t calc_dev_sboffset(struct md_rdev *rdev)
 {
-	sector_t num_sectors = i_size_read(rdev->bdev->bd_inode) / 512;
-	return MD_NEW_SIZE_SECTORS(num_sectors);
+	return MD_NEW_SIZE_SECTORS(bdev_nr_sectors(rdev->bdev));
 }
 
 static int alloc_disk_sb(struct md_rdev *rdev)
@@ -1633,8 +1632,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
 	 */
 	switch(minor_version) {
 	case 0:
-		sb_start = i_size_read(rdev->bdev->bd_inode) >> 9;
-		sb_start -= 8*2;
+		sb_start = bdev_nr_sectors(rdev->bdev) - 8 * 2;
 		sb_start &= ~(sector_t)(4*2-1);
 		break;
 	case 1:
@@ -1789,10 +1787,9 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_
 		else
 			ret = 0;
 	}
-	if (minor_version) {
-		sectors = (i_size_read(rdev->bdev->bd_inode) >> 9);
-		sectors -= rdev->data_offset;
-	} else
+	if (minor_version)
+		sectors = bdev_nr_sectors(rdev->bdev) - rdev->data_offset;
+	else
 		sectors = rdev->sb_start;
 	if (sectors < le64_to_cpu(sb->data_size))
 		return -EINVAL;
@@ -2170,8 +2167,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 		return 0; /* too confusing */
 	if (rdev->sb_start < rdev->data_offset) {
 		/* minor versions 1 and 2; superblock before data */
-		max_sectors = i_size_read(rdev->bdev->bd_inode) >> 9;
-		max_sectors -= rdev->data_offset;
+		max_sectors = bdev_nr_sectors(rdev->bdev) - rdev->data_offset;
 		if (!num_sectors || num_sectors > max_sectors)
 			num_sectors = max_sectors;
 	} else if (rdev->mddev->bitmap_info.offset) {
@@ -2180,7 +2176,7 @@ super_1_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors)
 	} else {
 		/* minor version 0; superblock after data */
 		sector_t sb_start, bm_space;
-		sector_t dev_size = i_size_read(rdev->bdev->bd_inode) >> 9;
+		sector_t dev_size = bdev_nr_sectors(rdev->bdev);
 
 		/* 8K is for superblock */
 		sb_start = dev_size - 8*2;
@@ -3384,7 +3380,7 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len)
 			if (!sectors)
 				return -EBUSY;
 		} else if (!sectors)
-			sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) -
+			sectors = bdev_nr_sectors(rdev->bdev) -
 				rdev->data_offset;
 		if (!my_mddev->pers->resize)
 			/* Cannot change size for RAID0 or Linear etc */
@@ -3711,7 +3707,7 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe
 
 	kobject_init(&rdev->kobj, &rdev_ktype);
 
-	size = i_size_read(rdev->bdev->bd_inode) >> BLOCK_SIZE_BITS;
+	size = (bdev_nr_sectors(rdev->bdev) << SECTOR_SHIFT) >> BLOCK_SIZE_BITS;
 	if (!size) {
 		pr_warn("md: %s has zero or unknown size, marking faulty!\n",
 			bdevname(rdev->bdev,b));
@@ -6882,7 +6878,7 @@ int md_add_new_disk(struct mddev *mddev, struct mdu_disk_info_s *info)
 
 		if (!mddev->persistent) {
 			pr_debug("md: nonpersistent superblock ...\n");
-			rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512;
+			rdev->sb_start = bdev_nr_sectors(rdev->bdev);
 		} else
 			rdev->sb_start = calc_dev_sboffset(rdev);
 		rdev->sectors = rdev->sb_start;
@@ -6969,7 +6965,7 @@ static int hot_add_disk(struct mddev *mddev, dev_t dev)
 	if (mddev->persistent)
 		rdev->sb_start = calc_dev_sboffset(rdev);
 	else
-		rdev->sb_start = i_size_read(rdev->bdev->bd_inode) / 512;
+		rdev->sb_start = bdev_nr_sectors(rdev->bdev);
 
 	rdev->sectors = rdev->sb_start;
 
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:18 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:18 +0200
Subject: [PATCH 05/29] mtd/block2mtd: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-6-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/mtd/devices/block2mtd.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index c08721b11642b..d2d1a712188ce 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -269,7 +269,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 		goto err_free_block2mtd;
 	}
 
-	if ((long)dev->blkdev->bd_inode->i_size % erase_size) {
+	if ((long)(bdev_nr_sectors(dev->blkdev) << SECTOR_SHIFT) % erase_size) {
 		pr_err("erasesize must be a divisor of device size\n");
 		goto err_free_block2mtd;
 	}
@@ -284,7 +284,8 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	dev->mtd.name = name;
 
-	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
+	dev->mtd.size =
+		(bdev_nr_sectors(dev->blkdev) << SECTOR_SHIFT) & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
 	dev->mtd.writesize = 1;
 	dev->mtd.writebufsize = PAGE_SIZE;
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:19 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:19 +0200
Subject: [PATCH 06/29] nvmet: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-7-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/nvme/target/io-cmd-bdev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index 6139e1de50a66..683246303f62e 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -87,7 +87,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
 		ns->bdev = NULL;
 		return ret;
 	}
-	ns->size = i_size_read(ns->bdev->bd_inode);
+	ns->size = bdev_nr_sectors(ns->bdev) << SECTOR_SHIFT;
 	ns->blksize_shift = blksize_bits(bdev_logical_block_size(ns->bdev));
 
 	ns->pi_type = 0;
@@ -108,7 +108,7 @@ int nvmet_bdev_ns_enable(struct nvmet_ns *ns)
 
 void nvmet_bdev_ns_revalidate(struct nvmet_ns *ns)
 {
-	ns->size = i_size_read(ns->bdev->bd_inode);
+	ns->size = bdev_nr_sectors(ns->bdev) << SECTOR_SHIFT;
 }
 
 u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts)
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:20 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:20 +0200
Subject: [PATCH 07/29] target/iblock: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-8-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/target/target_core_iblock.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 31df20abe141f..ab7f5678ebc44 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -232,8 +232,9 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
 	struct block_device *bd,
 	struct request_queue *q)
 {
-	unsigned long long blocks_long = (div_u64(i_size_read(bd->bd_inode),
-					bdev_logical_block_size(bd)) - 1);
+	loff_t size = bdev_nr_sectors(bd) << SECTOR_SHIFT;
+	unsigned long long blocks_long =
+		div_u64(size, bdev_logical_block_size(bd)) - 1;
 	u32 block_size = bdev_logical_block_size(bd);
 
 	if (block_size == dev->dev_attrib.block_size)
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:21 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:21 +0200
Subject: [PATCH 08/29] fs: use bdev_nr_sectors instead of open coding it in
 blkdev_max_block
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-9-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index c615387aedcae..3fb9c5b457ab6 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -878,7 +878,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
 static sector_t blkdev_max_block(struct block_device *bdev, unsigned int size)
 {
 	sector_t retval = ~((sector_t)0);
-	loff_t sz = i_size_read(bdev->bd_inode);
+	loff_t sz = bdev_nr_sectors(bdev) << SECTOR_SHIFT;
 
 	if (sz) {
 		unsigned int sizebits = blksize_bits(size);
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:22 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:22 +0200
Subject: [PATCH 09/29] fs: simplify init_page_buffers
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-10-hch@lst.de>

No need to convert from bdev to inode and back.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/buffer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/buffer.c b/fs/buffer.c
index 3fb9c5b457ab6..ef1fe4f77a952 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -897,7 +897,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
 	struct buffer_head *head = page_buffers(page);
 	struct buffer_head *bh = head;
 	int uptodate = PageUptodate(page);
-	sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode), size);
+	sector_t end_block = blkdev_max_block(bdev, size);
 
 	do {
 		if (!buffer_mapped(bh)) {
-- 
2.30.2



From colyli at suse.de  Tue Oct 12 22:21:22 2021
From: colyli at suse.de (Coly Li)
Date: Wed, 13 Oct 2021 13:21:22 +0800
Subject: [PATCH 01/29] bcache: remove bdev_sectors
In-Reply-To: <20211013051042.1065752-2-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-2-hch@lst.de>
Message-ID: <cd1b2185-9682-1d97-9789-96f833007f62@suse.de>

On 10/13/21 1:10 PM, Christoph Hellwig wrote:
> Use the equivalent block layer helper instead.
>
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Acked-by: Coly Li <colyli at suse.de>

Thanks.

Coly Li

> ---
>   drivers/md/bcache/super.c     | 2 +-
>   drivers/md/bcache/util.h      | 4 ----
>   drivers/md/bcache/writeback.c | 2 +-
>   3 files changed, 2 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
> index f2874c77ff797..4f89985abe4b7 100644
> --- a/drivers/md/bcache/super.c
> +++ b/drivers/md/bcache/super.c
> @@ -1002,7 +1002,7 @@ static void calc_cached_dev_sectors(struct cache_set *c)
>   	struct cached_dev *dc;
>   
>   	list_for_each_entry(dc, &c->cached_devs, list)
> -		sectors += bdev_sectors(dc->bdev);
> +		sectors += bdev_nr_sectors(dc->bdev);
>   
>   	c->cached_dev_sectors = sectors;
>   }
> diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
> index b64460a762677..a7da7930a7fda 100644
> --- a/drivers/md/bcache/util.h
> +++ b/drivers/md/bcache/util.h
> @@ -584,8 +584,4 @@ static inline unsigned int fract_exp_two(unsigned int x,
>   void bch_bio_map(struct bio *bio, void *base);
>   int bch_bio_alloc_pages(struct bio *bio, gfp_t gfp_mask);
>   
> -static inline sector_t bdev_sectors(struct block_device *bdev)
> -{
> -	return bdev->bd_inode->i_size >> 9;
> -}
>   #endif /* _BCACHE_UTIL_H */
> diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c
> index 8120da278161e..c7560f66dca88 100644
> --- a/drivers/md/bcache/writeback.c
> +++ b/drivers/md/bcache/writeback.c
> @@ -45,7 +45,7 @@ static uint64_t __calc_target_rate(struct cached_dev *dc)
>   	 * backing volume uses about 2% of the cache for dirty data.
>   	 */
>   	uint32_t bdev_share =
> -		div64_u64(bdev_sectors(dc->bdev) << WRITEBACK_SHARE_SHIFT,
> +		div64_u64(bdev_nr_sectors(dc->bdev) << WRITEBACK_SHARE_SHIFT,
>   				c->cached_dev_sectors);
>   
>   	uint64_t cache_dirty_target =



From hch at lst.de  Tue Oct 12 22:10:23 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:23 +0200
Subject: [PATCH 10/29] affs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-11-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/affs/super.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/affs/super.c b/fs/affs/super.c
index c6c2a513ec92d..c609005a9eaaa 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -389,7 +389,7 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
 	 * blocks, we will have to change it.
 	 */
 
-	size = i_size_read(sb->s_bdev->bd_inode) >> 9;
+	size = bdev_nr_sectors(sb->s_bdev);
 	pr_debug("initial blocksize=%d, #blocks=%d\n", 512, size);
 
 	affs_set_blocksize(sb, PAGE_SIZE);
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:24 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:24 +0200
Subject: [PATCH 11/29] btrfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-12-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/btrfs/dev-replace.c | 2 +-
 fs/btrfs/disk-io.c     | 3 ++-
 fs/btrfs/ioctl.c       | 4 ++--
 fs/btrfs/volumes.c     | 7 ++++---
 4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index d029be40ea6f0..67799b3132120 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -283,7 +283,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 	}
 
 
-	if (i_size_read(bdev->bd_inode) <
+	if ((bdev_nr_sectors(bdev) << SECTOR_SHIFT) <
 	    btrfs_device_get_total_bytes(srcdev)) {
 		btrfs_err(fs_info,
 			  "target device is smaller than source device!");
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 355ea88d5c5f7..07983f7e66e9f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3740,7 +3740,8 @@ struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev,
 	else if (ret)
 		return ERR_PTR(ret);
 
-	if (bytenr + BTRFS_SUPER_INFO_SIZE >= i_size_read(bdev->bd_inode))
+	if (bytenr + BTRFS_SUPER_INFO_SIZE >=
+	    (bdev_nr_sectors(bdev) << SECTOR_SHIFT))
 		return ERR_PTR(-EINVAL);
 
 	page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS);
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index cc61813213d83..5e6589b6ad8e4 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1730,7 +1730,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
 	}
 
 	if (!strcmp(sizestr, "max"))
-		new_size = device->bdev->bd_inode->i_size;
+		new_size = bdev_nr_sectors(device->bdev) << SECTOR_SHIFT;
 	else {
 		if (sizestr[0] == '-') {
 			mod = -1;
@@ -1771,7 +1771,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
 		ret = -EINVAL;
 		goto out_finish;
 	}
-	if (new_size > device->bdev->bd_inode->i_size) {
+	if (new_size > (bdev_nr_sectors(device->bdev) << SECTOR_SHIFT)) {
 		ret = -EFBIG;
 		goto out_finish;
 	}
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2ec3b8ac8fa35..11c5f9ec02511 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1286,7 +1286,7 @@ static struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev
 	pgoff_t index;
 
 	/* make sure our super fits in the device */
-	if (bytenr + PAGE_SIZE >= i_size_read(bdev->bd_inode))
+	if (bytenr + PAGE_SIZE >= (bdev_nr_sectors(bdev) << SECTOR_SHIFT))
 		return ERR_PTR(-EINVAL);
 
 	/* make sure our super fits in the page */
@@ -2610,7 +2610,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
 	device->io_width = fs_info->sectorsize;
 	device->io_align = fs_info->sectorsize;
 	device->sector_size = fs_info->sectorsize;
-	device->total_bytes = round_down(i_size_read(bdev->bd_inode),
+	device->total_bytes = round_down(bdev_nr_sectors(bdev) << SECTOR_SHIFT,
 					 fs_info->sectorsize);
 	device->disk_total_bytes = device->total_bytes;
 	device->commit_total_bytes = device->total_bytes;
@@ -7236,7 +7236,8 @@ static int read_one_dev(struct extent_buffer *leaf,
 
 	fill_device_from_item(leaf, dev_item, device);
 	if (device->bdev) {
-		u64 max_total_bytes = i_size_read(device->bdev->bd_inode);
+		u64 max_total_bytes =
+			bdev_nr_sectors(device->bdev) << SECTOR_SHIFT;
 
 		if (device->total_bytes > max_total_bytes) {
 			btrfs_err(fs_info,
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:25 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:25 +0200
Subject: [PATCH 12/29] cramfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-13-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/cramfs/inode.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index 2be65269a987c..3e44cc3ed0543 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -209,7 +209,7 @@ static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset,
 		return read_buffers[i] + blk_offset;
 	}
 
-	devsize = mapping->host->i_size >> PAGE_SHIFT;
+	devsize = bdev_nr_sectors(sb->s_bdev) >> (PAGE_SHIFT - SECTOR_SHIFT);
 
 	/* Ok, read in BLKS_PER_BUF pages completely first. */
 	for (i = 0; i < BLKS_PER_BUF; i++) {
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:26 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:26 +0200
Subject: [PATCH 13/29] fat: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-14-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/fat/inode.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index de0c9b013a851..9f3cd03668adc 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1536,14 +1536,11 @@ static int fat_read_static_bpb(struct super_block *sb,
 	struct fat_bios_param_block *bpb)
 {
 	static const char *notdos1x = "This doesn't look like a DOS 1.x volume";
-
+	sector_t bd_sects = bdev_nr_sectors(sb->s_bdev);
 	struct fat_floppy_defaults *fdefaults = NULL;
 	int error = -EINVAL;
-	sector_t bd_sects;
 	unsigned i;
 
-	bd_sects = i_size_read(sb->s_bdev->bd_inode) / SECTOR_SIZE;
-
 	/* 16-bit DOS 1.x reliably wrote bootstrap short-jmp code */
 	if (b->ignored[0] != 0xeb || b->ignored[2] != 0x90) {
 		if (!silent)
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:27 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:27 +0200
Subject: [PATCH 14/29] hfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-15-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/hfs/mdb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/hfs/mdb.c b/fs/hfs/mdb.c
index cdf0edeeb2781..5beb826524354 100644
--- a/fs/hfs/mdb.c
+++ b/fs/hfs/mdb.c
@@ -36,7 +36,7 @@ static int hfs_get_last_session(struct super_block *sb,
 
 	/* default values */
 	*start = 0;
-	*size = i_size_read(sb->s_bdev->bd_inode) >> 9;
+	*size = bdev_nr_sectors(sb->s_bdev);
 
 	if (HFS_SB(sb)->session >= 0) {
 		struct cdrom_tocentry te;
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:28 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:28 +0200
Subject: [PATCH 15/29] hfsplus: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-16-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/hfsplus/wrapper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
index 0350dc7821bf9..51ae6f1eb4a55 100644
--- a/fs/hfsplus/wrapper.c
+++ b/fs/hfsplus/wrapper.c
@@ -131,7 +131,7 @@ static int hfsplus_get_last_session(struct super_block *sb,
 
 	/* default values */
 	*start = 0;
-	*size = i_size_read(sb->s_bdev->bd_inode) >> 9;
+	*size = bdev_nr_sectors(sb->s_bdev);
 
 	if (HFSPLUS_SB(sb)->session >= 0) {
 		struct cdrom_tocentry te;
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:29 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:29 +0200
Subject: [PATCH 16/29] jfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-17-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/jfs/resize.c | 2 +-
 fs/jfs/super.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index bde787c354fcc..51a8b22e71030 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -199,7 +199,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
 	txQuiesce(sb);
 
 	/* Reset size of direct inode */
-	sbi->direct_inode->i_size =  i_size_read(sb->s_bdev->bd_inode);
+	sbi->direct_inode->i_size = bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT;
 
 	if (sbi->mntflag & JFS_INLINELOG) {
 		/*
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 9030aeaf0f886..992870160903d 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -551,7 +551,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
 		ret = -ENOMEM;
 		goto out_unload;
 	}
-	inode->i_size = i_size_read(sb->s_bdev->bd_inode);
+	inode->i_size = bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT;
 	inode->i_mapping->a_ops = &jfs_metapage_aops;
 	inode_fake_hash(inode);
 	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:30 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:30 +0200
Subject: [PATCH 17/29] nfs/blocklayout: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-18-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/nfs/blocklayout/dev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c
index acb1d22907daf..42772985cb43e 100644
--- a/fs/nfs/blocklayout/dev.c
+++ b/fs/nfs/blocklayout/dev.c
@@ -252,7 +252,7 @@ bl_parse_simple(struct nfs_server *server, struct pnfs_block_dev *d,
 	d->bdev = bdev;
 
 
-	d->len = i_size_read(d->bdev->bd_inode);
+	d->len = bdev_nr_sectors(d->bdev) << SECTOR_SHIFT;
 	d->map = bl_map_simple;
 
 	printk(KERN_INFO "pNFS: using block device %s\n",
@@ -367,7 +367,7 @@ bl_parse_scsi(struct nfs_server *server, struct pnfs_block_dev *d,
 		return PTR_ERR(bdev);
 	d->bdev = bdev;
 
-	d->len = i_size_read(d->bdev->bd_inode);
+	d->len = bdev_nr_sectors(d->bdev) << SECTOR_SHIFT;
 	d->map = bl_map_simple;
 	d->pr_key = v->scsi.pr_key;
 
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:31 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:31 +0200
Subject: [PATCH 18/29] nilfs2: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-19-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/nilfs2/ioctl.c     | 2 +-
 fs/nilfs2/super.c     | 2 +-
 fs/nilfs2/the_nilfs.c | 3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 640ac8fe891e6..4c12cc0e265e1 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -1107,7 +1107,7 @@ static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
 		goto out;
 
 	ret = -ERANGE;
-	if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
+	if (range[1] > (bdev_nr_sectors(inode->i_sb->s_bdev) << SECTOR_SHIFT))
 		goto out;
 
 	segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index f6b2d280aab5a..1842663339acc 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -403,7 +403,7 @@ int nilfs_resize_fs(struct super_block *sb, __u64 newsize)
 	int ret;
 
 	ret = -ERANGE;
-	devsize = i_size_read(sb->s_bdev->bd_inode);
+	devsize = bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT;
 	if (newsize > devsize)
 		goto out;
 
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index c8bfc01da5d71..d68df998213e9 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -489,7 +489,8 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
 {
 	struct nilfs_super_block **sbp = nilfs->ns_sbp;
 	struct buffer_head **sbh = nilfs->ns_sbh;
-	u64 sb2off = NILFS_SB2_OFFSET_BYTES(nilfs->ns_bdev->bd_inode->i_size);
+	loff_t size = bdev_nr_sectors(nilfs->ns_bdev) << SECTOR_SHIFT;
+	u64 sb2off = NILFS_SB2_OFFSET_BYTES(size);
 	int valid[2], swp = 0;
 
 	sbp[0] = nilfs_read_super_block(sb, NILFS_SB_OFFSET_BYTES, blocksize,
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:32 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:32 +0200
Subject: [PATCH 19/29] ntfs3: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-20-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/ntfs3/super.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
index 55bbc9200a10e..b9782b57a4036 100644
--- a/fs/ntfs3/super.c
+++ b/fs/ntfs3/super.c
@@ -918,7 +918,6 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
 	int err;
 	struct ntfs_sb_info *sbi;
 	struct block_device *bdev = sb->s_bdev;
-	struct inode *bd_inode = bdev->bd_inode;
 	struct request_queue *rq = bdev_get_queue(bdev);
 	struct inode *inode = NULL;
 	struct ntfs_inode *ni;
@@ -967,7 +966,7 @@ static int ntfs_fill_super(struct super_block *sb, void *data, int silent)
 
 	/* Parse boot. */
 	err = ntfs_init_from_boot(sb, rq ? queue_logical_block_size(rq) : 512,
-				  bd_inode->i_size);
+				  bdev_nr_sectors(bdev) << SECTOR_SHIFT);
 	if (err)
 		goto out;
 
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:33 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:33 +0200
Subject: [PATCH 20/29] pstore/blk: use bdev_nr_sectors instead of open coding
 it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-21-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/pstore/blk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/pstore/blk.c b/fs/pstore/blk.c
index 04ce58c939a0b..f43009cb2ec82 100644
--- a/fs/pstore/blk.c
+++ b/fs/pstore/blk.c
@@ -223,8 +223,8 @@ static int __register_pstore_blk(struct pstore_device_info *dev,
 		goto err_fput;
 	}
 
-	inode = I_BDEV(psblk_file->f_mapping->host)->bd_inode;
-	dev->zone.total_size = i_size_read(inode);
+	inode = psblk_file->f_mapping->host;
+	dev->zone.total_size = bdev_nr_sectors(I_BDEV(inode)) << SECTOR_SHIFT;
 
 	ret = __register_pstore_device(dev);
 	if (ret)
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:34 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:34 +0200
Subject: [PATCH 21/29] reiserfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-22-hch@lst.de>

Use the proper helper to read the block device size and remove two
cargo culted checks that can't be false.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/reiserfs/super.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 58481f8d63d5b..6c9681e2809f0 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1986,8 +1986,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
 	 * smaller than the filesystem. If the check fails then abort and
 	 * scream, because bad stuff will happen otherwise.
 	 */
-	if (s->s_bdev && s->s_bdev->bd_inode
-	    && i_size_read(s->s_bdev->bd_inode) <
+	if ((bdev_nr_sectors(s->s_bdev) << SECTOR_SHIFT) <
 	    sb_block_count(rs) * sb_blocksize(rs)) {
 		SWARN(silent, s, "", "Filesystem cannot be "
 		      "mounted because it is bigger than the device");
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:35 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:35 +0200
Subject: [PATCH 22/29] squashfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-23-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/squashfs/super.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c
index 60d6951915f44..e83042ecf0d86 100644
--- a/fs/squashfs/super.c
+++ b/fs/squashfs/super.c
@@ -16,6 +16,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/blkdev.h>
 #include <linux/fs.h>
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
@@ -179,8 +180,8 @@ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
 	/* Check the filesystem does not extend beyond the end of the
 	   block device */
 	msblk->bytes_used = le64_to_cpu(sblk->bytes_used);
-	if (msblk->bytes_used < 0 || msblk->bytes_used >
-			i_size_read(sb->s_bdev->bd_inode))
+	if (msblk->bytes_used < 0 ||
+	    msblk->bytes_used > (bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT))
 		goto failed_mount;
 
 	/* Check block size for sanity */
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:36 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:36 +0200
Subject: [PATCH 23/29] block: use bdev_nr_sectors instead of open coding it in
 blkdev_fallocate
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-24-hch@lst.de>

Use the proper helper to read the block device size.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/fops.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/fops.c b/block/fops.c
index 7bb9581a146cf..6e27dd2748504 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -548,7 +548,7 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start,
 		return -EOPNOTSUPP;
 
 	/* Don't go off the end of the device. */
-	isize = i_size_read(bdev->bd_inode);
+	isize = bdev_nr_sectors(bdev) << SECTOR_SHIFT;
 	if (start >= isize)
 		return -EINVAL;
 	if (end >= isize) {
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:37 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:37 +0200
Subject: [PATCH 24/29] block: add a sb_bdev_nr_blocks helper
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-25-hch@lst.de>

Add a helper to return the size of sb->s_bdev in sb->s_blocksize_bits
based unites.  Note that SECTOR_SHIFT has to be open coded due to
include dependency issues for now, but I have a plan to sort that out
eventually.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 include/linux/genhd.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 082a3e5fd8fa1..6eaef8fa78bcd 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -245,6 +245,12 @@ static inline sector_t get_capacity(struct gendisk *disk)
 	return bdev_nr_sectors(disk->part0);
 }
 
+static inline u64 sb_bdev_nr_blocks(struct super_block *sb)
+{
+	return bdev_nr_sectors(sb->s_bdev) >>
+		(sb->s_blocksize_bits - 9 /* SECTOR_SHIFT */);
+}
+
 int bdev_disk_changed(struct gendisk *disk, bool invalidate);
 void blk_drop_partitions(struct gendisk *disk);
 
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:38 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:38 +0200
Subject: [PATCH 25/29] ext4: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-26-hch@lst.de>

Use the sb_bdev_nr_blocks helper instead of open coding it.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/ext4/super.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 0775950ee84e3..3dde8be5df490 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4468,7 +4468,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
 		goto cantfind_ext4;
 
 	/* check blocks count against device size */
-	blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
+	blocks_count = sb_bdev_nr_blocks(sb);
 	if (blocks_count && ext4_blocks_count(es) > blocks_count) {
 		ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu "
 		       "exceeds size of device (%llu blocks)",
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:39 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:39 +0200
Subject: [PATCH 26/29] jfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-27-hch@lst.de>

Use the sb_bdev_nr_blocks helper instead of open coding it.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/jfs/resize.c | 3 +--
 fs/jfs/super.c  | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
index 51a8b22e71030..f23445fa4b417 100644
--- a/fs/jfs/resize.c
+++ b/fs/jfs/resize.c
@@ -86,8 +86,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
 		goto out;
 	}
 
-	VolumeSize = i_size_read(sb->s_bdev->bd_inode) >> sb->s_blocksize_bits;
-
+	VolumeSize = sb_bdev_nr_blocks(sb);
 	if (VolumeSize) {
 		if (newLVSize > VolumeSize) {
 			printk(KERN_WARNING "jfs_extendfs: invalid size\n");
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 992870160903d..fecef43f94ae8 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -284,8 +284,7 @@ static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
 		}
 		case Opt_resize_nosize:
 		{
-			*newLVSize = i_size_read(sb->s_bdev->bd_inode) >>
-				sb->s_blocksize_bits;
+			*newLVSize = sb_bdev_nr_blocks(sb);
 			if (*newLVSize == 0)
 				pr_err("JFS: Cannot determine volume size\n");
 			break;
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:40 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:40 +0200
Subject: [PATCH 27/29] ntfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-28-hch@lst.de>

Use the sb_bdev_nr_blocks helper instead of open coding it.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/ntfs/super.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
index 0d7e948cb29c9..5ae8de09b271b 100644
--- a/fs/ntfs/super.c
+++ b/fs/ntfs/super.c
@@ -2772,13 +2772,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 	ntfs_debug("Set device block size to %i bytes (block size bits %i).",
 			blocksize, sb->s_blocksize_bits);
 	/* Determine the size of the device in units of block_size bytes. */
-	if (!i_size_read(sb->s_bdev->bd_inode)) {
+	vol->nr_blocks = sb_bdev_nr_blocks(sb);
+	if (!vol->nr_blocks) {
 		if (!silent)
 			ntfs_error(sb, "Unable to determine device size.");
 		goto err_out_now;
 	}
-	vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
-			sb->s_blocksize_bits;
 	/* Read the boot sector and return unlocked buffer head to it. */
 	if (!(bh = read_ntfs_boot_sector(sb, silent))) {
 		if (!silent)
@@ -2816,8 +2815,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
 			goto err_out_now;
 		}
 		BUG_ON(blocksize != sb->s_blocksize);
-		vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
-				sb->s_blocksize_bits;
+		vol->nr_blocks = sb_bdev_nr_blocks(sb);
 		ntfs_debug("Changed device block size to %i bytes (block size "
 				"bits %i) to match volume sector size.",
 				blocksize, sb->s_blocksize_bits);
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:41 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:41 +0200
Subject: [PATCH 28/29] reiserfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-29-hch@lst.de>

Use the sb_bdev_nr_blocks helper instead of open coding it.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/reiserfs/super.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 6c9681e2809f0..b12baadb7e9bb 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1199,9 +1199,7 @@ static int reiserfs_parse_options(struct super_block *s,
 
 			if (!strcmp(arg, "auto")) {
 				/* From JFS code, to auto-get the size. */
-				*blocks =
-				    i_size_read(s->s_bdev->bd_inode) >> s->
-				    s_blocksize_bits;
+				*blocks = sb_bdev_nr_blocks(s);
 			} else {
 				*blocks = simple_strtoul(arg, &p, 0);
 				if (*p != '\0') {
-- 
2.30.2



From hch at lst.de  Tue Oct 12 22:10:42 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 13 Oct 2021 07:10:42 +0200
Subject: [PATCH 29/29] udf: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211013051042.1065752-30-hch@lst.de>

Use the sb_bdev_nr_blocks helper instead of open coding it.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/udf/lowlevel.c | 5 ++---
 fs/udf/super.c    | 9 +++------
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index f1094cdcd6cde..46d6971721975 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -47,8 +47,7 @@ unsigned int udf_get_last_session(struct super_block *sb)
 
 unsigned long udf_get_last_block(struct super_block *sb)
 {
-	struct block_device *bdev = sb->s_bdev;
-	struct cdrom_device_info *cdi = disk_to_cdi(bdev->bd_disk);
+	struct cdrom_device_info *cdi = disk_to_cdi(sb->s_bdev->bd_disk);
 	unsigned long lblock = 0;
 
 	/*
@@ -56,7 +55,7 @@ unsigned long udf_get_last_block(struct super_block *sb)
 	 * Try using the device size...
 	 */
 	if (!cdi || cdrom_get_last_written(cdi, &lblock) || lblock == 0)
-		lblock = i_size_read(bdev->bd_inode) >> sb->s_blocksize_bits;
+		lblock = sb_bdev_nr_blocks(sb);
 
 	if (lblock)
 		return lblock - 1;
diff --git a/fs/udf/super.c b/fs/udf/super.c
index b2d7c57d06881..34247fba6df91 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1175,8 +1175,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index)
 	struct udf_inode_info *vati;
 	uint32_t pos;
 	struct virtualAllocationTable20 *vat20;
-	sector_t blocks = i_size_read(sb->s_bdev->bd_inode) >>
-			  sb->s_blocksize_bits;
+	sector_t blocks = sb_bdev_nr_blocks(sb);
 
 	udf_find_vat_block(sb, p_index, type1_index, sbi->s_last_block);
 	if (!sbi->s_vat_inode &&
@@ -1838,8 +1837,7 @@ static int udf_check_anchor_block(struct super_block *sb, sector_t block,
 	int ret;
 
 	if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) &&
-	    udf_fixed_to_variable(block) >=
-	    i_size_read(sb->s_bdev->bd_inode) >> sb->s_blocksize_bits)
+	    udf_fixed_to_variable(block) >= sb_bdev_nr_blocks(sb))
 		return -EAGAIN;
 
 	bh = udf_read_tagged(sb, block, block, &ident);
@@ -1901,8 +1899,7 @@ static int udf_scan_anchors(struct super_block *sb, sector_t *lastblock,
 		last[last_count++] = *lastblock - 152;
 
 	for (i = 0; i < last_count; i++) {
-		if (last[i] >= i_size_read(sb->s_bdev->bd_inode) >>
-				sb->s_blocksize_bits)
+		if (last[i] >= sb_bdev_nr_blocks(sb))
 			continue;
 		ret = udf_check_anchor_block(sb, last[i], fileset);
 		if (ret != -EAGAIN) {
-- 
2.30.2



From ceggers at arri.de  Tue Oct 12 23:00:26 2021
From: ceggers at arri.de (Christian Eggers)
Date: Wed, 13 Oct 2021 08:00:26 +0200
Subject: [RFC PATCH 1/2] mtd: rawnand: gpmi: Remove explicit default gpmi
 clock setting for i.MX6
In-Reply-To: <20211012090224.4101984-1-s.riedmueller@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
Message-ID: <4352240.LvFx2qVVIh@n95hx1g2>

On Tuesday, 12 October 2021, 11:02:23 CEST, Stefan Riedmueller wrote:
> There is no need to explicitly set the default gpmi clock rate during
> boot for the i.MX 6 since this is done during nand_detect anyway.
> 
> Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> ---
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 9 ---------
>  1 file changed, 9 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 4d08e4ab5c1b..a1f7000f033e 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -1034,15 +1034,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this)
>  		r->clock[i] = clk;
>  	}
>  
> -	if (GPMI_IS_MX6(this))
> -		/*
> -		 * Set the default value for the gpmi clock.
> -		 *
> -		 * If you want to use the ONFI nand which is in the
> -		 * Synchronous Mode, you should change the clock as you need.
> -		 */
> -		clk_set_rate(r->clock[0], 22000000);
> -
>  	return 0;
>  
>  err_clock:
> 

Tested-by: Christian Eggers <ceggers at arri.de>  # on i.MX6ULL with MT29F4G08ABADAH4
Cc: stable at vger.kernel.org





From keescook at chromium.org  Tue Oct 12 23:09:17 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:09:17 -0700
Subject: [PATCH 01/29] bcache: remove bdev_sectors
In-Reply-To: <20211013051042.1065752-2-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-2-hch@lst.de>
Message-ID: <202110122309.010F81F49A@keescook>

On Wed, Oct 13, 2021 at 07:10:14AM +0200, Christoph Hellwig wrote:
> Use the equivalent block layer helper instead.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:09:38 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:09:38 -0700
Subject: [PATCH 02/29] drbd: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-3-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-3-hch@lst.de>
Message-ID: <202110122309.FB5CB2DE3@keescook>

On Wed, Oct 13, 2021 at 07:10:15AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:10:10 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:10:10 -0700
Subject: [PATCH 03/29] dm: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-4-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-4-hch@lst.de>
Message-ID: <202110122310.36F4C08@keescook>

On Wed, Oct 13, 2021 at 07:10:16AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From ceggers at arri.de  Tue Oct 12 23:10:10 2021
From: ceggers at arri.de (Christian Eggers)
Date: Wed, 13 Oct 2021 08:10:10 +0200
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211012090224.4101984-2-s.riedmueller@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
Message-ID: <2799559.e9J7NaK4W3@n95hx1g2>

On Tuesday, 12 October 2021, 11:02:24 CEST, Stefan Riedmueller wrote:
> According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> when doing a gpmi_io clk rate change. So gate the clocks off before
> the rate change in nfc_apply_timings and ungate them again after the
> change.
> 
> Otherwise this rate change can lead to an unresponsive GPMI core which
> results in DMA timeouts and failed driver probe:
> 
> [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> ...
> [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> ...
> [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
> [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> ...
> 
> Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> ---
> Hi,
Hi Stefan,

thanks for providing the patches! I am suffering from this problem for some
time now and I am happy to get this fixed!

> 
> I'm not sure about the error handling here, if it is actually neccessary.
> So some feedback would be nice here.

IMHO errors should always be handled.

> 
> Thanks,
> Stefan
> ---
>  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index a1f7000f033e..326c8a895f1f 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>  			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
>  }
>  
> -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
>  {
>  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
>  	struct resources *r = &this->resources;
>  	void __iomem *gpmi_regs = r->gpmi_regs;
>  	unsigned int dll_wait_time_us;
> +	int ret;
> +
> +	if (GPMI_IS_MX6Q(this)) {
I would like to explicitly see i.MX6UL(L) here (in order to make clear that
not only Solo/Dual/Quad are affected):
#define GPMI_IS_MX6UL(x)		((x)->devdata->type == IS_MX6Q)
...
if (GPMI_IS_MX6Q(this) || GPMI_IS_MX6UL(this)) {

But if Han Xu is sure that also SoloX and i.MX7 are affected, GPMI_IS_MX6(x)
is fine for me. In this case I would like to explicitly mention this in the 
commit message, so that nobody will change this later because ERR007117
exists only for Solo/Dual/Quad.

> +		ret = __gpmi_enable_clk(this, false);
> +		if (ret)
> +			return ret;
> +	}
>  
>  	clk_set_rate(r->clock[0], hw->clk_rate);
>  
> +	if (GPMI_IS_MX6Q(this)) {
> +		ret = __gpmi_enable_clk(this, true);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
>  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
>  
> @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
>  
>  	/* Wait for the DLL to settle. */
>  	udelay(dll_wait_time_us);
> +
> +	return 0;
>  }
>  
>  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
>  	 */
>  	if (this->hw.must_apply_timings) {
>  		this->hw.must_apply_timings = false;
> -		gpmi_nfc_apply_timings(this);
> +		ret = gpmi_nfc_apply_timings(this);
> +		if (ret)
> +			return ret;
>  	}
>  
>  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
> 

Tested-by: Christian Eggers <ceggers at arri.de>  # on i.MX6ULL with MT29F4G08ABADAH4
Cc: stable at vger.kernel.org





From keescook at chromium.org  Tue Oct 12 23:12:52 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:12:52 -0700
Subject: [PATCH 04/29] md: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-5-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-5-hch@lst.de>
Message-ID: <202110122311.B43459E21@keescook>

On Wed, Oct 13, 2021 at 07:10:17AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

I think it might make sense, as you suggest earlier, to add a "bytes"
helper. This is the first user in the series needing:

	bdev_nr_sectors(...bdev) << SECTOR_SHIFT

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:14:14 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:14:14 -0700
Subject: [PATCH 09/29] fs: simplify init_page_buffers
In-Reply-To: <20211013051042.1065752-10-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-10-hch@lst.de>
Message-ID: <202110122314.664187AA@keescook>

On Wed, Oct 13, 2021 at 07:10:22AM +0200, Christoph Hellwig wrote:
> No need to convert from bdev to inode and back.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:14:23 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:14:23 -0700
Subject: [PATCH 10/29] affs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-11-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-11-hch@lst.de>
Message-ID: <202110122314.6BE3F05AA3@keescook>

On Wed, Oct 13, 2021 at 07:10:23AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From ceggers at arri.de  Tue Oct 12 23:15:17 2021
From: ceggers at arri.de (Christian Eggers)
Date: Wed, 13 Oct 2021 08:15:17 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <2811233.e9J7NaK4W3@n95hx1g2>
References: <89ae32a0-9b19-4735-90eb-4ffa22aad704@kernel.org>
 <20211008180752.09f33896@xps13> <2811233.e9J7NaK4W3@n95hx1g2>
Message-ID: <7977464.T7Z3S40VBb@n95hx1g2>

On Saturday, 9 October 2021, 08:26:36 CEST, Christian Eggers wrote:
> > > Do you think that the need for avoiding clock glitches is i.MX6 specific?
> > > The errata I mentioned is specific for the bootloader software, but (I think)
> > > the requirement for switching off the clocks gates prior changing the dividers
> > > may apply also for other series.
> > 
> > I honestly don't know, perhaps Han have more details about it. If you
> > think it's a wider issue, then we can just do the disable/enable step
> > without any further checks.
> I also don't know. I can not find the required sequence in the reference manual
> (only in the errata sheet), so I cannot compare with other series. For best
> performance we can start with checking for GPMI_IS_MX6Q(x) and extend it later
> if this issue comes up on other devices.
> 
> I sent a question for this on NXP community:
> https://community.nxp.com/t5/i-MX-Processors/ERR007117-Which-i-MX-devices-require-gating-the-clocks-when/m-p/1353018
> 
> 1. Which i.MX models / series require this sequence?
> 2. Where can I find this sequence in the reference manuals (e.g. for i.MX6 ULL)?
> 3. How is CCM_CCGR2[CG7] (iomux_ipt_clk_io_clk) related to "gating enfc_clk_root"?

@Han Xu: Can you provide further information about this? Do you have contact to
the hardware developers?

regards
Christian





From keescook at chromium.org  Tue Oct 12 23:16:11 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:16:11 -0700
Subject: [PATCH 12/29] cramfs: use bdev_nr_sectors instead of open coding
 it
In-Reply-To: <20211013051042.1065752-13-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-13-hch@lst.de>
Message-ID: <202110122315.7CFF5F6@keescook>

On Wed, Oct 13, 2021 at 07:10:25AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>  fs/cramfs/inode.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
> index 2be65269a987c..3e44cc3ed0543 100644
> --- a/fs/cramfs/inode.c
> +++ b/fs/cramfs/inode.c
> @@ -209,7 +209,7 @@ static void *cramfs_blkdev_read(struct super_block *sb, unsigned int offset,
>  		return read_buffers[i] + blk_offset;
>  	}
>  
> -	devsize = mapping->host->i_size >> PAGE_SHIFT;
> +	devsize = bdev_nr_sectors(sb->s_bdev) >> (PAGE_SHIFT - SECTOR_SHIFT);

I find this less readable than "bytes >> PAGE_SHIFT". I'd suggest this
use a new bdev_nr_bytes() helper.

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:16:34 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:16:34 -0700
Subject: [PATCH 13/29] fat: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-14-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-14-hch@lst.de>
Message-ID: <202110122316.8ED0742@keescook>

On Wed, Oct 13, 2021 at 07:10:26AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:16:43 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:16:43 -0700
Subject: [PATCH 14/29] hfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-15-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-15-hch@lst.de>
Message-ID: <202110122316.C8D15CD2@keescook>

On Wed, Oct 13, 2021 at 07:10:27AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:16:51 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:16:51 -0700
Subject: [PATCH 15/29] hfsplus: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-16-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-16-hch@lst.de>
Message-ID: <202110122316.9C54C2F@keescook>

On Wed, Oct 13, 2021 at 07:10:28AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:27:42 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:27:42 -0700
Subject: [PATCH 24/29] block: add a sb_bdev_nr_blocks helper
In-Reply-To: <20211013051042.1065752-25-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-25-hch@lst.de>
Message-ID: <202110122319.3029AE5AA@keescook>

On Wed, Oct 13, 2021 at 07:10:37AM +0200, Christoph Hellwig wrote:
> Add a helper to return the size of sb->s_bdev in sb->s_blocksize_bits
> based unites.  Note that SECTOR_SHIFT has to be open coded due to
> include dependency issues for now, but I have a plan to sort that out
> eventually.

Wouldn't that just need a quick lift into a new header file to be
included by genhd.h, blkev.h, and:

drivers/mtd/ssfdc.c:#define SECTOR_SHIFT                9
fs/hfsplus/hfsplus_raw.h:#define HFSPLUS_SECTOR_SHIFT         9

I think that's worth doing at some point in this series since genhd.h
already has existing open-coded "9"s. And, really, a *lot* of other
places too:

$ git grep -E '(<<|>>) 9' | grep -E '\b(block|blk|sector|bdev)\b' | wc -l
240

> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>  include/linux/genhd.h | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/include/linux/genhd.h b/include/linux/genhd.h
> index 082a3e5fd8fa1..6eaef8fa78bcd 100644
> --- a/include/linux/genhd.h
> +++ b/include/linux/genhd.h
> @@ -245,6 +245,12 @@ static inline sector_t get_capacity(struct gendisk *disk)
>  	return bdev_nr_sectors(disk->part0);
>  }
>  
> +static inline u64 sb_bdev_nr_blocks(struct super_block *sb)
> +{
> +	return bdev_nr_sectors(sb->s_bdev) >>
> +		(sb->s_blocksize_bits - 9 /* SECTOR_SHIFT */);
> +}
> +
>  int bdev_disk_changed(struct gendisk *disk, bool invalidate);
>  void blk_drop_partitions(struct gendisk *disk);
>  
> -- 
> 2.30.2
> 

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:29:39 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:29:39 -0700
Subject: [PATCH 25/29] ext4: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-26-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-26-hch@lst.de>
Message-ID: <202110122328.92B4FC41F4@keescook>

On Wed, Oct 13, 2021 at 07:10:38AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>  fs/ext4/super.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 0775950ee84e3..3dde8be5df490 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -4468,7 +4468,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
>  		goto cantfind_ext4;
>  
>  	/* check blocks count against device size */
> -	blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
> +	blocks_count = sb_bdev_nr_blocks(sb);

Is s_blocksize_bits always 9 here? If not, this isn't equivalent.

-Kees

>  	if (blocks_count && ext4_blocks_count(es) > blocks_count) {
>  		ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu "
>  		       "exceeds size of device (%llu blocks)",
> -- 
> 2.30.2
> 

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:30:43 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:30:43 -0700
Subject: [PATCH 25/29] ext4: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-26-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-26-hch@lst.de>
Message-ID: <202110122330.6E549D2@keescook>

On Wed, Oct 13, 2021 at 07:10:38AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>  fs/ext4/super.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 0775950ee84e3..3dde8be5df490 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -4468,7 +4468,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
>  		goto cantfind_ext4;
>  
>  	/* check blocks count against device size */
> -	blocks_count = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits;
> +	blocks_count = sb_bdev_nr_blocks(sb);

Wait, my bad. Yes, this is fine. It's going through two helpers. :)

Reviewed-by: Kees Cook <keescook at chromium.org>


>  	if (blocks_count && ext4_blocks_count(es) > blocks_count) {
>  		ext4_msg(sb, KERN_WARNING, "bad geometry: block count %llu "
>  		       "exceeds size of device (%llu blocks)",
> -- 
> 2.30.2
> 

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:31:03 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:31:03 -0700
Subject: [PATCH 26/29] jfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-27-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-27-hch@lst.de>
Message-ID: <202110122331.C020EA7@keescook>

On Wed, Oct 13, 2021 at 07:10:39AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:33:04 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:33:04 -0700
Subject: [PATCH 27/29] ntfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-28-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-28-hch@lst.de>
Message-ID: <202110122332.53B5925A@keescook>

On Wed, Oct 13, 2021 at 07:10:40AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>  fs/ntfs/super.c | 8 +++-----
>  1 file changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c
> index 0d7e948cb29c9..5ae8de09b271b 100644
> --- a/fs/ntfs/super.c
> +++ b/fs/ntfs/super.c
> @@ -2772,13 +2772,12 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
>  	ntfs_debug("Set device block size to %i bytes (block size bits %i).",
>  			blocksize, sb->s_blocksize_bits);
>  	/* Determine the size of the device in units of block_size bytes. */
> -	if (!i_size_read(sb->s_bdev->bd_inode)) {
> +	vol->nr_blocks = sb_bdev_nr_blocks(sb);
> +	if (!vol->nr_blocks) {

I might be worth mentioning in the commit log why this is safe (i.e. the
"side effect" of the assignment doesn't need to be delayed since it will
be thrown away in the failure path).

>  		if (!silent)
>  			ntfs_error(sb, "Unable to determine device size.");
>  		goto err_out_now;
>  	}
> -	vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
> -			sb->s_blocksize_bits;
>  	/* Read the boot sector and return unlocked buffer head to it. */
>  	if (!(bh = read_ntfs_boot_sector(sb, silent))) {
>  		if (!silent)
> @@ -2816,8 +2815,7 @@ static int ntfs_fill_super(struct super_block *sb, void *opt, const int silent)
>  			goto err_out_now;
>  		}
>  		BUG_ON(blocksize != sb->s_blocksize);
> -		vol->nr_blocks = i_size_read(sb->s_bdev->bd_inode) >>
> -				sb->s_blocksize_bits;
> +		vol->nr_blocks = sb_bdev_nr_blocks(sb);
>  		ntfs_debug("Changed device block size to %i bytes (block size "
>  				"bits %i) to match volume sector size.",
>  				blocksize, sb->s_blocksize_bits);

Reviewed-by: Kees Cook <keescook at chromium.org>


> -- 
> 2.30.2
> 

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:33:19 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:33:19 -0700
Subject: [PATCH 28/29] reiserfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-29-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-29-hch@lst.de>
Message-ID: <202110122333.7CE920EB9@keescook>

On Wed, Oct 13, 2021 at 07:10:41AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:34:09 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:34:09 -0700
Subject: [PATCH 29/29] udf: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-30-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-30-hch@lst.de>
Message-ID: <202110122334.7A3E933D@keescook>

On Wed, Oct 13, 2021 at 07:10:42AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Reviewed-by: Kees Cook <keescook at chromium.org>

-- 
Kees Cook


From keescook at chromium.org  Tue Oct 12 23:39:25 2021
From: keescook at chromium.org (Kees Cook)
Date: Tue, 12 Oct 2021 23:39:25 -0700
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <202110122335.19348E8E8@keescook>

On Wed, Oct 13, 2021 at 07:10:13AM +0200, Christoph Hellwig wrote:
> I wondered about adding a helper for looking at the size in byte units
> to avoid the SECTOR_SHIFT shifts in various places.  But given that
> I could not come up with a good name and block devices fundamentally
> work in sector size granularity I decided against that.

Without something like bdev_nr_bytes(), this series has 13 of 29 patches
actually _adding_ an open-coded calculation:

[PATCH 05/29] mtd/block2mtd: use bdev_nr_sectors instead of open coding it
[PATCH 06/29] nvmet: use bdev_nr_sectors instead of open coding it
[PATCH 07/29] target/iblock: use bdev_nr_sectors instead of open coding it
[PATCH 08/29] fs: use bdev_nr_sectors instead of open coding it in blkdev_max_block
[PATCH 11/29] btrfs: use bdev_nr_sectors instead of open coding it
[PATCH 16/29] jfs: use bdev_nr_sectors instead of open coding it
[PATCH 17/29] nfs/blocklayout: use bdev_nr_sectors instead of open coding it
[PATCH 18/29] nilfs2: use bdev_nr_sectors instead of open coding it
[PATCH 19/29] ntfs3: use bdev_nr_sectors instead of open coding it
[PATCH 20/29] pstore/blk: use bdev_nr_sectors instead of open coding it
[PATCH 21/29] reiserfs: use bdev_nr_sectors instead of open coding it
[PATCH 22/29] squashfs: use bdev_nr_sectors instead of open coding it
[PATCH 23/29] block: use bdev_nr_sectors instead of open coding it in blkdev_fallocate

I think it's well worth having that helper (or at least leaving these
alone). Otherwise, this is a lot of churn without a clear net benefit,
IMO.

The others look good to me, though!

-Kees

>
> Diffstat:
>  block/fops.c                        |    2 +-
>  drivers/block/drbd/drbd_int.h       |    3 +--
>  drivers/md/bcache/super.c           |    2 +-
>  drivers/md/bcache/util.h            |    4 ----
>  drivers/md/bcache/writeback.c       |    2 +-
>  drivers/md/dm-bufio.c               |    2 +-
>  drivers/md/dm-cache-metadata.c      |    2 +-
>  drivers/md/dm-cache-target.c        |    2 +-
>  drivers/md/dm-clone-target.c        |    2 +-
>  drivers/md/dm-dust.c                |    5 ++---
>  drivers/md/dm-ebs-target.c          |    2 +-
>  drivers/md/dm-era-target.c          |    2 +-
>  drivers/md/dm-exception-store.h     |    2 +-
>  drivers/md/dm-flakey.c              |    3 +--
>  drivers/md/dm-integrity.c           |    6 +++---
>  drivers/md/dm-linear.c              |    3 +--
>  drivers/md/dm-log-writes.c          |    4 ++--
>  drivers/md/dm-log.c                 |    2 +-
>  drivers/md/dm-mpath.c               |    2 +-
>  drivers/md/dm-raid.c                |    6 +++---
>  drivers/md/dm-switch.c              |    2 +-
>  drivers/md/dm-table.c               |    3 +--
>  drivers/md/dm-thin-metadata.c       |    2 +-
>  drivers/md/dm-thin.c                |    2 +-
>  drivers/md/dm-verity-target.c       |    3 +--
>  drivers/md/dm-writecache.c          |    2 +-
>  drivers/md/dm-zoned-target.c        |    2 +-
>  drivers/md/md.c                     |   26 +++++++++++---------------
>  drivers/mtd/devices/block2mtd.c     |    5 +++--
>  drivers/nvme/target/io-cmd-bdev.c   |    4 ++--
>  drivers/target/target_core_iblock.c |    5 +++--
>  fs/affs/super.c                     |    2 +-
>  fs/btrfs/dev-replace.c              |    2 +-
>  fs/btrfs/disk-io.c                  |    3 ++-
>  fs/btrfs/ioctl.c                    |    4 ++--
>  fs/btrfs/volumes.c                  |    7 ++++---
>  fs/buffer.c                         |    4 ++--
>  fs/cramfs/inode.c                   |    2 +-
>  fs/ext4/super.c                     |    2 +-
>  fs/fat/inode.c                      |    5 +----
>  fs/hfs/mdb.c                        |    2 +-
>  fs/hfsplus/wrapper.c                |    2 +-
>  fs/jfs/resize.c                     |    5 ++---
>  fs/jfs/super.c                      |    5 ++---
>  fs/nfs/blocklayout/dev.c            |    4 ++--
>  fs/nilfs2/ioctl.c                   |    2 +-
>  fs/nilfs2/super.c                   |    2 +-
>  fs/nilfs2/the_nilfs.c               |    3 ++-
>  fs/ntfs/super.c                     |    8 +++-----
>  fs/ntfs3/super.c                    |    3 +--
>  fs/pstore/blk.c                     |    4 ++--
>  fs/reiserfs/super.c                 |    7 ++-----
>  fs/squashfs/super.c                 |    5 +++--
>  fs/udf/lowlevel.c                   |    5 ++---
>  fs/udf/super.c                      |    9 +++------
>  include/linux/genhd.h               |    6 ++++++
>  56 files changed, 100 insertions(+), 117 deletions(-)

--
Kees Cook


From zhengxunli at mxic.com.tw  Wed Oct 13 00:04:15 2021
From: zhengxunli at mxic.com.tw (zhengxunli at mxic.com.tw)
Date: Wed, 13 Oct 2021 15:04:15 +0800
Subject: =?Big5?B?UmU6IKZeq0g6IFtSRkMgUEFUQ0ggMDgvMTBdIHNwaTogbXhpYzogRml4IHRoZQ==?=
 =?Big5?B?IHRyYW5zbWl0IHBhdGg=?=
In-Reply-To: <OF11A0CCB6.4C81ABAD-ON4825876D.00256D6A-4825876D.00256F7A@LocalDomain>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-9-miquel.raynal@bootlin.com>
 <OF11A0CCB6.4C81ABAD-ON4825876D.00256D6A-4825876D.00256F7A@LocalDomain>
Message-ID: <OF7B755571.931AC374-ON4825876D.0025ED60-4825876D.0026D775@mxic.com.tw>


> By working with external hardware ECC engines, we figured out that
> Under certain circumstances, it is needed for the SPI controller to
> check INT_TX_EMPTY and INT_RX_NOT_EMPTY in both receive and transmit
> path (not only in the receive path). The delay penalty being
> negligible, move this code in the common path.
> 
> Fixes: b942d80b0a39 ("spi: Add MXIC controller driver")
> Cc: stable at vger.kernel.org
> Suggested-by: Mason Yang <masonccyang at mxic.com.tw>
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  drivers/spi/spi-mxic.c | 28 ++++++++++++----------------
>  1 file changed, 12 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
> index 96b418293bf2..4fb19e6f94b0 100644
> --- a/drivers/spi/spi-mxic.c
> +++ b/drivers/spi/spi-mxic.c
> @@ -304,25 +304,21 @@ static int mxic_spi_data_xfer(struct mxic_spi 
> *mxic, const void *txbuf,
> 
>        writel(data, mxic->regs + TXD(nbytes % 4));
> 
> +      ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> +                sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
> +      if (ret)
> +         return ret;
> +
> +      ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> +                sts & INT_RX_NOT_EMPTY, 0,
> +                USEC_PER_SEC);
> +      if (ret)
> +         return ret;
> +
> +      data = readl(mxic->regs + RXD);
>        if (rxbuf) {
> -         ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> -                   sts & INT_TX_EMPTY, 0,
> -                   USEC_PER_SEC);
> -         if (ret)
> -            return ret;
> -
> -         ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
> -                   sts & INT_RX_NOT_EMPTY, 0,
> -                   USEC_PER_SEC);
> -         if (ret)
> -            return ret;
> -
> -         data = readl(mxic->regs + RXD);
>           data >>= (8 * (4 - nbytes));
>           memcpy(rxbuf + pos, &data, nbytes);
> -         WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
> -      } else {
> -         readl(mxic->regs + RXD);
>        }
>        WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
> 
> -- 
> 2.27.0
> 

Reviewed-by: Zhengxun Li <zhengxunli at mxic.com.tw>


CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information 
and/or personal data, which is protected by applicable laws. Please be 
reminded that duplication, disclosure, distribution, or use of this e-mail 
(and/or its attachments) or any part thereof is prohibited. If you receive 
this e-mail in error, please notify us immediately and delete this mail as 
well as its attachment(s) from your system. In addition, please be 
informed that collection, processing, and/or use of personal data is 
prohibited unless expressly permitted by personal data protection laws. 
Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



============================================================================

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



From anand.jain at oracle.com  Wed Oct 13 00:08:48 2021
From: anand.jain at oracle.com (Anand Jain)
Date: Wed, 13 Oct 2021 15:08:48 +0800
Subject: [PATCH 11/29] btrfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-12-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-12-hch@lst.de>
Message-ID: <91d3eb0f-95a6-a528-9445-da5b32b69cba@oracle.com>

On 13/10/2021 13:10, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Anand Jain <anand.jain at oracle.com>



From anand.jain at oracle.com  Wed Oct 13 00:14:55 2021
From: anand.jain at oracle.com (Anand Jain)
Date: Wed, 13 Oct 2021 15:14:55 +0800
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <6d96d52b-3a19-8e00-4089-c2483a4cdbcc@oracle.com>

On 13/10/2021 13:10, Christoph Hellwig wrote:
> Hi Jens,
> 
> various drivers currently poke directy at the block device inode, which
> is a bit of a mess.  This series cleans up the places that read the
> block device size to use the proper helpers.  I have separate patches
> for many of the other bd_inode uses, but this series is already big
> enough as-is,
> 
> I wondered about adding a helper for looking at the size in byte units
> to avoid the SECTOR_SHIFT shifts in various places.  But given that
> I could not come up with a good name and 


> block devices fundamentally
> work in sector size granularity I decided against that.

Yes.  However,  POV of its usage outside the block-layer, a wrapper 
helper is a lot better. No.? If you agree, how about naming it bdev_size()?

Thanks, Anand

> 
> Diffstat:
>   block/fops.c                        |    2 +-
>   drivers/block/drbd/drbd_int.h       |    3 +--
>   drivers/md/bcache/super.c           |    2 +-
>   drivers/md/bcache/util.h            |    4 ----
>   drivers/md/bcache/writeback.c       |    2 +-
>   drivers/md/dm-bufio.c               |    2 +-
>   drivers/md/dm-cache-metadata.c      |    2 +-
>   drivers/md/dm-cache-target.c        |    2 +-
>   drivers/md/dm-clone-target.c        |    2 +-
>   drivers/md/dm-dust.c                |    5 ++---
>   drivers/md/dm-ebs-target.c          |    2 +-
>   drivers/md/dm-era-target.c          |    2 +-
>   drivers/md/dm-exception-store.h     |    2 +-
>   drivers/md/dm-flakey.c              |    3 +--
>   drivers/md/dm-integrity.c           |    6 +++---
>   drivers/md/dm-linear.c              |    3 +--
>   drivers/md/dm-log-writes.c          |    4 ++--
>   drivers/md/dm-log.c                 |    2 +-
>   drivers/md/dm-mpath.c               |    2 +-
>   drivers/md/dm-raid.c                |    6 +++---
>   drivers/md/dm-switch.c              |    2 +-
>   drivers/md/dm-table.c               |    3 +--
>   drivers/md/dm-thin-metadata.c       |    2 +-
>   drivers/md/dm-thin.c                |    2 +-
>   drivers/md/dm-verity-target.c       |    3 +--
>   drivers/md/dm-writecache.c          |    2 +-
>   drivers/md/dm-zoned-target.c        |    2 +-
>   drivers/md/md.c                     |   26 +++++++++++---------------
>   drivers/mtd/devices/block2mtd.c     |    5 +++--
>   drivers/nvme/target/io-cmd-bdev.c   |    4 ++--
>   drivers/target/target_core_iblock.c |    5 +++--
>   fs/affs/super.c                     |    2 +-
>   fs/btrfs/dev-replace.c              |    2 +-
>   fs/btrfs/disk-io.c                  |    3 ++-
>   fs/btrfs/ioctl.c                    |    4 ++--
>   fs/btrfs/volumes.c                  |    7 ++++---
>   fs/buffer.c                         |    4 ++--
>   fs/cramfs/inode.c                   |    2 +-
>   fs/ext4/super.c                     |    2 +-
>   fs/fat/inode.c                      |    5 +----
>   fs/hfs/mdb.c                        |    2 +-
>   fs/hfsplus/wrapper.c                |    2 +-
>   fs/jfs/resize.c                     |    5 ++---
>   fs/jfs/super.c                      |    5 ++---
>   fs/nfs/blocklayout/dev.c            |    4 ++--
>   fs/nilfs2/ioctl.c                   |    2 +-
>   fs/nilfs2/super.c                   |    2 +-
>   fs/nilfs2/the_nilfs.c               |    3 ++-
>   fs/ntfs/super.c                     |    8 +++-----
>   fs/ntfs3/super.c                    |    3 +--
>   fs/pstore/blk.c                     |    4 ++--
>   fs/reiserfs/super.c                 |    7 ++-----
>   fs/squashfs/super.c                 |    5 +++--
>   fs/udf/lowlevel.c                   |    5 ++---
>   fs/udf/super.c                      |    9 +++------
>   include/linux/genhd.h               |    6 ++++++
>   56 files changed, 100 insertions(+), 117 deletions(-)
> 



From zhengxunli at mxic.com.tw  Wed Oct 13 00:23:47 2021
From: zhengxunli at mxic.com.tw (zhengxunli at mxic.com.tw)
Date: Wed, 13 Oct 2021 15:23:47 +0800
Subject: =?Big5?B?UmU6IKZeq0g6IFtSRkMgUEFUQ0ggMDkvMTBdIHNwaTogbXhpYzogQWRk?=
 =?Big5?B?IHN1cHBvcnQgZm9yIGRpcmVjdCBtYXBwaW5n?=
In-Reply-To: <OF86339F0C.88E145E3-ON4825876D.002567AA-4825876D.002569D9@LocalDomain>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-10-miquel.raynal@bootlin.com>
 <OF86339F0C.88E145E3-ON4825876D.002567AA-4825876D.002569D9@LocalDomain>
Message-ID: <OF2120B7BA.FA9EA9F2-ON4825876D.002705BD-4825876D.0028A142@mxic.com.tw>


> Implement the ->dirmap_create() and ->dirmap_read/write() hooks to
> provide a fast path for read and write accesses.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  drivers/spi/spi-mxic.c | 171 ++++++++++++++++++++++++++++++++++-------
>  1 file changed, 144 insertions(+), 27 deletions(-)

Hi Miquel,

I verified it by reading, writing, and erasing through normal and quad 
modes
on the Xilinx Zynq PicoZed FPGA board. Except for the need to update the 
SPI
MXIC driver version, it looks good.

Tested-by: Zhengxun Li <zhengxunli at mxic.com.tw>
Reviewed-by: Zhengxun Li <zhengxunli at mxic.com.tw>



CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information 
and/or personal data, which is protected by applicable laws. Please be 
reminded that duplication, disclosure, distribution, or use of this e-mail 
(and/or its attachments) or any part thereof is prohibited. If you receive 
this e-mail in error, please notify us immediately and delete this mail as 
well as its attachment(s) from your system. In addition, please be 
informed that collection, processing, and/or use of personal data is 
prohibited unless expressly permitted by personal data protection laws. 
Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



============================================================================

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



From Alexander.Stein at ew.tq-group.com  Wed Oct 13 01:47:04 2021
From: Alexander.Stein at ew.tq-group.com (Alexander Stein)
Date: Wed, 13 Oct 2021 08:47:04 +0000
Subject: AW: (EXT) Re: [PATCH v2 1/2] dt-bindings: mtd: spi-nor: Add
 output-driver-strength property
Message-ID: <kcEE.9geNR42QRKGTSoedF1sEfQ.ALRP5Q7A1wE@vtuxmail01.tq-net.de>

Hello Michael,


Am 2021-10-12 09:48, schrieb Michael Walle:
> Am 2021-10-12 08:17, schrieb Alexander Stein:
> > This property is for optimizing output voltage impedance and is
> > specific to each board. It overwrites the default set by the flash
> > device. Various flash devices support different impedances.
> > 
> > Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
> > ---
> > Changes in v2:
> > * Updated the property description and the commit message accordingly
> > 
> >  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > index ed590d7c6e37..4c3c506a8853 100644
> > --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > @@ -72,6 +72,14 @@ properties:
> >        be used on such systems, to denote the absence of a reliable 
> > reset
> >        mechanism.
> > 
> > +  output-driver-strength:
> > +    $ref: /schemas/types.yaml#/definitions/uint32
> > +    description:
> > +      Output driver strength in ohms which optimizes the impedance at 
> > Vcc/2
> > +      output voltage. This property overwrites the default set by the 
> > flash
> > +      device. This is board specific and should be determined by the
> > +      manufacturer. Various flash devices support different 
> > impedances.
> 
> Mh, this seems to be very tailored to this flash chip. Eg. the "Vcc/2", 
> is
> this something specific to this flash or is this some kind of common 
> usage?

"Vcc/2" is taken from the datasheet description.

> For example, Winbond flashes specifies the output driver strength in 
> percent.
> Settings are 25%, 50%, 75%, 100% there.
> 
> I'd have to ask a hardware guy, if one could convert between these two
> representations of the driver strength.

Well, 100% must map to some actual value. Which then can be used to create
a discrete value table, which are then supported by the flash driver.
E.g. for Micron not every flash supports the same set of settings for
driver strength.
Macronix uses similar settings (values and bitmask), but in a different
register. But if some vendors have pretty much incompatible settings, it
might be feasible to provide vendor specific settings, e.g.
"micron,drive-strength = <45>" (for 45 Ohm) or "winbond,drive-strength = <100>"
(for 100%).

Best regards,
Alexander



From mika.westerberg at linux.intel.com  Wed Oct 13 02:03:53 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Wed, 13 Oct 2021 12:03:53 +0300
Subject: [PATCH 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <CAArk9MPY+rCQse+JXtvb4KqunN9FZ=toK_v=PV-ro4cO6=5s7Q@mail.gmail.com>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-2-mika.westerberg@linux.intel.com>
 <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>
 <YVqOjF/xjqFV+Dl3@lahna>
 <CAArk9MPY+rCQse+JXtvb4KqunN9FZ=toK_v=PV-ro4cO6=5s7Q@mail.gmail.com>
Message-ID: <YWag+RpkujjggPsW@lahna>

Hi,

On Tue, Oct 12, 2021 at 03:49:22PM -0300, Mauro Lima wrote:
> Hi Mika
> 
> On Mon, Oct 4, 2021 at 2:18 AM Mika Westerberg
> <mika.westerberg at linux.intel.com> wrote:
> >
> > Hi,
> >
> > On Fri, Oct 01, 2021 at 05:23:23PM -0300, Mauro Lima wrote:
> > > Question for maintainers: With these changes is it safe to remove the
> > > *(DANGEROUS)* tag from menuconfig?
> >
> > I don't think we want to remove that. This driver is not for regular
> > users, at least in its current form.
> Do we know why this is still dangerous for the user?

There was a bug in the driver in the past (that was already fixed but it
did not yet reach the stable trees or something like that). At this
unfortunate time there was no DANGEROUS in the name so Ubuntu kernel
went and enabled it. Combined with the bug certain Lenovo laptops BIOS
turned into read-only which prevented booting from non-default devices.

This happened even when the driver did not do any "write" or "erase"
operations, just clearing the status register or so.

We don't want that to happen again.

> My plan is to make a sys/class driver to query write protection status
> of the SPI, this will be
> used by fwupd to gather information about vendors, also should be easy
> for the user to use
> 'cat' and see the information from userspace. For this to be possible
> we need kernel engineers
> to compile the kernel with this driver enabled, but the (DANGEROUS)
> tag is a no go for most
> of them.
> Is there anything I can do to make this possible?

IMHO we can make certain parts of the driver, that are known not to
cause any issues available without the DANGEROUS. I mean the controller
exposes some information that I think you are intersted in and that does
not cause anything to be sent to the flash chip itself.


From xiangsheng.hou at mediatek.com  Wed Oct 13 02:15:49 2021
From: xiangsheng.hou at mediatek.com (xiangsheng.hou)
Date: Wed, 13 Oct 2021 17:15:49 +0800
Subject: [RFC PATCH 06/10] mtd: nand: mxic-ecc: Add Macronix external
 ECC engine support
In-Reply-To: <20211008162228.1753083-7-miquel.raynal@bootlin.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-7-miquel.raynal@bootlin.com>
Message-ID: <872348abea7317c6b3d2ed53c8139e0927bb991f.camel@mediatek.com>

Hi,

On Fri, 2021-10-08 at 18:22 +0200, Miquel Raynal wrote:
> 
> +static int mxic_ecc_count_biterrs(struct mxic_ecc_engine *eng,
> struct mtd_info *mtd)
> +{
> +	struct device *dev = eng->dev;
> +	unsigned int max_bf = 0;
> +	int step;
> +
> +	for (step = 0; step < eng->steps; step++) {
> +		u8 stat = eng->status[step];
> +
> +		if (stat == NO_ERR) {
> +			dev_dbg(dev, "ECC step %d: no error\n", step);
> +		} else if (stat == ERASED_CHUNK) {
> +			dev_dbg(dev, "ECC step %d: erased\n", step);
> +		} else if (stat == UNCORR_ERR || stat > MAX_CORR_ERR) {
> +			dev_dbg(dev, "ECC step %d: uncorrectable\n",
> step);
> +			mtd->ecc_stats.failed++;
> +		} else {
> +			dev_dbg(dev, "ECC step %d: %d bits
> corrected\n",
> +				step, stat);
> +			max_bf = max_t(unsigned int, max_bf, stat);
> +			mtd->ecc_stats.corrected += stat;
> +		}
> +	}
> +
> +	return max_bf;
> +}

In spinand_mtd_read() function, rely on the return value -EBADMSG to
check whether ecc failed. Therefore, maybe there also need return this
value in mxic_ecc_count_biterrs() function when uncorrectable ecc
error?

Thanks
Xiangsheng Hou

From bostroesser at gmail.com  Wed Oct 13 02:31:11 2021
From: bostroesser at gmail.com (Bodo Stroesser)
Date: Wed, 13 Oct 2021 11:31:11 +0200
Subject: [PATCH 07/29] target/iblock: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-8-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-8-hch@lst.de>
Message-ID: <3babe7ca-cf08-fd19-6793-39f6d78bca12@gmail.com>

On 13.10.21 07:10, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
>   drivers/target/target_core_iblock.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
> index 31df20abe141f..ab7f5678ebc44 100644
> --- a/drivers/target/target_core_iblock.c
> +++ b/drivers/target/target_core_iblock.c
> @@ -232,8 +232,9 @@ static unsigned long long iblock_emulate_read_cap_with_block_size(
>   	struct block_device *bd,
>   	struct request_queue *q)
>   {
> -	unsigned long long blocks_long = (div_u64(i_size_read(bd->bd_inode),
> -					bdev_logical_block_size(bd)) - 1);
> +	loff_t size = bdev_nr_sectors(bd) << SECTOR_SHIFT;
> +	unsigned long long blocks_long =
> +		div_u64(size, bdev_logical_block_size(bd)) - 1;
>   	u32 block_size = bdev_logical_block_size(bd);

To enhance readability, would it make sense to shift the new lines
behind "u32 block_size = ...", so block_size can be used in div_u64
instead of using bdev_logical_block_size twice?

>   
>   	if (block_size == dev->dev_attrib.block_size)
> 


From miquel.raynal at bootlin.com  Wed Oct 13 03:08:07 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 13 Oct 2021 12:08:07 +0200
Subject: [PATCH mtd-utils] mtd-tests: Read and write pages during speed tests
Message-ID: <20211013100807.306920-1-miquel.raynal@bootlin.com>

The speed test does reads and writes of different sizes:
- eraseblock
- page
- two pages

At least this is the theory because, as opposed to the legacy kernel
module doing the same measurement, the userspace tool uses the subpage
size (hence accessing the same page 4, 8 or 16 times depending on the
subpage setting). Of course if the controller does not support subpages,
this issue is not visible.

Use mtd.min_io_size instead for non-NOR devices in order to get the
right bandwidth (at least one that fits the logs).

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

diff --git a/tests/mtd-tests/flash_speed.c b/tests/mtd-tests/flash_speed.c
index 0058269..2fc70a1 100644
--- a/tests/mtd-tests/flash_speed.c
+++ b/tests/mtd-tests/flash_speed.c
@@ -343,7 +343,7 @@ int main(int argc, char **argv)
 		puts("not NAND flash, assume page size is 512 bytes.");
 		pgsize = 512;
 	} else {
-		pgsize = mtd.subpage_size;
+		pgsize = mtd.min_io_size;
 	}
 
 	pgcnt = mtd.eb_size / pgsize;
-- 
2.27.0



From jack at suse.cz  Wed Oct 13 03:42:07 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:42:07 +0200
Subject: [PATCH 09/29] fs: simplify init_page_buffers
In-Reply-To: <20211013051042.1065752-10-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-10-hch@lst.de>
Message-ID: <20211013104207.GD19200@quack2.suse.cz>

On Wed 13-10-21 07:10:22, Christoph Hellwig wrote:
> No need to convert from bdev to inode and back.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:42:27 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:42:27 +0200
Subject: [PATCH 08/29] fs: use bdev_nr_sectors instead of open coding it
 in blkdev_max_block
In-Reply-To: <20211013051042.1065752-9-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-9-hch@lst.de>
Message-ID: <20211013104227.GE19200@quack2.suse.cz>

On Wed 13-10-21 07:10:21, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:43:43 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:43:43 +0200
Subject: [PATCH 21/29] reiserfs: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-22-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-22-hch@lst.de>
Message-ID: <20211013104343.GF19200@quack2.suse.cz>

On Wed 13-10-21 07:10:34, Christoph Hellwig wrote:
> Use the proper helper to read the block device size and remove two
> cargo culted checks that can't be false.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

> ---
>  fs/reiserfs/super.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
> index 58481f8d63d5b..6c9681e2809f0 100644
> --- a/fs/reiserfs/super.c
> +++ b/fs/reiserfs/super.c
> @@ -1986,8 +1986,7 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent)
>  	 * smaller than the filesystem. If the check fails then abort and
>  	 * scream, because bad stuff will happen otherwise.
>  	 */
> -	if (s->s_bdev && s->s_bdev->bd_inode
> -	    && i_size_read(s->s_bdev->bd_inode) <
> +	if ((bdev_nr_sectors(s->s_bdev) << SECTOR_SHIFT) <
>  	    sb_block_count(rs) * sb_blocksize(rs)) {
>  		SWARN(silent, s, "", "Filesystem cannot be "
>  		      "mounted because it is bigger than the device");
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:44:18 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:44:18 +0200
Subject: [PATCH 23/29] block: use bdev_nr_sectors instead of open coding
 it in blkdev_fallocate
In-Reply-To: <20211013051042.1065752-24-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-24-hch@lst.de>
Message-ID: <20211013104418.GG19200@quack2.suse.cz>

On Wed 13-10-21 07:10:36, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:46:15 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:46:15 +0200
Subject: [PATCH 28/29] reiserfs: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-29-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-29-hch@lst.de>
Message-ID: <20211013104615.GH19200@quack2.suse.cz>

On Wed 13-10-21 07:10:41, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:46:33 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:46:33 +0200
Subject: [PATCH 25/29] ext4: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-26-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-26-hch@lst.de>
Message-ID: <20211013104633.GI19200@quack2.suse.cz>

On Wed 13-10-21 07:10:38, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Wed Oct 13 03:47:27 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 13 Oct 2021 12:47:27 +0200
Subject: [PATCH 29/29] udf: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-30-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-30-hch@lst.de>
Message-ID: <20211013104727.GJ19200@quack2.suse.cz>

On Wed 13-10-21 07:10:42, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From richard at nod.at  Wed Oct 13 04:12:43 2021
From: richard at nod.at (Richard Weinberger)
Date: Wed, 13 Oct 2021 13:12:43 +0200 (CEST)
Subject: [PATCH mtd-utils] mtd-tests: Read and write pages during speed
 tests
In-Reply-To: <20211013100807.306920-1-miquel.raynal@bootlin.com>
References: <20211013100807.306920-1-miquel.raynal@bootlin.com>
Message-ID: <308700286.68659.1634123563780.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "Miquel Raynal" <miquel.raynal at bootlin.com>
> An: "david oberhollenzer" <david.oberhollenzer at sigma-star.at>
> CC: "richard" <richard at nod.at>, "Vignesh Raghavendra" <vigneshr at ti.com>, "Tudor Ambarus" <Tudor.Ambarus at microchip.com>,
> "linux-mtd" <linux-mtd at lists.infradead.org>, "Miquel Raynal" <miquel.raynal at bootlin.com>
> Gesendet: Mittwoch, 13. Oktober 2021 12:08:07
> Betreff: [PATCH mtd-utils] mtd-tests: Read and write pages during speed tests

> The speed test does reads and writes of different sizes:
> - eraseblock
> - page
> - two pages
> 
> At least this is the theory because, as opposed to the legacy kernel
> module doing the same measurement, the userspace tool uses the subpage
> size (hence accessing the same page 4, 8 or 16 times depending on the
> subpage setting). Of course if the controller does not support subpages,
> this issue is not visible.
> 
> Use mtd.min_io_size instead for non-NOR devices in order to get the
> right bandwidth (at least one that fits the logs).
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
> tests/mtd-tests/flash_speed.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tests/mtd-tests/flash_speed.c b/tests/mtd-tests/flash_speed.c
> index 0058269..2fc70a1 100644
> --- a/tests/mtd-tests/flash_speed.c
> +++ b/tests/mtd-tests/flash_speed.c
> @@ -343,7 +343,7 @@ int main(int argc, char **argv)
> 		puts("not NAND flash, assume page size is 512 bytes.");
> 		pgsize = 512;
> 	} else {
> -		pgsize = mtd.subpage_size;
> +		pgsize = mtd.min_io_size;

Now the userspace does the same as the kernel test.
On the kernel side it uses mtd->writesize.

Reviewed-by: Richard Weinberger <richard at nod.at>

Thanks,
//richard


From david.oberhollenzer at sigma-star.at  Wed Oct 13 04:20:38 2021
From: david.oberhollenzer at sigma-star.at (David Oberhollenzer)
Date: Wed, 13 Oct 2021 11:20:38 +0000
Subject: [PATCH mtd-utils] mtd-tests: Read and write pages during speed
 tests
In-Reply-To: <308700286.68659.1634123563780.JavaMail.zimbra@nod.at>
References: <20211013100807.306920-1-miquel.raynal@bootlin.com>
 <308700286.68659.1634123563780.JavaMail.zimbra@nod.at>
Message-ID: <fdad1128-af1b-3024-c3dc-09bd2c05cd4e@sigma-star.at>

Applied to mtd-utils.git master.

Thanks,

David



From mika.westerberg at linux.intel.com  Wed Oct 13 04:44:29 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Wed, 13 Oct 2021 14:44:29 +0300
Subject: [PATCH v3 0/3] mtd: spi-nor / spi / MFD: Convert intel-spi to SPI MEM
Message-ID: <20211013114432.31352-1-mika.westerberg@linux.intel.com>

Hi all,

Based on discussion on the patch I sent some time ago here:

  http://lists.infradead.org/pipermail/linux-mtd/2021-June/086867.html

it turns out that the preferred way to deal with the SPI flash controller
drivers is through SPI MEM which is part of Linux SPI subsystem.

This series does that for the intel-spi driver. This also renames the
driver to follow the convention used in the SPI subsystem. The first patch
improves the write protection handling to be slightly more safer. The
following two patches do the conversion itself. Note the Intel SPI flash
controller only allows commands such as read, write and so on and it
internally uses whatever addressing etc. it figured from the SFDP on the
flash device.

Previous versions of the patch series can be found here:

  v2: https://lore.kernel.org/linux-mtd/20211007112132.30934-1-mika.westerberg at linux.intel.com/
  v1: https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/

Changes from v2:

  * Added tag from Andy
  * Check buswidth in intel_spi_supports_mem_op() and return false if octal
    mode is asked. The Intel controllers support buswidths 1-4 but this is
    not exposed to software. It figures this itself through SFDP tables.
  * In case of software sequencer, support same opcodes than we support with
    the hardware sequencer if found in the opcodes table.

Changes from v1:

  * Arrange dependencies in Kconfig entries the same way in both glue
    drivers.
  * Added empty lines between different subsystem includes.
  * dev_err() to single line
  * Return intel_spi_sw_cycle() directly in intel_spi_erase().
  * Drop redundant elses.
  * Fixed typo in the commit message of the patch 3/3.

Mika Westerberg (3):
  mtd: spi-nor: intel-spi: Disable write protection only if asked
  mtd: spi-nor: intel-spi: Convert to SPI MEM
  Documentation / MTD: Rename the intel-spi driver

 Documentation/driver-api/mtd/index.rst        |   2 +-
 .../mtd/{intel-spi.rst => spi-intel.rst}      |   8 +-
 drivers/mfd/lpc_ich.c                         |  59 ++-
 drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
 drivers/mtd/spi-nor/controllers/Makefile      |   3 -
 drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
 drivers/spi/Kconfig                           |  39 ++
 drivers/spi/Makefile                          |   3 +
 .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  49 ++-
 .../spi-intel-platform.c}                     |  21 +-
 .../intel-spi.c => spi/spi-intel.c}           | 357 +++++++++++-------
 drivers/spi/spi-intel.h                       |  19 +
 include/linux/mfd/lpc_ich.h                   |   2 +-
 .../x86/{intel-spi.h => spi-intel.h}          |  12 +-
 14 files changed, 367 insertions(+), 264 deletions(-)
 rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)
 delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
 rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (84%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (77%)
 create mode 100644 drivers/spi/spi-intel.h
 rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (64%)

-- 
2.33.0



From mika.westerberg at linux.intel.com  Wed Oct 13 04:44:30 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Wed, 13 Oct 2021 14:44:30 +0300
Subject: [PATCH v3 1/3] mtd: spi-nor: intel-spi: Disable write protection only
 if asked
In-Reply-To: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
Message-ID: <20211013114432.31352-2-mika.westerberg@linux.intel.com>

Currently the driver tries to disable the BIOS write protection
automatically even if this is not what the user wants. For this reason
modify the driver so that by default it does not touch the write
protection. Only if specifically asked by the user (setting writeable=1
command line parameter) the driver tries to disable the BIOS write
protection.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/mfd/lpc_ich.c                         | 59 +++++++++++++++++--
 .../mtd/spi-nor/controllers/intel-spi-pci.c   | 29 +++++----
 drivers/mtd/spi-nor/controllers/intel-spi.c   | 41 ++++++-------
 include/linux/platform_data/x86/intel-spi.h   |  6 +-
 4 files changed, 96 insertions(+), 39 deletions(-)

diff --git a/drivers/mfd/lpc_ich.c b/drivers/mfd/lpc_ich.c
index f10e53187f67..9ffab9aafd81 100644
--- a/drivers/mfd/lpc_ich.c
+++ b/drivers/mfd/lpc_ich.c
@@ -63,6 +63,8 @@
 #define SPIBASE_BYT		0x54
 #define SPIBASE_BYT_SZ		512
 #define SPIBASE_BYT_EN		BIT(1)
+#define BYT_BCR			0xfc
+#define BYT_BCR_WPD		BIT(0)
 
 #define SPIBASE_LPT		0x3800
 #define SPIBASE_LPT_SZ		512
@@ -1084,12 +1086,57 @@ static int lpc_ich_init_wdt(struct pci_dev *dev)
 	return ret;
 }
 
+static bool lpc_ich_byt_set_writeable(void __iomem *base, void *data)
+{
+	u32 val;
+
+	val = readl(base + BYT_BCR);
+	if (!(val & BYT_BCR_WPD)) {
+		val |= BYT_BCR_WPD;
+		writel(val, base + BYT_BCR);
+		val = readl(base + BYT_BCR);
+	}
+
+	return val & BYT_BCR_WPD;
+}
+
+static bool lpc_ich_lpt_set_writeable(void __iomem *base, void *data)
+{
+	struct pci_dev *pdev = data;
+	u32 bcr;
+
+	pci_read_config_dword(pdev, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_write_config_dword(pdev, BCR, bcr);
+		pci_read_config_dword(pdev, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
+static bool lpc_ich_bxt_set_writeable(void __iomem *base, void *data)
+{
+	unsigned int spi = PCI_DEVFN(13, 2);
+	struct pci_bus *bus = data;
+	u32 bcr;
+
+	pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_bus_write_config_dword(bus, spi, BCR, bcr);
+		pci_bus_read_config_dword(bus, spi, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
 static int lpc_ich_init_spi(struct pci_dev *dev)
 {
 	struct lpc_ich_priv *priv = pci_get_drvdata(dev);
 	struct resource *res = &intel_spi_res[0];
 	struct intel_spi_boardinfo *info;
-	u32 spi_base, rcba, bcr;
+	u32 spi_base, rcba;
 
 	info = devm_kzalloc(&dev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -1103,6 +1150,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 		if (spi_base & SPIBASE_BYT_EN) {
 			res->start = spi_base & ~(SPIBASE_BYT_SZ - 1);
 			res->end = res->start + SPIBASE_BYT_SZ - 1;
+
+			info->set_writeable = lpc_ich_byt_set_writeable;
 		}
 		break;
 
@@ -1113,8 +1162,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 			res->start = spi_base + SPIBASE_LPT;
 			res->end = res->start + SPIBASE_LPT_SZ - 1;
 
-			pci_read_config_dword(dev, BCR, &bcr);
-			info->writeable = !!(bcr & BCR_WPD);
+			info->set_writeable = lpc_ich_lpt_set_writeable;
+			info->data = dev;
 		}
 		break;
 
@@ -1135,8 +1184,8 @@ static int lpc_ich_init_spi(struct pci_dev *dev)
 			res->start = spi_base & 0xfffffff0;
 			res->end = res->start + SPIBASE_APL_SZ - 1;
 
-			pci_bus_read_config_dword(bus, spi, BCR, &bcr);
-			info->writeable = !!(bcr & BCR_WPD);
+			info->set_writeable = lpc_ich_bxt_set_writeable;
+			info->data = bus;
 		}
 
 		pci_bus_write_config_byte(bus, p2sb, 0xe1, 0x1);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
index 1bc53b8bb88a..508f7ca098ef 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
@@ -16,12 +16,30 @@
 #define BCR		0xdc
 #define BCR_WPD		BIT(0)
 
+static bool intel_spi_pci_set_writeable(void __iomem *base, void *data)
+{
+	struct pci_dev *pdev = data;
+	u32 bcr;
+
+	/* Try to make the chip read/write */
+	pci_read_config_dword(pdev, BCR, &bcr);
+	if (!(bcr & BCR_WPD)) {
+		bcr |= BCR_WPD;
+		pci_write_config_dword(pdev, BCR, bcr);
+		pci_read_config_dword(pdev, BCR, &bcr);
+	}
+
+	return bcr & BCR_WPD;
+}
+
 static const struct intel_spi_boardinfo bxt_info = {
 	.type = INTEL_SPI_BXT,
+	.set_writeable = intel_spi_pci_set_writeable,
 };
 
 static const struct intel_spi_boardinfo cnl_info = {
 	.type = INTEL_SPI_CNL,
+	.set_writeable = intel_spi_pci_set_writeable,
 };
 
 static int intel_spi_pci_probe(struct pci_dev *pdev,
@@ -29,7 +47,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 {
 	struct intel_spi_boardinfo *info;
 	struct intel_spi *ispi;
-	u32 bcr;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -41,15 +58,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 	if (!info)
 		return -ENOMEM;
 
-	/* Try to make the chip read/write */
-	pci_read_config_dword(pdev, BCR, &bcr);
-	if (!(bcr & BCR_WPD)) {
-		bcr |= BCR_WPD;
-		pci_write_config_dword(pdev, BCR, bcr);
-		pci_read_config_dword(pdev, BCR, &bcr);
-	}
-	info->writeable = !!(bcr & BCR_WPD);
-
+	info->data = pdev;
 	ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
 	if (IS_ERR(ispi))
 		return PTR_ERR(ispi);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
index a413892ff449..f35597cbea0c 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi.c
+++ b/drivers/mtd/spi-nor/controllers/intel-spi.c
@@ -131,7 +131,6 @@
  * @sregs: Start of software sequencer registers
  * @nregions: Maximum number of regions
  * @pr_num: Maximum number of protected range registers
- * @writeable: Is the chip writeable
  * @locked: Is SPI setting locked
  * @swseq_reg: Use SW sequencer in register reads/writes
  * @swseq_erase: Use SW sequencer in erase operation
@@ -149,7 +148,6 @@ struct intel_spi {
 	void __iomem *sregs;
 	size_t nregions;
 	size_t pr_num;
-	bool writeable;
 	bool locked;
 	bool swseq_reg;
 	bool swseq_erase;
@@ -304,6 +302,14 @@ static int intel_spi_wait_sw_busy(struct intel_spi *ispi)
 				  INTEL_SPI_TIMEOUT * 1000);
 }
 
+static bool intel_spi_set_writeable(struct intel_spi *ispi)
+{
+	if (!ispi->info->set_writeable)
+		return false;
+
+	return ispi->info->set_writeable(ispi->base, ispi->info->data);
+}
+
 static int intel_spi_init(struct intel_spi *ispi)
 {
 	u32 opmenu0, opmenu1, lvscc, uvscc, val;
@@ -316,19 +322,6 @@ static int intel_spi_init(struct intel_spi *ispi)
 		ispi->nregions = BYT_FREG_NUM;
 		ispi->pr_num = BYT_PR_NUM;
 		ispi->swseq_reg = true;
-
-		if (writeable) {
-			/* Disable write protection */
-			val = readl(ispi->base + BYT_BCR);
-			if (!(val & BYT_BCR_WPD)) {
-				val |= BYT_BCR_WPD;
-				writel(val, ispi->base + BYT_BCR);
-				val = readl(ispi->base + BYT_BCR);
-			}
-
-			ispi->writeable = !!(val & BYT_BCR_WPD);
-		}
-
 		break;
 
 	case INTEL_SPI_LPT:
@@ -358,6 +351,12 @@ static int intel_spi_init(struct intel_spi *ispi)
 		return -EINVAL;
 	}
 
+	/* Try to disable write protection if user asked to do so */
+	if (writeable && !intel_spi_set_writeable(ispi)) {
+		dev_warn(ispi->dev, "can't disable chip write protection\n");
+		writeable = false;
+	}
+
 	/* Disable #SMI generation from HW sequencer */
 	val = readl(ispi->base + HSFSTS_CTL);
 	val &= ~HSFSTS_CTL_FSMIE;
@@ -884,9 +883,12 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
 		/*
 		 * If any of the regions have protection bits set, make the
 		 * whole partition read-only to be on the safe side.
+		 *
+		 * Also if the user did not ask the chip to be writeable
+		 * mask the bit too.
 		 */
-		if (intel_spi_is_protected(ispi, base, limit))
-			ispi->writeable = false;
+		if (!writeable || intel_spi_is_protected(ispi, base, limit))
+			part->mask_flags |= MTD_WRITEABLE;
 
 		end = (limit << 12) + 4096;
 		if (end > part->size)
@@ -927,7 +929,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
 
 	ispi->dev = dev;
 	ispi->info = info;
-	ispi->writeable = info->writeable;
 
 	ret = intel_spi_init(ispi);
 	if (ret)
@@ -945,10 +946,6 @@ struct intel_spi *intel_spi_probe(struct device *dev,
 
 	intel_spi_fill_partition(ispi, &part);
 
-	/* Prevent writes if not explicitly enabled */
-	if (!ispi->writeable || !writeable)
-		ispi->nor.mtd.flags &= ~MTD_WRITEABLE;
-
 	ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
 	if (ret)
 		return ERR_PTR(ret);
diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/intel-spi.h
index 7f53a5c6f35e..7dda3f690465 100644
--- a/include/linux/platform_data/x86/intel-spi.h
+++ b/include/linux/platform_data/x86/intel-spi.h
@@ -19,11 +19,13 @@ enum intel_spi_type {
 /**
  * struct intel_spi_boardinfo - Board specific data for Intel SPI driver
  * @type: Type which this controller is compatible with
- * @writeable: The chip is writeable
+ * @set_writeable: Try to make the chip writeable (optional)
+ * @data: Data to be passed to @set_writeable can be %NULL
  */
 struct intel_spi_boardinfo {
 	enum intel_spi_type type;
-	bool writeable;
+	bool (*set_writeable)(void __iomem *base, void *data);
+	void *data;
 };
 
 #endif /* INTEL_SPI_PDATA_H */
-- 
2.33.0



From mika.westerberg at linux.intel.com  Wed Oct 13 04:44:32 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Wed, 13 Oct 2021 14:44:32 +0300
Subject: [PATCH v3 3/3] Documentation / MTD: Rename the intel-spi driver
In-Reply-To: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
Message-ID: <20211013114432.31352-4-mika.westerberg@linux.intel.com>

Since the driver is renamed (and moved) update the BIOS upgrade guide
accordingly from intel-spi to spi-intel. Keep the guide under MTD
documentation because this is pretty much still about MTD and SPI-NOR.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 Documentation/driver-api/mtd/index.rst                    | 2 +-
 .../driver-api/mtd/{intel-spi.rst => spi-intel.rst}       | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)
 rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)

diff --git a/Documentation/driver-api/mtd/index.rst b/Documentation/driver-api/mtd/index.rst
index 436ba5a851d7..6a4278f409d7 100644
--- a/Documentation/driver-api/mtd/index.rst
+++ b/Documentation/driver-api/mtd/index.rst
@@ -7,6 +7,6 @@ Memory Technology Device (MTD)
 .. toctree::
    :maxdepth: 1
 
-   intel-spi
+   spi-intel
    nand_ecc
    spi-nor
diff --git a/Documentation/driver-api/mtd/intel-spi.rst b/Documentation/driver-api/mtd/spi-intel.rst
similarity index 94%
rename from Documentation/driver-api/mtd/intel-spi.rst
rename to Documentation/driver-api/mtd/spi-intel.rst
index 0465f6879262..df854f20ead1 100644
--- a/Documentation/driver-api/mtd/intel-spi.rst
+++ b/Documentation/driver-api/mtd/spi-intel.rst
@@ -1,5 +1,5 @@
 ==============================
-Upgrading BIOS using intel-spi
+Upgrading BIOS using spi-intel
 ==============================
 
 Many Intel CPUs like Baytrail and Braswell include SPI serial flash host
@@ -11,12 +11,12 @@ avoid accidental (or on purpose) overwrite of the content.
 Not all manufacturers protect the SPI serial flash, mainly because it
 allows upgrading the BIOS image directly from an OS.
 
-The intel-spi driver makes it possible to read and write the SPI serial
+The spi-intel driver makes it possible to read and write the SPI serial
 flash, if certain protection bits are not set and locked. If it finds
 any of them set, the whole MTD device is made read-only to prevent
 partial overwrites. By default the driver exposes SPI serial flash
 contents as read-only but it can be changed from kernel command line,
-passing "intel-spi.writeable=1".
+passing "spi_intel.writeable=1".
 
 Please keep in mind that overwriting the BIOS image on SPI serial flash
 might render the machine unbootable and requires special equipment like
@@ -32,7 +32,7 @@ Linux.
     serial flash. Distros like Debian and Fedora have this prepackaged with
     name "mtd-utils".
 
- 3) Add "intel-spi.writeable=1" to the kernel command line and reboot
+ 3) Add "spi_intel.writeable=1" to the kernel command line and reboot
     the board (you can also reload the driver passing "writeable=1" as
     module parameter to modprobe).
 
-- 
2.33.0



From mika.westerberg at linux.intel.com  Wed Oct 13 04:44:31 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Wed, 13 Oct 2021 14:44:31 +0300
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
Message-ID: <20211013114432.31352-3-mika.westerberg@linux.intel.com>

The preferred way to implement SPI-NOR controller drivers is through SPI
subsubsystem utilizing the SPI MEM core functions. This converts the
Intel SPI flash controller driver over the SPI MEM by moving the driver
from SPI-NOR subsystem to SPI subsystem and in one go make it use the
SPI MEM functions. The driver name will be changed from intel-spi to
spi-intel to match the convention used in the SPI subsystem.

Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
---
 drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
 drivers/mtd/spi-nor/controllers/Makefile      |   3 -
 drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
 drivers/spi/Kconfig                           |  39 +++
 drivers/spi/Makefile                          |   3 +
 .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
 .../spi-intel-platform.c}                     |  21 +-
 .../intel-spi.c => spi/spi-intel.c}           | 316 +++++++++++-------
 drivers/spi/spi-intel.h                       |  19 ++
 include/linux/mfd/lpc_ich.h                   |   2 +-
 .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
 11 files changed, 266 insertions(+), 220 deletions(-)
 delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
 rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
 rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (79%)
 create mode 100644 drivers/spi/spi-intel.h
 rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)

diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig
index 5c0e0ec2e6d1..50f4f3484d42 100644
--- a/drivers/mtd/spi-nor/controllers/Kconfig
+++ b/drivers/mtd/spi-nor/controllers/Kconfig
@@ -26,39 +26,3 @@ config SPI_NXP_SPIFI
 	  SPIFI is a specialized controller for connecting serial SPI
 	  Flash. Enable this option if you have a device with a SPIFI
 	  controller and want to access the Flash as a mtd device.
-
-config SPI_INTEL_SPI
-	tristate
-
-config SPI_INTEL_SPI_PCI
-	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
-	depends on X86 && PCI
-	select SPI_INTEL_SPI
-	help
-	  This enables PCI support for the Intel PCH/PCU SPI controller in
-	  master mode. This controller is present in modern Intel hardware
-	  and is used to hold BIOS and other persistent settings. Using
-	  this driver it is possible to upgrade BIOS directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-pci.
-
-config SPI_INTEL_SPI_PLATFORM
-	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
-	depends on X86
-	select SPI_INTEL_SPI
-	help
-	  This enables platform support for the Intel PCH/PCU SPI
-	  controller in master mode. This controller is present in modern
-	  Intel hardware and is used to hold BIOS and other persistent
-	  settings. Using this driver it is possible to upgrade BIOS
-	  directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-platform.
diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile
index e7abba491d98..6e2a1dc68466 100644
--- a/drivers/mtd/spi-nor/controllers/Makefile
+++ b/drivers/mtd/spi-nor/controllers/Makefile
@@ -2,6 +2,3 @@
 obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
 obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
 obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
-obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
-obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
-obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h
deleted file mode 100644
index f2871179fd34..000000000000
--- a/drivers/mtd/spi-nor/controllers/intel-spi.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Intel PCH/PCU SPI flash driver.
- *
- * Copyright (C) 2016, Intel Corporation
- * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
- */
-
-#ifndef INTEL_SPI_H
-#define INTEL_SPI_H
-
-#include <linux/platform_data/x86/intel-spi.h>
-
-struct intel_spi;
-struct resource;
-
-struct intel_spi *intel_spi_probe(struct device *dev,
-	struct resource *mem, const struct intel_spi_boardinfo *info);
-int intel_spi_remove(struct intel_spi *ispi);
-
-#endif /* INTEL_SPI_H */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 83e352b0c8f9..5fe26de43537 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -406,6 +406,45 @@ config SPI_IMX
 	help
 	  This enables support for the Freescale i.MX SPI controllers.
 
+config SPI_INTEL
+	tristate
+
+config SPI_INTEL_PCI
+	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
+	depends on PCI
+	depends on X86 || COMPILE_TEST
+	depends on SPI_MEM
+	select SPI_INTEL
+	help
+	  This enables PCI support for the Intel PCH/PCU SPI controller in
+	  master mode. This controller is present in modern Intel hardware
+	  and is used to hold BIOS and other persistent settings. Using
+	  this driver it is possible to upgrade BIOS directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called spi-intel-pci.
+
+config SPI_INTEL_PLATFORM
+	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
+	depends on X86 || COMPILE_TEST
+	depends on SPI_MEM
+	select SPI_INTEL
+	help
+	  This enables platform support for the Intel PCH/PCU SPI
+	  controller in master mode. This controller is present in modern
+	  Intel hardware and is used to hold BIOS and other persistent
+	  settings. Using this driver it is possible to upgrade BIOS
+	  directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called spi-intel-platform.
+
 config SPI_JCORE
 	tristate "J-Core SPI Master"
 	depends on OF && (SUPERH || COMPILE_TEST)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 699db95c8441..070918a79362 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -59,6 +59,9 @@ obj-$(CONFIG_SPI_HISI_KUNPENG)		+= spi-hisi-kunpeng.o
 obj-$(CONFIG_SPI_HISI_SFC_V3XX)		+= spi-hisi-sfc-v3xx.o
 obj-$(CONFIG_SPI_IMG_SPFI)		+= spi-img-spfi.o
 obj-$(CONFIG_SPI_IMX)			+= spi-imx.o
+obj-$(CONFIG_SPI_INTEL)			+= spi-intel.o
+obj-$(CONFIG_SPI_INTEL_PCI)		+= spi-intel-pci.o
+obj-$(CONFIG_SPI_INTEL_PLATFORM)	+= spi-intel-platform.o
 obj-$(CONFIG_SPI_LANTIQ_SSC)		+= spi-lantiq-ssc.o
 obj-$(CONFIG_SPI_JCORE)			+= spi-jcore.o
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi-lm70llp.o
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c b/drivers/spi/spi-intel-pci.c
similarity index 86%
rename from drivers/mtd/spi-nor/controllers/intel-spi-pci.c
rename to drivers/spi/spi-intel-pci.c
index 508f7ca098ef..a177b10bc288 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
+++ b/drivers/spi/spi-intel-pci.c
@@ -2,16 +2,14 @@
 /*
  * Intel PCH/PCU SPI flash PCI driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/ioport.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 
-#include "intel-spi.h"
+#include "spi-intel.h"
 
 #define BCR		0xdc
 #define BCR_WPD		BIT(0)
@@ -46,7 +44,6 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 			       const struct pci_device_id *id)
 {
 	struct intel_spi_boardinfo *info;
-	struct intel_spi *ispi;
 	int ret;
 
 	ret = pcim_enable_device(pdev);
@@ -59,17 +56,7 @@ static int intel_spi_pci_probe(struct pci_dev *pdev,
 		return -ENOMEM;
 
 	info->data = pdev;
-	ispi = intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
-	if (IS_ERR(ispi))
-		return PTR_ERR(ispi);
-
-	pci_set_drvdata(pdev, ispi);
-	return 0;
-}
-
-static void intel_spi_pci_remove(struct pci_dev *pdev)
-{
-	intel_spi_remove(pci_get_drvdata(pdev));
+	return intel_spi_probe(&pdev->dev, &pdev->resource[0], info);
 }
 
 static const struct pci_device_id intel_spi_pci_ids[] = {
@@ -98,7 +85,6 @@ static struct pci_driver intel_spi_pci_driver = {
 	.name = "intel-spi",
 	.id_table = intel_spi_pci_ids,
 	.probe = intel_spi_pci_probe,
-	.remove = intel_spi_pci_remove,
 };
 
 module_pci_driver(intel_spi_pci_driver);
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c b/drivers/spi/spi-intel-platform.c
similarity index 65%
rename from drivers/mtd/spi-nor/controllers/intel-spi-platform.c
rename to drivers/spi/spi-intel-platform.c
index f80f1086f928..293e03f239de 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi-platform.c
+++ b/drivers/spi/spi-intel-platform.c
@@ -2,20 +2,18 @@
 /*
  * Intel PCH/PCU SPI flash platform driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
-#include "intel-spi.h"
+#include "spi-intel.h"
 
 static int intel_spi_platform_probe(struct platform_device *pdev)
 {
 	struct intel_spi_boardinfo *info;
-	struct intel_spi *ispi;
 	struct resource *mem;
 
 	info = dev_get_platdata(&pdev->dev);
@@ -23,24 +21,11 @@ static int intel_spi_platform_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	ispi = intel_spi_probe(&pdev->dev, mem, info);
-	if (IS_ERR(ispi))
-		return PTR_ERR(ispi);
-
-	platform_set_drvdata(pdev, ispi);
-	return 0;
-}
-
-static int intel_spi_platform_remove(struct platform_device *pdev)
-{
-	struct intel_spi *ispi = platform_get_drvdata(pdev);
-
-	return intel_spi_remove(ispi);
+	return intel_spi_probe(&pdev->dev, mem, info);
 }
 
 static struct platform_driver intel_spi_platform_driver = {
 	.probe = intel_spi_platform_probe,
-	.remove = intel_spi_platform_remove,
 	.driver = {
 		.name = "intel-spi",
 	},
diff --git a/drivers/mtd/spi-nor/controllers/intel-spi.c b/drivers/spi/spi-intel.c
similarity index 79%
rename from drivers/mtd/spi-nor/controllers/intel-spi.c
rename to drivers/spi/spi-intel.c
index f35597cbea0c..6ce981637ba6 100644
--- a/drivers/mtd/spi-nor/controllers/intel-spi.c
+++ b/drivers/spi/spi-intel.c
@@ -2,21 +2,21 @@
 /*
  * Intel PCH/PCU SPI flash driver.
  *
- * Copyright (C) 2016, Intel Corporation
+ * Copyright (C) 2016 - 2021 Intel Corporation
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#include <linux/err.h>
-#include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/mtd/mtd.h>
+
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/spi-nor.h>
 
-#include "intel-spi.h"
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+#include "spi-intel.h"
 
 /* Offsets are from @ispi->base */
 #define BFPREG				0x00
@@ -92,8 +92,6 @@
 /* CPU specifics */
 #define BYT_PR				0x74
 #define BYT_SSFSTS_CTL			0x90
-#define BYT_BCR				0xfc
-#define BYT_BCR_WPD			BIT(0)
 #define BYT_FREG_NUM			5
 #define BYT_PR_NUM			5
 
@@ -125,10 +123,10 @@
  * struct intel_spi - Driver private data
  * @dev: Device pointer
  * @info: Pointer to board specific info
- * @nor: SPI NOR layer structure
  * @base: Beginning of MMIO space
  * @pregs: Start of protection registers
  * @sregs: Start of software sequencer registers
+ * @master: Pointer to the SPI controller structure
  * @nregions: Maximum number of regions
  * @pr_num: Maximum number of protected range registers
  * @locked: Is SPI setting locked
@@ -142,10 +140,10 @@
 struct intel_spi {
 	struct device *dev;
 	const struct intel_spi_boardinfo *info;
-	struct spi_nor nor;
 	void __iomem *base;
 	void __iomem *pregs;
 	void __iomem *sregs;
+	struct spi_controller *master;
 	size_t nregions;
 	size_t pr_num;
 	bool locked;
@@ -199,9 +197,6 @@ static void intel_spi_dump_regs(struct intel_spi *ispi)
 			readl(ispi->sregs + OPMENU1));
 	}
 
-	if (ispi->info->type == INTEL_SPI_BYT)
-		dev_dbg(ispi->dev, "BCR=0x%08x\n", readl(ispi->base + BYT_BCR));
-
 	dev_dbg(ispi->dev, "LVSCC=0x%08x\n", readl(ispi->base + LVSCC));
 	dev_dbg(ispi->dev, "UVSCC=0x%08x\n", readl(ispi->base + UVSCC));
 
@@ -419,7 +414,6 @@ static int intel_spi_init(struct intel_spi *ispi)
 	}
 
 	intel_spi_dump_regs(ispi);
-
 	return 0;
 }
 
@@ -553,10 +547,9 @@ static int intel_spi_sw_cycle(struct intel_spi *ispi, u8 opcode, size_t len,
 	return 0;
 }
 
-static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+static int intel_spi_read_reg(struct intel_spi *ispi, u8 opcode, void *buf,
 			      size_t len)
 {
-	struct intel_spi *ispi = nor->priv;
 	int ret;
 
 	/* Address of the first chip */
@@ -574,10 +567,9 @@ static int intel_spi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
 	return intel_spi_read_block(ispi, buf, len);
 }
 
-static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
+static int intel_spi_write_reg(struct intel_spi *ispi, u8 opcode, const void *buf,
 			       size_t len)
 {
-	struct intel_spi *ispi = nor->priv;
 	int ret;
 
 	/*
@@ -632,10 +624,9 @@ static int intel_spi_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
 	return intel_spi_hw_cycle(ispi, opcode, len);
 }
 
-static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
-			      u_char *read_buf)
+static ssize_t intel_spi_read(struct intel_spi *ispi, u32 from, size_t len,
+			      void *read_buf)
 {
-	struct intel_spi *ispi = nor->priv;
 	size_t block_size, retlen = 0;
 	u32 val, status;
 	ssize_t ret;
@@ -647,16 +638,6 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 	if (WARN_ON_ONCE(ispi->atomic_preopcode))
 		ispi->atomic_preopcode = 0;
 
-	switch (nor->read_opcode) {
-	case SPINOR_OP_READ:
-	case SPINOR_OP_READ_FAST:
-	case SPINOR_OP_READ_4B:
-	case SPINOR_OP_READ_FAST_4B:
-		break;
-	default:
-		return -EINVAL;
-	}
-
 	while (len > 0) {
 		block_size = min_t(size_t, len, INTEL_SPI_FIFO_SZ);
 
@@ -685,8 +666,7 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 			ret = -EACCES;
 
 		if (ret < 0) {
-			dev_err(ispi->dev, "read error: %llx: %#x\n", from,
-				status);
+			dev_err(ispi->dev, "read error: %x: %#x\n", from, status);
 			return ret;
 		}
 
@@ -703,10 +683,9 @@ static ssize_t intel_spi_read(struct spi_nor *nor, loff_t from, size_t len,
 	return retlen;
 }
 
-static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
-			       const u_char *write_buf)
+static ssize_t intel_spi_write(struct intel_spi *ispi, u32 to, size_t len,
+			       const void *write_buf)
 {
-	struct intel_spi *ispi = nor->priv;
 	size_t block_size, retlen = 0;
 	u32 val, status;
 	ssize_t ret;
@@ -752,8 +731,7 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
 			ret = -EACCES;
 
 		if (ret < 0) {
-			dev_err(ispi->dev, "write error: %llx: %#x\n", to,
-				status);
+			dev_err(ispi->dev, "write error: %x: %#x\n", to, status);
 			return ret;
 		}
 
@@ -766,68 +744,160 @@ static ssize_t intel_spi_write(struct spi_nor *nor, loff_t to, size_t len,
 	return retlen;
 }
 
-static int intel_spi_erase(struct spi_nor *nor, loff_t offs)
+static int intel_spi_erase(struct intel_spi *ispi, u8 opcode, u32 offs)
 {
-	size_t erase_size, len = nor->mtd.erasesize;
-	struct intel_spi *ispi = nor->priv;
 	u32 val, status, cmd;
 	int ret;
 
-	/* If the hardware can do 64k erase use that when possible */
-	if (len >= SZ_64K && ispi->erase_64k) {
+	switch (opcode) {
+	case SPINOR_OP_SE:
 		cmd = HSFSTS_CTL_FCYCLE_ERASE_64K;
-		erase_size = SZ_64K;
-	} else {
+		break;
+
+	case SPINOR_OP_BE_4K:
 		cmd = HSFSTS_CTL_FCYCLE_ERASE;
-		erase_size = SZ_4K;
+		break;
+
+	default:
+		return -EINVAL;
 	}
 
-	if (ispi->swseq_erase) {
-		while (len > 0) {
-			writel(offs, ispi->base + FADDR);
+	writel(offs, ispi->base + FADDR);
+
+	if (ispi->swseq_erase)
+		return intel_spi_sw_cycle(ispi, opcode, 0,
+					  OPTYPE_WRITE_WITH_ADDR);
+
+	/* Not needed with HW sequencer erase, make sure it is cleared */
+	ispi->atomic_preopcode = 0;
+
+	val = readl(ispi->base + HSFSTS_CTL);
+	val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
+	val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
+	val |= HSFSTS_CTL_FGO;
+	val |= cmd;
+	writel(val, ispi->base + HSFSTS_CTL);
+
+	ret = intel_spi_wait_hw_busy(ispi);
+	if (ret)
+		return ret;
+
+	status = readl(ispi->base + HSFSTS_CTL);
+	if (status & HSFSTS_CTL_FCERR)
+		return -EIO;
+	if (status & HSFSTS_CTL_AEL)
+		return -EACCES;
 
-			ret = intel_spi_sw_cycle(ispi, nor->erase_opcode,
-						 0, OPTYPE_WRITE_WITH_ADDR);
-			if (ret)
-				return ret;
+	return 0;
+}
 
-			offs += erase_size;
-			len -= erase_size;
+static bool intel_spi_supports_mem_op(struct spi_mem *mem,
+				      const struct spi_mem_op *op)
+{
+	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+
+	if (op->cmd.dtr)
+		return false;
+
+	/*
+	 * The Intel controller supports widths up to 4 but it handles
+	 * them automatically and does not expose them to software. Here
+	 * we accept anything up to 4.
+	 */
+	if (op->cmd.buswidth > 4 ||
+	    (op->addr.nbytes && op->addr.buswidth > 4) ||
+	    (op->dummy.nbytes && op->dummy.buswidth > 4))
+		return false;
+
+	if (ispi->swseq_reg && ispi->locked) {
+		int i;
+
+		/* Check if it is in the locked opcodes list */
+		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
+			if (ispi->opcodes[i] == op->cmd.opcode)
+				goto check_opcode;
 		}
 
-		return 0;
+		return false;
 	}
 
-	/* Not needed with HW sequencer erase, make sure it is cleared */
-	ispi->atomic_preopcode = 0;
+check_opcode:
+	switch (op->cmd.opcode) {
+	case SPINOR_OP_RDID:
+	case SPINOR_OP_RDSR:
+	case SPINOR_OP_WRSR:
+		return true;
 
-	while (len > 0) {
-		writel(offs, ispi->base + FADDR);
+	case SPINOR_OP_READ:
+	case SPINOR_OP_READ_FAST:
+	case SPINOR_OP_READ_4B:
+	case SPINOR_OP_READ_FAST_4B:
+		return true;
 
-		val = readl(ispi->base + HSFSTS_CTL);
-		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
-		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
-		val |= cmd;
-		val |= HSFSTS_CTL_FGO;
-		writel(val, ispi->base + HSFSTS_CTL);
+	case SPINOR_OP_PP:
+	case SPINOR_OP_PP_4B:
+	case SPINOR_OP_WREN:
+	case SPINOR_OP_WRDI:
+		return true;
 
-		ret = intel_spi_wait_hw_busy(ispi);
-		if (ret)
-			return ret;
+	case SPINOR_OP_SE:
+	case SPINOR_OP_SE_4B:
+		return ispi->erase_64k;
 
-		status = readl(ispi->base + HSFSTS_CTL);
-		if (status & HSFSTS_CTL_FCERR)
-			return -EIO;
-		else if (status & HSFSTS_CTL_AEL)
-			return -EACCES;
+	case SPINOR_OP_BE_4K:
+	case SPINOR_OP_BE_4K_4B:
+		return true;
+	}
 
-		offs += erase_size;
-		len -= erase_size;
+	return false;
+}
+
+static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+	size_t nbytes = op->data.nbytes;
+	u8 opcode = op->cmd.opcode;
+
+	if (op->addr.nbytes) {
+		if  (op->data.dir == SPI_MEM_DATA_IN)
+			return intel_spi_read(ispi, op->addr.val, nbytes,
+					      op->data.buf.in);
+		if (op->data.dir == SPI_MEM_DATA_OUT)
+			return intel_spi_write(ispi, op->addr.val, nbytes,
+					       op->data.buf.out);
+		if (op->data.dir == SPI_MEM_NO_DATA)
+			return intel_spi_erase(ispi, opcode, op->addr.val);
+	} else {
+		if  (op->data.dir == SPI_MEM_DATA_IN)
+			return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
+						  nbytes);
+		if (op->data.dir == SPI_MEM_DATA_OUT)
+			return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
+						   nbytes);
+		if (op->data.dir == SPI_MEM_NO_DATA)
+			return intel_spi_write_reg(ispi, opcode, NULL, 0);
 	}
 
-	return 0;
+	return -EINVAL;
+}
+
+static const char *intel_spi_get_name(struct spi_mem *mem)
+{
+	const struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
+
+	/*
+	 * Return name of the flash controller device to be compatible
+	 * with the MTD version.
+	 */
+	return dev_name(ispi->dev);
 }
 
+static const struct spi_controller_mem_ops intel_spi_mem_ops = {
+	.supports_op = intel_spi_supports_mem_op,
+	.exec_op = intel_spi_exec_mem_op,
+	.get_name = intel_spi_get_name,
+};
+
 static bool intel_spi_is_protected(const struct intel_spi *ispi,
 				   unsigned int base, unsigned int limit)
 {
@@ -896,70 +966,74 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
 	}
 }
 
-static const struct spi_nor_controller_ops intel_spi_controller_ops = {
-	.read_reg = intel_spi_read_reg,
-	.write_reg = intel_spi_write_reg,
-	.read = intel_spi_read,
-	.write = intel_spi_write,
-	.erase = intel_spi_erase,
-};
+static int intel_spi_populate_chip(struct intel_spi *ispi)
+{
+	struct flash_platform_data *pdata;
+	struct spi_board_info chip;
+
+	pdata = devm_kzalloc(ispi->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->nr_parts = 1;
+	pdata->parts = devm_kcalloc(ispi->dev, sizeof(*pdata->parts),
+				    pdata->nr_parts, GFP_KERNEL);
+	if (!pdata->parts)
+		return -ENOMEM;
+
+	intel_spi_fill_partition(ispi, pdata->parts);
+
+	memset(&chip, 0, sizeof(chip));
+	snprintf(chip.modalias, 8, "spi-nor");
+	chip.platform_data = pdata;
+
+	return spi_new_device(ispi->master, &chip) ? 0 : -ENODEV;
+}
 
-struct intel_spi *intel_spi_probe(struct device *dev,
-	struct resource *mem, const struct intel_spi_boardinfo *info)
+/**
+ * intel_spi_probe() - Probe the Intel SPI flash controller
+ * @dev: Pointer to the parent device
+ * @mem: MMIO resource
+ * @info: Platform spefific information
+ *
+ * Probes Intel SPI flash controller and creates the flash chip device.
+ * Returns %0 on success and negative errno in case of failure.
+ */
+int intel_spi_probe(struct device *dev, struct resource *mem,
+		    const struct intel_spi_boardinfo *info)
 {
-	const struct spi_nor_hwcaps hwcaps = {
-		.mask = SNOR_HWCAPS_READ |
-			SNOR_HWCAPS_READ_FAST |
-			SNOR_HWCAPS_PP,
-	};
-	struct mtd_partition part;
+	struct spi_controller *master;
 	struct intel_spi *ispi;
 	int ret;
 
-	if (!info || !mem)
-		return ERR_PTR(-EINVAL);
+	master = devm_spi_alloc_master(dev, sizeof(*ispi));
+	if (!master)
+		return -ENOMEM;
+
+	master->mem_ops = &intel_spi_mem_ops;
 
-	ispi = devm_kzalloc(dev, sizeof(*ispi), GFP_KERNEL);
-	if (!ispi)
-		return ERR_PTR(-ENOMEM);
+	ispi = spi_master_get_devdata(master);
 
 	ispi->base = devm_ioremap_resource(dev, mem);
 	if (IS_ERR(ispi->base))
-		return ERR_CAST(ispi->base);
+		return PTR_ERR(ispi->base);
 
 	ispi->dev = dev;
+	ispi->master = master;
 	ispi->info = info;
 
 	ret = intel_spi_init(ispi);
 	if (ret)
-		return ERR_PTR(ret);
-
-	ispi->nor.dev = ispi->dev;
-	ispi->nor.priv = ispi;
-	ispi->nor.controller_ops = &intel_spi_controller_ops;
-
-	ret = spi_nor_scan(&ispi->nor, NULL, &hwcaps);
-	if (ret) {
-		dev_info(dev, "failed to locate the chip\n");
-		return ERR_PTR(ret);
-	}
-
-	intel_spi_fill_partition(ispi, &part);
+		return ret;
 
-	ret = mtd_device_register(&ispi->nor.mtd, &part, 1);
+	ret = devm_spi_register_master(dev, master);
 	if (ret)
-		return ERR_PTR(ret);
+		return ret;
 
-	return ispi;
+	return intel_spi_populate_chip(ispi);
 }
 EXPORT_SYMBOL_GPL(intel_spi_probe);
 
-int intel_spi_remove(struct intel_spi *ispi)
-{
-	return mtd_device_unregister(&ispi->nor.mtd);
-}
-EXPORT_SYMBOL_GPL(intel_spi_remove);
-
 MODULE_DESCRIPTION("Intel PCH/PCU SPI flash core driver");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg at linux.intel.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/spi/spi-intel.h b/drivers/spi/spi-intel.h
new file mode 100644
index 000000000000..40f947f6941a
--- /dev/null
+++ b/drivers/spi/spi-intel.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Intel PCH/PCU SPI flash driver.
+ *
+ * Copyright (C) 2016 - 2021, Intel Corporation
+ * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
+ */
+
+#ifndef SPI_INTEL_H
+#define SPI_INTEL_H
+
+#include <linux/platform_data/x86/spi-intel.h>
+
+struct resource;
+
+int intel_spi_probe(struct device *dev, struct resource *mem,
+		    const struct intel_spi_boardinfo *info);
+
+#endif /* SPI_INTEL_H */
diff --git a/include/linux/mfd/lpc_ich.h b/include/linux/mfd/lpc_ich.h
index 39967a5eca6d..ea4a4b1b246a 100644
--- a/include/linux/mfd/lpc_ich.h
+++ b/include/linux/mfd/lpc_ich.h
@@ -8,7 +8,7 @@
 #ifndef LPC_ICH_H
 #define LPC_ICH_H
 
-#include <linux/platform_data/x86/intel-spi.h>
+#include <linux/platform_data/x86/spi-intel.h>
 
 /* GPIO resources */
 #define ICH_RES_GPIO	0
diff --git a/include/linux/platform_data/x86/intel-spi.h b/include/linux/platform_data/x86/spi-intel.h
similarity index 89%
rename from include/linux/platform_data/x86/intel-spi.h
rename to include/linux/platform_data/x86/spi-intel.h
index 7dda3f690465..a512ec37abbb 100644
--- a/include/linux/platform_data/x86/intel-spi.h
+++ b/include/linux/platform_data/x86/spi-intel.h
@@ -6,8 +6,8 @@
  * Author: Mika Westerberg <mika.westerberg at linux.intel.com>
  */
 
-#ifndef INTEL_SPI_PDATA_H
-#define INTEL_SPI_PDATA_H
+#ifndef SPI_INTEL_PDATA_H
+#define SPI_INTEL_PDATA_H
 
 enum intel_spi_type {
 	INTEL_SPI_BYT = 1,
@@ -28,4 +28,4 @@ struct intel_spi_boardinfo {
 	void *data;
 };
 
-#endif /* INTEL_SPI_PDATA_H */
+#endif /* SPI_INTEL_PDATA_H */
-- 
2.33.0



From miquel.raynal at bootlin.com  Wed Oct 13 05:44:29 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 13 Oct 2021 14:44:29 +0200
Subject: [PATCH v2 13/20] mtd: dataflash: Warn about failure to
 unregister mtd device
In-Reply-To: <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
 <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>
Message-ID: <20211013144429.65b294e5@xps13>

Hi Uwe,

u.kleine-koenig at pengutronix.de wrote on Tue, 12 Oct 2021 17:39:38 +0200:

> When an spi driver's remove function returns a non-zero error code

Should we s/an spi/a SPI/?

> nothing happens apart from emitting a generic error message. Make this
> error message more device specific and return zero instead.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---
>  drivers/mtd/devices/mtd_dataflash.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
> index 9802e265fca8..2691b6b79df8 100644
> --- a/drivers/mtd/devices/mtd_dataflash.c
> +++ b/drivers/mtd/devices/mtd_dataflash.c
> @@ -919,7 +919,10 @@ static int dataflash_remove(struct spi_device *spi)
>  	status = mtd_device_unregister(&flash->mtd);
>  	if (status == 0)
>  		kfree(flash);
> -	return status;
> +	else
> +		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
> +			 ERR_PTR(status));
> +	return 0;

As part of a recent NAND cleanup series we ended up adding WARN_ON() [1]
to make it very clear that if this happens, it's not expected at all (it
was Boris' advice).

I don't think there is only one good solution but perhaps its best to
keep it sync'ed with the other drivers in MTD?

Thanks,
Miqu?l

[1]
d6e4fd522461 mtd: rawnand: nandsim: Stop using nand_release()
9fdd78f7bcda mtd: rawnand: xway: Stop using nand_release()
d9f2a1af817d mtd: rawnand: vf610: Stop using nand_release()
f6fc75978d88 mtd: rawnand: txx9ndfmc: Stop using nand_release()
f3e169f44bdb mtd: rawnand: tmio: Stop using nand_release()
ab135c51bb81 mtd: rawnand: tango: Stop using nand_release()
068d86ecd9d9 mtd: rawnand: sunxi: Stop using nand_release()
24acc3fa8b36 mtd: rawnand: stm32_fmc2: Stop using nand_release()
c121cb980c09 mtd: rawnand: socrates: Stop using nand_release()
35a37f9198e5 mtd: rawnand: sharpsl: Stop using nand_release()
50abacbb621f mtd: rawnand: sh_flctl: Stop using nand_release()
9748110bd22c mtd: rawnand: s3c2410: Stop using nand_release()
10b87750ae17 mtd: rawnand: r852: Stop using nand_release()
0a2bc9919cf7 mtd: rawnand: qcom: Stop using nand_release()
d1aae005a00e mtd: rawnand: plat_nand: Stop using nand_release()
23cf34615010 mtd: rawnand: pasemi: Stop using nand_release()
2d9cf6f129f8 mtd: rawnand: oxnas: Stop using nand_release()
f342df67b19a mtd: rawnand: orion: Stop using nand_release()
b4533679c958 mtd: rawnand: omap2: Stop using nand_release()
a9384f95fe77 mtd: rawnand: ndfc: Stop using nand_release()
8fd507bb4210 mtd: rawnand: mxic: Stop using nand_release()
c6dc082793d2 mtd: rawnand: mxc: Stop using nand_release()
1fec333aadc2 mtd: rawnand: mtk: Stop using nand_release()
1a36a7f78898 mtd: rawnand: mpc5121: Stop using nand_release()
5ecbba617446 mtd: rawnand: marvell: Stop using nand_release()
21b758277724 mtd: rawnand: lpc32xx_slc: Stop using nand_release()
5f3bce3a5275 mtd: rawnand: lpc32xx_mlc: Stop using nand_release()
28dcc4e8a831 mtd: rawnand: ingenic: Stop using nand_release()
71a4917b4d4b mtd: rawnand: hisi504: Stop using nand_release()
194f6c48cdd8 mtd: rawnand: gpmi: Stop using nand_release()
dbe0241570ed mtd: rawnand: gpio: Stop using nand_release()
9cc02f4c0a87 mtd: rawnand: fsmc: Stop using nand_release()
f6c4e661491a mtd: rawnand: fsl_upm: Stop using nand_release()
e9f2f5a80754 mtd: rawnand: fsl_ifc: Stop using nand_release()
128bbbf0ac4d mtd: rawnand: fsl_elbc: Stop using nand_release()
63a1460768a1 mtd: rawnand: diskonchip: Stop using nand_release()
009e2e1d8318 mtd: rawnand: denali: Stop using nand_release()
a9575c48e520 mtd: rawnand: davinci: Stop using nand_release()
970024f031ae mtd: rawnand: cs553x: Stop using nand_release()
544bac8999a6 mtd: rawnand: cafe: Stop using nand_release()
8b88f4e0a88b mtd: rawnand: cadence: Stop using nand_release()
937d039dfdcf mtd: rawnand: brcmnand: Stop using nand_release()
936904305928 mtd: rawnand: bcm47xx: Stop using nand_release()
4a3d21bc25c1 mtd: rawnand: au1550nd: Stop using nand_release()
08f25cd767e1 mtd: rawnand: ams-delta: Stop using nand_release()


From u.kleine-koenig at pengutronix.de  Wed Oct 13 07:08:35 2021
From: u.kleine-koenig at pengutronix.de (Uwe =?utf-8?Q?Kleine-K=C3=B6nig?=)
Date: Wed, 13 Oct 2021 16:08:35 +0200
Subject: [PATCH v2 13/20] mtd: dataflash: Warn about failure to
 unregister mtd device
In-Reply-To: <20211013144429.65b294e5@xps13>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
 <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>
 <20211013144429.65b294e5@xps13>
Message-ID: <20211013140835.olo2dxdno6zlom7n@pengutronix.de>

On Wed, Oct 13, 2021 at 02:44:29PM +0200, Miquel Raynal wrote:
> Hi Uwe,
> 
> u.kleine-koenig at pengutronix.de wrote on Tue, 12 Oct 2021 17:39:38 +0200:
> 
> > When an spi driver's remove function returns a non-zero error code
> 
> Should we s/an spi/a SPI/?

My (German) knowledge about the English Grammar claims that independent
of how you spell SPI, it must be "an" because when I say it, it's
[?spi:a?] (unless you call it [spa?]?)

In my eyes "spi" is right, because SPI is the protocol and "spi" is the
kernel framework. But I don't feel strong here and you're already the
second who suggests something similar.
 
> > nothing happens apart from emitting a generic error message. Make this
> > error message more device specific and return zero instead.
> > 
> > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> > ---
> >  drivers/mtd/devices/mtd_dataflash.c | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
> > index 9802e265fca8..2691b6b79df8 100644
> > --- a/drivers/mtd/devices/mtd_dataflash.c
> > +++ b/drivers/mtd/devices/mtd_dataflash.c
> > @@ -919,7 +919,10 @@ static int dataflash_remove(struct spi_device *spi)
> >  	status = mtd_device_unregister(&flash->mtd);
> >  	if (status == 0)
> >  		kfree(flash);
> > -	return status;
> > +	else
> > +		dev_warn(&spi->dev, "Failed to unregister mtd device (%pe)\n",
> > +			 ERR_PTR(status));
> > +	return 0;
> 
> As part of a recent NAND cleanup series we ended up adding WARN_ON() [1]
> to make it very clear that if this happens, it's not expected at all (it
> was Boris' advice).
> 
> I don't think there is only one good solution but perhaps its best to
> keep it sync'ed with the other drivers in MTD?

Well, if WARN_ON or dev_warn is the right thing is subjective. Your
subjective counts more as you're an MTD maintainer. Can rework
accordingly for v3.

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | https://www.pengutronix.de/ |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211013/5535c006/attachment.sig>

From dave.kleikamp at oracle.com  Wed Oct 13 07:13:57 2021
From: dave.kleikamp at oracle.com (Dave Kleikamp)
Date: Wed, 13 Oct 2021 09:13:57 -0500
Subject: [PATCH 16/29] jfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-17-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-17-hch@lst.de>
Message-ID: <b9fdcc41-2ec5-d628-968b-0aea1091cf9a@oracle.com>

On 10/13/21 12:10AM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Acked-by: Dave Kleikamp <dave.kleikamp at oracle.com>

> ---
>   fs/jfs/resize.c | 2 +-
>   fs/jfs/super.c  | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c
> index bde787c354fcc..51a8b22e71030 100644
> --- a/fs/jfs/resize.c
> +++ b/fs/jfs/resize.c
> @@ -199,7 +199,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
>   	txQuiesce(sb);
>   
>   	/* Reset size of direct inode */
> -	sbi->direct_inode->i_size =  i_size_read(sb->s_bdev->bd_inode);
> +	sbi->direct_inode->i_size = bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT;
>   
>   	if (sbi->mntflag & JFS_INLINELOG) {
>   		/*
> diff --git a/fs/jfs/super.c b/fs/jfs/super.c
> index 9030aeaf0f886..992870160903d 100644
> --- a/fs/jfs/super.c
> +++ b/fs/jfs/super.c
> @@ -551,7 +551,7 @@ static int jfs_fill_super(struct super_block *sb, void *data, int silent)
>   		ret = -ENOMEM;
>   		goto out_unload;
>   	}
> -	inode->i_size = i_size_read(sb->s_bdev->bd_inode);
> +	inode->i_size = bdev_nr_sectors(sb->s_bdev) << SECTOR_SHIFT;
>   	inode->i_mapping->a_ops = &jfs_metapage_aops;
>   	inode_fake_hash(inode);
>   	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
> 


From michael at walle.cc  Wed Oct 13 07:23:49 2021
From: michael at walle.cc (Michael Walle)
Date: Wed, 13 Oct 2021 16:23:49 +0200
Subject: AW: (EXT) Re: [PATCH v2 1/2] dt-bindings: mtd: spi-nor: Add
 output-driver-strength property
In-Reply-To: <kcEE.9geNR42QRKGTSoedF1sEfQ.ALRP5Q7A1wE@vtuxmail01.tq-net.de>
References: <kcEE.9geNR42QRKGTSoedF1sEfQ.ALRP5Q7A1wE@vtuxmail01.tq-net.de>
Message-ID: <da3f810389e3bd42392424a0ddc80cac@walle.cc>

Hi,

Am 2021-10-13 10:47, schrieb Alexander Stein:
> Am 2021-10-12 09:48, schrieb Michael Walle:
>> Am 2021-10-12 08:17, schrieb Alexander Stein:
>> > This property is for optimizing output voltage impedance and is
>> > specific to each board. It overwrites the default set by the flash
>> > device. Various flash devices support different impedances.
>> >
>> > Signed-off-by: Alexander Stein <alexander.stein at ew.tq-group.com>
>> > ---
>> > Changes in v2:
>> > * Updated the property description and the commit message accordingly
>> >
>> >  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 8 ++++++++
>> >  1 file changed, 8 insertions(+)
>> >
>> > diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> > b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> > index ed590d7c6e37..4c3c506a8853 100644
>> > --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> > +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
>> > @@ -72,6 +72,14 @@ properties:
>> >        be used on such systems, to denote the absence of a reliable
>> > reset
>> >        mechanism.
>> >
>> > +  output-driver-strength:
>> > +    $ref: /schemas/types.yaml#/definitions/uint32
>> > +    description:
>> > +      Output driver strength in ohms which optimizes the impedance at
>> > Vcc/2
>> > +      output voltage. This property overwrites the default set by the
>> > flash
>> > +      device. This is board specific and should be determined by the
>> > +      manufacturer. Various flash devices support different
>> > impedances.
>> 
>> Mh, this seems to be very tailored to this flash chip. Eg. the 
>> "Vcc/2",
>> is
>> this something specific to this flash or is this some kind of common
>> usage?
> 
> "Vcc/2" is taken from the datasheet description.

But this property should be as generic as possible. So at least I'd
drop the "optimizes the imdance at Vcc/2". And as Rob mentioned,
"strength" implies (milli)amps. Shouldn't it be output-driver-impedance
in this case?

>> For example, Winbond flashes specifies the output driver strength in
>> percent.
>> Settings are 25%, 50%, 75%, 100% there.
>> 
>> I'd have to ask a hardware guy, if one could convert between these two
>> representations of the driver strength.
> 
> Well, 100% must map to some actual value. Which then can be used to 
> create
> a discrete value table, which are then supported by the flash driver.

Which unfortunatly isn't possible because there is no refence for this
obscure value. That is, the datasheet doesn't mention what 100% actually
is.

> E.g. for Micron not every flash supports the same set of settings for
> driver strength.
> Macronix uses similar settings (values and bitmask), but in a different
> register. But if some vendors have pretty much incompatible settings, 
> it
> might be feasible to provide vendor specific settings, e.g.
> "micron,drive-strength = <45>" (for 45 Ohm) or "winbond,drive-strength 
> = <100>"
> (for 100%).

Different registers/values aren't the problem here. The problem is that
different units are used to express the same thing. But lets wait for
Rob's answer to my previous question.

To summarize there are flashes where you can select different impedances
for the output driver and flashes where you can select different 
percentages
for the output driver strength and there might also be flashes where you
can specify the output driver strength in (milli)amps. And it might not
always be possible to convert between these values. Therefore, will 
these
be three different DT properties?

-michael


From miquel.raynal at bootlin.com  Wed Oct 13 07:33:57 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 13 Oct 2021 16:33:57 +0200
Subject: [PATCH v2 13/20] mtd: dataflash: Warn about failure to
 unregister mtd device
In-Reply-To: <20211013140835.olo2dxdno6zlom7n@pengutronix.de>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
 <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>
 <20211013144429.65b294e5@xps13>
 <20211013140835.olo2dxdno6zlom7n@pengutronix.de>
Message-ID: <20211013163357.41c7471d@xps13>

Hi Uwe,

u.kleine-koenig at pengutronix.de wrote on Wed, 13 Oct 2021 16:08:35 +0200:

> On Wed, Oct 13, 2021 at 02:44:29PM +0200, Miquel Raynal wrote:
> > Hi Uwe,
> > 
> > u.kleine-koenig at pengutronix.de wrote on Tue, 12 Oct 2021 17:39:38 +0200:
> >   
> > > When an spi driver's remove function returns a non-zero error code  
> > 
> > Should we s/an spi/a SPI/?  
> 
> My (German) knowledge about the English Grammar claims that independent
> of how you spell SPI, it must be "an" because when I say it, it's
> [?spi:a?] (unless you call it [spa?]?)

I (personally) pronounce it [spa?] with my French background and it
looks wrong to my eyes to use "an" before SPI because of that, but this
is biased and possibly wrong as well so please keep it your way, it's
fine.

> In my eyes "spi" is right, because SPI is the protocol and "spi" is
> the kernel framework. But I don't feel strong here and you're already
> the second who suggests something similar.

I get it. Indeed I always use uppercase letters when I use acronyms
(such as SPI or MTD) and it's the first time I hear that the lowercase
letter refers to the framework more than the protocol, but TBH the
explanation kind of seduces me :)

> > > nothing happens apart from emitting a generic error message. Make
> > > this error message more device specific and return zero instead.
> > > 
> > > Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> > > ---
> > >  drivers/mtd/devices/mtd_dataflash.c | 5 ++++-
> > >  1 file changed, 4 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/drivers/mtd/devices/mtd_dataflash.c
> > > b/drivers/mtd/devices/mtd_dataflash.c index
> > > 9802e265fca8..2691b6b79df8 100644 ---
> > > a/drivers/mtd/devices/mtd_dataflash.c +++
> > > b/drivers/mtd/devices/mtd_dataflash.c @@ -919,7 +919,10 @@ static
> > > int dataflash_remove(struct spi_device *spi) status =
> > > mtd_device_unregister(&flash->mtd); if (status == 0)
> > >  		kfree(flash);
> > > -	return status;
> > > +	else
> > > +		dev_warn(&spi->dev, "Failed to unregister mtd
> > > device (%pe)\n",
> > > +			 ERR_PTR(status));
> > > +	return 0;  
> > 
> > As part of a recent NAND cleanup series we ended up adding
> > WARN_ON() [1] to make it very clear that if this happens, it's not
> > expected at all (it was Boris' advice).
> > 
> > I don't think there is only one good solution but perhaps its best
> > to keep it sync'ed with the other drivers in MTD?  
> 
> Well, if WARN_ON or dev_warn is the right thing is subjective. Your
> subjective counts more as you're an MTD maintainer. Can rework
> accordingly for v3.

Then let's all use WARN_ON() for now.

Thanks,
Miqu?l


From broonie at kernel.org  Wed Oct 13 08:13:54 2021
From: broonie at kernel.org (Mark Brown)
Date: Wed, 13 Oct 2021 16:13:54 +0100
Subject: [PATCH v2 13/20] mtd: dataflash: Warn about failure to
 unregister mtd device
In-Reply-To: <20211013163357.41c7471d@xps13>
References: <20211012153945.2651412-1-u.kleine-koenig@pengutronix.de>
 <20211012153945.2651412-14-u.kleine-koenig@pengutronix.de>
 <20211013144429.65b294e5@xps13>
 <20211013140835.olo2dxdno6zlom7n@pengutronix.de>
 <20211013163357.41c7471d@xps13>
Message-ID: <YWb3sjwS2FBsLHzL@sirena.org.uk>

On Wed, Oct 13, 2021 at 04:33:57PM +0200, Miquel Raynal wrote:
> > On Wed, Oct 13, 2021 at 02:44:29PM +0200, Miquel Raynal wrote:

> > My (German) knowledge about the English Grammar claims that independent
> > of how you spell SPI, it must be "an" because when I say it, it's
> > [?spi:a?] (unless you call it [spa?]?)

> I (personally) pronounce it [spa?] with my French background and it
> looks wrong to my eyes to use "an" before SPI because of that, but this
> is biased and possibly wrong as well so please keep it your way, it's
> fine.

I'd say a here too but really don't care too much, I hadn't noticed.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211013/5aa6ae74/attachment.sig>

From tytso at mit.edu  Wed Oct 13 08:51:02 2021
From: tytso at mit.edu (Theodore Ts'o)
Date: Wed, 13 Oct 2021 11:51:02 -0400
Subject: [PATCH 25/29] ext4: use sb_bdev_nr_blocks
In-Reply-To: <20211013051042.1065752-26-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-26-hch@lst.de>
Message-ID: <YWcAZq8eGQiZyxZS@mit.edu>

On Wed, Oct 13, 2021 at 07:10:38AM +0200, Christoph Hellwig wrote:
> Use the sb_bdev_nr_blocks helper instead of open coding it.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Acked-by: Theodore Ts'o <tytso at mit.edu>


From snitzer at redhat.com  Wed Oct 13 09:43:12 2021
From: snitzer at redhat.com (Mike Snitzer)
Date: Wed, 13 Oct 2021 12:43:12 -0400
Subject: [PATCH 03/29] dm: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-4-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-4-hch@lst.de>
Message-ID: <YWcMoCZxfpUzKZQ+@redhat.com>

On Wed, Oct 13 2021 at  1:10P -0400,
Christoph Hellwig <hch at lst.de> wrote:

> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Acked-by: Mike Snitzer <snitzer at redhat.com>



From mauro.lima at eclypsium.com  Wed Oct 13 11:22:40 2021
From: mauro.lima at eclypsium.com (Mauro Lima)
Date: Wed, 13 Oct 2021 15:22:40 -0300
Subject: [PATCH 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <YWag+RpkujjggPsW@lahna>
References: <20210930100719.2176-1-mika.westerberg@linux.intel.com>
 <20210930100719.2176-2-mika.westerberg@linux.intel.com>
 <CAArk9MPWh4f1E=ecKBHy8PFzvU_y_ROgDyUU_O3ZQ0FuMhkj5Q@mail.gmail.com>
 <YVqOjF/xjqFV+Dl3@lahna>
 <CAArk9MPY+rCQse+JXtvb4KqunN9FZ=toK_v=PV-ro4cO6=5s7Q@mail.gmail.com>
 <YWag+RpkujjggPsW@lahna>
Message-ID: <CAArk9MPKLy0abox-ULNNuQ1XO_96aJn449qM0pAp_amxFY6RDg@mail.gmail.com>

Hi!
On Wed, Oct 13, 2021 at 6:04 AM Mika Westerberg
<mika.westerberg at linux.intel.com> wrote:
>
> Hi,
>
> On Tue, Oct 12, 2021 at 03:49:22PM -0300, Mauro Lima wrote:
> > Hi Mika
> >
> > On Mon, Oct 4, 2021 at 2:18 AM Mika Westerberg
> > <mika.westerberg at linux.intel.com> wrote:
> > >
> > > Hi,
> > >
> > > On Fri, Oct 01, 2021 at 05:23:23PM -0300, Mauro Lima wrote:
> > > > Question for maintainers: With these changes is it safe to remove the
> > > > *(DANGEROUS)* tag from menuconfig?
> > >
> > > I don't think we want to remove that. This driver is not for regular
> > > users, at least in its current form.
> > Do we know why this is still dangerous for the user?
>
> There was a bug in the driver in the past (that was already fixed but it
> did not yet reach the stable trees or something like that). At this
> unfortunate time there was no DANGEROUS in the name so Ubuntu kernel
> went and enabled it. Combined with the bug certain Lenovo laptops BIOS
> turned into read-only which prevented booting from non-default devices.
>
> This happened even when the driver did not do any "write" or "erase"
> operations, just clearing the status register or so.
>
> We don't want that to happen again.
>
> > My plan is to make a sys/class driver to query write protection status
> > of the SPI, this will be
> > used by fwupd to gather information about vendors, also should be easy
> > for the user to use
> > 'cat' and see the information from userspace. For this to be possible
> > we need kernel engineers
> > to compile the kernel with this driver enabled, but the (DANGEROUS)
> > tag is a no go for most
> > of them.
> > Is there anything I can do to make this possible?
>
> IMHO we can make certain parts of the driver, that are known not to
> cause any issues available without the DANGEROUS. I mean the controller
> exposes some information that I think you are intersted in and that does
> not cause anything to be sent to the flash chip itself.
This will work for me.
Thanks!


From phillip at squashfs.org.uk  Wed Oct 13 12:37:03 2021
From: phillip at squashfs.org.uk (Phillip Lougher)
Date: Wed, 13 Oct 2021 20:37:03 +0100
Subject: [PATCH 22/29] squashfs: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-23-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-23-hch@lst.de>
Message-ID: <cbd3585f-87c6-ab31-2911-4d3550287e22@squashfs.org.uk>

On 13/10/2021 06:10, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Acked-by: Phillip Lougher <phillip at squashfs.org.uk>


From song at kernel.org  Wed Oct 13 14:14:32 2021
From: song at kernel.org (Song Liu)
Date: Wed, 13 Oct 2021 14:14:32 -0700
Subject: [PATCH 04/29] md: use bdev_nr_sectors instead of open coding it
In-Reply-To: <202110122311.B43459E21@keescook>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-5-hch@lst.de>
 <202110122311.B43459E21@keescook>
Message-ID: <CAPhsuW6MFRmKfpUxLL3=TRAgNTuTMFySc=_-NA7YOWDAvYAxyQ@mail.gmail.com>

On Tue, Oct 12, 2021 at 11:12 PM Kees Cook <keescook at chromium.org> wrote:
>
> On Wed, Oct 13, 2021 at 07:10:17AM +0200, Christoph Hellwig wrote:
> > Use the proper helper to read the block device size.
> >
> > Signed-off-by: Christoph Hellwig <hch at lst.de>
>
> I think it might make sense, as you suggest earlier, to add a "bytes"
> helper. This is the first user in the series needing:
>
>         bdev_nr_sectors(...bdev) << SECTOR_SHIFT
>
> Reviewed-by: Kees Cook <keescook at chromium.org>

Acked-by: Song Liu <song at kernel.org>


From chaitanyak at nvidia.com  Wed Oct 13 15:33:16 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:33:16 +0000
Subject: [PATCH 06/29] nvmet: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-7-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-7-hch@lst.de>
Message-ID: <d061489a-af65-93e3-0e1a-5742b009ac79@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>

From chaitanyak at nvidia.com  Wed Oct 13 15:33:58 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:33:58 +0000
Subject: [PATCH 02/29] drbd: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-3-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-3-hch@lst.de>
Message-ID: <473988dd-f18a-3ca0-7b3e-f5ad34f1b045@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>

From chaitanyak at nvidia.com  Wed Oct 13 15:34:35 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:34:35 +0000
Subject: [PATCH 23/29] block: use bdev_nr_sectors instead of open coding
 it in blkdev_fallocate
In-Reply-To: <20211013051042.1065752-24-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-24-hch@lst.de>
Message-ID: <929af081-c794-dd38-21da-32d585680194@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From chaitanyak at nvidia.com  Wed Oct 13 15:35:20 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:35:20 +0000
Subject: [PATCH 08/29] fs: use bdev_nr_sectors instead of open coding it
 in blkdev_max_block
In-Reply-To: <20211013051042.1065752-9-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-9-hch@lst.de>
Message-ID: <9d9cfa90-9fe6-23a7-ba13-c12d6fd59a0c@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From chaitanyak at nvidia.com  Wed Oct 13 15:36:25 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:36:25 +0000
Subject: [PATCH 11/29] btrfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-12-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-12-hch@lst.de>
Message-ID: <9e275603-359d-4492-98b5-520bbd15cc92@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From chaitanyak at nvidia.com  Wed Oct 13 15:37:47 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 13 Oct 2021 22:37:47 +0000
Subject: [PATCH 07/29] target/iblock: use bdev_nr_sectors instead of open
 coding it
In-Reply-To: <20211013051042.1065752-8-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-8-hch@lst.de>
Message-ID: <a225b3d3-372a-9804-374f-936f8d91c553@nvidia.com>

On 10/12/2021 10:10 PM, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Bodo's comment is good for the code reliability.

Either way, looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From kbusch at kernel.org  Wed Oct 13 19:44:38 2021
From: kbusch at kernel.org (Keith Busch)
Date: Wed, 13 Oct 2021 19:44:38 -0700
Subject: [PATCH 11/29] btrfs: use bdev_nr_sectors instead of open coding it
In-Reply-To: <20211013051042.1065752-12-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211013051042.1065752-12-hch@lst.de>
Message-ID: <20211014024438.GG1594461@dhcp-10-100-145-180.wdc.com>

On Wed, Oct 13, 2021 at 07:10:24AM +0200, Christoph Hellwig wrote:
> Use the proper helper to read the block device size.

Just IMO, this patch looks like it wants a new bdev_nr_bytes() helper
instead of using the double shifting sectors back to bytes.


From hch at lst.de  Wed Oct 13 23:28:44 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 14 Oct 2021 08:28:44 +0200
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <20211013051042.1065752-1-hch@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
Message-ID: <20211014062844.GA25448@lst.de>

On Wed, Oct 13, 2021 at 07:10:13AM +0200, Christoph Hellwig wrote:
> I wondered about adding a helper for looking at the size in byte units
> to avoid the SECTOR_SHIFT shifts in various places.  But given that
> I could not come up with a good name and block devices fundamentally
> work in sector size granularity I decided against that.

So it seems like the biggest review feedback is that we should have
such a helper.  I think the bdev_size name is the worst as size does
not imply a particular unit.  bdev_nr_bytes is a little better but I'm
not too happy.  Any other suggestions or strong opinions?


From oliver.sang at intel.com  Wed Oct 13 23:50:25 2021
From: oliver.sang at intel.com (kernel test robot)
Date: Thu, 14 Oct 2021 14:50:25 +0800
Subject: [mtd]  d3ff51cfa9: WARNING:at_kernel/locking/rwsem.c:#down_read
In-Reply-To: <20211011115253.38497-2-sean@geanix.com>
Message-ID: <20211014065025.GB17658@xsang-OptiPlex-9020>



Greeting,

FYI, we noticed the following commit (built with clang-14):

commit: d3ff51cfa9a64cdc18abe24c9821891b5122e617 ("[PATCH 1/3] mtd: core: protect access to MTD devices while in suspend")
url: https://github.com/0day-ci/linux/commits/Sean-Nyekjaer/mtd-core-protect-access-to-mtd-devices-while-in-suspend/20211011-195606
base: https://git.kernel.org/cgit/linux/kernel/git/mtd/linux.git mtd/next

in testcase: boot

on test machine: qemu-system-i386 -enable-kvm -cpu SandyBridge -smp 2 -m 4G

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):


+----------------------------------------------+------------+------------+
|                                              | b72841e4dc | d3ff51cfa9 |
+----------------------------------------------+------------+------------+
| boot_successes                               | 20         | 0          |
| boot_failures                                | 0          | 21         |
| INFO:trying_to_register_non-static_key       | 0          | 21         |
| WARNING:at_kernel/locking/rwsem.c:#down_read | 0          | 21         |
| EIP:down_read                                | 0          | 21         |
| WARNING:at_kernel/locking/rwsem.c:#__up_read | 0          | 21         |
| EIP:__up_read                                | 0          | 21         |
+----------------------------------------------+------------+------------+


If you fix the issue, kindly add following tag
Reported-by: kernel test robot <oliver.sang at intel.com>


[    4.304729][    T1] ------------[ cut here ]------------
[    4.305194][    T1] DEBUG_RWSEMS_WARN_ON(sem->magic != sem): count = 0x0, magic = 0x0, owner = 0x0, curr 0xb3690000, list not empty
[    4.306218][    T1] WARNING: CPU: 1 PID: 1 at kernel/locking/rwsem.c:1240 down_read+0xff/0x110
[    4.306989][    T1] Modules linked in:
[    4.307318][    T1] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc1-00002-gd3ff51cfa9a6 #1
[    4.308071][    T1] EIP: down_read+0xff/0x110
[    4.308445][    T1] Code: 9f 03 b2 ba 0f 44 d1 52 0f 44 d1 52 ff 75 f0 ff ff 75 f0 ff 00 b2 68 79 00 b2 68 79 c7 d5 5a ff c7 d5 5a ff c4 1c 0f 0b c4 1c <0f> 0b 58 ff ff ff 58 ff ff ff ff 90 90 3e ff 90 90 3e 55 89 e5 53
[    4.310153][    T1] EAX: 00000000 EBX: b15a2702 ECX: 80000001 EDX: 00000001
[    4.310861][    T1] ESI: f5dc0404 EDI: 00000000 EBP: b3693c98 ESP: b3693c84
[    4.311546][    T1] DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 EFLAGS: 00010296
[    4.312277][    T1] CR0: 80050033 CR2: 00000000 CR3: 027d9000 CR4: 000406d0
[    4.312919][    T1] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[    4.313518][    T1] DR6: fffe0ff0 DR7: 00000400
[    4.313926][    T1] Call Trace:
[    4.314237][    T1]  mtd_start_access+0x32/0xc0
[    4.314707][    T1]  ? ledtrig_mtd_activity+0x37/0x40
[    4.315194][    T1]  mtd_read_oob+0x75/0x1e0
[    4.315572][    T1]  scan_block_fast+0x6a/0xc0
[    4.316003][    T1]  create_bbt+0x130/0x2a0
[    4.316399][    T1]  ? __kmalloc+0x146/0x1a0
[    4.316811][    T1]  ? trace_kmalloc_node+0x39/0x100
[    4.317267][    T1]  nand_create_bbt+0x1fe/0x9e0
[    4.317685][    T1]  ? ns_alloc_device+0xa4/0x18b
[    4.318107][    T1]  ? ns_init+0x3b6/0x688
[    4.318459][    T1]  ? __kmalloc+0x146/0x1a0
[    4.318858][    T1]  ns_init_module+0x5f9/0x809
[    4.319254][    T1]  ? __this_cpu_preempt_check+0xf/0x11
[    4.319719][    T1]  ? debug_smp_processor_id+0x12/0x20
[    4.320174][    T1]  ? generic_onenand_driver_init+0x16/0x16
[    4.320662][    T1]  ? rcu_read_lock_sched_held+0x36/0x70
[    4.321122][    T1]  ? generic_onenand_driver_init+0x16/0x16
[    4.321602][    T1]  do_one_initcall+0x93/0x160
[    4.321997][    T1]  ? irqentry_exit+0x56/0x80
[    4.322382][    T1]  ? __this_cpu_preempt_check+0xf/0x11
[    4.322854][    T1]  ? lockdep_hardirqs_on+0x82/0x110
[    4.323273][    T1]  ? irqentry_exit+0x56/0x80
[    4.323642][    T1]  ? sysvec_call_function_single+0x30/0x30
[    4.324124][    T1]  ? trace_hardirqs_on+0x45/0x50
[    4.324523][    T1]  ? irqentry_exit+0x56/0x80
[    4.324893][    T1]  ? sysvec_apic_timer_interrupt+0x29/0x30
[    4.325367][    T1]  ? handle_exception+0x101/0x101
[    4.325776][    T1]  ? p9_client_readlink+0x9b/0xa0
[    4.326186][    T1]  ? strlen+0xd/0x20
[    4.326508][    T1]  ? next_arg+0xfb/0x110
[    4.326877][    T1]  ? parse_args+0x15c/0x330
[    4.327244][    T1]  ? __this_cpu_preempt_check+0xf/0x11
[    4.327688][    T1]  ? debug_smp_processor_id+0x12/0x20
[    4.328155][    T1]  ? generic_onenand_driver_init+0x16/0x16
[    4.328664][    T1]  do_initcall_level+0x80/0x92
[    4.329088][    T1]  ? rest_init+0x1c0/0x1c0
[    4.329475][    T1]  do_initcalls+0x41/0x62
[    4.329838][    T1]  do_basic_setup+0x17/0x19
[    4.330214][    T1]  kernel_init_freeable+0x8c/0xd1
[    4.330657][    T1]  kernel_init+0x17/0x170
[    4.331087][    T1]  ret_from_fork+0x1c/0x28
[    4.331503][    T1] irq event stamp: 319917
[    4.331919][    T1] hardirqs last  enabled at (319917): [<b10e59cc>] __up_console_sem+0x5c/0x90
[    4.332719][    T1] hardirqs last disabled at (319916): [<b10e59b3>] __up_console_sem+0x43/0x90
[    4.333495][    T1] softirqs last  enabled at (318956): [<b121d2f1>] bdi_register_va+0x1d1/0x1f0
[    4.334243][    T1] softirqs last disabled at (318954): [<b121d202>] bdi_register_va+0xe2/0x1f0
[    4.334994][    T1] _warn_unseeded_randomness: 5 callbacks suppressed
[    4.334997][    T1] random: get_random_bytes called from __warn+0xc3/0x140 with crng_init=0
[    4.335006][    T1] ---[ end trace 8e9a8c821c89b3d1 ]---




To reproduce:

        # build kernel
	cd linux
	cp config-5.15.0-rc1-00002-gd3ff51cfa9a6 .config
	make HOSTCC=clang-14 CC=clang-14 ARCH=i386 olddefconfig prepare modules_prepare bzImage

        git clone https://github.com/intel/lkp-tests.git
        cd lkp-tests
        bin/lkp qemu -k <bzImage> job-script # job-script is attached in this email

        # if come across any failure that blocks the test,
        # please remove ~/.lkp and /lkp dir to run from a clean state.



---
0DAY/LKP+ Test Infrastructure                   Open Source Technology Center
https://lists.01.org/hyperkitty/list/lkp at lists.01.org       Intel Corporation

Thanks,
Oliver Sang

-------------- next part --------------
#
# Automatically generated file; DO NOT EDIT.
# Linux/i386 5.15.0-rc1 Kernel Configuration
#
CONFIG_CC_VERSION_TEXT="clang version 14.0.0 (git://gitmirror/llvm_project b6a8c695542b2987eb9a203d5663a0740cb4725f)"
CONFIG_GCC_VERSION=0
CONFIG_CC_IS_CLANG=y
CONFIG_CLANG_VERSION=140000
CONFIG_AS_IS_LLVM=y
CONFIG_AS_VERSION=140000
CONFIG_LD_VERSION=0
CONFIG_LD_IS_LLD=y
CONFIG_LLD_VERSION=140000
CONFIG_CC_CAN_LINK=y
CONFIG_CC_CAN_LINK_STATIC=y
CONFIG_CC_HAS_ASM_GOTO=y
CONFIG_CC_HAS_ASM_GOTO_OUTPUT=y
CONFIG_TOOLS_SUPPORT_RELR=y
CONFIG_CC_HAS_ASM_INLINE=y
CONFIG_CC_HAS_NO_PROFILE_FN_ATTR=y
CONFIG_IRQ_WORK=y
CONFIG_BUILDTIME_TABLE_SORT=y
CONFIG_THREAD_INFO_IN_TASK=y

#
# General setup
#
CONFIG_INIT_ENV_ARG_LIMIT=32
# CONFIG_COMPILE_TEST is not set
# CONFIG_WERROR is not set
CONFIG_LOCALVERSION=""
CONFIG_LOCALVERSION_AUTO=y
CONFIG_BUILD_SALT=""
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_XZ=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_HAVE_KERNEL_LZ4=y
CONFIG_HAVE_KERNEL_ZSTD=y
# CONFIG_KERNEL_GZIP is not set
CONFIG_KERNEL_BZIP2=y
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_XZ is not set
# CONFIG_KERNEL_LZO is not set
# CONFIG_KERNEL_LZ4 is not set
# CONFIG_KERNEL_ZSTD is not set
CONFIG_DEFAULT_INIT=""
CONFIG_DEFAULT_HOSTNAME="(none)"
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
# CONFIG_POSIX_MQUEUE is not set
CONFIG_WATCH_QUEUE=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_USELIB=y
# CONFIG_AUDIT is not set
CONFIG_HAVE_ARCH_AUDITSYSCALL=y

#
# IRQ subsystem
#
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_GENERIC_IRQ_MIGRATION=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_SIM=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
CONFIG_GENERIC_IRQ_RESERVATION_MODE=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_SPARSE_IRQ=y
# CONFIG_GENERIC_IRQ_DEBUGFS is not set
# end of IRQ subsystem

CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_ARCH_CLOCKSOURCE_INIT=y
CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
CONFIG_TIME_KUNIT_TEST=y

#
# Timers subsystem
#
CONFIG_HZ_PERIODIC=y
# CONFIG_NO_HZ_IDLE is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
# end of Timers subsystem

CONFIG_BPF=y
CONFIG_HAVE_EBPF_JIT=y

#
# BPF subsystem
#
CONFIG_BPF_SYSCALL=y
# CONFIG_BPF_JIT is not set
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
# CONFIG_BPF_PRELOAD is not set
# end of BPF subsystem

# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
CONFIG_PREEMPT=y
CONFIG_PREEMPT_COUNT=y
CONFIG_PREEMPTION=y
CONFIG_PREEMPT_DYNAMIC=y
# CONFIG_SCHED_CORE is not set

#
# CPU/Task time and stats accounting
#
CONFIG_TICK_CPU_ACCOUNTING=y
# CONFIG_IRQ_TIME_ACCOUNTING is not set
CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
# CONFIG_TASKSTATS is not set
# CONFIG_PSI is not set
# end of CPU/Task time and stats accounting

CONFIG_CPU_ISOLATION=y

#
# RCU Subsystem
#
CONFIG_TREE_RCU=y
CONFIG_PREEMPT_RCU=y
CONFIG_RCU_EXPERT=y
CONFIG_SRCU=y
CONFIG_TREE_SRCU=y
CONFIG_TASKS_RCU_GENERIC=y
CONFIG_TASKS_RCU=y
CONFIG_TASKS_RUDE_RCU=y
CONFIG_TASKS_TRACE_RCU=y
CONFIG_RCU_STALL_COMMON=y
CONFIG_RCU_NEED_SEGCBLIST=y
CONFIG_RCU_FANOUT=32
CONFIG_RCU_FANOUT_LEAF=16
CONFIG_RCU_BOOST=y
CONFIG_RCU_BOOST_DELAY=500
# CONFIG_RCU_NOCB_CPU is not set
CONFIG_TASKS_TRACE_RCU_READ_MB=y
# end of RCU Subsystem

CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_IKHEADERS is not set
CONFIG_LOG_BUF_SHIFT=20
CONFIG_LOG_CPU_MAX_BUF_SHIFT=12
CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13
# CONFIG_PRINTK_INDEX is not set
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y

#
# Scheduler features
#
# end of Scheduler features

CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y
CONFIG_CGROUPS=y
# CONFIG_MEMCG is not set
# CONFIG_CGROUP_SCHED is not set
# CONFIG_CGROUP_PIDS is not set
# CONFIG_CGROUP_RDMA is not set
# CONFIG_CGROUP_FREEZER is not set
# CONFIG_CPUSETS is not set
# CONFIG_CGROUP_DEVICE is not set
# CONFIG_CGROUP_CPUACCT is not set
# CONFIG_CGROUP_PERF is not set
# CONFIG_CGROUP_BPF is not set
# CONFIG_CGROUP_MISC is not set
# CONFIG_CGROUP_DEBUG is not set
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_TIME_NS=y
# CONFIG_IPC_NS is not set
CONFIG_USER_NS=y
# CONFIG_PID_NS is not set
CONFIG_NET_NS=y
# CONFIG_CHECKPOINT_RESTORE is not set
# CONFIG_SCHED_AUTOGROUP is not set
# CONFIG_SYSFS_DEPRECATED is not set
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
# CONFIG_RD_BZIP2 is not set
CONFIG_RD_LZMA=y
# CONFIG_RD_XZ is not set
CONFIG_RD_LZO=y
# CONFIG_RD_LZ4 is not set
CONFIG_RD_ZSTD=y
CONFIG_BOOT_CONFIG=y
CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_LD_ORPHAN_WARN=y
CONFIG_SYSCTL=y
CONFIG_HAVE_UID16=y
CONFIG_SYSCTL_EXCEPTION_TRACE=y
CONFIG_HAVE_PCSPKR_PLATFORM=y
CONFIG_EXPERT=y
CONFIG_UID16=y
CONFIG_MULTIUSER=y
# CONFIG_SGETMASK_SYSCALL is not set
# CONFIG_SYSFS_SYSCALL is not set
CONFIG_FHANDLE=y
CONFIG_POSIX_TIMERS=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_PCSPKR_PLATFORM=y
# CONFIG_BASE_FULL is not set
CONFIG_FUTEX=y
CONFIG_FUTEX_PI=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
# CONFIG_AIO is not set
# CONFIG_IO_URING is not set
# CONFIG_ADVISE_SYSCALLS is not set
# CONFIG_MEMBARRIER is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_KALLSYMS_BASE_RELATIVE=y
CONFIG_USERFAULTFD=y
CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y
# CONFIG_KCMP is not set
# CONFIG_RSEQ is not set
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
# CONFIG_PC104 is not set

#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
# end of Kernel Performance Events And Counters

CONFIG_VM_EVENT_COUNTERS=y
CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
CONFIG_SLAB_MERGE_DEFAULT=y
CONFIG_SHUFFLE_PAGE_ALLOCATOR=y
# CONFIG_PROFILING is not set
CONFIG_TRACEPOINTS=y
# end of General setup

CONFIG_X86_32=y
CONFIG_FORCE_DYNAMIC_FTRACE=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf32-i386"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_MMU=y
CONFIG_ARCH_MMAP_RND_BITS_MIN=8
CONFIG_ARCH_MMAP_RND_BITS_MAX=16
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8
CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_BUG=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_FILTER_PGPROT=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
CONFIG_X86_32_SMP=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_PGTABLE_LEVELS=2

#
# Processor type and features
#
CONFIG_SMP=y
CONFIG_X86_FEATURE_NAMES=y
CONFIG_X86_MPPARSE=y
# CONFIG_GOLDFISH is not set
CONFIG_RETPOLINE=y
CONFIG_X86_CPU_RESCTRL=y
CONFIG_X86_BIGSMP=y
CONFIG_X86_EXTENDED_PLATFORM=y
# CONFIG_X86_GOLDFISH is not set
# CONFIG_X86_INTEL_LPSS is not set
# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
CONFIG_IOSF_MBI=y
# CONFIG_IOSF_MBI_DEBUG is not set
CONFIG_X86_RDC321X=y
# CONFIG_X86_32_NON_STANDARD is not set
CONFIG_X86_32_IRIS=y
# CONFIG_SCHED_OMIT_FRAME_POINTER is not set
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
# CONFIG_PARAVIRT_DEBUG is not set
# CONFIG_PARAVIRT_SPINLOCKS is not set
CONFIG_X86_HV_CALLBACK_VECTOR=y
CONFIG_KVM_GUEST=y
CONFIG_ARCH_CPUIDLE_HALTPOLL=y
# CONFIG_PVH is not set
# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set
CONFIG_PARAVIRT_CLOCK=y
# CONFIG_M486SX is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
CONFIG_M686=y
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MELAN is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MCORE2 is not set
# CONFIG_MATOM is not set
CONFIG_X86_GENERIC=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=6
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_IA32_FEAT_CTL=y
CONFIG_X86_VMX_FEATURE_NAMES=y
# CONFIG_PROCESSOR_SELECT is not set
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_CYRIX_32=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_HYGON=y
CONFIG_CPU_SUP_CENTAUR=y
CONFIG_CPU_SUP_TRANSMETA_32=y
CONFIG_CPU_SUP_UMC_32=y
CONFIG_CPU_SUP_ZHAOXIN=y
CONFIG_HPET_TIMER=y
# CONFIG_DMI is not set
CONFIG_NR_CPUS_RANGE_BEGIN=2
CONFIG_NR_CPUS_RANGE_END=64
CONFIG_NR_CPUS_DEFAULT=32
CONFIG_NR_CPUS=32
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
# CONFIG_SCHED_MC_PRIO is not set
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS=y
CONFIG_X86_MCE=y
CONFIG_X86_MCELOG_LEGACY=y
# CONFIG_X86_MCE_INTEL is not set
CONFIG_X86_MCE_AMD=y
CONFIG_X86_ANCIENT_MCE=y
CONFIG_X86_MCE_THRESHOLD=y
CONFIG_X86_MCE_INJECT=y

#
# Performance monitoring
#
CONFIG_PERF_EVENTS_INTEL_UNCORE=y
CONFIG_PERF_EVENTS_INTEL_RAPL=y
CONFIG_PERF_EVENTS_INTEL_CSTATE=y
# CONFIG_PERF_EVENTS_AMD_POWER is not set
CONFIG_PERF_EVENTS_AMD_UNCORE=y
# end of Performance monitoring

# CONFIG_X86_LEGACY_VM86 is not set
CONFIG_X86_IOPL_IOPERM=y
CONFIG_TOSHIBA=y
CONFIG_I8K=y
CONFIG_X86_REBOOTFIXUPS=y
# CONFIG_MICROCODE is not set
# CONFIG_X86_MSR is not set
CONFIG_X86_CPUID=y
# CONFIG_NOHIGHMEM is not set
CONFIG_HIGHMEM4G=y
# CONFIG_HIGHMEM64G is not set
# CONFIG_VMSPLIT_3G is not set
CONFIG_VMSPLIT_3G_OPT=y
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_2G_OPT is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xB0000000
CONFIG_HIGHMEM=y
CONFIG_X86_CPA_STATISTICS=y
CONFIG_ARCH_FLATMEM_ENABLE=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ILLEGAL_POINTER_VALUE=0
CONFIG_HIGHPTE=y
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
CONFIG_MTRR=y
# CONFIG_MTRR_SANITIZER is not set
CONFIG_X86_PAT=y
CONFIG_ARCH_USES_PG_UNCACHED=y
CONFIG_ARCH_RANDOM=y
CONFIG_X86_SMAP=y
CONFIG_X86_UMIP=y
# CONFIG_X86_INTEL_TSX_MODE_OFF is not set
# CONFIG_X86_INTEL_TSX_MODE_ON is not set
CONFIG_X86_INTEL_TSX_MODE_AUTO=y
# CONFIG_EFI is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_KEXEC=y
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x1000000
# CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x200000
CONFIG_HOTPLUG_CPU=y
CONFIG_BOOTPARAM_HOTPLUG_CPU0=y
# CONFIG_DEBUG_HOTPLUG_CPU0 is not set
CONFIG_COMPAT_VDSO=y
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_MODIFY_LDT_SYSCALL is not set
# end of Processor type and features

CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y

#
# Power management and ACPI options
#
# CONFIG_SUSPEND is not set
# CONFIG_PM is not set
CONFIG_ARCH_SUPPORTS_ACPI=y
CONFIG_ACPI=y
CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y
# CONFIG_ACPI_DEBUGGER is not set
# CONFIG_ACPI_SPCR_TABLE is not set
# CONFIG_ACPI_REV_OVERRIDE_POSSIBLE is not set
CONFIG_ACPI_EC_DEBUGFS=y
CONFIG_ACPI_AC=y
# CONFIG_ACPI_BATTERY is not set
CONFIG_ACPI_BUTTON=y
CONFIG_ACPI_FAN=y
# CONFIG_ACPI_DOCK is not set
CONFIG_ACPI_CPU_FREQ_PSS=y
CONFIG_ACPI_PROCESSOR_CSTATE=y
CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_IPMI=y
CONFIG_ACPI_HOTPLUG_CPU=y
CONFIG_ACPI_PROCESSOR_AGGREGATOR=y
CONFIG_ACPI_THERMAL=y
CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y
CONFIG_ACPI_TABLE_UPGRADE=y
# CONFIG_ACPI_DEBUG is not set
# CONFIG_ACPI_PCI_SLOT is not set
CONFIG_ACPI_CONTAINER=y
CONFIG_ACPI_HOTPLUG_IOAPIC=y
CONFIG_ACPI_SBS=y
CONFIG_ACPI_HED=y
# CONFIG_ACPI_CUSTOM_METHOD is not set
# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
CONFIG_HAVE_ACPI_APEI=y
CONFIG_HAVE_ACPI_APEI_NMI=y
# CONFIG_ACPI_APEI is not set
# CONFIG_ACPI_DPTF is not set
CONFIG_ACPI_CONFIGFS=y
# CONFIG_PMIC_OPREGION is not set
CONFIG_X86_PM_TIMER=y

#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
# end of CPU Frequency scaling

#
# CPU Idle
#
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_LADDER=y
# CONFIG_CPU_IDLE_GOV_MENU is not set
# CONFIG_CPU_IDLE_GOV_TEO is not set
# CONFIG_CPU_IDLE_GOV_HALTPOLL is not set
CONFIG_HALTPOLL_CPUIDLE=y
# end of CPU Idle

CONFIG_INTEL_IDLE=y
# end of Power management and ACPI options

#
# Bus options (PCI etc.)
#
# CONFIG_PCI_GOBIOS is not set
# CONFIG_PCI_GOMMCONFIG is not set
# CONFIG_PCI_GODIRECT is not set
CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
# CONFIG_PCI_CNB20LE_QUIRK is not set
# CONFIG_ISA_BUS is not set
CONFIG_ISA_DMA_API=y
# CONFIG_ISA is not set
CONFIG_SCx200=y
# CONFIG_SCx200HR_TIMER is not set
# CONFIG_OLPC is not set
# CONFIG_ALIX is not set
# CONFIG_NET5501 is not set
CONFIG_AMD_NB=y
# end of Bus options (PCI etc.)

#
# Binary Emulations
#
CONFIG_COMPAT_32=y
# end of Binary Emulations

CONFIG_HAVE_ATOMIC_IOMAP=y

#
# Firmware Drivers
#

#
# ARM System Control and Management Interface Protocol
#
# end of ARM System Control and Management Interface Protocol

# CONFIG_EDD is not set
CONFIG_FIRMWARE_MEMMAP=y
# CONFIG_FW_CFG_SYSFS is not set
CONFIG_SYSFB=y
# CONFIG_SYSFB_SIMPLEFB is not set
CONFIG_GOOGLE_FIRMWARE=y
CONFIG_GOOGLE_COREBOOT_TABLE=y
CONFIG_GOOGLE_MEMCONSOLE=y
CONFIG_GOOGLE_MEMCONSOLE_COREBOOT=y
# CONFIG_GOOGLE_VPD is not set

#
# Tegra firmware driver
#
# end of Tegra firmware driver
# end of Firmware Drivers

CONFIG_HAVE_KVM=y
CONFIG_VIRTUALIZATION=y
CONFIG_AS_AVX512=y
CONFIG_AS_SHA1_NI=y
CONFIG_AS_SHA256_NI=y
CONFIG_AS_TPAUSE=y

#
# General architecture-dependent options
#
CONFIG_CRASH_CORE=y
CONFIG_KEXEC_CORE=y
CONFIG_HOTPLUG_SMT=y
CONFIG_GENERIC_ENTRY=y
# CONFIG_KPROBES is not set
CONFIG_JUMP_LABEL=y
# CONFIG_STATIC_KEYS_SELFTEST is not set
# CONFIG_STATIC_CALL_SELFTEST is not set
CONFIG_UPROBES=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_ARCH_USE_BUILTIN_BSWAP=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_KPROBES_ON_FTRACE=y
CONFIG_HAVE_FUNCTION_ERROR_INJECTION=y
CONFIG_HAVE_NMI=y
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_CONTIGUOUS=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ARCH_HAS_FORTIFY_SOURCE=y
CONFIG_ARCH_HAS_SET_MEMORY=y
CONFIG_ARCH_HAS_SET_DIRECT_MAP=y
CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y
CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_HAVE_ASM_MODVERSIONS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_RSEQ=y
CONFIG_HAVE_FUNCTION_ARG_ACCESS_API=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y
CONFIG_HAVE_PERF_EVENTS_NMI=y
CONFIG_HAVE_HARDLOCKUP_DETECTOR_PERF=y
CONFIG_HAVE_PERF_REGS=y
CONFIG_HAVE_PERF_USER_STACK_DUMP=y
CONFIG_HAVE_ARCH_JUMP_LABEL=y
CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE=y
CONFIG_MMU_GATHER_TABLE_FREE=y
CONFIG_MMU_GATHER_RCU_TABLE_FREE=y
CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
CONFIG_HAVE_CMPXCHG_LOCAL=y
CONFIG_HAVE_CMPXCHG_DOUBLE=y
CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
CONFIG_HAVE_ARCH_SECCOMP=y
CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
# CONFIG_SECCOMP_CACHE_DEBUG is not set
CONFIG_HAVE_ARCH_STACKLEAK=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
CONFIG_LTO_NONE=y
CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y
CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
CONFIG_HAVE_MOVE_PUD=y
CONFIG_HAVE_MOVE_PMD=y
CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK=y
CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
CONFIG_HAVE_ARCH_MMAP_RND_BITS=y
CONFIG_HAVE_EXIT_THREAD=y
CONFIG_ARCH_MMAP_RND_BITS=8
CONFIG_ISA_BUS_API=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OLD_SIGACTION=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET=y
# CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT is not set
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y
CONFIG_STRICT_KERNEL_RWX=y
CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y
CONFIG_STRICT_MODULE_RWX=y
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y
# CONFIG_LOCK_EVENT_COUNTS is not set
CONFIG_ARCH_HAS_MEM_ENCRYPT=y
CONFIG_HAVE_STATIC_CALL=y
CONFIG_HAVE_PREEMPT_DYNAMIC=y
CONFIG_ARCH_WANT_LD_ORPHAN_WARN=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_ARCH_SPLIT_ARG64=y
CONFIG_ARCH_HAS_PARANOID_L1D_FLUSH=y

#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
# end of GCOV-based kernel profiling

CONFIG_HAVE_GCC_PLUGINS=y
# end of General architecture-dependent options

CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=1
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
# CONFIG_MODULE_SIG is not set
CONFIG_MODULE_COMPRESS_NONE=y
# CONFIG_MODULE_COMPRESS_GZIP is not set
# CONFIG_MODULE_COMPRESS_XZ is not set
# CONFIG_MODULE_COMPRESS_ZSTD is not set
# CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS is not set
CONFIG_MODPROBE_PATH="/sbin/modprobe"
# CONFIG_TRIM_UNUSED_KSYMS is not set
CONFIG_MODULES_TREE_LOOKUP=y
# CONFIG_BLOCK is not set
CONFIG_PADATA=y
CONFIG_ASN1=y
CONFIG_UNINLINE_SPIN_UNLOCK=y
CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_ARCH_USE_QUEUED_RWLOCKS=y
CONFIG_QUEUED_RWLOCKS=y
CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE=y
CONFIG_ARCH_HAS_SYNC_CORE_BEFORE_USERMODE=y
CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y

#
# Executable file formats
#
CONFIG_BINFMT_ELF=y
CONFIG_ELFCORE=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_BINFMT_MISC=y
# CONFIG_COREDUMP is not set
# end of Executable file formats

#
# Memory Management options
#
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_SPARSEMEM_STATIC=y
CONFIG_HAVE_FAST_GUP=y
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MEMORY_BALLOON=y
# CONFIG_COMPACTION is not set
CONFIG_PAGE_REPORTING=y
CONFIG_VIRT_TO_BUS=y
CONFIG_KSM=y
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
# CONFIG_TRANSPARENT_HUGEPAGE is not set
# CONFIG_CLEANCACHE is not set
# CONFIG_CMA is not set
# CONFIG_ZPOOL is not set
# CONFIG_ZSMALLOC is not set
CONFIG_GENERIC_EARLY_IOREMAP=y
# CONFIG_IDLE_PAGE_TRACKING is not set
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_ARCH_HAS_ZONE_DMA_SET=y
CONFIG_ZONE_DMA=y
CONFIG_PERCPU_STATS=y
CONFIG_GUP_TEST=y
CONFIG_ARCH_HAS_PTE_SPECIAL=y
CONFIG_KMAP_LOCAL=y

#
# Data Access Monitoring
#
# CONFIG_DAMON is not set
# end of Data Access Monitoring
# end of Memory Management options

CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
# CONFIG_PACKET_DIAG is not set
CONFIG_UNIX=y
CONFIG_UNIX_SCM=y
CONFIG_AF_UNIX_OOB=y
# CONFIG_UNIX_DIAG is not set
# CONFIG_TLS is not set
# CONFIG_XFRM_USER is not set
# CONFIG_NET_KEY is not set
# CONFIG_XDP_SOCKETS is not set
CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
# CONFIG_IP_PNP_BOOTP is not set
# CONFIG_IP_PNP_RARP is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE_DEMUX is not set
CONFIG_NET_IP_TUNNEL=y
# CONFIG_SYN_COOKIES is not set
# CONFIG_NET_IPVTI is not set
# CONFIG_NET_FOU is not set
# CONFIG_NET_FOU_IP_TUNNELS is not set
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
CONFIG_INET_TUNNEL=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_INET_UDP_DIAG is not set
# CONFIG_INET_RAW_DIAG is not set
# CONFIG_INET_DIAG_DESTROY is not set
# CONFIG_TCP_CONG_ADVANCED is not set
CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
CONFIG_IPV6=y
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
# CONFIG_INET6_AH is not set
# CONFIG_INET6_ESP is not set
# CONFIG_INET6_IPCOMP is not set
# CONFIG_IPV6_MIP6 is not set
# CONFIG_IPV6_VTI is not set
CONFIG_IPV6_SIT=y
# CONFIG_IPV6_SIT_6RD is not set
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
# CONFIG_IPV6_SEG6_LWTUNNEL is not set
# CONFIG_IPV6_SEG6_HMAC is not set
# CONFIG_IPV6_RPL_LWTUNNEL is not set
# CONFIG_IPV6_IOAM6_LWTUNNEL is not set
# CONFIG_NETLABEL is not set
# CONFIG_MPTCP is not set
# CONFIG_NETWORK_SECMARK is not set
CONFIG_NET_PTP_CLASSIFY=y
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
# CONFIG_NETFILTER is not set
# CONFIG_BPFILTER is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_RDS is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_L2TP is not set
# CONFIG_BRIDGE is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_PHONET is not set
# CONFIG_6LOWPAN is not set
# CONFIG_IEEE802154 is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
CONFIG_DNS_RESOLVER=m
# CONFIG_BATMAN_ADV is not set
# CONFIG_OPENVSWITCH is not set
# CONFIG_VSOCKETS is not set
# CONFIG_NETLINK_DIAG is not set
# CONFIG_MPLS is not set
# CONFIG_NET_NSH is not set
# CONFIG_HSR is not set
# CONFIG_NET_SWITCHDEV is not set
# CONFIG_NET_L3_MASTER_DEV is not set
# CONFIG_QRTR is not set
# CONFIG_NET_NCSI is not set
CONFIG_PCPU_DEV_REFCNT=y
CONFIG_RPS=y
CONFIG_RFS_ACCEL=y
CONFIG_SOCK_RX_QUEUE_MAPPING=y
CONFIG_XPS=y
# CONFIG_CGROUP_NET_PRIO is not set
# CONFIG_CGROUP_NET_CLASSID is not set
CONFIG_NET_RX_BUSY_POLL=y
CONFIG_BQL=y
CONFIG_NET_FLOW_LIMIT=y

#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_NET_DROP_MONITOR is not set
# end of Network testing
# end of Networking options

# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
# CONFIG_AF_KCM is not set
# CONFIG_MCTP is not set
CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set

#
# CFG80211 needs to be enabled for MAC80211
#
CONFIG_MAC80211_STA_HASH_MAX_SIZE=0
# CONFIG_RFKILL is not set
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
# CONFIG_NET_9P_DEBUG is not set
# CONFIG_CAIF is not set
# CONFIG_CEPH_LIB is not set
# CONFIG_NFC is not set
# CONFIG_PSAMPLE is not set
# CONFIG_NET_IFE is not set
# CONFIG_LWTUNNEL is not set
CONFIG_DST_CACHE=y
CONFIG_GRO_CELLS=y
CONFIG_NET_SOCK_MSG=y
CONFIG_FAILOVER=m
CONFIG_ETHTOOL_NETLINK=y

#
# Device Drivers
#
CONFIG_HAVE_EISA=y
CONFIG_EISA=y
# CONFIG_EISA_VLB_PRIMING is not set
CONFIG_EISA_PCI_EISA=y
# CONFIG_EISA_VIRTUAL_ROOT is not set
# CONFIG_EISA_NAMES is not set
CONFIG_HAVE_PCI=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
# CONFIG_PCIEPORTBUS is not set
CONFIG_PCIEASPM=y
CONFIG_PCIEASPM_DEFAULT=y
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
# CONFIG_PCIEASPM_PERFORMANCE is not set
# CONFIG_PCIE_PTM is not set
# CONFIG_PCI_MSI is not set
CONFIG_PCI_QUIRKS=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
CONFIG_PCI_LOCKLESS_CONFIG=y
# CONFIG_PCI_IOV is not set
# CONFIG_PCI_PRI is not set
# CONFIG_PCI_PASID is not set
CONFIG_PCI_LABEL=y
# CONFIG_PCIE_BUS_TUNE_OFF is not set
CONFIG_PCIE_BUS_DEFAULT=y
# CONFIG_PCIE_BUS_SAFE is not set
# CONFIG_PCIE_BUS_PERFORMANCE is not set
# CONFIG_PCIE_BUS_PEER2PEER is not set
# CONFIG_HOTPLUG_PCI is not set

#
# PCI controller drivers
#

#
# DesignWare PCI Core Support
#
# end of DesignWare PCI Core Support

#
# Mobiveil PCIe Core Support
#
# end of Mobiveil PCIe Core Support

#
# Cadence PCIe controllers support
#
# end of Cadence PCIe controllers support
# end of PCI controller drivers

#
# PCI Endpoint
#
# CONFIG_PCI_ENDPOINT is not set
# end of PCI Endpoint

#
# PCI switch controller drivers
#
# CONFIG_PCI_SW_SWITCHTEC is not set
# end of PCI switch controller drivers

# CONFIG_CXL_BUS is not set
# CONFIG_PCCARD is not set
# CONFIG_RAPIDIO is not set

#
# Generic Driver Options
#
CONFIG_AUXILIARY_BUS=y
# CONFIG_UEVENT_HELPER is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set

#
# Firmware loader
#
CONFIG_FW_LOADER=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_EXTRA_FIRMWARE=""
# CONFIG_FW_LOADER_USER_HELPER is not set
CONFIG_FW_LOADER_COMPRESS=y
# end of Firmware loader

# CONFIG_ALLOW_DEV_COREDUMP is not set
# CONFIG_DEBUG_DRIVER is not set
CONFIG_DEBUG_DEVRES=y
# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set
CONFIG_PM_QOS_KUNIT_TEST=y
# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set
CONFIG_DRIVER_PE_KUNIT_TEST=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_W1=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGMAP_IRQ=y
CONFIG_REGMAP_SOUNDWIRE=y
CONFIG_REGMAP_SOUNDWIRE_MBQ=y
CONFIG_DMA_SHARED_BUFFER=y
# CONFIG_DMA_FENCE_TRACE is not set
# end of Generic Driver Options

#
# Bus devices
#
CONFIG_MHI_BUS=y
# CONFIG_MHI_BUS_DEBUG is not set
# CONFIG_MHI_BUS_PCI_GENERIC is not set
# end of Bus devices

# CONFIG_CONNECTOR is not set
CONFIG_GNSS=y
CONFIG_MTD=y
# CONFIG_MTD_TESTS is not set

#
# Partition parsers
#
CONFIG_MTD_AR7_PARTS=y
# CONFIG_MTD_CMDLINE_PARTS is not set
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
# end of Partition parsers

#
# User Modules And Translation Layers
#
CONFIG_MTD_OOPS=y
# CONFIG_MTD_PARTITIONED_MASTER is not set

#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
# CONFIG_MTD_JEDECPROBE is not set
CONFIG_MTD_GEN_PROBE=y
# CONFIG_MTD_CFI_ADV_OPTIONS is not set
CONFIG_MTD_MAP_BANK_WIDTH_1=y
CONFIG_MTD_MAP_BANK_WIDTH_2=y
CONFIG_MTD_MAP_BANK_WIDTH_4=y
CONFIG_MTD_CFI_I1=y
CONFIG_MTD_CFI_I2=y
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_STAA=y
CONFIG_MTD_CFI_UTIL=y
CONFIG_MTD_RAM=y
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
# end of RAM/ROM/Flash chip drivers

#
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
CONFIG_MTD_PHYSMAP=y
# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_PHYSMAP_GPIO_ADDR is not set
# CONFIG_MTD_SCx200_DOCFLASH is not set
# CONFIG_MTD_PCI is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
# CONFIG_MTD_PLATRAM is not set
# end of Mapping drivers for chip access

#
# Self-contained MTD device drivers
#
# CONFIG_MTD_PMC551 is not set
CONFIG_MTD_SLRAM=y
CONFIG_MTD_PHRAM=y
# CONFIG_MTD_MTDRAM is not set

#
# Disk-On-Chip Device Drivers
#
CONFIG_MTD_DOCG3=y
CONFIG_BCH_CONST_M=14
CONFIG_BCH_CONST_T=4
# end of Self-contained MTD device drivers

#
# NAND
#
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_ONENAND=y
# CONFIG_MTD_ONENAND_VERIFY_WRITE is not set
CONFIG_MTD_ONENAND_GENERIC=y
# CONFIG_MTD_ONENAND_OTP is not set
CONFIG_MTD_ONENAND_2X_PROGRAM=y
CONFIG_MTD_RAW_NAND=y

#
# Raw/parallel NAND flash controllers
#
# CONFIG_MTD_NAND_DENALI_PCI is not set
# CONFIG_MTD_NAND_CAFE is not set
CONFIG_MTD_NAND_CS553X=y
# CONFIG_MTD_NAND_MXIC is not set
CONFIG_MTD_NAND_GPIO=y
CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_NAND_ARASAN=y

#
# Misc
#
CONFIG_MTD_NAND_NANDSIM=y
# CONFIG_MTD_NAND_RICOH is not set
# CONFIG_MTD_NAND_DISKONCHIP is not set

#
# ECC engine support
#
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set
# CONFIG_MTD_NAND_ECC_SW_BCH is not set
# end of ECC engine support
# end of NAND

#
# LPDDR & LPDDR2 PCM memory drivers
#
# CONFIG_MTD_LPDDR is not set
# end of LPDDR & LPDDR2 PCM memory drivers

CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_FASTMAP=y
CONFIG_MTD_UBI_GLUEBI=y
# CONFIG_MTD_HYPERBUS is not set
# CONFIG_OF is not set
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_PARPORT=y
# CONFIG_PARPORT_PC is not set
CONFIG_PARPORT_AX88796=y
# CONFIG_PARPORT_1284 is not set
CONFIG_PARPORT_NOT_PC=y
CONFIG_PNP=y
# CONFIG_PNP_DEBUG_MESSAGES is not set

#
# Protocols
#
CONFIG_PNPACPI=y

#
# NVME Support
#
# end of NVME Support

#
# Misc devices
#
CONFIG_AD525X_DPOT=y
CONFIG_AD525X_DPOT_I2C=y
CONFIG_DUMMY_IRQ=y
# CONFIG_IBM_ASM is not set
# CONFIG_PHANTOM is not set
# CONFIG_TIFM_CORE is not set
# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
CONFIG_APDS9802ALS=y
CONFIG_ISL29003=y
CONFIG_ISL29020=y
# CONFIG_SENSORS_TSL2550 is not set
CONFIG_SENSORS_BH1770=y
# CONFIG_SENSORS_APDS990X is not set
CONFIG_HMC6352=y
CONFIG_DS1682=y
# CONFIG_PCH_PHUB is not set
CONFIG_SRAM=y
# CONFIG_DW_XDATA_PCIE is not set
# CONFIG_PCI_ENDPOINT_TEST is not set
# CONFIG_XILINX_SDFEC is not set
# CONFIG_C2PORT is not set

#
# EEPROM support
#
# CONFIG_EEPROM_AT24 is not set
CONFIG_EEPROM_LEGACY=y
CONFIG_EEPROM_MAX6875=y
# CONFIG_EEPROM_93CX6 is not set
# CONFIG_EEPROM_IDT_89HPESX is not set
CONFIG_EEPROM_EE1004=y
# end of EEPROM support

# CONFIG_CB710_CORE is not set

#
# Texas Instruments shared transport line discipline
#
# CONFIG_TI_ST is not set
# end of Texas Instruments shared transport line discipline

# CONFIG_SENSORS_LIS3_I2C is not set
CONFIG_ALTERA_STAPL=y
# CONFIG_INTEL_MEI is not set
# CONFIG_INTEL_MEI_ME is not set
# CONFIG_INTEL_MEI_TXE is not set
# CONFIG_VMWARE_VMCI is not set
# CONFIG_ECHO is not set
# CONFIG_MISC_ALCOR_PCI is not set
# CONFIG_MISC_RTSX_PCI is not set
# CONFIG_HABANA_AI is not set
# CONFIG_UACCE is not set
# CONFIG_PVPANIC is not set
# end of Misc devices

#
# SCSI device support
#
CONFIG_SCSI_MOD=y
# end of SCSI device support

# CONFIG_FUSION is not set

#
# IEEE 1394 (FireWire) support
#
# CONFIG_FIREWIRE is not set
# CONFIG_FIREWIRE_NOSY is not set
# end of IEEE 1394 (FireWire) support

# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
CONFIG_NET_CORE=y
# CONFIG_BONDING is not set
# CONFIG_DUMMY is not set
# CONFIG_WIREGUARD is not set
# CONFIG_EQUALIZER is not set
# CONFIG_NET_TEAM is not set
# CONFIG_MACVLAN is not set
# CONFIG_IPVLAN is not set
# CONFIG_VXLAN is not set
# CONFIG_GENEVE is not set
# CONFIG_BAREUDP is not set
# CONFIG_GTP is not set
# CONFIG_MACSEC is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_TUN is not set
# CONFIG_TUN_VNET_CROSS_LE is not set
# CONFIG_VETH is not set
CONFIG_VIRTIO_NET=m
# CONFIG_NLMON is not set
# CONFIG_MHI_NET is not set
# CONFIG_ARCNET is not set
CONFIG_ETHERNET=y
CONFIG_NET_VENDOR_3COM=y
# CONFIG_EL3 is not set
# CONFIG_VORTEX is not set
# CONFIG_TYPHOON is not set
CONFIG_NET_VENDOR_ADAPTEC=y
# CONFIG_ADAPTEC_STARFIRE is not set
CONFIG_NET_VENDOR_AGERE=y
# CONFIG_ET131X is not set
CONFIG_NET_VENDOR_ALACRITECH=y
# CONFIG_SLICOSS is not set
CONFIG_NET_VENDOR_ALTEON=y
# CONFIG_ACENIC is not set
# CONFIG_ALTERA_TSE is not set
CONFIG_NET_VENDOR_AMAZON=y
CONFIG_NET_VENDOR_AMD=y
# CONFIG_AMD8111_ETH is not set
# CONFIG_PCNET32 is not set
# CONFIG_AMD_XGBE is not set
CONFIG_NET_VENDOR_AQUANTIA=y
# CONFIG_AQTION is not set
CONFIG_NET_VENDOR_ARC=y
CONFIG_NET_VENDOR_ATHEROS=y
# CONFIG_ATL2 is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
# CONFIG_ATL1C is not set
# CONFIG_ALX is not set
CONFIG_NET_VENDOR_BROADCOM=y
# CONFIG_B44 is not set
# CONFIG_BCMGENET is not set
# CONFIG_BNX2 is not set
# CONFIG_CNIC is not set
# CONFIG_TIGON3 is not set
# CONFIG_BNX2X is not set
# CONFIG_SYSTEMPORT is not set
# CONFIG_BNXT is not set
CONFIG_NET_VENDOR_BROCADE=y
# CONFIG_BNA is not set
CONFIG_NET_VENDOR_CADENCE=y
# CONFIG_MACB is not set
CONFIG_NET_VENDOR_CAVIUM=y
CONFIG_NET_VENDOR_CHELSIO=y
# CONFIG_CHELSIO_T1 is not set
# CONFIG_CHELSIO_T3 is not set
# CONFIG_CHELSIO_T4 is not set
# CONFIG_CHELSIO_T4VF is not set
CONFIG_NET_VENDOR_CIRRUS=y
CONFIG_NET_VENDOR_CISCO=y
# CONFIG_ENIC is not set
CONFIG_NET_VENDOR_CORTINA=y
# CONFIG_CX_ECAT is not set
# CONFIG_DNET is not set
CONFIG_NET_VENDOR_DEC=y
# CONFIG_NET_TULIP is not set
CONFIG_NET_VENDOR_DLINK=y
# CONFIG_DL2K is not set
# CONFIG_SUNDANCE is not set
CONFIG_NET_VENDOR_EMULEX=y
# CONFIG_BE2NET is not set
CONFIG_NET_VENDOR_EZCHIP=y
CONFIG_NET_VENDOR_GOOGLE=y
CONFIG_NET_VENDOR_HUAWEI=y
CONFIG_NET_VENDOR_I825XX=y
CONFIG_NET_VENDOR_INTEL=y
# CONFIG_E100 is not set
CONFIG_E1000=y
# CONFIG_E1000E is not set
# CONFIG_IGB is not set
# CONFIG_IGBVF is not set
# CONFIG_IXGB is not set
# CONFIG_IXGBE is not set
# CONFIG_I40E is not set
# CONFIG_IGC is not set
CONFIG_NET_VENDOR_MICROSOFT=y
# CONFIG_JME is not set
CONFIG_NET_VENDOR_LITEX=y
CONFIG_NET_VENDOR_MARVELL=y
# CONFIG_MVMDIO is not set
# CONFIG_SKGE is not set
# CONFIG_SKY2 is not set
CONFIG_NET_VENDOR_MELLANOX=y
# CONFIG_MLX4_EN is not set
# CONFIG_MLX5_CORE is not set
# CONFIG_MLXSW_CORE is not set
# CONFIG_MLXFW is not set
CONFIG_NET_VENDOR_MICREL=y
# CONFIG_KS8842 is not set
# CONFIG_KS8851_MLL is not set
# CONFIG_KSZ884X_PCI is not set
CONFIG_NET_VENDOR_MICROCHIP=y
# CONFIG_LAN743X is not set
CONFIG_NET_VENDOR_MICROSEMI=y
CONFIG_NET_VENDOR_MYRI=y
# CONFIG_MYRI10GE is not set
# CONFIG_FEALNX is not set
CONFIG_NET_VENDOR_NATSEMI=y
# CONFIG_NATSEMI is not set
# CONFIG_NS83820 is not set
CONFIG_NET_VENDOR_NETERION=y
# CONFIG_S2IO is not set
# CONFIG_VXGE is not set
CONFIG_NET_VENDOR_NETRONOME=y
CONFIG_NET_VENDOR_NI=y
# CONFIG_NI_XGE_MANAGEMENT_ENET is not set
CONFIG_NET_VENDOR_8390=y
# CONFIG_NE2K_PCI is not set
CONFIG_NET_VENDOR_NVIDIA=y
# CONFIG_FORCEDETH is not set
CONFIG_NET_VENDOR_OKI=y
# CONFIG_PCH_GBE is not set
# CONFIG_ETHOC is not set
CONFIG_NET_VENDOR_PACKET_ENGINES=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
CONFIG_NET_VENDOR_PENSANDO=y
CONFIG_NET_VENDOR_QLOGIC=y
# CONFIG_QLA3XXX is not set
# CONFIG_QLCNIC is not set
# CONFIG_NETXEN_NIC is not set
# CONFIG_QED is not set
CONFIG_NET_VENDOR_QUALCOMM=y
# CONFIG_QCOM_EMAC is not set
# CONFIG_RMNET is not set
CONFIG_NET_VENDOR_RDC=y
# CONFIG_R6040 is not set
CONFIG_NET_VENDOR_REALTEK=y
# CONFIG_ATP is not set
# CONFIG_8139CP is not set
# CONFIG_8139TOO is not set
# CONFIG_R8169 is not set
CONFIG_NET_VENDOR_RENESAS=y
CONFIG_NET_VENDOR_ROCKER=y
CONFIG_NET_VENDOR_SAMSUNG=y
# CONFIG_SXGBE_ETH is not set
CONFIG_NET_VENDOR_SEEQ=y
CONFIG_NET_VENDOR_SOLARFLARE=y
# CONFIG_SFC is not set
# CONFIG_SFC_FALCON is not set
CONFIG_NET_VENDOR_SILAN=y
# CONFIG_SC92031 is not set
CONFIG_NET_VENDOR_SIS=y
# CONFIG_SIS900 is not set
# CONFIG_SIS190 is not set
CONFIG_NET_VENDOR_SMSC=y
# CONFIG_EPIC100 is not set
# CONFIG_SMSC911X is not set
# CONFIG_SMSC9420 is not set
CONFIG_NET_VENDOR_SOCIONEXT=y
CONFIG_NET_VENDOR_STMICRO=y
# CONFIG_STMMAC_ETH is not set
CONFIG_NET_VENDOR_SUN=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_CASSINI is not set
# CONFIG_NIU is not set
CONFIG_NET_VENDOR_SYNOPSYS=y
# CONFIG_DWC_XLGMAC is not set
CONFIG_NET_VENDOR_TEHUTI=y
# CONFIG_TEHUTI is not set
CONFIG_NET_VENDOR_TI=y
# CONFIG_TI_CPSW_PHY_SEL is not set
# CONFIG_TLAN is not set
CONFIG_NET_VENDOR_VIA=y
# CONFIG_VIA_RHINE is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_NET_VENDOR_WIZNET=y
# CONFIG_WIZNET_W5100 is not set
# CONFIG_WIZNET_W5300 is not set
CONFIG_NET_VENDOR_XILINX=y
# CONFIG_XILINX_EMACLITE is not set
# CONFIG_XILINX_AXI_EMAC is not set
# CONFIG_XILINX_LL_TEMAC is not set
# CONFIG_FDDI is not set
# CONFIG_HIPPI is not set
# CONFIG_NET_SB1000 is not set
# CONFIG_PHYLIB is not set
# CONFIG_MDIO_DEVICE is not set

#
# PCS device drivers
#
# end of PCS device drivers

# CONFIG_PLIP is not set
# CONFIG_PPP is not set
# CONFIG_SLIP is not set

#
# Host-side USB support is needed for USB Network Adapter support
#
CONFIG_WLAN=y
CONFIG_WLAN_VENDOR_ADMTEK=y
CONFIG_WLAN_VENDOR_ATH=y
# CONFIG_ATH_DEBUG is not set
# CONFIG_ATH5K_PCI is not set
CONFIG_WLAN_VENDOR_ATMEL=y
CONFIG_WLAN_VENDOR_BROADCOM=y
CONFIG_WLAN_VENDOR_CISCO=y
CONFIG_WLAN_VENDOR_INTEL=y
CONFIG_WLAN_VENDOR_INTERSIL=y
# CONFIG_HOSTAP is not set
CONFIG_WLAN_VENDOR_MARVELL=y
CONFIG_WLAN_VENDOR_MEDIATEK=y
CONFIG_WLAN_VENDOR_MICROCHIP=y
CONFIG_WLAN_VENDOR_RALINK=y
CONFIG_WLAN_VENDOR_REALTEK=y
CONFIG_WLAN_VENDOR_RSI=y
CONFIG_WLAN_VENDOR_ST=y
CONFIG_WLAN_VENDOR_TI=y
CONFIG_WLAN_VENDOR_ZYDAS=y
CONFIG_WLAN_VENDOR_QUANTENNA=y
# CONFIG_WAN is not set

#
# Wireless WAN
#
# CONFIG_WWAN is not set
# end of Wireless WAN

# CONFIG_VMXNET3 is not set
# CONFIG_FUJITSU_ES is not set
# CONFIG_NETDEVSIM is not set
CONFIG_NET_FAILOVER=m
# CONFIG_ISDN is not set

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_LEDS=y
# CONFIG_INPUT_FF_MEMLESS is not set
# CONFIG_INPUT_SPARSEKMAP is not set
# CONFIG_INPUT_MATRIXKMAP is not set

#
# Userland interfaces
#
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_JOYDEV is not set
# CONFIG_INPUT_EVDEV is not set
# CONFIG_INPUT_EVBUG is not set

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
# CONFIG_KEYBOARD_ADC is not set
# CONFIG_KEYBOARD_ADP5520 is not set
# CONFIG_KEYBOARD_ADP5588 is not set
# CONFIG_KEYBOARD_ADP5589 is not set
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_QT1050 is not set
# CONFIG_KEYBOARD_QT1070 is not set
# CONFIG_KEYBOARD_QT2160 is not set
# CONFIG_KEYBOARD_DLINK_DIR685 is not set
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_GPIO is not set
# CONFIG_KEYBOARD_GPIO_POLLED is not set
# CONFIG_KEYBOARD_TCA6416 is not set
# CONFIG_KEYBOARD_TCA8418 is not set
# CONFIG_KEYBOARD_MATRIX is not set
# CONFIG_KEYBOARD_LM8323 is not set
# CONFIG_KEYBOARD_LM8333 is not set
# CONFIG_KEYBOARD_MAX7359 is not set
# CONFIG_KEYBOARD_MCS is not set
# CONFIG_KEYBOARD_MPR121 is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_SAMSUNG is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set
# CONFIG_KEYBOARD_TWL4030 is not set
# CONFIG_KEYBOARD_XTKBD is not set
# CONFIG_KEYBOARD_CROS_EC is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_BYD=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_SYNAPTICS_SMBUS=y
CONFIG_MOUSE_PS2_CYPRESS=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_SENTELIC is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
CONFIG_MOUSE_PS2_FOCALTECH=y
# CONFIG_MOUSE_PS2_VMMOUSE is not set
CONFIG_MOUSE_PS2_SMBUS=y
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_APPLETOUCH is not set
# CONFIG_MOUSE_BCM5974 is not set
# CONFIG_MOUSE_CYAPA is not set
# CONFIG_MOUSE_ELAN_I2C is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_MOUSE_GPIO is not set
# CONFIG_MOUSE_SYNAPTICS_I2C is not set
# CONFIG_MOUSE_SYNAPTICS_USB is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TABLET is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
# CONFIG_INPUT_MISC is not set
# CONFIG_RMI4_CORE is not set

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
CONFIG_SERIO_CT82C710=y
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_PCIPS2 is not set
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_RAW=y
# CONFIG_SERIO_ALTERA_PS2 is not set
CONFIG_SERIO_PS2MULT=y
CONFIG_SERIO_ARC_PS2=y
CONFIG_SERIO_GPIO_PS2=y
# CONFIG_USERIO is not set
# CONFIG_GAMEPORT is not set
# end of Hardware I/O ports
# end of Input device support

#
# Character devices
#
CONFIG_TTY=y
# CONFIG_VT is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_LEGACY_PTYS is not set
# CONFIG_LDISC_AUTOLOAD is not set

#
# Serial drivers
#
CONFIG_SERIAL_EARLYCON=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
# CONFIG_SERIAL_8250_PNP is not set
CONFIG_SERIAL_8250_16550A_VARIANTS=y
CONFIG_SERIAL_8250_FINTEK=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_SERIAL_8250_DMA is not set
CONFIG_SERIAL_8250_PCI=y
CONFIG_SERIAL_8250_EXAR=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
# CONFIG_SERIAL_8250_EXTENDED is not set
CONFIG_SERIAL_8250_DWLIB=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_8250_RT288X=y
CONFIG_SERIAL_8250_LPSS=y
CONFIG_SERIAL_8250_MID=y

#
# Non-8250 serial port support
#
CONFIG_SERIAL_UARTLITE=y
CONFIG_SERIAL_UARTLITE_CONSOLE=y
CONFIG_SERIAL_UARTLITE_NR_UARTS=1
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_SERIAL_LANTIQ=y
# CONFIG_SERIAL_LANTIQ_CONSOLE is not set
CONFIG_SERIAL_SCCNXP=y
CONFIG_SERIAL_SCCNXP_CONSOLE=y
CONFIG_SERIAL_SC16IS7XX=y
# CONFIG_SERIAL_SC16IS7XX_I2C is not set
CONFIG_SERIAL_TIMBERDALE=y
CONFIG_SERIAL_BCM63XX=y
CONFIG_SERIAL_BCM63XX_CONSOLE=y
# CONFIG_SERIAL_ALTERA_JTAGUART is not set
CONFIG_SERIAL_ALTERA_UART=y
CONFIG_SERIAL_ALTERA_UART_MAXPORTS=4
CONFIG_SERIAL_ALTERA_UART_BAUDRATE=115200
CONFIG_SERIAL_ALTERA_UART_CONSOLE=y
# CONFIG_SERIAL_PCH_UART is not set
CONFIG_SERIAL_ARC=y
# CONFIG_SERIAL_ARC_CONSOLE is not set
CONFIG_SERIAL_ARC_NR_PORTS=1
# CONFIG_SERIAL_RP2 is not set
CONFIG_SERIAL_FSL_LPUART=y
CONFIG_SERIAL_FSL_LPUART_CONSOLE=y
# CONFIG_SERIAL_FSL_LINFLEXUART is not set
CONFIG_SERIAL_SPRD=y
# CONFIG_SERIAL_SPRD_CONSOLE is not set
# end of Serial drivers

CONFIG_SERIAL_MCTRL_GPIO=y
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_N_GSM is not set
# CONFIG_NOZOMI is not set
# CONFIG_NULL_TTY is not set
CONFIG_HVC_DRIVER=y
# CONFIG_SERIAL_DEV_BUS is not set
# CONFIG_TTY_PRINTK is not set
CONFIG_PRINTER=y
CONFIG_LP_CONSOLE=y
# CONFIG_PPDEV is not set
CONFIG_VIRTIO_CONSOLE=y
CONFIG_IPMI_HANDLER=y
CONFIG_IPMI_PLAT_DATA=y
CONFIG_IPMI_PANIC_EVENT=y
# CONFIG_IPMI_PANIC_STRING is not set
# CONFIG_IPMI_DEVICE_INTERFACE is not set
CONFIG_IPMI_SI=y
# CONFIG_IPMI_SSIF is not set
CONFIG_IPMI_WATCHDOG=y
CONFIG_IPMI_POWEROFF=y
CONFIG_IPMB_DEVICE_INTERFACE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_APPLICOM is not set
# CONFIG_SONYPI is not set
CONFIG_MWAVE=y
CONFIG_SCx200_GPIO=y
# CONFIG_PC8736x_GPIO is not set
CONFIG_NSC_GPIO=y
# CONFIG_DEVMEM is not set
# CONFIG_NVRAM is not set
CONFIG_DEVPORT=y
CONFIG_HPET=y
# CONFIG_HPET_MMAP is not set
# CONFIG_HANGCHECK_TIMER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_TELCLOCK is not set
# CONFIG_XILLYBUS is not set
# CONFIG_RANDOM_TRUST_CPU is not set
# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# end of Character devices

#
# I2C support
#
CONFIG_I2C=y
CONFIG_ACPI_I2C_OPREGION=y
CONFIG_I2C_BOARDINFO=y
# CONFIG_I2C_COMPAT is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y

#
# Multiplexer I2C Chip support
#
CONFIG_I2C_MUX_GPIO=y
CONFIG_I2C_MUX_LTC4306=y
# CONFIG_I2C_MUX_PCA9541 is not set
CONFIG_I2C_MUX_PCA954x=y
# CONFIG_I2C_MUX_REG is not set
# CONFIG_I2C_MUX_MLXCPLD is not set
# end of Multiplexer I2C Chip support

CONFIG_I2C_HELPER_AUTO=y
CONFIG_I2C_SMBUS=y
CONFIG_I2C_ALGOBIT=y

#
# I2C Hardware Bus support
#

#
# PC SMBus host controller drivers
#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_AMD_MP2 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_ISMT is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_CHT_WC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_NVIDIA_GPU is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set

#
# ACPI drivers
#
CONFIG_I2C_SCMI=y

#
# I2C system bus drivers (mostly embedded / system-on-chip)
#
CONFIG_I2C_CBUS_GPIO=y
CONFIG_I2C_DESIGNWARE_CORE=y
# CONFIG_I2C_DESIGNWARE_SLAVE is not set
CONFIG_I2C_DESIGNWARE_PLATFORM=y
# CONFIG_I2C_DESIGNWARE_BAYTRAIL is not set
# CONFIG_I2C_DESIGNWARE_PCI is not set
# CONFIG_I2C_EG20T is not set
CONFIG_I2C_EMEV2=y
# CONFIG_I2C_GPIO is not set
CONFIG_I2C_OCORES=y
# CONFIG_I2C_PCA_PLATFORM is not set
# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_XILINX is not set

#
# External I2C/SMBus adapter drivers
#
CONFIG_I2C_PARPORT=y
CONFIG_I2C_TAOS_EVM=y

#
# Other I2C/SMBus bus drivers
#
CONFIG_I2C_CROS_EC_TUNNEL=y
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_VIRTIO is not set
# end of I2C Hardware Bus support

# CONFIG_I2C_STUB is not set
CONFIG_I2C_SLAVE=y
# CONFIG_I2C_SLAVE_EEPROM is not set
CONFIG_I2C_SLAVE_TESTUNIT=y
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
# end of I2C support

CONFIG_I3C=y
CONFIG_CDNS_I3C_MASTER=y
# CONFIG_DW_I3C_MASTER is not set
CONFIG_SVC_I3C_MASTER=y
CONFIG_MIPI_I3C_HCI=y
# CONFIG_SPI is not set
# CONFIG_SPMI is not set
# CONFIG_HSI is not set
CONFIG_PPS=y
# CONFIG_PPS_DEBUG is not set
# CONFIG_NTP_PPS is not set

#
# PPS clients support
#
CONFIG_PPS_CLIENT_KTIMER=y
# CONFIG_PPS_CLIENT_LDISC is not set
CONFIG_PPS_CLIENT_PARPORT=y
CONFIG_PPS_CLIENT_GPIO=y

#
# PPS generators support
#

#
# PTP clock support
#
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y

#
# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
#
# CONFIG_PTP_1588_CLOCK_PCH is not set
CONFIG_PTP_1588_CLOCK_KVM=y
# CONFIG_PTP_1588_CLOCK_IDT82P33 is not set
# CONFIG_PTP_1588_CLOCK_IDTCM is not set
# CONFIG_PTP_1588_CLOCK_VMW is not set
# CONFIG_PTP_1588_CLOCK_OCP is not set
# end of PTP clock support

CONFIG_PINCTRL=y
CONFIG_PINMUX=y
CONFIG_PINCONF=y
CONFIG_GENERIC_PINCONF=y
CONFIG_DEBUG_PINCTRL=y
CONFIG_PINCTRL_AMD=y
# CONFIG_PINCTRL_MCP23S08 is not set
CONFIG_PINCTRL_SX150X=y
CONFIG_PINCTRL_BAYTRAIL=y
CONFIG_PINCTRL_CHERRYVIEW=y
# CONFIG_PINCTRL_LYNXPOINT is not set
CONFIG_PINCTRL_INTEL=y
# CONFIG_PINCTRL_ALDERLAKE is not set
# CONFIG_PINCTRL_BROXTON is not set
CONFIG_PINCTRL_CANNONLAKE=y
CONFIG_PINCTRL_CEDARFORK=y
# CONFIG_PINCTRL_DENVERTON is not set
# CONFIG_PINCTRL_ELKHARTLAKE is not set
# CONFIG_PINCTRL_EMMITSBURG is not set
CONFIG_PINCTRL_GEMINILAKE=y
CONFIG_PINCTRL_ICELAKE=y
# CONFIG_PINCTRL_JASPERLAKE is not set
CONFIG_PINCTRL_LAKEFIELD=y
CONFIG_PINCTRL_LEWISBURG=y
CONFIG_PINCTRL_SUNRISEPOINT=y
# CONFIG_PINCTRL_TIGERLAKE is not set

#
# Renesas pinctrl drivers
#
# end of Renesas pinctrl drivers

CONFIG_PINCTRL_MADERA=y
CONFIG_PINCTRL_CS47L35=y
CONFIG_PINCTRL_CS47L85=y
CONFIG_PINCTRL_CS47L90=y
CONFIG_GPIOLIB=y
CONFIG_GPIOLIB_FASTPATH_LIMIT=512
CONFIG_GPIO_ACPI=y
CONFIG_GPIOLIB_IRQCHIP=y
# CONFIG_DEBUG_GPIO is not set
# CONFIG_GPIO_SYSFS is not set
CONFIG_GPIO_CDEV=y
# CONFIG_GPIO_CDEV_V1 is not set
CONFIG_GPIO_GENERIC=y

#
# Memory mapped GPIO drivers
#
CONFIG_GPIO_AMDPT=y
CONFIG_GPIO_DWAPB=y
# CONFIG_GPIO_EXAR is not set
CONFIG_GPIO_GENERIC_PLATFORM=y
# CONFIG_GPIO_MB86S7X is not set
# CONFIG_GPIO_VX855 is not set
CONFIG_GPIO_AMD_FCH=y
# end of Memory mapped GPIO drivers

#
# Port-mapped I/O GPIO drivers
#
CONFIG_GPIO_F7188X=y
# CONFIG_GPIO_IT87 is not set
CONFIG_GPIO_SCH311X=y
CONFIG_GPIO_WINBOND=y
CONFIG_GPIO_WS16C48=y
# end of Port-mapped I/O GPIO drivers

#
# I2C GPIO expanders
#
# CONFIG_GPIO_ADP5588 is not set
# CONFIG_GPIO_MAX7300 is not set
# CONFIG_GPIO_MAX732X is not set
# CONFIG_GPIO_PCA953X is not set
# CONFIG_GPIO_PCA9570 is not set
# CONFIG_GPIO_PCF857X is not set
CONFIG_GPIO_TPIC2810=y
# end of I2C GPIO expanders

#
# MFD GPIO expanders
#
# CONFIG_GPIO_ADP5520 is not set
CONFIG_GPIO_ARIZONA=y
CONFIG_GPIO_CRYSTAL_COVE=y
# CONFIG_GPIO_DA9052 is not set
# CONFIG_GPIO_MADERA is not set
# CONFIG_GPIO_PALMAS is not set
CONFIG_GPIO_RC5T583=y
# CONFIG_GPIO_TPS65086 is not set
CONFIG_GPIO_TPS65912=y
CONFIG_GPIO_TQMX86=y
CONFIG_GPIO_TWL4030=y
# CONFIG_GPIO_TWL6040 is not set
# CONFIG_GPIO_UCB1400 is not set
CONFIG_GPIO_WM831X=y
# end of MFD GPIO expanders

#
# PCI GPIO expanders
#
# CONFIG_GPIO_AMD8111 is not set
# CONFIG_GPIO_BT8XX is not set
# CONFIG_GPIO_ML_IOH is not set
# CONFIG_GPIO_PCH is not set
# CONFIG_GPIO_PCI_IDIO_16 is not set
# CONFIG_GPIO_PCIE_IDIO_24 is not set
# CONFIG_GPIO_RDC321X is not set
# end of PCI GPIO expanders

#
# Virtual GPIO drivers
#
CONFIG_GPIO_AGGREGATOR=y
CONFIG_GPIO_MOCKUP=y
# CONFIG_GPIO_VIRTIO is not set
# end of Virtual GPIO drivers

CONFIG_W1=y

#
# 1-wire Bus Masters
#
# CONFIG_W1_MASTER_MATROX is not set
# CONFIG_W1_MASTER_DS2482 is not set
CONFIG_W1_MASTER_DS1WM=y
# CONFIG_W1_MASTER_GPIO is not set
CONFIG_W1_MASTER_SGI=y
# end of 1-wire Bus Masters

#
# 1-wire Slaves
#
CONFIG_W1_SLAVE_THERM=y
CONFIG_W1_SLAVE_SMEM=y
# CONFIG_W1_SLAVE_DS2405 is not set
CONFIG_W1_SLAVE_DS2408=y
# CONFIG_W1_SLAVE_DS2408_READBACK is not set
# CONFIG_W1_SLAVE_DS2413 is not set
# CONFIG_W1_SLAVE_DS2406 is not set
CONFIG_W1_SLAVE_DS2423=y
CONFIG_W1_SLAVE_DS2805=y
CONFIG_W1_SLAVE_DS2430=y
CONFIG_W1_SLAVE_DS2431=y
# CONFIG_W1_SLAVE_DS2433 is not set
CONFIG_W1_SLAVE_DS2438=y
CONFIG_W1_SLAVE_DS250X=y
CONFIG_W1_SLAVE_DS2780=y
# CONFIG_W1_SLAVE_DS2781 is not set
CONFIG_W1_SLAVE_DS28E04=y
CONFIG_W1_SLAVE_DS28E17=y
# end of 1-wire Slaves

# CONFIG_POWER_RESET is not set
CONFIG_POWER_SUPPLY=y
# CONFIG_POWER_SUPPLY_DEBUG is not set
CONFIG_POWER_SUPPLY_HWMON=y
CONFIG_PDA_POWER=y
CONFIG_GENERIC_ADC_BATTERY=y
CONFIG_MAX8925_POWER=y
CONFIG_WM831X_BACKUP=y
CONFIG_WM831X_POWER=y
CONFIG_TEST_POWER=y
CONFIG_CHARGER_ADP5061=y
# CONFIG_BATTERY_CW2015 is not set
CONFIG_BATTERY_DS2760=y
CONFIG_BATTERY_DS2780=y
# CONFIG_BATTERY_DS2781 is not set
CONFIG_BATTERY_DS2782=y
CONFIG_BATTERY_SBS=y
CONFIG_CHARGER_SBS=y
CONFIG_MANAGER_SBS=y
CONFIG_BATTERY_BQ27XXX=y
CONFIG_BATTERY_BQ27XXX_I2C=y
CONFIG_BATTERY_BQ27XXX_HDQ=y
# CONFIG_BATTERY_BQ27XXX_DT_UPDATES_NVM is not set
CONFIG_BATTERY_DA9030=y
CONFIG_BATTERY_DA9052=y
CONFIG_BATTERY_DA9150=y
CONFIG_CHARGER_AXP20X=y
CONFIG_BATTERY_AXP20X=y
CONFIG_AXP20X_POWER=y
CONFIG_AXP288_FUEL_GAUGE=y
# CONFIG_BATTERY_MAX17040 is not set
CONFIG_BATTERY_MAX17042=y
CONFIG_BATTERY_MAX1721X=y
CONFIG_BATTERY_TWL4030_MADC=y
CONFIG_BATTERY_RX51=y
# CONFIG_CHARGER_MAX8903 is not set
CONFIG_CHARGER_TWL4030=y
CONFIG_CHARGER_LP8727=y
CONFIG_CHARGER_GPIO=y
CONFIG_CHARGER_MANAGER=y
CONFIG_CHARGER_LT3651=y
CONFIG_CHARGER_LTC4162L=y
CONFIG_CHARGER_MAX77693=y
# CONFIG_CHARGER_MAX8997 is not set
# CONFIG_CHARGER_MT6360 is not set
CONFIG_CHARGER_BQ2415X=y
CONFIG_CHARGER_BQ24190=y
CONFIG_CHARGER_BQ24257=y
CONFIG_CHARGER_BQ24735=y
CONFIG_CHARGER_BQ2515X=y
CONFIG_CHARGER_BQ25890=y
CONFIG_CHARGER_BQ25980=y
CONFIG_CHARGER_BQ256XX=y
CONFIG_CHARGER_SMB347=y
CONFIG_BATTERY_GAUGE_LTC2941=y
CONFIG_BATTERY_GOLDFISH=y
# CONFIG_BATTERY_RT5033 is not set
CONFIG_CHARGER_RT9455=y
CONFIG_CHARGER_CROS_PCHG=y
CONFIG_CHARGER_BD99954=y
CONFIG_HWMON=y
CONFIG_HWMON_VID=y
# CONFIG_HWMON_DEBUG_CHIP is not set

#
# Native drivers
#
CONFIG_SENSORS_AD7414=y
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
CONFIG_SENSORS_ADM1025=y
CONFIG_SENSORS_ADM1026=y
CONFIG_SENSORS_ADM1029=y
CONFIG_SENSORS_ADM1031=y
# CONFIG_SENSORS_ADM1177 is not set
CONFIG_SENSORS_ADM9240=y
CONFIG_SENSORS_ADT7X10=y
CONFIG_SENSORS_ADT7410=y
# CONFIG_SENSORS_ADT7411 is not set
CONFIG_SENSORS_ADT7462=y
CONFIG_SENSORS_ADT7470=y
CONFIG_SENSORS_ADT7475=y
CONFIG_SENSORS_AHT10=y
CONFIG_SENSORS_AS370=y
CONFIG_SENSORS_ASC7621=y
CONFIG_SENSORS_AXI_FAN_CONTROL=y
# CONFIG_SENSORS_K8TEMP is not set
# CONFIG_SENSORS_K10TEMP is not set
# CONFIG_SENSORS_FAM15H_POWER is not set
# CONFIG_SENSORS_APPLESMC is not set
CONFIG_SENSORS_ASB100=y
CONFIG_SENSORS_ASPEED=y
CONFIG_SENSORS_ATXP1=y
# CONFIG_SENSORS_CORSAIR_CPRO is not set
# CONFIG_SENSORS_CORSAIR_PSU is not set
# CONFIG_SENSORS_DS620 is not set
CONFIG_SENSORS_DS1621=y
CONFIG_SENSORS_DELL_SMM=y
CONFIG_SENSORS_DA9052_ADC=y
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
CONFIG_SENSORS_F71882FG=y
CONFIG_SENSORS_F75375S=y
CONFIG_SENSORS_MC13783_ADC=y
CONFIG_SENSORS_FSCHMD=y
# CONFIG_SENSORS_FTSTEUTATES is not set
CONFIG_SENSORS_GL518SM=y
# CONFIG_SENSORS_GL520SM is not set
CONFIG_SENSORS_G760A=y
CONFIG_SENSORS_G762=y
CONFIG_SENSORS_HIH6130=y
CONFIG_SENSORS_IBMAEM=y
CONFIG_SENSORS_IBMPEX=y
CONFIG_SENSORS_IIO_HWMON=y
# CONFIG_SENSORS_I5500 is not set
CONFIG_SENSORS_CORETEMP=y
CONFIG_SENSORS_IT87=y
CONFIG_SENSORS_JC42=y
# CONFIG_SENSORS_POWR1220 is not set
CONFIG_SENSORS_LINEAGE=y
# CONFIG_SENSORS_LTC2945 is not set
CONFIG_SENSORS_LTC2947=y
CONFIG_SENSORS_LTC2947_I2C=y
CONFIG_SENSORS_LTC2990=y
CONFIG_SENSORS_LTC2992=y
CONFIG_SENSORS_LTC4151=y
CONFIG_SENSORS_LTC4215=y
CONFIG_SENSORS_LTC4222=y
# CONFIG_SENSORS_LTC4245 is not set
# CONFIG_SENSORS_LTC4260 is not set
CONFIG_SENSORS_LTC4261=y
CONFIG_SENSORS_MAX127=y
# CONFIG_SENSORS_MAX16065 is not set
CONFIG_SENSORS_MAX1619=y
CONFIG_SENSORS_MAX1668=y
CONFIG_SENSORS_MAX197=y
CONFIG_SENSORS_MAX31730=y
# CONFIG_SENSORS_MAX6621 is not set
CONFIG_SENSORS_MAX6639=y
# CONFIG_SENSORS_MAX6642 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_MAX6697 is not set
# CONFIG_SENSORS_MAX31790 is not set
CONFIG_SENSORS_MCP3021=y
CONFIG_SENSORS_MLXREG_FAN=y
CONFIG_SENSORS_TC654=y
CONFIG_SENSORS_TPS23861=y
# CONFIG_SENSORS_MENF21BMC_HWMON is not set
# CONFIG_SENSORS_MR75203 is not set
CONFIG_SENSORS_LM63=y
CONFIG_SENSORS_LM73=y
# CONFIG_SENSORS_LM75 is not set
CONFIG_SENSORS_LM77=y
# CONFIG_SENSORS_LM78 is not set
CONFIG_SENSORS_LM80=y
CONFIG_SENSORS_LM83=y
CONFIG_SENSORS_LM85=y
CONFIG_SENSORS_LM87=y
CONFIG_SENSORS_LM90=y
CONFIG_SENSORS_LM92=y
# CONFIG_SENSORS_LM93 is not set
CONFIG_SENSORS_LM95234=y
# CONFIG_SENSORS_LM95241 is not set
# CONFIG_SENSORS_LM95245 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
# CONFIG_SENSORS_NTC_THERMISTOR is not set
# CONFIG_SENSORS_NCT6683 is not set
CONFIG_SENSORS_NCT6775=y
CONFIG_SENSORS_NCT7802=y
# CONFIG_SENSORS_NCT7904 is not set
# CONFIG_SENSORS_NPCM7XX is not set
CONFIG_SENSORS_PCF8591=y
# CONFIG_PMBUS is not set
CONFIG_SENSORS_SBTSI=y
# CONFIG_SENSORS_SBRMI is not set
# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SHT21 is not set
# CONFIG_SENSORS_SHT3x is not set
# CONFIG_SENSORS_SHT4x is not set
CONFIG_SENSORS_SHTC1=y
# CONFIG_SENSORS_SIS5595 is not set
CONFIG_SENSORS_DME1737=y
CONFIG_SENSORS_EMC1403=y
CONFIG_SENSORS_EMC2103=y
CONFIG_SENSORS_EMC6W201=y
# CONFIG_SENSORS_SMSC47M1 is not set
CONFIG_SENSORS_SMSC47M192=y
CONFIG_SENSORS_SMSC47B397=y
CONFIG_SENSORS_SCH56XX_COMMON=y
CONFIG_SENSORS_SCH5627=y
CONFIG_SENSORS_SCH5636=y
CONFIG_SENSORS_STTS751=y
CONFIG_SENSORS_SMM665=y
CONFIG_SENSORS_ADC128D818=y
CONFIG_SENSORS_ADS7828=y
CONFIG_SENSORS_AMC6821=y
CONFIG_SENSORS_INA209=y
# CONFIG_SENSORS_INA2XX is not set
CONFIG_SENSORS_INA3221=y
# CONFIG_SENSORS_TC74 is not set
CONFIG_SENSORS_THMC50=y
# CONFIG_SENSORS_TMP102 is not set
# CONFIG_SENSORS_TMP103 is not set
CONFIG_SENSORS_TMP108=y
CONFIG_SENSORS_TMP401=y
CONFIG_SENSORS_TMP421=y
# CONFIG_SENSORS_TMP513 is not set
# CONFIG_SENSORS_VIA_CPUTEMP is not set
# CONFIG_SENSORS_VIA686A is not set
CONFIG_SENSORS_VT1211=y
# CONFIG_SENSORS_VT8231 is not set
CONFIG_SENSORS_W83773G=y
# CONFIG_SENSORS_W83781D is not set
CONFIG_SENSORS_W83791D=y
CONFIG_SENSORS_W83792D=y
CONFIG_SENSORS_W83793=y
CONFIG_SENSORS_W83795=y
CONFIG_SENSORS_W83795_FANCTRL=y
CONFIG_SENSORS_W83L785TS=y
CONFIG_SENSORS_W83L786NG=y
CONFIG_SENSORS_W83627HF=y
CONFIG_SENSORS_W83627EHF=y
# CONFIG_SENSORS_WM831X is not set

#
# ACPI drivers
#
# CONFIG_SENSORS_ACPI_POWER is not set
CONFIG_SENSORS_ATK0110=y
CONFIG_THERMAL=y
# CONFIG_THERMAL_NETLINK is not set
CONFIG_THERMAL_STATISTICS=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
# CONFIG_THERMAL_HWMON is not set
# CONFIG_THERMAL_WRITABLE_TRIPS is not set
# CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE is not set
CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE=y
# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
CONFIG_THERMAL_GOV_FAIR_SHARE=y
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_GOV_BANG_BANG=y
# CONFIG_THERMAL_GOV_USER_SPACE is not set
CONFIG_DEVFREQ_THERMAL=y
# CONFIG_THERMAL_EMULATION is not set

#
# Intel thermal drivers
#
CONFIG_INTEL_POWERCLAMP=y
CONFIG_X86_THERMAL_VECTOR=y
# CONFIG_X86_PKG_TEMP_THERMAL is not set
# CONFIG_INTEL_SOC_DTS_THERMAL is not set

#
# ACPI INT340X thermal drivers
#
# CONFIG_INT340X_THERMAL is not set
# end of ACPI INT340X thermal drivers

# CONFIG_INTEL_PCH_THERMAL is not set
CONFIG_INTEL_TCC_COOLING=y
# CONFIG_INTEL_MENLOW is not set
# end of Intel thermal drivers

CONFIG_GENERIC_ADC_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_CORE=y
# CONFIG_WATCHDOG_NOWAYOUT is not set
# CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED is not set
CONFIG_WATCHDOG_OPEN_TIMEOUT=0
# CONFIG_WATCHDOG_SYSFS is not set
# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set

#
# Watchdog Pretimeout Governors
#
# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set

#
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
CONFIG_DA9052_WATCHDOG=y
CONFIG_DA9063_WATCHDOG=y
# CONFIG_MENF21BMC_WATCHDOG is not set
# CONFIG_WDAT_WDT is not set
CONFIG_WM831X_WATCHDOG=y
CONFIG_XILINX_WATCHDOG=y
# CONFIG_ZIIRAVE_WATCHDOG is not set
# CONFIG_MLX_WDT is not set
# CONFIG_CADENCE_WATCHDOG is not set
CONFIG_DW_WATCHDOG=y
# CONFIG_TWL4030_WATCHDOG is not set
# CONFIG_MAX63XX_WATCHDOG is not set
# CONFIG_RETU_WATCHDOG is not set
# CONFIG_ACQUIRE_WDT is not set
# CONFIG_ADVANTECH_WDT is not set
# CONFIG_ALIM1535_WDT is not set
# CONFIG_ALIM7101_WDT is not set
CONFIG_EBC_C384_WDT=y
CONFIG_F71808E_WDT=y
# CONFIG_SP5100_TCO is not set
CONFIG_SBC_FITPC2_WATCHDOG=y
# CONFIG_EUROTECH_WDT is not set
CONFIG_IB700_WDT=y
# CONFIG_IBMASR is not set
# CONFIG_WAFER_WDT is not set
# CONFIG_I6300ESB_WDT is not set
# CONFIG_IE6XX_WDT is not set
# CONFIG_ITCO_WDT is not set
CONFIG_IT8712F_WDT=y
CONFIG_IT87_WDT=y
# CONFIG_HP_WATCHDOG is not set
CONFIG_SC1200_WDT=y
# CONFIG_SCx200_WDT is not set
CONFIG_PC87413_WDT=y
# CONFIG_NV_TCO is not set
# CONFIG_RDC321X_WDT is not set
CONFIG_60XX_WDT=y
# CONFIG_SBC8360_WDT is not set
CONFIG_SBC7240_WDT=y
CONFIG_CPU5_WDT=y
CONFIG_SMSC_SCH311X_WDT=y
CONFIG_SMSC37B787_WDT=y
CONFIG_TQMX86_WDT=y
# CONFIG_VIA_WDT is not set
CONFIG_W83627HF_WDT=y
CONFIG_W83877F_WDT=y
CONFIG_W83977F_WDT=y
CONFIG_MACHZ_WDT=y
# CONFIG_SBC_EPX_C3_WATCHDOG is not set
# CONFIG_NI903X_WDT is not set
CONFIG_NIC7018_WDT=y
CONFIG_MEN_A21_WDT=y

#
# PCI-based Watchdog Cards
#
# CONFIG_PCIPCWATCHDOG is not set
# CONFIG_WDTPCI is not set
CONFIG_SSB_POSSIBLE=y
CONFIG_SSB=y
CONFIG_SSB_SPROM=y
CONFIG_SSB_PCIHOST_POSSIBLE=y
CONFIG_SSB_PCIHOST=y
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
# CONFIG_SSB_DRIVER_PCICORE is not set
# CONFIG_SSB_DRIVER_GPIO is not set
CONFIG_BCMA_POSSIBLE=y
CONFIG_BCMA=y
CONFIG_BCMA_HOST_PCI_POSSIBLE=y
CONFIG_BCMA_HOST_PCI=y
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_DRIVER_PCI=y
# CONFIG_BCMA_SFLASH is not set
# CONFIG_BCMA_DRIVER_GMAC_CMN is not set
CONFIG_BCMA_DRIVER_GPIO=y
CONFIG_BCMA_DEBUG=y

#
# Multifunction device drivers
#
CONFIG_MFD_CORE=y
# CONFIG_MFD_CS5535 is not set
CONFIG_MFD_AS3711=y
CONFIG_PMIC_ADP5520=y
CONFIG_MFD_AAT2870_CORE=y
# CONFIG_MFD_BCM590XX is not set
# CONFIG_MFD_BD9571MWV is not set
CONFIG_MFD_AXP20X=y
CONFIG_MFD_AXP20X_I2C=y
CONFIG_MFD_CROS_EC_DEV=y
CONFIG_MFD_MADERA=y
CONFIG_MFD_MADERA_I2C=y
# CONFIG_MFD_CS47L15 is not set
CONFIG_MFD_CS47L35=y
CONFIG_MFD_CS47L85=y
CONFIG_MFD_CS47L90=y
# CONFIG_MFD_CS47L92 is not set
CONFIG_PMIC_DA903X=y
CONFIG_PMIC_DA9052=y
CONFIG_MFD_DA9052_I2C=y
# CONFIG_MFD_DA9055 is not set
# CONFIG_MFD_DA9062 is not set
CONFIG_MFD_DA9063=y
CONFIG_MFD_DA9150=y
CONFIG_MFD_MC13XXX=y
CONFIG_MFD_MC13XXX_I2C=y
CONFIG_MFD_MP2629=y
CONFIG_HTC_PASIC3=y
# CONFIG_HTC_I2CPLD is not set
# CONFIG_MFD_INTEL_QUARK_I2C_GPIO is not set
# CONFIG_LPC_ICH is not set
# CONFIG_LPC_SCH is not set
CONFIG_INTEL_SOC_PMIC=y
CONFIG_INTEL_SOC_PMIC_CHTWC=y
# CONFIG_INTEL_SOC_PMIC_CHTDC_TI is not set
# CONFIG_MFD_INTEL_LPSS_ACPI is not set
# CONFIG_MFD_INTEL_LPSS_PCI is not set
# CONFIG_MFD_INTEL_PMT is not set
# CONFIG_MFD_IQS62X is not set
# CONFIG_MFD_JANZ_CMODIO is not set
# CONFIG_MFD_KEMPLD is not set
CONFIG_MFD_88PM800=y
CONFIG_MFD_88PM805=y
# CONFIG_MFD_88PM860X is not set
# CONFIG_MFD_MAX14577 is not set
CONFIG_MFD_MAX77693=y
# CONFIG_MFD_MAX77843 is not set
# CONFIG_MFD_MAX8907 is not set
CONFIG_MFD_MAX8925=y
CONFIG_MFD_MAX8997=y
CONFIG_MFD_MAX8998=y
CONFIG_MFD_MT6360=y
# CONFIG_MFD_MT6397 is not set
CONFIG_MFD_MENF21BMC=y
CONFIG_MFD_RETU=y
# CONFIG_MFD_PCF50633 is not set
CONFIG_UCB1400_CORE=y
# CONFIG_MFD_RDC321X is not set
# CONFIG_MFD_RT4831 is not set
CONFIG_MFD_RT5033=y
CONFIG_MFD_RC5T583=y
# CONFIG_MFD_SI476X_CORE is not set
CONFIG_MFD_SM501=y
# CONFIG_MFD_SM501_GPIO is not set
CONFIG_MFD_SKY81452=y
CONFIG_MFD_SYSCON=y
CONFIG_MFD_TI_AM335X_TSCADC=y
# CONFIG_MFD_LP3943 is not set
CONFIG_MFD_LP8788=y
CONFIG_MFD_TI_LMU=y
CONFIG_MFD_PALMAS=y
CONFIG_TPS6105X=y
# CONFIG_TPS65010 is not set
# CONFIG_TPS6507X is not set
CONFIG_MFD_TPS65086=y
# CONFIG_MFD_TPS65090 is not set
# CONFIG_MFD_TI_LP873X is not set
# CONFIG_MFD_TPS6586X is not set
# CONFIG_MFD_TPS65910 is not set
CONFIG_MFD_TPS65912=y
CONFIG_MFD_TPS65912_I2C=y
CONFIG_MFD_TPS80031=y
CONFIG_TWL4030_CORE=y
CONFIG_MFD_TWL4030_AUDIO=y
CONFIG_TWL6040_CORE=y
# CONFIG_MFD_WL1273_CORE is not set
CONFIG_MFD_LM3533=y
# CONFIG_MFD_TIMBERDALE is not set
CONFIG_MFD_TQMX86=y
# CONFIG_MFD_VX855 is not set
CONFIG_MFD_ARIZONA=y
CONFIG_MFD_ARIZONA_I2C=y
CONFIG_MFD_CS47L24=y
# CONFIG_MFD_WM5102 is not set
# CONFIG_MFD_WM5110 is not set
CONFIG_MFD_WM8997=y
CONFIG_MFD_WM8998=y
# CONFIG_MFD_WM8400 is not set
CONFIG_MFD_WM831X=y
CONFIG_MFD_WM831X_I2C=y
# CONFIG_MFD_WM8350_I2C is not set
# CONFIG_MFD_WM8994 is not set
# CONFIG_MFD_ATC260X_I2C is not set
# end of Multifunction device drivers

CONFIG_REGULATOR=y
# CONFIG_REGULATOR_DEBUG is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
CONFIG_REGULATOR_USERSPACE_CONSUMER=y
# CONFIG_REGULATOR_88PG86X is not set
CONFIG_REGULATOR_88PM800=y
CONFIG_REGULATOR_ACT8865=y
# CONFIG_REGULATOR_AD5398 is not set
CONFIG_REGULATOR_AAT2870=y
# CONFIG_REGULATOR_ARIZONA_LDO1 is not set
CONFIG_REGULATOR_ARIZONA_MICSUPP=y
CONFIG_REGULATOR_AS3711=y
# CONFIG_REGULATOR_AXP20X is not set
CONFIG_REGULATOR_DA9052=y
CONFIG_REGULATOR_DA9210=y
# CONFIG_REGULATOR_DA9211 is not set
CONFIG_REGULATOR_FAN53555=y
CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_ISL9305=y
# CONFIG_REGULATOR_ISL6271A is not set
CONFIG_REGULATOR_LM363X=y
# CONFIG_REGULATOR_LP3971 is not set
CONFIG_REGULATOR_LP3972=y
# CONFIG_REGULATOR_LP872X is not set
CONFIG_REGULATOR_LP8755=y
# CONFIG_REGULATOR_LP8788 is not set
CONFIG_REGULATOR_LTC3589=y
CONFIG_REGULATOR_LTC3676=y
# CONFIG_REGULATOR_MAX1586 is not set
CONFIG_REGULATOR_MAX8649=y
CONFIG_REGULATOR_MAX8660=y
# CONFIG_REGULATOR_MAX8893 is not set
# CONFIG_REGULATOR_MAX8925 is not set
CONFIG_REGULATOR_MAX8952=y
CONFIG_REGULATOR_MAX8997=y
# CONFIG_REGULATOR_MAX8998 is not set
CONFIG_REGULATOR_MAX77693=y
CONFIG_REGULATOR_MAX77826=y
CONFIG_REGULATOR_MC13XXX_CORE=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_REGULATOR_MP8859=y
CONFIG_REGULATOR_MT6311=y
CONFIG_REGULATOR_MT6360=y
CONFIG_REGULATOR_PALMAS=y
CONFIG_REGULATOR_PCA9450=y
CONFIG_REGULATOR_PV88060=y
# CONFIG_REGULATOR_PV88080 is not set
# CONFIG_REGULATOR_PV88090 is not set
CONFIG_REGULATOR_PWM=y
# CONFIG_REGULATOR_RC5T583 is not set
CONFIG_REGULATOR_RT4801=y
CONFIG_REGULATOR_RT5033=y
CONFIG_REGULATOR_RT6160=y
CONFIG_REGULATOR_RT6245=y
# CONFIG_REGULATOR_RTQ2134 is not set
CONFIG_REGULATOR_RTMV20=y
# CONFIG_REGULATOR_RTQ6752 is not set
# CONFIG_REGULATOR_SKY81452 is not set
CONFIG_REGULATOR_SLG51000=y
CONFIG_REGULATOR_TPS51632=y
CONFIG_REGULATOR_TPS6105X=y
CONFIG_REGULATOR_TPS62360=y
# CONFIG_REGULATOR_TPS65023 is not set
# CONFIG_REGULATOR_TPS6507X is not set
CONFIG_REGULATOR_TPS65086=y
CONFIG_REGULATOR_TPS65132=y
# CONFIG_REGULATOR_TPS65912 is not set
CONFIG_REGULATOR_TPS80031=y
CONFIG_REGULATOR_TWL4030=y
CONFIG_REGULATOR_WM831X=y
# CONFIG_RC_CORE is not set
CONFIG_CEC_CORE=y
# CONFIG_MEDIA_CEC_SUPPORT is not set
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y

#
# Media device types
#
# CONFIG_MEDIA_CAMERA_SUPPORT is not set
# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set
# CONFIG_MEDIA_DIGITAL_TV_SUPPORT is not set
# CONFIG_MEDIA_RADIO_SUPPORT is not set
CONFIG_MEDIA_SDR_SUPPORT=y
# CONFIG_MEDIA_PLATFORM_SUPPORT is not set
# CONFIG_MEDIA_TEST_SUPPORT is not set
# end of Media device types

CONFIG_VIDEO_DEV=y
CONFIG_MEDIA_CONTROLLER=y

#
# Video4Linux options
#
CONFIG_VIDEO_V4L2=y
CONFIG_VIDEO_V4L2_I2C=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_ADV_DEBUG=y
CONFIG_VIDEO_FIXED_MINOR_RANGES=y
CONFIG_V4L2_FWNODE=y
CONFIG_V4L2_ASYNC=y
# end of Video4Linux options

#
# Media controller options
#
# end of Media controller options

#
# Media drivers
#

#
# Drivers filtered as selected at 'Filter media drivers'
#
# CONFIG_MEDIA_PCI_SUPPORT is not set
CONFIG_VIDEOBUF2_CORE=y
CONFIG_VIDEOBUF2_V4L2=y
CONFIG_VIDEOBUF2_MEMOPS=y
CONFIG_VIDEOBUF2_VMALLOC=y
# end of Media drivers

#
# Media ancillary drivers
#

#
# Audio decoders, processors and mixers
#
# CONFIG_VIDEO_TVAUDIO is not set
# CONFIG_VIDEO_TDA7432 is not set
CONFIG_VIDEO_TDA9840=y
# CONFIG_VIDEO_TDA1997X is not set
CONFIG_VIDEO_TEA6415C=y
CONFIG_VIDEO_TEA6420=y
# CONFIG_VIDEO_MSP3400 is not set
# CONFIG_VIDEO_CS3308 is not set
# CONFIG_VIDEO_CS5345 is not set
# CONFIG_VIDEO_CS53L32A is not set
CONFIG_VIDEO_TLV320AIC23B=y
CONFIG_VIDEO_UDA1342=y
CONFIG_VIDEO_WM8775=y
CONFIG_VIDEO_WM8739=y
CONFIG_VIDEO_VP27SMPX=y
CONFIG_VIDEO_SONY_BTF_MPX=y
# end of Audio decoders, processors and mixers

#
# RDS decoders
#
# CONFIG_VIDEO_SAA6588 is not set
# end of RDS decoders

#
# Video decoders
#
CONFIG_VIDEO_ADV7180=y
CONFIG_VIDEO_ADV7183=y
CONFIG_VIDEO_ADV7604=y
# CONFIG_VIDEO_ADV7604_CEC is not set
CONFIG_VIDEO_ADV7842=y
CONFIG_VIDEO_ADV7842_CEC=y
CONFIG_VIDEO_BT819=y
CONFIG_VIDEO_BT856=y
CONFIG_VIDEO_BT866=y
CONFIG_VIDEO_KS0127=y
# CONFIG_VIDEO_ML86V7667 is not set
# CONFIG_VIDEO_SAA7110 is not set
CONFIG_VIDEO_SAA711X=y
# CONFIG_VIDEO_TC358743 is not set
# CONFIG_VIDEO_TVP514X is not set
CONFIG_VIDEO_TVP5150=y
# CONFIG_VIDEO_TVP7002 is not set
CONFIG_VIDEO_TW2804=y
# CONFIG_VIDEO_TW9903 is not set
CONFIG_VIDEO_TW9906=y
# CONFIG_VIDEO_TW9910 is not set
# CONFIG_VIDEO_VPX3220 is not set

#
# Video and audio decoders
#
# CONFIG_VIDEO_SAA717X is not set
CONFIG_VIDEO_CX25840=y
# end of Video decoders

#
# Video encoders
#
CONFIG_VIDEO_SAA7127=y
# CONFIG_VIDEO_SAA7185 is not set
CONFIG_VIDEO_ADV7170=y
# CONFIG_VIDEO_ADV7175 is not set
CONFIG_VIDEO_ADV7343=y
CONFIG_VIDEO_ADV7393=y
# CONFIG_VIDEO_ADV7511 is not set
CONFIG_VIDEO_AD9389B=y
CONFIG_VIDEO_AK881X=y
# CONFIG_VIDEO_THS8200 is not set
# end of Video encoders

#
# Video improvement chips
#
CONFIG_VIDEO_UPD64031A=y
CONFIG_VIDEO_UPD64083=y
# end of Video improvement chips

#
# Audio/Video compression chips
#
# CONFIG_VIDEO_SAA6752HS is not set
# end of Audio/Video compression chips

#
# SDR tuner chips
#
CONFIG_SDR_MAX2175=y
# end of SDR tuner chips

#
# Miscellaneous helper chips
#
CONFIG_VIDEO_THS7303=y
CONFIG_VIDEO_M52790=y
CONFIG_VIDEO_I2C=y
CONFIG_VIDEO_ST_MIPID02=y
# end of Miscellaneous helper chips

#
# SPI helper chips
#
# end of SPI helper chips

CONFIG_MEDIA_TUNER=y

#
# Customize TV tuners
#
CONFIG_MEDIA_TUNER_SIMPLE=y
CONFIG_MEDIA_TUNER_TDA18250=y
CONFIG_MEDIA_TUNER_TDA8290=y
CONFIG_MEDIA_TUNER_TDA827X=y
CONFIG_MEDIA_TUNER_TDA18271=y
CONFIG_MEDIA_TUNER_TDA9887=y
CONFIG_MEDIA_TUNER_TEA5761=y
CONFIG_MEDIA_TUNER_TEA5767=y
CONFIG_MEDIA_TUNER_MT20XX=y
# CONFIG_MEDIA_TUNER_MT2060 is not set
# CONFIG_MEDIA_TUNER_MT2063 is not set
CONFIG_MEDIA_TUNER_MT2266=y
CONFIG_MEDIA_TUNER_MT2131=y
CONFIG_MEDIA_TUNER_QT1010=y
CONFIG_MEDIA_TUNER_XC2028=y
CONFIG_MEDIA_TUNER_XC5000=y
CONFIG_MEDIA_TUNER_XC4000=y
# CONFIG_MEDIA_TUNER_MXL5005S is not set
CONFIG_MEDIA_TUNER_MXL5007T=y
CONFIG_MEDIA_TUNER_MC44S803=y
CONFIG_MEDIA_TUNER_MAX2165=y
# CONFIG_MEDIA_TUNER_TDA18218 is not set
CONFIG_MEDIA_TUNER_FC0011=y
# CONFIG_MEDIA_TUNER_FC0012 is not set
CONFIG_MEDIA_TUNER_FC0013=y
# CONFIG_MEDIA_TUNER_TDA18212 is not set
CONFIG_MEDIA_TUNER_E4000=y
CONFIG_MEDIA_TUNER_FC2580=y
# CONFIG_MEDIA_TUNER_M88RS6000T is not set
CONFIG_MEDIA_TUNER_TUA9001=y
CONFIG_MEDIA_TUNER_SI2157=y
CONFIG_MEDIA_TUNER_IT913X=y
CONFIG_MEDIA_TUNER_R820T=y
# CONFIG_MEDIA_TUNER_MXL301RF is not set
# CONFIG_MEDIA_TUNER_QM1D1C0042 is not set
# CONFIG_MEDIA_TUNER_QM1D1B0004 is not set
# end of Customize TV tuners
# end of Media ancillary drivers

#
# Graphics support
#
# CONFIG_AGP is not set
CONFIG_VGA_ARB=y
CONFIG_VGA_ARB_MAX_GPUS=16
# CONFIG_VGA_SWITCHEROO is not set
# CONFIG_DRM is not set

#
# ARM devices
#
# end of ARM devices

#
# Frame buffer Devices
#
# CONFIG_FB is not set
# end of Frame buffer Devices

#
# Backlight & LCD device support
#
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=y
# CONFIG_BACKLIGHT_CLASS_DEVICE is not set
# end of Backlight & LCD device support

CONFIG_HDMI=y
# end of Graphics support

CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
CONFIG_SND_DMAENGINE_PCM=y
CONFIG_SND_RAWMIDI=y
CONFIG_SND_COMPRESS_OFFLOAD=y
CONFIG_SND_JACK=y
CONFIG_SND_JACK_INPUT_DEV=y
# CONFIG_SND_OSSEMUL is not set
CONFIG_SND_PCM_TIMER=y
# CONFIG_SND_DYNAMIC_MINORS is not set
CONFIG_SND_SUPPORT_OLD_API=y
CONFIG_SND_PROC_FS=y
CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SND_VERBOSE_PRINTK=y
CONFIG_SND_DEBUG=y
CONFIG_SND_DEBUG_VERBOSE=y
CONFIG_SND_PCM_XRUN_DEBUG=y
CONFIG_SND_CTL_VALIDATION=y
# CONFIG_SND_JACK_INJECTION_DEBUG is not set
CONFIG_SND_VMASTER=y
CONFIG_SND_DMA_SGBUF=y
# CONFIG_SND_SEQUENCER is not set
CONFIG_SND_MPU401_UART=y
CONFIG_SND_AC97_CODEC=y
CONFIG_SND_DRIVERS=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_ALOOP is not set
CONFIG_SND_MTPAV=y
CONFIG_SND_MTS64=y
# CONFIG_SND_SERIAL_U16550 is not set
CONFIG_SND_MPU401=y
CONFIG_SND_PORTMAN2X4=y
# CONFIG_SND_AC97_POWER_SAVE is not set
CONFIG_SND_PCI=y
# CONFIG_SND_AD1889 is not set
# CONFIG_SND_ALS300 is not set
# CONFIG_SND_ALS4000 is not set
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ASIHPI is not set
# CONFIG_SND_ATIIXP is not set
# CONFIG_SND_ATIIXP_MODEM is not set
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
# CONFIG_SND_AW2 is not set
# CONFIG_SND_AZT3328 is not set
# CONFIG_SND_BT87X is not set
# CONFIG_SND_CA0106 is not set
# CONFIG_SND_CMIPCI is not set
# CONFIG_SND_OXYGEN is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CS5530 is not set
# CONFIG_SND_CS5535AUDIO is not set
# CONFIG_SND_CTXFI is not set
# CONFIG_SND_DARLA20 is not set
# CONFIG_SND_GINA20 is not set
# CONFIG_SND_LAYLA20 is not set
# CONFIG_SND_DARLA24 is not set
# CONFIG_SND_GINA24 is not set
# CONFIG_SND_LAYLA24 is not set
# CONFIG_SND_MONA is not set
# CONFIG_SND_MIA is not set
# CONFIG_SND_ECHO3G is not set
# CONFIG_SND_INDIGO is not set
# CONFIG_SND_INDIGOIO is not set
# CONFIG_SND_INDIGODJ is not set
# CONFIG_SND_INDIGOIOX is not set
# CONFIG_SND_INDIGODJX is not set
# CONFIG_SND_EMU10K1 is not set
# CONFIG_SND_EMU10K1X is not set
# CONFIG_SND_ENS1370 is not set
# CONFIG_SND_ENS1371 is not set
# CONFIG_SND_ES1938 is not set
# CONFIG_SND_ES1968 is not set
# CONFIG_SND_FM801 is not set
# CONFIG_SND_HDSP is not set
# CONFIG_SND_HDSPM is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_LOLA is not set
# CONFIG_SND_LX6464ES is not set
# CONFIG_SND_MAESTRO3 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
# CONFIG_SND_PCXHR is not set
# CONFIG_SND_RIPTIDE is not set
# CONFIG_SND_RME32 is not set
# CONFIG_SND_RME96 is not set
# CONFIG_SND_RME9652 is not set
# CONFIG_SND_SE6X is not set
# CONFIG_SND_SIS7019 is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_TRIDENT is not set
# CONFIG_SND_VIA82XX is not set
# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VIRTUOSO is not set
# CONFIG_SND_VX222 is not set
# CONFIG_SND_YMFPCI is not set

#
# HD-Audio
#
# CONFIG_SND_HDA_INTEL is not set
# end of HD-Audio

CONFIG_SND_HDA_PREALLOC_SIZE=0
CONFIG_SND_INTEL_NHLT=y
CONFIG_SND_INTEL_DSP_CONFIG=y
CONFIG_SND_INTEL_SOUNDWIRE_ACPI=y
CONFIG_SND_SOC=y
CONFIG_SND_SOC_AC97_BUS=y
CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM=y
CONFIG_SND_SOC_COMPRESS=y
CONFIG_SND_SOC_ACPI=y
CONFIG_SND_SOC_ADI=y
CONFIG_SND_SOC_ADI_AXI_I2S=y
CONFIG_SND_SOC_ADI_AXI_SPDIF=y
# CONFIG_SND_SOC_AMD_ACP is not set
# CONFIG_SND_SOC_AMD_ACP3x is not set
# CONFIG_SND_SOC_AMD_RENOIR is not set
# CONFIG_SND_SOC_AMD_ACP5x is not set
CONFIG_SND_ATMEL_SOC=y
CONFIG_SND_BCM63XX_I2S_WHISTLER=y
# CONFIG_SND_DESIGNWARE_I2S is not set

#
# SoC Audio for Freescale CPUs
#

#
# Common SoC Audio options for Freescale CPUs:
#
# CONFIG_SND_SOC_FSL_ASRC is not set
CONFIG_SND_SOC_FSL_SAI=y
CONFIG_SND_SOC_FSL_MQS=y
CONFIG_SND_SOC_FSL_AUDMIX=y
CONFIG_SND_SOC_FSL_SSI=y
# CONFIG_SND_SOC_FSL_SPDIF is not set
# CONFIG_SND_SOC_FSL_ESAI is not set
# CONFIG_SND_SOC_FSL_MICFIL is not set
CONFIG_SND_SOC_FSL_XCVR=y
CONFIG_SND_SOC_IMX_AUDMUX=y
# end of SoC Audio for Freescale CPUs

# CONFIG_SND_I2S_HI6210_I2S is not set
# CONFIG_SND_SOC_IMG is not set
CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y
# CONFIG_SND_SOC_INTEL_CATPT is not set
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=y
# CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI is not set
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=y
# CONFIG_SND_SOC_INTEL_SKYLAKE is not set
# CONFIG_SND_SOC_INTEL_SKL is not set
# CONFIG_SND_SOC_INTEL_APL is not set
# CONFIG_SND_SOC_INTEL_KBL is not set
# CONFIG_SND_SOC_INTEL_GLK is not set
# CONFIG_SND_SOC_INTEL_CNL is not set
# CONFIG_SND_SOC_INTEL_CFL is not set
# CONFIG_SND_SOC_INTEL_CML_H is not set
# CONFIG_SND_SOC_INTEL_CML_LP is not set
CONFIG_SND_SOC_ACPI_INTEL_MATCH=y
CONFIG_SND_SOC_INTEL_MACH=y
# CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES is not set
CONFIG_SND_SOC_MTK_BTCVSD=y
# CONFIG_SND_SOC_SOF_TOPLEVEL is not set

#
# STMicroelectronics STM32 SOC audio support
#
# end of STMicroelectronics STM32 SOC audio support

CONFIG_SND_SOC_XILINX_I2S=y
CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=y
CONFIG_SND_SOC_XILINX_SPDIF=y
CONFIG_SND_SOC_XTFPGA_I2S=y
CONFIG_SND_SOC_I2C_AND_SPI=y

#
# CODEC drivers
#
CONFIG_SND_SOC_AC97_CODEC=y
CONFIG_SND_SOC_ADAU_UTILS=y
# CONFIG_SND_SOC_ADAU1372_I2C is not set
CONFIG_SND_SOC_ADAU1701=y
CONFIG_SND_SOC_ADAU17X1=y
CONFIG_SND_SOC_ADAU1761=y
CONFIG_SND_SOC_ADAU1761_I2C=y
CONFIG_SND_SOC_ADAU7002=y
CONFIG_SND_SOC_ADAU7118=y
CONFIG_SND_SOC_ADAU7118_HW=y
CONFIG_SND_SOC_ADAU7118_I2C=y
CONFIG_SND_SOC_AK4118=y
# CONFIG_SND_SOC_AK4458 is not set
CONFIG_SND_SOC_AK4554=y
# CONFIG_SND_SOC_AK4613 is not set
# CONFIG_SND_SOC_AK4642 is not set
# CONFIG_SND_SOC_AK5386 is not set
# CONFIG_SND_SOC_AK5558 is not set
CONFIG_SND_SOC_ALC5623=y
CONFIG_SND_SOC_BD28623=y
# CONFIG_SND_SOC_BT_SCO is not set
# CONFIG_SND_SOC_CROS_EC_CODEC is not set
CONFIG_SND_SOC_CS35L32=y
CONFIG_SND_SOC_CS35L33=y
CONFIG_SND_SOC_CS35L34=y
CONFIG_SND_SOC_CS35L35=y
# CONFIG_SND_SOC_CS35L36 is not set
CONFIG_SND_SOC_CS42L42=y
CONFIG_SND_SOC_CS42L51=y
CONFIG_SND_SOC_CS42L51_I2C=y
# CONFIG_SND_SOC_CS42L52 is not set
# CONFIG_SND_SOC_CS42L56 is not set
CONFIG_SND_SOC_CS42L73=y
CONFIG_SND_SOC_CS4234=y
CONFIG_SND_SOC_CS4265=y
CONFIG_SND_SOC_CS4270=y
CONFIG_SND_SOC_CS4271=y
CONFIG_SND_SOC_CS4271_I2C=y
CONFIG_SND_SOC_CS42XX8=y
CONFIG_SND_SOC_CS42XX8_I2C=y
CONFIG_SND_SOC_CS43130=y
# CONFIG_SND_SOC_CS4341 is not set
CONFIG_SND_SOC_CS4349=y
CONFIG_SND_SOC_CS53L30=y
CONFIG_SND_SOC_CX2072X=y
CONFIG_SND_SOC_DA7213=y
CONFIG_SND_SOC_DMIC=y
CONFIG_SND_SOC_ES7134=y
CONFIG_SND_SOC_ES7241=y
CONFIG_SND_SOC_ES8316=y
# CONFIG_SND_SOC_ES8328_I2C is not set
# CONFIG_SND_SOC_GTM601 is not set
# CONFIG_SND_SOC_ICS43432 is not set
CONFIG_SND_SOC_INNO_RK3036=y
CONFIG_SND_SOC_MAX98088=y
CONFIG_SND_SOC_MAX98357A=y
CONFIG_SND_SOC_MAX98504=y
# CONFIG_SND_SOC_MAX9867 is not set
CONFIG_SND_SOC_MAX98927=y
CONFIG_SND_SOC_MAX98373=y
CONFIG_SND_SOC_MAX98373_I2C=y
# CONFIG_SND_SOC_MAX98373_SDW is not set
CONFIG_SND_SOC_MAX98390=y
CONFIG_SND_SOC_MAX9860=y
CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=y
CONFIG_SND_SOC_PCM1681=y
CONFIG_SND_SOC_PCM1789=y
CONFIG_SND_SOC_PCM1789_I2C=y
CONFIG_SND_SOC_PCM179X=y
CONFIG_SND_SOC_PCM179X_I2C=y
# CONFIG_SND_SOC_PCM186X_I2C is not set
CONFIG_SND_SOC_PCM3060=y
CONFIG_SND_SOC_PCM3060_I2C=y
CONFIG_SND_SOC_PCM3168A=y
CONFIG_SND_SOC_PCM3168A_I2C=y
# CONFIG_SND_SOC_PCM5102A is not set
CONFIG_SND_SOC_PCM512x=y
CONFIG_SND_SOC_PCM512x_I2C=y
CONFIG_SND_SOC_RK3328=y
CONFIG_SND_SOC_RL6231=y
# CONFIG_SND_SOC_RT1308_SDW is not set
# CONFIG_SND_SOC_RT1316_SDW is not set
# CONFIG_SND_SOC_RT5616 is not set
# CONFIG_SND_SOC_RT5631 is not set
# CONFIG_SND_SOC_RT5640 is not set
CONFIG_SND_SOC_RT5659=y
# CONFIG_SND_SOC_RT5682_SDW is not set
CONFIG_SND_SOC_RT700=y
CONFIG_SND_SOC_RT700_SDW=y
# CONFIG_SND_SOC_RT711_SDW is not set
CONFIG_SND_SOC_RT711_SDCA_SDW=y
# CONFIG_SND_SOC_RT715_SDW is not set
CONFIG_SND_SOC_RT715_SDCA_SDW=y
# CONFIG_SND_SOC_SDW_MOCKUP is not set
CONFIG_SND_SOC_SGTL5000=y
CONFIG_SND_SOC_SIGMADSP=y
CONFIG_SND_SOC_SIGMADSP_I2C=y
CONFIG_SND_SOC_SIGMADSP_REGMAP=y
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=y
CONFIG_SND_SOC_SIMPLE_MUX=y
# CONFIG_SND_SOC_SPDIF is not set
CONFIG_SND_SOC_SSM2305=y
# CONFIG_SND_SOC_SSM2518 is not set
CONFIG_SND_SOC_SSM2602=y
CONFIG_SND_SOC_SSM2602_I2C=y
# CONFIG_SND_SOC_SSM4567 is not set
# CONFIG_SND_SOC_STA32X is not set
CONFIG_SND_SOC_STA350=y
CONFIG_SND_SOC_STI_SAS=y
# CONFIG_SND_SOC_TAS2552 is not set
CONFIG_SND_SOC_TAS2562=y
# CONFIG_SND_SOC_TAS2764 is not set
CONFIG_SND_SOC_TAS2770=y
CONFIG_SND_SOC_TAS5086=y
CONFIG_SND_SOC_TAS571X=y
CONFIG_SND_SOC_TAS5720=y
# CONFIG_SND_SOC_TAS6424 is not set
CONFIG_SND_SOC_TDA7419=y
CONFIG_SND_SOC_TFA9879=y
# CONFIG_SND_SOC_TFA989X is not set
# CONFIG_SND_SOC_TLV320AIC23_I2C is not set
CONFIG_SND_SOC_TLV320AIC31XX=y
CONFIG_SND_SOC_TLV320AIC32X4=y
CONFIG_SND_SOC_TLV320AIC32X4_I2C=y
CONFIG_SND_SOC_TLV320AIC3X=y
CONFIG_SND_SOC_TLV320AIC3X_I2C=y
CONFIG_SND_SOC_TLV320ADCX140=y
# CONFIG_SND_SOC_TS3A227E is not set
CONFIG_SND_SOC_TSCS42XX=y
# CONFIG_SND_SOC_TSCS454 is not set
CONFIG_SND_SOC_UDA1334=y
# CONFIG_SND_SOC_WCD938X_SDW is not set
# CONFIG_SND_SOC_WM8510 is not set
CONFIG_SND_SOC_WM8523=y
# CONFIG_SND_SOC_WM8524 is not set
CONFIG_SND_SOC_WM8580=y
# CONFIG_SND_SOC_WM8711 is not set
CONFIG_SND_SOC_WM8728=y
# CONFIG_SND_SOC_WM8731 is not set
# CONFIG_SND_SOC_WM8737 is not set
# CONFIG_SND_SOC_WM8741 is not set
CONFIG_SND_SOC_WM8750=y
# CONFIG_SND_SOC_WM8753 is not set
# CONFIG_SND_SOC_WM8776 is not set
CONFIG_SND_SOC_WM8782=y
# CONFIG_SND_SOC_WM8804_I2C is not set
# CONFIG_SND_SOC_WM8903 is not set
CONFIG_SND_SOC_WM8904=y
CONFIG_SND_SOC_WM8960=y
# CONFIG_SND_SOC_WM8962 is not set
CONFIG_SND_SOC_WM8974=y
# CONFIG_SND_SOC_WM8978 is not set
# CONFIG_SND_SOC_WM8985 is not set
CONFIG_SND_SOC_WSA881X=y
# CONFIG_SND_SOC_MAX9759 is not set
# CONFIG_SND_SOC_MT6351 is not set
CONFIG_SND_SOC_MT6358=y
CONFIG_SND_SOC_MT6660=y
CONFIG_SND_SOC_NAU8315=y
CONFIG_SND_SOC_NAU8540=y
CONFIG_SND_SOC_NAU8810=y
CONFIG_SND_SOC_NAU8822=y
CONFIG_SND_SOC_NAU8824=y
CONFIG_SND_SOC_TPA6130A2=y
CONFIG_SND_SOC_LPASS_WSA_MACRO=y
# CONFIG_SND_SOC_LPASS_VA_MACRO is not set
# CONFIG_SND_SOC_LPASS_RX_MACRO is not set
CONFIG_SND_SOC_LPASS_TX_MACRO=y
# end of CODEC drivers

CONFIG_SND_SIMPLE_CARD_UTILS=y
CONFIG_SND_SIMPLE_CARD=y
CONFIG_SND_X86=y
CONFIG_SND_VIRTIO=y
CONFIG_AC97_BUS=y

#
# HID support
#
CONFIG_HID=y
# CONFIG_HID_BATTERY_STRENGTH is not set
# CONFIG_HIDRAW is not set
# CONFIG_UHID is not set
CONFIG_HID_GENERIC=y

#
# Special HID drivers
#
# CONFIG_HID_A4TECH is not set
# CONFIG_HID_ACRUX is not set
# CONFIG_HID_APPLE is not set
# CONFIG_HID_AUREAL is not set
# CONFIG_HID_BELKIN is not set
# CONFIG_HID_CHERRY is not set
# CONFIG_HID_CHICONY is not set
# CONFIG_HID_COUGAR is not set
# CONFIG_HID_MACALLY is not set
# CONFIG_HID_PRODIKEYS is not set
# CONFIG_HID_CMEDIA is not set
# CONFIG_HID_CYPRESS is not set
# CONFIG_HID_DRAGONRISE is not set
# CONFIG_HID_EMS_FF is not set
# CONFIG_HID_ELECOM is not set
# CONFIG_HID_EZKEY is not set
# CONFIG_HID_GEMBIRD is not set
# CONFIG_HID_GFRM is not set
# CONFIG_HID_GLORIOUS is not set
# CONFIG_HID_VIVALDI is not set
# CONFIG_HID_KEYTOUCH is not set
# CONFIG_HID_KYE is not set
# CONFIG_HID_WALTOP is not set
# CONFIG_HID_VIEWSONIC is not set
# CONFIG_HID_GYRATION is not set
# CONFIG_HID_ICADE is not set
# CONFIG_HID_ITE is not set
# CONFIG_HID_JABRA is not set
# CONFIG_HID_TWINHAN is not set
# CONFIG_HID_KENSINGTON is not set
# CONFIG_HID_LCPOWER is not set
# CONFIG_HID_LED is not set
# CONFIG_HID_LENOVO is not set
# CONFIG_HID_LOGITECH is not set
# CONFIG_HID_MAGICMOUSE is not set
# CONFIG_HID_MALTRON is not set
# CONFIG_HID_MAYFLASH is not set
# CONFIG_HID_REDRAGON is not set
# CONFIG_HID_MICROSOFT is not set
# CONFIG_HID_MONTEREY is not set
# CONFIG_HID_MULTITOUCH is not set
# CONFIG_HID_NTI is not set
# CONFIG_HID_ORTEK is not set
# CONFIG_HID_PANTHERLORD is not set
# CONFIG_HID_PETALYNX is not set
# CONFIG_HID_PICOLCD is not set
# CONFIG_HID_PLANTRONICS is not set
# CONFIG_HID_PLAYSTATION is not set
# CONFIG_HID_PRIMAX is not set
# CONFIG_HID_SAITEK is not set
# CONFIG_HID_SAMSUNG is not set
# CONFIG_HID_SEMITEK is not set
# CONFIG_HID_SPEEDLINK is not set
# CONFIG_HID_STEAM is not set
# CONFIG_HID_STEELSERIES is not set
# CONFIG_HID_SUNPLUS is not set
# CONFIG_HID_RMI is not set
# CONFIG_HID_GREENASIA is not set
# CONFIG_HID_SMARTJOYPLUS is not set
# CONFIG_HID_TIVO is not set
# CONFIG_HID_TOPSEED is not set
# CONFIG_HID_THINGM is not set
# CONFIG_HID_UDRAW_PS3 is not set
# CONFIG_HID_WIIMOTE is not set
# CONFIG_HID_XINMO is not set
# CONFIG_HID_ZEROPLUS is not set
# CONFIG_HID_ZYDACRON is not set
# CONFIG_HID_SENSOR_HUB is not set
# CONFIG_HID_ALPS is not set
# end of Special HID drivers

#
# I2C HID support
#
# CONFIG_I2C_HID_ACPI is not set
# end of I2C HID support
# end of HID support

CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_SUPPORT=y
# CONFIG_USB_LED_TRIG is not set
# CONFIG_USB_ULPI_BUS is not set
# CONFIG_USB_CONN_GPIO is not set
CONFIG_USB_ARCH_HAS_HCD=y
# CONFIG_USB is not set
CONFIG_USB_PCI=y

#
# USB port drivers
#

#
# USB Physical Layer drivers
#
# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_USB_GPIO_VBUS is not set
# CONFIG_TAHVO_USB is not set
# end of USB Physical Layer drivers

# CONFIG_USB_GADGET is not set
# CONFIG_TYPEC is not set
# CONFIG_USB_ROLE_SWITCH is not set
# CONFIG_MMC is not set
CONFIG_MEMSTICK=y
# CONFIG_MEMSTICK_DEBUG is not set

#
# MemoryStick drivers
#
# CONFIG_MEMSTICK_UNSAFE_RESUME is not set

#
# MemoryStick Host Controller Drivers
#
# CONFIG_MEMSTICK_TIFM_MS is not set
# CONFIG_MEMSTICK_JMICRON_38X is not set
# CONFIG_MEMSTICK_R592 is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
# CONFIG_LEDS_CLASS_FLASH is not set
CONFIG_LEDS_CLASS_MULTICOLOR=y
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set

#
# LED drivers
#
CONFIG_LEDS_LM3530=y
CONFIG_LEDS_LM3532=y
CONFIG_LEDS_LM3533=y
CONFIG_LEDS_LM3642=y
CONFIG_LEDS_NET48XX=y
# CONFIG_LEDS_WRAP is not set
# CONFIG_LEDS_PCA9532 is not set
# CONFIG_LEDS_GPIO is not set
CONFIG_LEDS_LP3944=y
# CONFIG_LEDS_LP3952 is not set
CONFIG_LEDS_LP50XX=y
CONFIG_LEDS_LP8788=y
CONFIG_LEDS_PCA955X=y
# CONFIG_LEDS_PCA955X_GPIO is not set
CONFIG_LEDS_PCA963X=y
CONFIG_LEDS_WM831X_STATUS=y
CONFIG_LEDS_DA903X=y
# CONFIG_LEDS_DA9052 is not set
CONFIG_LEDS_PWM=y
CONFIG_LEDS_REGULATOR=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_LT3593 is not set
CONFIG_LEDS_ADP5520=y
CONFIG_LEDS_MC13783=y
CONFIG_LEDS_TCA6507=y
CONFIG_LEDS_TLC591XX=y
CONFIG_LEDS_MAX8997=y
CONFIG_LEDS_LM355x=y
CONFIG_LEDS_OT200=y
CONFIG_LEDS_MENF21BMC=y

#
# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
#
CONFIG_LEDS_BLINKM=y
CONFIG_LEDS_MLXREG=y
CONFIG_LEDS_USER=y
# CONFIG_LEDS_NIC78BX is not set
CONFIG_LEDS_TI_LMU_COMMON=y
# CONFIG_LEDS_LM36274 is not set
CONFIG_LEDS_TPS6105X=y

#
# Flash and Torch LED drivers
#

#
# LED Triggers
#
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_MTD=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_BACKLIGHT=y
CONFIG_LEDS_TRIGGER_CPU=y
# CONFIG_LEDS_TRIGGER_ACTIVITY is not set
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y

#
# iptables trigger is under Netfilter config (LED target)
#
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_LEDS_TRIGGER_PANIC=y
# CONFIG_LEDS_TRIGGER_NETDEV is not set
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_LEDS_TRIGGER_AUDIO=y
CONFIG_LEDS_TRIGGER_TTY=y
# CONFIG_ACCESSIBILITY is not set
# CONFIG_INFINIBAND is not set
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
# CONFIG_EDAC is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_MC146818_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
# CONFIG_RTC_SYSTOHC is not set
# CONFIG_RTC_DEBUG is not set
# CONFIG_RTC_LIB_KUNIT_TEST is not set
CONFIG_RTC_NVMEM=y

#
# RTC interfaces
#
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
CONFIG_RTC_DRV_TEST=y

#
# I2C RTC drivers
#
CONFIG_RTC_DRV_88PM80X=y
# CONFIG_RTC_DRV_ABB5ZES3 is not set
CONFIG_RTC_DRV_ABEOZ9=y
# CONFIG_RTC_DRV_ABX80X is not set
CONFIG_RTC_DRV_DS1307=y
CONFIG_RTC_DRV_DS1307_CENTURY=y
CONFIG_RTC_DRV_DS1374=y
CONFIG_RTC_DRV_DS1374_WDT=y
CONFIG_RTC_DRV_DS1672=y
CONFIG_RTC_DRV_LP8788=y
CONFIG_RTC_DRV_MAX6900=y
CONFIG_RTC_DRV_MAX8925=y
# CONFIG_RTC_DRV_MAX8998 is not set
CONFIG_RTC_DRV_MAX8997=y
# CONFIG_RTC_DRV_RS5C372 is not set
CONFIG_RTC_DRV_ISL1208=y
CONFIG_RTC_DRV_ISL12022=y
# CONFIG_RTC_DRV_X1205 is not set
CONFIG_RTC_DRV_PCF8523=y
# CONFIG_RTC_DRV_PCF85063 is not set
# CONFIG_RTC_DRV_PCF85363 is not set
CONFIG_RTC_DRV_PCF8563=y
# CONFIG_RTC_DRV_PCF8583 is not set
# CONFIG_RTC_DRV_M41T80 is not set
CONFIG_RTC_DRV_BQ32K=y
# CONFIG_RTC_DRV_PALMAS is not set
CONFIG_RTC_DRV_TPS80031=y
CONFIG_RTC_DRV_RC5T583=y
CONFIG_RTC_DRV_S35390A=y
# CONFIG_RTC_DRV_FM3130 is not set
CONFIG_RTC_DRV_RX8010=y
# CONFIG_RTC_DRV_RX8581 is not set
CONFIG_RTC_DRV_RX8025=y
CONFIG_RTC_DRV_EM3027=y
CONFIG_RTC_DRV_RV3028=y
# CONFIG_RTC_DRV_RV3032 is not set
CONFIG_RTC_DRV_RV8803=y
# CONFIG_RTC_DRV_SD3078 is not set

#
# SPI RTC drivers
#
CONFIG_RTC_I2C_AND_SPI=y

#
# SPI and I2C RTC drivers
#
CONFIG_RTC_DRV_DS3232=y
CONFIG_RTC_DRV_DS3232_HWMON=y
# CONFIG_RTC_DRV_PCF2127 is not set
CONFIG_RTC_DRV_RV3029C2=y
# CONFIG_RTC_DRV_RV3029_HWMON is not set
# CONFIG_RTC_DRV_RX6110 is not set

#
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
CONFIG_RTC_DRV_DS1286=y
CONFIG_RTC_DRV_DS1511=y
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1685_FAMILY is not set
CONFIG_RTC_DRV_DS1742=y
CONFIG_RTC_DRV_DS2404=y
CONFIG_RTC_DRV_DA9052=y
CONFIG_RTC_DRV_DA9063=y
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
CONFIG_RTC_DRV_M48T35=y
CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_MSM6242=y
CONFIG_RTC_DRV_BQ4802=y
CONFIG_RTC_DRV_RP5C01=y
# CONFIG_RTC_DRV_V3020 is not set
CONFIG_RTC_DRV_WM831X=y
# CONFIG_RTC_DRV_CROS_EC is not set

#
# on-CPU RTC drivers
#
# CONFIG_RTC_DRV_FTRTC010 is not set
# CONFIG_RTC_DRV_MC13XXX is not set

#
# HID Sensor RTC drivers
#
# CONFIG_RTC_DRV_GOLDFISH is not set
CONFIG_DMADEVICES=y
CONFIG_DMADEVICES_DEBUG=y
# CONFIG_DMADEVICES_VDEBUG is not set

#
# DMA Devices
#
CONFIG_DMA_ENGINE=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DMA_ACPI=y
CONFIG_ALTERA_MSGDMA=y
CONFIG_INTEL_IDMA64=y
# CONFIG_PCH_DMA is not set
# CONFIG_PLX_DMA is not set
CONFIG_QCOM_HIDMA_MGMT=y
# CONFIG_QCOM_HIDMA is not set
CONFIG_DW_DMAC_CORE=y
CONFIG_DW_DMAC=y
# CONFIG_DW_DMAC_PCI is not set
# CONFIG_SF_PDMA is not set
# CONFIG_INTEL_LDMA is not set

#
# DMA Clients
#
# CONFIG_ASYNC_TX_DMA is not set
CONFIG_DMATEST=y
CONFIG_DMA_ENGINE_RAID=y

#
# DMABUF options
#
# CONFIG_SYNC_FILE is not set
# CONFIG_UDMABUF is not set
# CONFIG_DMABUF_MOVE_NOTIFY is not set
# CONFIG_DMABUF_DEBUG is not set
# CONFIG_DMABUF_SELFTESTS is not set
CONFIG_DMABUF_HEAPS=y
# CONFIG_DMABUF_SYSFS_STATS is not set
CONFIG_DMABUF_HEAPS_SYSTEM=y
# end of DMABUF options

CONFIG_AUXDISPLAY=y
CONFIG_CHARLCD=y
CONFIG_HD44780_COMMON=y
CONFIG_HD44780=y
CONFIG_IMG_ASCII_LCD=y
CONFIG_LCD2S=y
CONFIG_PARPORT_PANEL=y
CONFIG_PANEL_PARPORT=0
CONFIG_PANEL_PROFILE=5
# CONFIG_PANEL_CHANGE_MESSAGE is not set
# CONFIG_CHARLCD_BL_OFF is not set
CONFIG_CHARLCD_BL_ON=y
# CONFIG_CHARLCD_BL_FLASH is not set
CONFIG_PANEL=y
# CONFIG_UIO is not set
CONFIG_VFIO=y
CONFIG_VFIO_IOMMU_TYPE1=y
# CONFIG_VFIO_NOIOMMU is not set
CONFIG_VFIO_PCI_MMAP=y
CONFIG_VFIO_PCI_INTX=y
# CONFIG_VFIO_PCI is not set
CONFIG_VFIO_MDEV=y
CONFIG_VIRT_DRIVERS=y
# CONFIG_VBOXGUEST is not set
# CONFIG_NITRO_ENCLAVES is not set
CONFIG_VIRTIO=y
CONFIG_VIRTIO_MENU=y
# CONFIG_VIRTIO_PCI is not set
CONFIG_VIRTIO_BALLOON=y
# CONFIG_VIRTIO_INPUT is not set
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
# CONFIG_VDPA is not set
CONFIG_VHOST_MENU=y
# CONFIG_VHOST_NET is not set
CONFIG_VHOST_CROSS_ENDIAN_LEGACY=y

#
# Microsoft Hyper-V guest support
#
# CONFIG_HYPERV is not set
# end of Microsoft Hyper-V guest support

CONFIG_GREYBUS=y
CONFIG_COMEDI=y
CONFIG_COMEDI_DEBUG=y
CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB=2048
CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB=20480
CONFIG_COMEDI_MISC_DRIVERS=y
# CONFIG_COMEDI_BOND is not set
# CONFIG_COMEDI_TEST is not set
# CONFIG_COMEDI_PARPORT is not set
# CONFIG_COMEDI_SSV_DNP is not set
CONFIG_COMEDI_ISA_DRIVERS=y
CONFIG_COMEDI_PCL711=y
CONFIG_COMEDI_PCL724=y
# CONFIG_COMEDI_PCL726 is not set
# CONFIG_COMEDI_PCL730 is not set
CONFIG_COMEDI_PCL812=y
# CONFIG_COMEDI_PCL816 is not set
CONFIG_COMEDI_PCL818=y
CONFIG_COMEDI_PCM3724=y
CONFIG_COMEDI_AMPLC_DIO200_ISA=y
CONFIG_COMEDI_AMPLC_PC236_ISA=y
CONFIG_COMEDI_AMPLC_PC263_ISA=y
CONFIG_COMEDI_RTI800=y
# CONFIG_COMEDI_RTI802 is not set
CONFIG_COMEDI_DAC02=y
CONFIG_COMEDI_DAS16M1=y
CONFIG_COMEDI_DAS08_ISA=y
# CONFIG_COMEDI_DAS16 is not set
CONFIG_COMEDI_DAS800=y
# CONFIG_COMEDI_DAS1800 is not set
CONFIG_COMEDI_DAS6402=y
CONFIG_COMEDI_DT2801=y
# CONFIG_COMEDI_DT2811 is not set
CONFIG_COMEDI_DT2814=y
# CONFIG_COMEDI_DT2815 is not set
CONFIG_COMEDI_DT2817=y
CONFIG_COMEDI_DT282X=y
# CONFIG_COMEDI_DMM32AT is not set
# CONFIG_COMEDI_FL512 is not set
CONFIG_COMEDI_AIO_AIO12_8=y
# CONFIG_COMEDI_AIO_IIRO_16 is not set
CONFIG_COMEDI_II_PCI20KC=y
CONFIG_COMEDI_C6XDIGIO=y
# CONFIG_COMEDI_MPC624 is not set
CONFIG_COMEDI_ADQ12B=y
CONFIG_COMEDI_NI_AT_A2150=y
CONFIG_COMEDI_NI_AT_AO=y
# CONFIG_COMEDI_NI_ATMIO is not set
CONFIG_COMEDI_NI_ATMIO16D=y
# CONFIG_COMEDI_NI_LABPC_ISA is not set
# CONFIG_COMEDI_PCMAD is not set
CONFIG_COMEDI_PCMDA12=y
CONFIG_COMEDI_PCMMIO=y
CONFIG_COMEDI_PCMUIO=y
# CONFIG_COMEDI_MULTIQ3 is not set
# CONFIG_COMEDI_S526 is not set
# CONFIG_COMEDI_PCI_DRIVERS is not set
CONFIG_COMEDI_8254=y
CONFIG_COMEDI_8255=y
CONFIG_COMEDI_8255_SA=y
# CONFIG_COMEDI_KCOMEDILIB is not set
CONFIG_COMEDI_AMPLC_DIO200=y
CONFIG_COMEDI_AMPLC_PC236=y
CONFIG_COMEDI_DAS08=y
CONFIG_COMEDI_ISADMA=y
# CONFIG_COMEDI_TESTS is not set
# CONFIG_STAGING is not set
# CONFIG_X86_PLATFORM_DEVICES is not set
CONFIG_PMC_ATOM=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_CHROMEOS_PSTORE=y
# CONFIG_CHROMEOS_TBMC is not set
CONFIG_CROS_EC=y
CONFIG_CROS_EC_I2C=y
# CONFIG_CROS_EC_LPC is not set
CONFIG_CROS_EC_PROTO=y
CONFIG_CROS_KBD_LED_BACKLIGHT=y
# CONFIG_CROS_EC_CHARDEV is not set
# CONFIG_CROS_EC_LIGHTBAR is not set
CONFIG_CROS_EC_DEBUGFS=y
CONFIG_CROS_EC_SENSORHUB=y
CONFIG_CROS_EC_SYSFS=y
# CONFIG_CROS_USBPD_NOTIFY is not set
CONFIG_MELLANOX_PLATFORM=y
# CONFIG_MLXREG_HOTPLUG is not set
CONFIG_MLXREG_IO=y
CONFIG_SURFACE_PLATFORMS=y
CONFIG_SURFACE_3_POWER_OPREGION=y
CONFIG_SURFACE_HOTPLUG=y
# CONFIG_SURFACE_PRO3_BUTTON is not set
CONFIG_HAVE_CLK=y
CONFIG_HAVE_CLK_PREPARE=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_WM831X=y

#
# Clock driver for ARM Reference designs
#
# CONFIG_ICST is not set
CONFIG_CLK_SP810=y
# end of Clock driver for ARM Reference designs

CONFIG_COMMON_CLK_MAX9485=y
CONFIG_COMMON_CLK_SI5341=y
CONFIG_COMMON_CLK_SI5351=y
CONFIG_COMMON_CLK_SI544=y
CONFIG_COMMON_CLK_CDCE706=y
CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_CLK_TWL6040=y
CONFIG_COMMON_CLK_PALMAS=y
CONFIG_COMMON_CLK_PWM=y
CONFIG_XILINX_VCU=y
CONFIG_HWSPINLOCK=y

#
# Clock Source drivers
#
CONFIG_CLKSRC_I8253=y
CONFIG_CLKEVT_I8253=y
CONFIG_I8253_LOCK=y
CONFIG_CLKBLD_I8253=y
# end of Clock Source drivers

# CONFIG_MAILBOX is not set
CONFIG_IOMMU_API=y
# CONFIG_IOMMU_SUPPORT is not set

#
# Remoteproc drivers
#
# CONFIG_REMOTEPROC is not set
# end of Remoteproc drivers

#
# Rpmsg drivers
#
# CONFIG_RPMSG_VIRTIO is not set
# end of Rpmsg drivers

CONFIG_SOUNDWIRE=y

#
# SoundWire Devices
#
CONFIG_SOUNDWIRE_CADENCE=y
CONFIG_SOUNDWIRE_INTEL=y
CONFIG_SOUNDWIRE_QCOM=y
CONFIG_SOUNDWIRE_GENERIC_ALLOCATION=y

#
# SOC (System On Chip) specific Drivers
#

#
# Amlogic SoC drivers
#
# end of Amlogic SoC drivers

#
# Broadcom SoC drivers
#
# end of Broadcom SoC drivers

#
# NXP/Freescale QorIQ SoC drivers
#
# end of NXP/Freescale QorIQ SoC drivers

#
# i.MX SoC drivers
#
# end of i.MX SoC drivers

#
# Enable LiteX SoC Builder specific drivers
#
# end of Enable LiteX SoC Builder specific drivers

#
# Qualcomm SoC drivers
#
# end of Qualcomm SoC drivers

# CONFIG_SOC_TI is not set

#
# Xilinx SoC drivers
#
# end of Xilinx SoC drivers
# end of SOC (System On Chip) specific Drivers

CONFIG_PM_DEVFREQ=y

#
# DEVFREQ Governors
#
CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
CONFIG_DEVFREQ_GOV_PERFORMANCE=y
CONFIG_DEVFREQ_GOV_POWERSAVE=y
# CONFIG_DEVFREQ_GOV_USERSPACE is not set
# CONFIG_DEVFREQ_GOV_PASSIVE is not set

#
# DEVFREQ Drivers
#
# CONFIG_PM_DEVFREQ_EVENT is not set
CONFIG_EXTCON=y

#
# Extcon Device Drivers
#
# CONFIG_EXTCON_ADC_JACK is not set
# CONFIG_EXTCON_AXP288 is not set
# CONFIG_EXTCON_FSA9480 is not set
CONFIG_EXTCON_GPIO=y
CONFIG_EXTCON_INTEL_INT3496=y
CONFIG_EXTCON_INTEL_CHT_WC=y
CONFIG_EXTCON_MAX3355=y
# CONFIG_EXTCON_MAX77693 is not set
CONFIG_EXTCON_MAX8997=y
CONFIG_EXTCON_PALMAS=y
# CONFIG_EXTCON_PTN5150 is not set
# CONFIG_EXTCON_RT8973A is not set
CONFIG_EXTCON_SM5502=y
CONFIG_EXTCON_USB_GPIO=y
# CONFIG_EXTCON_USBC_CROS_EC is not set
CONFIG_EXTCON_USBC_TUSB320=y
# CONFIG_MEMORY is not set
CONFIG_IIO=y
CONFIG_IIO_BUFFER=y
CONFIG_IIO_BUFFER_CB=y
CONFIG_IIO_BUFFER_DMA=y
CONFIG_IIO_BUFFER_DMAENGINE=y
# CONFIG_IIO_BUFFER_HW_CONSUMER is not set
CONFIG_IIO_KFIFO_BUF=y
CONFIG_IIO_TRIGGERED_BUFFER=y
# CONFIG_IIO_CONFIGFS is not set
CONFIG_IIO_TRIGGER=y
CONFIG_IIO_CONSUMERS_PER_TRIGGER=2
# CONFIG_IIO_SW_DEVICE is not set
# CONFIG_IIO_SW_TRIGGER is not set
CONFIG_IIO_TRIGGERED_EVENT=y

#
# Accelerometers
#
CONFIG_ADXL345=y
CONFIG_ADXL345_I2C=y
# CONFIG_ADXL372_I2C is not set
CONFIG_BMA180=y
# CONFIG_BMA400 is not set
# CONFIG_BMC150_ACCEL is not set
# CONFIG_DA280 is not set
# CONFIG_DA311 is not set
CONFIG_DMARD09=y
CONFIG_DMARD10=y
# CONFIG_FXLS8962AF_I2C is not set
CONFIG_IIO_ST_ACCEL_3AXIS=y
CONFIG_IIO_ST_ACCEL_I2C_3AXIS=y
CONFIG_KXSD9=y
CONFIG_KXSD9_I2C=y
# CONFIG_KXCJK1013 is not set
CONFIG_MC3230=y
CONFIG_MMA7455=y
CONFIG_MMA7455_I2C=y
CONFIG_MMA7660=y
CONFIG_MMA8452=y
# CONFIG_MMA9551 is not set
# CONFIG_MMA9553 is not set
# CONFIG_MXC4005 is not set
CONFIG_MXC6255=y
CONFIG_STK8312=y
# CONFIG_STK8BA50 is not set
# end of Accelerometers

#
# Analog to digital converters
#
CONFIG_AD7091R5=y
CONFIG_AD7291=y
# CONFIG_AD7606_IFACE_PARALLEL is not set
CONFIG_AD799X=y
CONFIG_AXP20X_ADC=y
CONFIG_AXP288_ADC=y
# CONFIG_CC10001_ADC is not set
# CONFIG_DA9150_GPADC is not set
# CONFIG_HX711 is not set
CONFIG_INA2XX_ADC=y
# CONFIG_LP8788_ADC is not set
# CONFIG_LTC2471 is not set
CONFIG_LTC2485=y
CONFIG_LTC2497=y
# CONFIG_MAX1363 is not set
# CONFIG_MAX9611 is not set
CONFIG_MCP3422=y
# CONFIG_MEDIATEK_MT6360_ADC is not set
# CONFIG_MP2629_ADC is not set
CONFIG_NAU7802=y
CONFIG_PALMAS_GPADC=y
CONFIG_TI_ADC081C=y
CONFIG_TI_ADS1015=y
CONFIG_TI_AM335X_ADC=y
CONFIG_TWL4030_MADC=y
# CONFIG_TWL6030_GPADC is not set
CONFIG_XILINX_XADC=y
# end of Analog to digital converters

#
# Analog Front Ends
#
# end of Analog Front Ends

#
# Amplifiers
#
# CONFIG_HMC425 is not set
# end of Amplifiers

#
# Capacitance to digital converters
#
CONFIG_AD7150=y
# end of Capacitance to digital converters

#
# Chemical Sensors
#
CONFIG_ATLAS_PH_SENSOR=y
CONFIG_ATLAS_EZO_SENSOR=y
# CONFIG_BME680 is not set
CONFIG_CCS811=y
# CONFIG_IAQCORE is not set
CONFIG_SCD30_CORE=y
CONFIG_SCD30_I2C=y
CONFIG_SENSIRION_SGP30=y
# CONFIG_SENSIRION_SGP40 is not set
# CONFIG_SPS30_I2C is not set
# CONFIG_VZ89X is not set
# end of Chemical Sensors

# CONFIG_IIO_CROS_EC_SENSORS_CORE is not set

#
# Hid Sensor IIO Common
#
# end of Hid Sensor IIO Common

CONFIG_IIO_MS_SENSORS_I2C=y

#
# IIO SCMI Sensors
#
# end of IIO SCMI Sensors

#
# SSP Sensor Common
#
# end of SSP Sensor Common

CONFIG_IIO_ST_SENSORS_I2C=y
CONFIG_IIO_ST_SENSORS_CORE=y

#
# Digital to analog converters
#
CONFIG_AD5064=y
CONFIG_AD5380=y
CONFIG_AD5446=y
CONFIG_AD5592R_BASE=y
CONFIG_AD5593R=y
CONFIG_AD5686=y
CONFIG_AD5696_I2C=y
CONFIG_DS4424=y
CONFIG_M62332=y
# CONFIG_MAX517 is not set
CONFIG_MCP4725=y
CONFIG_TI_DAC5571=y
# end of Digital to analog converters

#
# IIO dummy driver
#
# end of IIO dummy driver

#
# Frequency Synthesizers DDS/PLL
#

#
# Clock Generator/Distribution
#
# end of Clock Generator/Distribution

#
# Phase-Locked Loop (PLL) frequency synthesizers
#
# end of Phase-Locked Loop (PLL) frequency synthesizers
# end of Frequency Synthesizers DDS/PLL

#
# Digital gyroscope sensors
#
# CONFIG_BMG160 is not set
CONFIG_FXAS21002C=y
CONFIG_FXAS21002C_I2C=y
CONFIG_MPU3050=y
CONFIG_MPU3050_I2C=y
CONFIG_IIO_ST_GYRO_3AXIS=y
CONFIG_IIO_ST_GYRO_I2C_3AXIS=y
CONFIG_ITG3200=y
# end of Digital gyroscope sensors

#
# Health Sensors
#

#
# Heart Rate Monitors
#
# CONFIG_AFE4404 is not set
# CONFIG_MAX30100 is not set
CONFIG_MAX30102=y
# end of Heart Rate Monitors
# end of Health Sensors

#
# Humidity sensors
#
CONFIG_AM2315=y
# CONFIG_DHT11 is not set
# CONFIG_HDC100X is not set
CONFIG_HDC2010=y
# CONFIG_HTS221 is not set
CONFIG_HTU21=y
# CONFIG_SI7005 is not set
CONFIG_SI7020=y
# end of Humidity sensors

#
# Inertial measurement units
#
CONFIG_BMI160=y
CONFIG_BMI160_I2C=y
CONFIG_FXOS8700=y
CONFIG_FXOS8700_I2C=y
CONFIG_KMX61=y
# CONFIG_INV_ICM42600_I2C is not set
# CONFIG_INV_MPU6050_I2C is not set
# CONFIG_IIO_ST_LSM6DSX is not set
# CONFIG_IIO_ST_LSM9DS0 is not set
# end of Inertial measurement units

#
# Light sensors
#
CONFIG_ACPI_ALS=y
CONFIG_ADJD_S311=y
# CONFIG_ADUX1020 is not set
CONFIG_AL3010=y
# CONFIG_AL3320A is not set
CONFIG_APDS9300=y
CONFIG_APDS9960=y
CONFIG_AS73211=y
CONFIG_BH1750=y
# CONFIG_BH1780 is not set
# CONFIG_CM32181 is not set
# CONFIG_CM3232 is not set
# CONFIG_CM3323 is not set
CONFIG_CM36651=y
# CONFIG_GP2AP002 is not set
# CONFIG_GP2AP020A00F is not set
CONFIG_SENSORS_ISL29018=y
CONFIG_SENSORS_ISL29028=y
CONFIG_ISL29125=y
CONFIG_JSA1212=y
CONFIG_RPR0521=y
CONFIG_SENSORS_LM3533=y
# CONFIG_LTR501 is not set
CONFIG_LV0104CS=y
CONFIG_MAX44000=y
CONFIG_MAX44009=y
CONFIG_NOA1305=y
CONFIG_OPT3001=y
CONFIG_PA12203001=y
CONFIG_SI1133=y
CONFIG_SI1145=y
CONFIG_STK3310=y
CONFIG_ST_UVIS25=y
CONFIG_ST_UVIS25_I2C=y
# CONFIG_TCS3414 is not set
# CONFIG_TCS3472 is not set
# CONFIG_SENSORS_TSL2563 is not set
CONFIG_TSL2583=y
# CONFIG_TSL2591 is not set
CONFIG_TSL2772=y
CONFIG_TSL4531=y
CONFIG_US5182D=y
CONFIG_VCNL4000=y
CONFIG_VCNL4035=y
# CONFIG_VEML6030 is not set
# CONFIG_VEML6070 is not set
# CONFIG_VL6180 is not set
CONFIG_ZOPT2201=y
# end of Light sensors

#
# Magnetometer sensors
#
CONFIG_AK8975=y
CONFIG_AK09911=y
# CONFIG_BMC150_MAGN_I2C is not set
CONFIG_MAG3110=y
CONFIG_MMC35240=y
CONFIG_IIO_ST_MAGN_3AXIS=y
CONFIG_IIO_ST_MAGN_I2C_3AXIS=y
# CONFIG_SENSORS_HMC5843_I2C is not set
CONFIG_SENSORS_RM3100=y
CONFIG_SENSORS_RM3100_I2C=y
CONFIG_YAMAHA_YAS530=y
# end of Magnetometer sensors

#
# Multiplexers
#
# end of Multiplexers

#
# Inclinometer sensors
#
# end of Inclinometer sensors

CONFIG_IIO_TEST_FORMAT=y

#
# Triggers - standalone
#
CONFIG_IIO_INTERRUPT_TRIGGER=y
CONFIG_IIO_SYSFS_TRIGGER=y
# end of Triggers - standalone

#
# Linear and angular position sensors
#
# end of Linear and angular position sensors

#
# Digital potentiometers
#
# CONFIG_AD5110 is not set
# CONFIG_AD5272 is not set
CONFIG_DS1803=y
CONFIG_MAX5432=y
CONFIG_MCP4018=y
CONFIG_MCP4531=y
CONFIG_TPL0102=y
# end of Digital potentiometers

#
# Digital potentiostats
#
# CONFIG_LMP91000 is not set
# end of Digital potentiostats

#
# Pressure sensors
#
# CONFIG_ABP060MG is not set
CONFIG_BMP280=y
CONFIG_BMP280_I2C=y
CONFIG_DLHL60D=y
CONFIG_DPS310=y
CONFIG_HP03=y
# CONFIG_ICP10100 is not set
CONFIG_MPL115=y
CONFIG_MPL115_I2C=y
CONFIG_MPL3115=y
CONFIG_MS5611=y
CONFIG_MS5611_I2C=y
CONFIG_MS5637=y
# CONFIG_IIO_ST_PRESS is not set
CONFIG_T5403=y
CONFIG_HP206C=y
# CONFIG_ZPA2326 is not set
# end of Pressure sensors

#
# Lightning sensors
#
# end of Lightning sensors

#
# Proximity and distance sensors
#
CONFIG_CROS_EC_MKBP_PROXIMITY=y
CONFIG_ISL29501=y
CONFIG_LIDAR_LITE_V2=y
CONFIG_MB1232=y
# CONFIG_PING is not set
CONFIG_RFD77402=y
CONFIG_SRF04=y
CONFIG_SX9310=y
# CONFIG_SX9500 is not set
CONFIG_SRF08=y
CONFIG_VCNL3020=y
CONFIG_VL53L0X_I2C=y
# end of Proximity and distance sensors

#
# Resolver to digital converters
#
# end of Resolver to digital converters

#
# Temperature sensors
#
CONFIG_MLX90614=y
# CONFIG_MLX90632 is not set
CONFIG_TMP006=y
CONFIG_TMP007=y
CONFIG_TMP117=y
CONFIG_TSYS01=y
# CONFIG_TSYS02D is not set
# end of Temperature sensors

# CONFIG_NTB is not set
# CONFIG_VME_BUS is not set
CONFIG_PWM=y
CONFIG_PWM_SYSFS=y
CONFIG_PWM_DEBUG=y
# CONFIG_PWM_CRC is not set
# CONFIG_PWM_CROS_EC is not set
# CONFIG_PWM_DWC is not set
# CONFIG_PWM_LPSS_PCI is not set
# CONFIG_PWM_LPSS_PLATFORM is not set
# CONFIG_PWM_PCA9685 is not set
CONFIG_PWM_TWL=y
CONFIG_PWM_TWL_LED=y

#
# IRQ chip support
#
CONFIG_MADERA_IRQ=y
# end of IRQ chip support

# CONFIG_IPACK_BUS is not set
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_TI_SYSCON=y

#
# PHY Subsystem
#
CONFIG_GENERIC_PHY=y
# CONFIG_USB_LGM_PHY is not set
# CONFIG_PHY_CAN_TRANSCEIVER is not set
# CONFIG_BCM_KONA_USB2_PHY is not set
# CONFIG_PHY_PXA_28NM_HSIC is not set
CONFIG_PHY_PXA_28NM_USB2=y
# CONFIG_PHY_CPCAP_USB is not set
# CONFIG_PHY_INTEL_LGM_EMMC is not set
# end of PHY Subsystem

CONFIG_POWERCAP=y
# CONFIG_INTEL_RAPL is not set
# CONFIG_IDLE_INJECT is not set
CONFIG_DTPM=y
# CONFIG_MCB is not set

#
# Performance monitor support
#
# end of Performance monitor support

CONFIG_RAS=y
# CONFIG_USB4 is not set

#
# Android
#
# CONFIG_ANDROID is not set
# end of Android

CONFIG_DAX=y
CONFIG_NVMEM=y
# CONFIG_NVMEM_SYSFS is not set
# CONFIG_NVMEM_NINTENDO_OTP is not set
CONFIG_NVMEM_RMEM=y

#
# HW tracing support
#
CONFIG_STM=y
CONFIG_STM_PROTO_BASIC=y
CONFIG_STM_PROTO_SYS_T=y
CONFIG_STM_DUMMY=y
CONFIG_STM_SOURCE_CONSOLE=y
CONFIG_STM_SOURCE_HEARTBEAT=y
CONFIG_STM_SOURCE_FTRACE=y
CONFIG_INTEL_TH=y
# CONFIG_INTEL_TH_PCI is not set
CONFIG_INTEL_TH_ACPI=y
# CONFIG_INTEL_TH_GTH is not set
CONFIG_INTEL_TH_STH=y
CONFIG_INTEL_TH_MSU=y
CONFIG_INTEL_TH_PTI=y
CONFIG_INTEL_TH_DEBUG=y
# end of HW tracing support

# CONFIG_FPGA is not set
CONFIG_TEE=y

#
# TEE drivers
#
# end of TEE drivers

CONFIG_PM_OPP=y
# CONFIG_SIOX is not set
# CONFIG_SLIMBUS is not set
# CONFIG_INTERCONNECT is not set
CONFIG_COUNTER=y
# CONFIG_INTERRUPT_CNT is not set
# CONFIG_INTEL_QEP is not set
CONFIG_MOST=y
CONFIG_MOST_CDEV=y
CONFIG_MOST_SND=y
# end of Device Drivers

#
# File systems
#
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_VALIDATE_FS_PARSER=y
CONFIG_FS_POSIX_ACL=y
CONFIG_EXPORTFS=y
# CONFIG_EXPORTFS_BLOCK_OPS is not set
CONFIG_FILE_LOCKING=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_VERITY=y
# CONFIG_FS_VERITY_DEBUG is not set
# CONFIG_FS_VERITY_BUILTIN_SIGNATURES is not set
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_FANOTIFY is not set
# CONFIG_QUOTA is not set
# CONFIG_AUTOFS4_FS is not set
CONFIG_AUTOFS_FS=y
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_VIRTIO_FS=y
# CONFIG_OVERLAY_FS is not set

#
# Caches
#
# CONFIG_FSCACHE is not set
# end of Caches

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
# CONFIG_PROC_PAGE_MONITOR is not set
# CONFIG_PROC_CHILDREN is not set
CONFIG_PROC_PID_ARCH_STATUS=y
CONFIG_PROC_CPU_RESCTRL=y
CONFIG_KERNFS=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_TMPFS_XATTR is not set
# CONFIG_HUGETLBFS is not set
CONFIG_MEMFD_CREATE=y
CONFIG_CONFIGFS_FS=y
# end of Pseudo filesystems

# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V2=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
CONFIG_NFS_V4=m
# CONFIG_NFS_V4_1 is not set
# CONFIG_ROOT_NFS is not set
# CONFIG_NFS_USE_LEGACY_DNS is not set
CONFIG_NFS_USE_KERNEL_DNS=y
CONFIG_NFS_DISABLE_UDP_SUPPORT=y
# CONFIG_NFSD is not set
CONFIG_GRACE_PERIOD=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
CONFIG_SUNRPC_GSS=m
# CONFIG_SUNRPC_DEBUG is not set
# CONFIG_CEPH_FS is not set
CONFIG_CIFS=m
CONFIG_CIFS_STATS2=y
CONFIG_CIFS_ALLOW_INSECURE_LEGACY=y
# CONFIG_CIFS_UPCALL is not set
# CONFIG_CIFS_XATTR is not set
CONFIG_CIFS_DEBUG=y
# CONFIG_CIFS_DEBUG2 is not set
# CONFIG_CIFS_DEBUG_DUMP_KEYS is not set
# CONFIG_CIFS_DFS_UPCALL is not set
# CONFIG_CIFS_SWN_UPCALL is not set
# CONFIG_SMB_SERVER is not set
CONFIG_SMBFS_COMMON=m
# CONFIG_CODA_FS is not set
# CONFIG_AFS_FS is not set
# CONFIG_9P_FS is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="iso8859-1"
# CONFIG_NLS_CODEPAGE_437 is not set
CONFIG_NLS_CODEPAGE_737=y
CONFIG_NLS_CODEPAGE_775=y
# CONFIG_NLS_CODEPAGE_850 is not set
CONFIG_NLS_CODEPAGE_852=y
CONFIG_NLS_CODEPAGE_855=y
CONFIG_NLS_CODEPAGE_857=y
CONFIG_NLS_CODEPAGE_860=y
CONFIG_NLS_CODEPAGE_861=y
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
CONFIG_NLS_CODEPAGE_865=y
CONFIG_NLS_CODEPAGE_866=y
CONFIG_NLS_CODEPAGE_869=y
CONFIG_NLS_CODEPAGE_936=y
# CONFIG_NLS_CODEPAGE_950 is not set
CONFIG_NLS_CODEPAGE_932=y
# CONFIG_NLS_CODEPAGE_949 is not set
CONFIG_NLS_CODEPAGE_874=y
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
CONFIG_NLS_CODEPAGE_1251=y
# CONFIG_NLS_ASCII is not set
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_ISO8859_2=y
CONFIG_NLS_ISO8859_3=y
CONFIG_NLS_ISO8859_4=y
# CONFIG_NLS_ISO8859_5 is not set
CONFIG_NLS_ISO8859_6=y
# CONFIG_NLS_ISO8859_7 is not set
CONFIG_NLS_ISO8859_9=y
CONFIG_NLS_ISO8859_13=y
CONFIG_NLS_ISO8859_14=y
CONFIG_NLS_ISO8859_15=y
# CONFIG_NLS_KOI8_R is not set
CONFIG_NLS_KOI8_U=y
CONFIG_NLS_MAC_ROMAN=y
# CONFIG_NLS_MAC_CELTIC is not set
# CONFIG_NLS_MAC_CENTEURO is not set
CONFIG_NLS_MAC_CROATIAN=y
# CONFIG_NLS_MAC_CYRILLIC is not set
CONFIG_NLS_MAC_GAELIC=y
CONFIG_NLS_MAC_GREEK=y
# CONFIG_NLS_MAC_ICELAND is not set
CONFIG_NLS_MAC_INUIT=y
CONFIG_NLS_MAC_ROMANIAN=y
CONFIG_NLS_MAC_TURKISH=y
CONFIG_NLS_UTF8=y
# CONFIG_DLM is not set
# CONFIG_UNICODE is not set
# end of File systems

#
# Security options
#
CONFIG_KEYS=y
# CONFIG_KEYS_REQUEST_CACHE is not set
# CONFIG_PERSISTENT_KEYRINGS is not set
# CONFIG_BIG_KEYS is not set
CONFIG_ENCRYPTED_KEYS=y
CONFIG_KEY_DH_OPERATIONS=y
CONFIG_KEY_NOTIFICATIONS=y
# CONFIG_SECURITY_DMESG_RESTRICT is not set
CONFIG_SECURITY=y
# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_NETWORK is not set
# CONFIG_SECURITY_PATH is not set
CONFIG_FORTIFY_SOURCE=y
CONFIG_STATIC_USERMODEHELPER=y
CONFIG_STATIC_USERMODEHELPER_PATH="/sbin/usermode-helper"
# CONFIG_SECURITY_SMACK is not set
# CONFIG_SECURITY_TOMOYO is not set
# CONFIG_SECURITY_APPARMOR is not set
# CONFIG_SECURITY_YAMA is not set
# CONFIG_SECURITY_SAFESETID is not set
# CONFIG_SECURITY_LOCKDOWN_LSM is not set
# CONFIG_SECURITY_LANDLOCK is not set
CONFIG_INTEGRITY=y
# CONFIG_INTEGRITY_SIGNATURE is not set
# CONFIG_IMA is not set
# CONFIG_EVM is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_LSM="landlock,lockdown,yama,loadpin,safesetid,integrity,bpf"

#
# Kernel hardening options
#

#
# Memory initialization
#
CONFIG_CC_HAS_AUTO_VAR_INIT_PATTERN=y
CONFIG_CC_HAS_AUTO_VAR_INIT_ZERO=y
CONFIG_INIT_STACK_NONE=y
# CONFIG_INIT_STACK_ALL_PATTERN is not set
# CONFIG_INIT_STACK_ALL_ZERO is not set
# CONFIG_INIT_ON_ALLOC_DEFAULT_ON is not set
CONFIG_INIT_ON_FREE_DEFAULT_ON=y
# end of Memory initialization
# end of Kernel hardening options
# end of Security options

CONFIG_CRYPTO=y

#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_SKCIPHER=y
CONFIG_CRYPTO_SKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_RNG_DEFAULT=y
CONFIG_CRYPTO_AKCIPHER2=y
CONFIG_CRYPTO_AKCIPHER=y
CONFIG_CRYPTO_KPP2=y
CONFIG_CRYPTO_KPP=y
CONFIG_CRYPTO_ACOMP2=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_USER is not set
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_GF128MUL=y
CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_NULL2=y
CONFIG_CRYPTO_PCRYPT=y
CONFIG_CRYPTO_CRYPTD=y
CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set
CONFIG_CRYPTO_SIMD=y

#
# Public-key cryptography
#
# CONFIG_CRYPTO_RSA is not set
CONFIG_CRYPTO_DH=y
CONFIG_CRYPTO_ECC=y
# CONFIG_CRYPTO_ECDH is not set
# CONFIG_CRYPTO_ECDSA is not set
CONFIG_CRYPTO_ECRDSA=y
CONFIG_CRYPTO_SM2=y
CONFIG_CRYPTO_CURVE25519=y

#
# Authenticated Encryption with Associated Data
#
CONFIG_CRYPTO_CCM=y
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_CHACHA20POLY1305=y
# CONFIG_CRYPTO_AEGIS128 is not set
CONFIG_CRYPTO_SEQIV=y
CONFIG_CRYPTO_ECHAINIV=y

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CFB=y
CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_CTS=y
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=y
# CONFIG_CRYPTO_OFB is not set
CONFIG_CRYPTO_PCBC=y
# CONFIG_CRYPTO_XTS is not set
CONFIG_CRYPTO_KEYWRAP=y
# CONFIG_CRYPTO_ADIANTUM is not set
CONFIG_CRYPTO_ESSIV=y

#
# Hash modes
#
CONFIG_CRYPTO_CMAC=y
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
CONFIG_CRYPTO_VMAC=y

#
# Digest
#
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CRC32C_INTEL=y
# CONFIG_CRYPTO_CRC32 is not set
CONFIG_CRYPTO_CRC32_PCLMUL=y
# CONFIG_CRYPTO_XXHASH is not set
CONFIG_CRYPTO_BLAKE2B=y
CONFIG_CRYPTO_BLAKE2S=y
CONFIG_CRYPTO_CRCT10DIF=y
CONFIG_CRYPTO_GHASH=y
CONFIG_CRYPTO_POLY1305=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_RMD160=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_SHA3=y
CONFIG_CRYPTO_SM3=y
CONFIG_CRYPTO_STREEBOG=y
CONFIG_CRYPTO_WP512=y

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=y
# CONFIG_CRYPTO_AES_NI_INTEL is not set
CONFIG_CRYPTO_BLOWFISH=y
CONFIG_CRYPTO_BLOWFISH_COMMON=y
# CONFIG_CRYPTO_CAMELLIA is not set
CONFIG_CRYPTO_CAST_COMMON=y
# CONFIG_CRYPTO_CAST5 is not set
CONFIG_CRYPTO_CAST6=y
# CONFIG_CRYPTO_DES is not set
CONFIG_CRYPTO_FCRYPT=y
CONFIG_CRYPTO_CHACHA20=y
CONFIG_CRYPTO_SERPENT=y
CONFIG_CRYPTO_SERPENT_SSE2_586=y
CONFIG_CRYPTO_SM4=y
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_TWOFISH_586 is not set

#
# Compression
#
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_842=y
# CONFIG_CRYPTO_LZ4 is not set
CONFIG_CRYPTO_LZ4HC=y
CONFIG_CRYPTO_ZSTD=y

#
# Random Number Generation
#
CONFIG_CRYPTO_ANSI_CPRNG=y
CONFIG_CRYPTO_DRBG_MENU=y
CONFIG_CRYPTO_DRBG_HMAC=y
# CONFIG_CRYPTO_DRBG_HASH is not set
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_DRBG=y
CONFIG_CRYPTO_JITTERENTROPY=y
# CONFIG_CRYPTO_USER_API_HASH is not set
# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
# CONFIG_CRYPTO_USER_API_RNG is not set
# CONFIG_CRYPTO_USER_API_AEAD is not set
CONFIG_CRYPTO_HASH_INFO=y

#
# Crypto library routines
#
CONFIG_CRYPTO_LIB_AES=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_BLAKE2S=y
CONFIG_CRYPTO_LIB_CHACHA_GENERIC=y
CONFIG_CRYPTO_LIB_CHACHA=y
CONFIG_CRYPTO_LIB_CURVE25519_GENERIC=y
# CONFIG_CRYPTO_LIB_CURVE25519 is not set
CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
CONFIG_CRYPTO_LIB_POLY1305_GENERIC=y
CONFIG_CRYPTO_LIB_POLY1305=y
CONFIG_CRYPTO_LIB_CHACHA20POLY1305=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LIB_SM4=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_PADLOCK=y
CONFIG_CRYPTO_DEV_PADLOCK_AES=y
CONFIG_CRYPTO_DEV_PADLOCK_SHA=y
# CONFIG_CRYPTO_DEV_GEODE is not set
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
# CONFIG_CRYPTO_DEV_ATMEL_ECC is not set
# CONFIG_CRYPTO_DEV_ATMEL_SHA204A is not set
# CONFIG_CRYPTO_DEV_CCP is not set
# CONFIG_CRYPTO_DEV_QAT_DH895xCC is not set
# CONFIG_CRYPTO_DEV_QAT_C3XXX is not set
# CONFIG_CRYPTO_DEV_QAT_C62X is not set
# CONFIG_CRYPTO_DEV_QAT_4XXX is not set
# CONFIG_CRYPTO_DEV_QAT_DH895xCCVF is not set
# CONFIG_CRYPTO_DEV_QAT_C3XXXVF is not set
# CONFIG_CRYPTO_DEV_QAT_C62XVF is not set
# CONFIG_CRYPTO_DEV_VIRTIO is not set
# CONFIG_CRYPTO_DEV_SAFEXCEL is not set
# CONFIG_CRYPTO_DEV_AMLOGIC_GXL is not set
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
# CONFIG_X509_CERTIFICATE_PARSER is not set
CONFIG_PKCS8_PRIVATE_KEY_PARSER=y

#
# Certificates for signature checking
#
# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set
# end of Certificates for signature checking

CONFIG_BINARY_PRINTF=y

#
# Library routines
#
CONFIG_LINEAR_RANGES=y
CONFIG_PACKING=y
CONFIG_BITREVERSE=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GENERIC_NET_UTILS=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_CORDIC=y
CONFIG_PRIME_NUMBERS=y
CONFIG_RATIONAL=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_IOMAP=y
CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
CONFIG_ARCH_USE_SYM_ANNOTATIONS=y
# CONFIG_CRC_CCITT is not set
CONFIG_CRC16=y
# CONFIG_CRC_T10DIF is not set
CONFIG_CRC_ITU_T=y
CONFIG_CRC32=y
# CONFIG_CRC32_SELFTEST is not set
# CONFIG_CRC32_SLICEBY8 is not set
# CONFIG_CRC32_SLICEBY4 is not set
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_BIT=y
# CONFIG_CRC64 is not set
# CONFIG_CRC4 is not set
CONFIG_CRC7=y
CONFIG_LIBCRC32C=y
CONFIG_CRC8=y
CONFIG_XXHASH=y
# CONFIG_RANDOM32_SELFTEST is not set
CONFIG_842_COMPRESS=y
CONFIG_842_DECOMPRESS=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_LZ4HC_COMPRESS=y
CONFIG_LZ4_DECOMPRESS=y
CONFIG_ZSTD_COMPRESS=y
CONFIG_ZSTD_DECOMPRESS=y
CONFIG_XZ_DEC=y
# CONFIG_XZ_DEC_X86 is not set
# CONFIG_XZ_DEC_POWERPC is not set
# CONFIG_XZ_DEC_IA64 is not set
CONFIG_XZ_DEC_ARM=y
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_SPARC is not set
CONFIG_XZ_DEC_BCJ=y
# CONFIG_XZ_DEC_TEST is not set
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_ZSTD=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_BCH=y
CONFIG_BCH_CONST_PARAMS=y
CONFIG_ASSOCIATIVE_ARRAY=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HAS_DMA=y
CONFIG_NEED_SG_DMA_LENGTH=y
# CONFIG_DMA_API_DEBUG is not set
CONFIG_DMA_MAP_BENCHMARK=y
CONFIG_SGL_ALLOC=y
CONFIG_CPUMASK_OFFSTACK=y
CONFIG_CPU_RMAP=y
CONFIG_DQL=y
CONFIG_GLOB=y
# CONFIG_GLOB_SELFTEST is not set
CONFIG_NLATTR=y
CONFIG_CLZ_TAB=y
# CONFIG_IRQ_POLL is not set
CONFIG_MPILIB=y
CONFIG_OID_REGISTRY=y
CONFIG_HAVE_GENERIC_VDSO=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_VDSO_32=y
CONFIG_GENERIC_VDSO_TIME_NS=y
CONFIG_ARCH_STACKWALK=y
CONFIG_STACKDEPOT=y
CONFIG_STACK_HASH_ORDER=20
# end of Library routines

#
# Kernel hacking
#

#
# printk and dmesg options
#
CONFIG_PRINTK_TIME=y
CONFIG_PRINTK_CALLER=y
# CONFIG_STACKTRACE_BUILD_ID is not set
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7
CONFIG_CONSOLE_LOGLEVEL_QUIET=4
CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DYNAMIC_DEBUG_CORE is not set
# CONFIG_SYMBOLIC_ERRNAME is not set
CONFIG_DEBUG_BUGVERBOSE=y
# end of printk and dmesg options

#
# Compile-time checks and compiler options
#
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_INFO_REDUCED=y
# CONFIG_DEBUG_INFO_SPLIT is not set
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
# CONFIG_DEBUG_INFO_DWARF4 is not set
# CONFIG_DEBUG_INFO_DWARF5 is not set
CONFIG_PAHOLE_HAS_SPLIT_BTF=y
# CONFIG_GDB_SCRIPTS is not set
CONFIG_FRAME_WARN=1024
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_HEADERS_INSTALL is not set
CONFIG_SECTION_MISMATCH_WARN_ONLY=y
# CONFIG_DEBUG_FORCE_FUNCTION_ALIGN_64B is not set
CONFIG_FRAME_POINTER=y
CONFIG_VMLINUX_MAP=y
# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
# end of Compile-time checks and compiler options

#
# Generic Kernel Debugging Instruments
#
CONFIG_MAGIC_SYSRQ=y
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
CONFIG_MAGIC_SYSRQ_SERIAL=y
CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE=""
CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_FS_ALLOW_ALL is not set
# CONFIG_DEBUG_FS_DISALLOW_MOUNT is not set
CONFIG_DEBUG_FS_ALLOW_NONE=y
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y
CONFIG_UBSAN=y
# CONFIG_UBSAN_TRAP is not set
CONFIG_CC_HAS_UBSAN_BOUNDS=y
CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
CONFIG_UBSAN_BOUNDS=y
CONFIG_UBSAN_ARRAY_BOUNDS=y
CONFIG_UBSAN_SHIFT=y
# CONFIG_UBSAN_DIV_ZERO is not set
# CONFIG_UBSAN_UNREACHABLE is not set
# CONFIG_UBSAN_OBJECT_SIZE is not set
# CONFIG_UBSAN_BOOL is not set
# CONFIG_UBSAN_ENUM is not set
# CONFIG_UBSAN_ALIGNMENT is not set
CONFIG_UBSAN_SANITIZE_ALL=y
# CONFIG_TEST_UBSAN is not set
CONFIG_HAVE_KCSAN_COMPILER=y
# end of Generic Kernel Debugging Instruments

CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_MISC is not set

#
# Memory Debugging
#
CONFIG_PAGE_EXTENSION=y
# CONFIG_DEBUG_PAGEALLOC is not set
CONFIG_PAGE_OWNER=y
# CONFIG_PAGE_POISONING is not set
# CONFIG_DEBUG_PAGE_REF is not set
# CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_ARCH_HAS_DEBUG_WX=y
CONFIG_DEBUG_WX=y
CONFIG_GENERIC_PTDUMP=y
CONFIG_PTDUMP_CORE=y
CONFIG_PTDUMP_DEBUGFS=y
CONFIG_DEBUG_OBJECTS=y
CONFIG_DEBUG_OBJECTS_SELFTEST=y
# CONFIG_DEBUG_OBJECTS_FREE is not set
# CONFIG_DEBUG_OBJECTS_TIMERS is not set
# CONFIG_DEBUG_OBJECTS_WORK is not set
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
# CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER is not set
CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1
CONFIG_HAVE_DEBUG_KMEMLEAK=y
# CONFIG_DEBUG_KMEMLEAK is not set
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_ARCH_HAS_DEBUG_VM_PGTABLE=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_VM_PGTABLE is not set
CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y
# CONFIG_DEBUG_VIRTUAL is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_DEBUG_PER_CPU_MAPS=y
CONFIG_DEBUG_KMAP_LOCAL=y
CONFIG_ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP=y
CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP=y
CONFIG_DEBUG_HIGHMEM=y
CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
CONFIG_DEBUG_STACKOVERFLOW=y
CONFIG_CC_HAS_KASAN_GENERIC=y
CONFIG_CC_HAS_KASAN_SW_TAGS=y
CONFIG_CC_HAS_WORKING_NOSANITIZE_ADDRESS=y
CONFIG_HAVE_ARCH_KFENCE=y
# end of Memory Debugging

# CONFIG_DEBUG_SHIRQ is not set

#
# Debug Oops, Lockups and Hangs
#
CONFIG_PANIC_ON_OOPS=y
CONFIG_PANIC_ON_OOPS_VALUE=1
CONFIG_PANIC_TIMEOUT=0
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SOFTLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
CONFIG_HARDLOCKUP_DETECTOR_PERF=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=1
CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=480
CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
CONFIG_WQ_WATCHDOG=y
# CONFIG_TEST_LOCKUP is not set
# end of Debug Oops, Lockups and Hangs

#
# Scheduler Debugging
#
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHED_INFO=y
CONFIG_SCHEDSTATS=y
# end of Scheduler Debugging

CONFIG_DEBUG_TIMEKEEPING=y
CONFIG_DEBUG_PREEMPT=y

#
# Lock Debugging (spinlocks, mutexes, etc...)
#
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_PROVE_LOCKING=y
# CONFIG_PROVE_RAW_LOCK_NESTING is not set
CONFIG_LOCK_STAT=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
CONFIG_DEBUG_RWSEMS=y
CONFIG_DEBUG_LOCK_ALLOC=y
CONFIG_LOCKDEP=y
CONFIG_LOCKDEP_BITS=15
CONFIG_LOCKDEP_CHAINS_BITS=16
CONFIG_LOCKDEP_STACK_TRACE_BITS=19
CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14
CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12
# CONFIG_DEBUG_LOCKDEP is not set
CONFIG_DEBUG_ATOMIC_SLEEP=y
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
# CONFIG_LOCK_TORTURE_TEST is not set
# CONFIG_WW_MUTEX_SELFTEST is not set
# CONFIG_SCF_TORTURE_TEST is not set
# end of Lock Debugging (spinlocks, mutexes, etc...)

CONFIG_TRACE_IRQFLAGS=y
CONFIG_TRACE_IRQFLAGS_NMI=y
CONFIG_DEBUG_IRQFLAGS=y
CONFIG_STACKTRACE=y
CONFIG_WARN_ALL_UNSEEDED_RANDOM=y
# CONFIG_DEBUG_KOBJECT is not set

#
# Debug kernel data structures
#
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_PLIST=y
# CONFIG_DEBUG_SG is not set
CONFIG_DEBUG_NOTIFIERS=y
CONFIG_BUG_ON_DATA_CORRUPTION=y
# end of Debug kernel data structures

CONFIG_DEBUG_CREDENTIALS=y

#
# RCU Debugging
#
CONFIG_PROVE_RCU=y
CONFIG_PROVE_RCU_LIST=y
CONFIG_TORTURE_TEST=y
CONFIG_RCU_SCALE_TEST=y
# CONFIG_RCU_TORTURE_TEST is not set
# CONFIG_RCU_REF_SCALE_TEST is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=21
CONFIG_RCU_TRACE=y
CONFIG_RCU_EQS_DEBUG=y
# end of RCU Debugging

# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
CONFIG_LATENCYTOP=y
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_HAVE_FENTRY=y
CONFIG_HAVE_C_RECORDMCOUNT=y
CONFIG_TRACER_MAX_TRACE=y
CONFIG_TRACE_CLOCK=y
CONFIG_RING_BUFFER=y
CONFIG_EVENT_TRACING=y
CONFIG_CONTEXT_SWITCH_TRACER=y
CONFIG_PREEMPTIRQ_TRACEPOINTS=y
CONFIG_TRACING=y
CONFIG_GENERIC_TRACER=y
CONFIG_TRACING_SUPPORT=y
CONFIG_FTRACE=y
CONFIG_BOOTTIME_TRACING=y
CONFIG_FUNCTION_TRACER=y
# CONFIG_FUNCTION_GRAPH_TRACER is not set
CONFIG_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE_WITH_REGS=y
CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS=y
# CONFIG_FUNCTION_PROFILER is not set
CONFIG_STACK_TRACER=y
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_HWLAT_TRACER is not set
# CONFIG_OSNOISE_TRACER is not set
# CONFIG_TIMERLAT_TRACER is not set
# CONFIG_MMIOTRACE is not set
CONFIG_FTRACE_SYSCALLS=y
CONFIG_TRACER_SNAPSHOT=y
# CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP is not set
CONFIG_BRANCH_PROFILE_NONE=y
# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
CONFIG_UPROBE_EVENTS=y
CONFIG_BPF_EVENTS=y
CONFIG_DYNAMIC_EVENTS=y
CONFIG_PROBE_EVENTS=y
CONFIG_FTRACE_MCOUNT_RECORD=y
CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT=y
CONFIG_SYNTH_EVENTS=y
# CONFIG_HIST_TRIGGERS is not set
CONFIG_TRACE_EVENT_INJECT=y
CONFIG_TRACEPOINT_BENCHMARK=y
CONFIG_RING_BUFFER_BENCHMARK=y
# CONFIG_TRACE_EVAL_MAP_FILE is not set
CONFIG_FTRACE_RECORD_RECURSION=y
CONFIG_FTRACE_RECORD_RECURSION_SIZE=128
CONFIG_RING_BUFFER_RECORD_RECURSION=y
# CONFIG_FTRACE_STARTUP_TEST is not set
# CONFIG_RING_BUFFER_STARTUP_TEST is not set
CONFIG_RING_BUFFER_VALIDATE_TIME_DELTAS=y
# CONFIG_PREEMPTIRQ_DELAY_TEST is not set
CONFIG_SYNTH_EVENT_GEN_TEST=y
# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
CONFIG_SAMPLES=y
CONFIG_SAMPLE_AUXDISPLAY=y
# CONFIG_SAMPLE_TRACE_EVENTS is not set
# CONFIG_SAMPLE_TRACE_PRINTK is not set
# CONFIG_SAMPLE_TRACE_ARRAY is not set
CONFIG_SAMPLE_KOBJECT=y
# CONFIG_SAMPLE_HW_BREAKPOINT is not set
# CONFIG_SAMPLE_KFIFO is not set
# CONFIG_SAMPLE_CONFIGFS is not set
# CONFIG_SAMPLE_VFIO_MDEV_MTTY is not set
# CONFIG_SAMPLE_VFIO_MDEV_MDPY is not set
# CONFIG_SAMPLE_VFIO_MDEV_MBOCHS is not set
# CONFIG_SAMPLE_WATCHDOG is not set
CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y

#
# x86 Debugging
#
CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
CONFIG_EARLY_PRINTK_USB=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_EARLY_PRINTK_USB_XDBC=y
CONFIG_DEBUG_TLBFLUSH=y
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
# CONFIG_X86_DECODER_SELFTEST is not set
# CONFIG_IO_DELAY_0X80 is not set
CONFIG_IO_DELAY_0XED=y
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
# CONFIG_DEBUG_BOOT_PARAMS is not set
# CONFIG_CPA_DEBUG is not set
# CONFIG_DEBUG_ENTRY is not set
# CONFIG_DEBUG_NMI_SELFTEST is not set
CONFIG_X86_DEBUG_FPU=y
# CONFIG_PUNIT_ATOM_DEBUG is not set
CONFIG_UNWINDER_FRAME_POINTER=y
# end of x86 Debugging

#
# Kernel Testing and Coverage
#
CONFIG_KUNIT=y
CONFIG_KUNIT_DEBUGFS=y
CONFIG_KUNIT_TEST=y
CONFIG_KUNIT_EXAMPLE_TEST=y
# CONFIG_KUNIT_ALL_TESTS is not set
CONFIG_NOTIFIER_ERROR_INJECTION=y
# CONFIG_NETDEV_NOTIFIER_ERROR_INJECT is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_CC_HAS_SANCOV_TRACE_PC=y
CONFIG_RUNTIME_TESTING_MENU=y
# CONFIG_LKDTM is not set
# CONFIG_TEST_LIST_SORT is not set
# CONFIG_TEST_MIN_HEAP is not set
# CONFIG_TEST_SORT is not set
# CONFIG_TEST_DIV64 is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_REED_SOLOMON_TEST is not set
# CONFIG_INTERVAL_TREE_TEST is not set
# CONFIG_PERCPU_TEST is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_TEST_HEXDUMP is not set
CONFIG_STRING_SELFTEST=y
# CONFIG_TEST_STRING_HELPERS is not set
CONFIG_TEST_STRSCPY=y
# CONFIG_TEST_KSTRTOX is not set
CONFIG_TEST_PRINTF=y
CONFIG_TEST_SCANF=y
CONFIG_TEST_BITMAP=y
# CONFIG_TEST_UUID is not set
# CONFIG_TEST_XARRAY is not set
# CONFIG_TEST_OVERFLOW is not set
# CONFIG_TEST_RHASHTABLE is not set
# CONFIG_TEST_HASH is not set
# CONFIG_TEST_IDA is not set
# CONFIG_TEST_LKM is not set
# CONFIG_TEST_BITOPS is not set
# CONFIG_TEST_VMALLOC is not set
# CONFIG_TEST_USER_COPY is not set
# CONFIG_TEST_BPF is not set
# CONFIG_TEST_BLACKHOLE_DEV is not set
# CONFIG_FIND_BIT_BENCHMARK is not set
# CONFIG_TEST_FIRMWARE is not set
# CONFIG_TEST_SYSCTL is not set
CONFIG_BITFIELD_KUNIT=y
# CONFIG_RESOURCE_KUNIT_TEST is not set
CONFIG_SYSCTL_KUNIT_TEST=y
CONFIG_LIST_KUNIT_TEST=y
CONFIG_LINEAR_RANGES_TEST=y
# CONFIG_CMDLINE_KUNIT_TEST is not set
CONFIG_BITS_TEST=y
CONFIG_RATIONAL_KUNIT_TEST=y
# CONFIG_TEST_UDELAY is not set
# CONFIG_TEST_STATIC_KEYS is not set
# CONFIG_TEST_MEMCAT_P is not set
# CONFIG_TEST_STACKINIT is not set
# CONFIG_TEST_MEMINIT is not set
# CONFIG_TEST_FREE_PAGES is not set
CONFIG_TEST_FPU=y
# CONFIG_TEST_CLOCKSOURCE_WATCHDOG is not set
CONFIG_ARCH_USE_MEMTEST=y
# CONFIG_MEMTEST is not set
# end of Kernel Testing and Coverage
# end of Kernel hacking
-------------- next part --------------
#!/bin/sh

export_top_env()
{
	export suite='boot'
	export testcase='boot'
	export category='functional'
	export timeout='10m'
	export job_origin='boot-300s.yaml'
	export queue_cmdline_keys='branch
commit
queue_at_least_once'
	export queue='validate'
	export testbox='vm-snb-i386-27'
	export tbox_group='vm-snb-i386'
	export branch='linux-review/Sean-Nyekjaer/mtd-core-protect-access-to-mtd-devices-while-in-suspend/20211011-195606'
	export commit='d3ff51cfa9a64cdc18abe24c9821891b5122e617'
	export kconfig='i386-randconfig-a011-20211012'
	export repeat_to=6
	export nr_vm=160
	export submit_id='616719c1b2cb0f5340cb709e'
	export job_file='/lkp/jobs/scheduled/vm-snb-i386-27/boot-300-yocto-i386-minimal-20190520.cgz-d3ff51cfa9a64cdc18abe24c9821891b5122e617-20211014-86848-1be7mcg-4.yaml'
	export id='500f2ca586de13a96fe45743dbd4fb5f5811c267'
	export queuer_version='/lkp-src'
	export model='qemu-system-i386 -enable-kvm -cpu SandyBridge'
	export nr_cpu=2
	export memory='4G'
	export need_kconfig=\{\"KVM_GUEST\"\=\>\"y\"\}
	export ssh_base_port=23400
	export kernel_cmdline='vmalloc=128M initramfs_async=0 page_owner=on'
	export rootfs='yocto-i386-minimal-20190520.cgz'
	export compiler='clang-14'
	export enqueue_time='2021-10-14 01:39:14 +0800'
	export _id='616719c2b2cb0f5340cb709f'
	export _rt='/result/boot/300/vm-snb-i386/yocto-i386-minimal-20190520.cgz/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617'
	export user='lkp'
	export LKP_SERVER='internal-lkp-server'
	export result_root='/result/boot/300/vm-snb-i386/yocto-i386-minimal-20190520.cgz/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617/3'
	export scheduler_version='/lkp/lkp/.src-20211013-173054'
	export arch='i386'
	export max_uptime=600
	export initrd='/osimage/yocto/yocto-i386-minimal-20190520.cgz'
	export bootloader_append='root=/dev/ram0
user=lkp
job=/lkp/jobs/scheduled/vm-snb-i386-27/boot-300-yocto-i386-minimal-20190520.cgz-d3ff51cfa9a64cdc18abe24c9821891b5122e617-20211014-86848-1be7mcg-4.yaml
ARCH=i386
kconfig=i386-randconfig-a011-20211012
branch=linux-review/Sean-Nyekjaer/mtd-core-protect-access-to-mtd-devices-while-in-suspend/20211011-195606
commit=d3ff51cfa9a64cdc18abe24c9821891b5122e617
BOOT_IMAGE=/pkg/linux/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617/vmlinuz-5.15.0-rc1-00002-gd3ff51cfa9a6
vmalloc=128M initramfs_async=0 page_owner=on
max_uptime=600
RESULT_ROOT=/result/boot/300/vm-snb-i386/yocto-i386-minimal-20190520.cgz/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617/3
LKP_SERVER=internal-lkp-server
selinux=0
debug
apic=debug
sysrq_always_enabled
rcupdate.rcu_cpu_stall_timeout=100
net.ifnames=0
printk.devkmsg=on
panic=-1
softlockup_panic=1
nmi_watchdog=panic
oops=panic
load_ramdisk=2
prompt_ramdisk=0
drbd.minor_count=8
systemd.log_level=err
ignore_loglevel
console=tty0
earlyprintk=ttyS0,115200
console=ttyS0,115200
vga=normal
rw'
	export modules_initrd='/pkg/linux/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617/modules.cgz'
	export lkp_initrd='/osimage/user/lkp/lkp-i386.cgz'
	export site='inn'
	export LKP_CGI_PORT=80
	export LKP_CIFS_PORT=139
	export queue_at_least_once=1
	export kernel='/pkg/linux/i386-randconfig-a011-20211012/clang-14/d3ff51cfa9a64cdc18abe24c9821891b5122e617/vmlinuz-5.15.0-rc1-00002-gd3ff51cfa9a6'
	export dequeue_time='2021-10-14 01:39:41 +0800'
	export job_initrd='/lkp/jobs/scheduled/vm-snb-i386-27/boot-300-yocto-i386-minimal-20190520.cgz-d3ff51cfa9a64cdc18abe24c9821891b5122e617-20211014-86848-1be7mcg-4.cgz'

	[ -n "$LKP_SRC" ] ||
	export LKP_SRC=/lkp/${user:-lkp}/src
}

run_job()
{
	echo $$ > $TMP/run-job.pid

	. $LKP_SRC/lib/http.sh
	. $LKP_SRC/lib/job.sh
	. $LKP_SRC/lib/env.sh

	export_top_env

	run_monitor $LKP_SRC/monitors/one-shot/wrapper boot-slabinfo
	run_monitor $LKP_SRC/monitors/one-shot/wrapper boot-meminfo
	run_monitor $LKP_SRC/monitors/one-shot/wrapper memmap
	run_monitor $LKP_SRC/monitors/no-stdout/wrapper boot-time
	run_monitor $LKP_SRC/monitors/wrapper kmsg
	run_monitor $LKP_SRC/monitors/wrapper heartbeat
	run_monitor $LKP_SRC/monitors/wrapper meminfo
	run_monitor $LKP_SRC/monitors/wrapper oom-killer
	run_monitor $LKP_SRC/monitors/plain/watchdog

	run_test $LKP_SRC/tests/wrapper sleep 300
}

extract_stats()
{
	export stats_part_begin=
	export stats_part_end=

	$LKP_SRC/stats/wrapper boot-slabinfo
	$LKP_SRC/stats/wrapper boot-meminfo
	$LKP_SRC/stats/wrapper memmap
	$LKP_SRC/stats/wrapper boot-memory
	$LKP_SRC/stats/wrapper boot-time
	$LKP_SRC/stats/wrapper kernel-size
	$LKP_SRC/stats/wrapper kmsg
	$LKP_SRC/stats/wrapper sleep
	$LKP_SRC/stats/wrapper meminfo

	$LKP_SRC/stats/wrapper time sleep.time
	$LKP_SRC/stats/wrapper dmesg
	$LKP_SRC/stats/wrapper kmsg
	$LKP_SRC/stats/wrapper last_state
	$LKP_SRC/stats/wrapper stderr
	$LKP_SRC/stats/wrapper time
}

"$@"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dmesg.xz
Type: application/x-xz
Size: 19336 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211014/9f179474/attachment-0001.xz>

From anton at tuxera.com  Thu Oct 14 02:32:58 2021
From: anton at tuxera.com (Anton Altaparmakov)
Date: Thu, 14 Oct 2021 09:32:58 +0000
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <20211014062844.GA25448@lst.de>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211014062844.GA25448@lst.de>
Message-ID: <3AB8052D-DD45-478B-85F2-BFBEC1C7E9DF@tuxera.com>

Hi Christoph,

> On 14 Oct 2021, at 07:28, Christoph Hellwig <hch at lst.de> wrote:
> 
> On Wed, Oct 13, 2021 at 07:10:13AM +0200, Christoph Hellwig wrote:
>> I wondered about adding a helper for looking at the size in byte units
>> to avoid the SECTOR_SHIFT shifts in various places.  But given that
>> I could not come up with a good name and block devices fundamentally
>> work in sector size granularity I decided against that.
> 
> So it seems like the biggest review feedback is that we should have
> such a helper.  I think the bdev_size name is the worst as size does
> not imply a particular unit.  bdev_nr_bytes is a little better but I'm
> not too happy.  Any other suggestions or strong opinions?

bdev_byte_size() would seem to address your concerns?

bdev_nr_bytes() would work though - it is analogous to bdev_nr_sectors() after all.

No strong opinion here but I do agree with you that bdev_size() is a bad choice for sure.  It is bound to cause bugs down the line when people forget what unit it is in.

Best regards,

	Anton
-- 
Anton Altaparmakov <anton at tuxera.com> (replace at with @)
Lead in File System Development, Tuxera Inc., http://www.tuxera.com/
Linux NTFS maintainer



From caihuoqing at baidu.com  Thu Oct 14 04:06:14 2021
From: caihuoqing at baidu.com (Cai Huoqing)
Date: Thu, 14 Oct 2021 19:06:14 +0800
Subject: [PATCH] MAINTAINERS: Update the devicetree documentation path of
 hyperbus
Message-ID: <20211014110614.3320-1-caihuoqing@baidu.com>

Change the devicetree documentation path
to "Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml"
since 'cypress,hyperflash.txt' and 'ti,am654-hbmc.txt' have
been converted to 'ti,am654-hbmc.yaml'.

Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>
---
*resend +Cc others.

 MAINTAINERS | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 9b255cf4fca8..48949cd7f898 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8783,8 +8783,7 @@ S:	Supported
 Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/
 C:	irc://irc.oftc.net/mtd
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git cfi/next
-F:	Documentation/devicetree/bindings/mtd/cypress,hyperflash.txt
-F:	Documentation/devicetree/bindings/mtd/ti,am654-hbmc.txt
+F:	Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
 F:	drivers/mtd/hyperbus/
 F:	include/linux/mtd/hyperbus.h
 
-- 
2.25.1



From dave.kleikamp at oracle.com  Thu Oct 14 06:13:59 2021
From: dave.kleikamp at oracle.com (Dave Kleikamp)
Date: Thu, 14 Oct 2021 08:13:59 -0500
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <3AB8052D-DD45-478B-85F2-BFBEC1C7E9DF@tuxera.com>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211014062844.GA25448@lst.de>
 <3AB8052D-DD45-478B-85F2-BFBEC1C7E9DF@tuxera.com>
Message-ID: <a5eb3c18-deb2-6539-cc24-57e6d5d3500c@oracle.com>

On 10/14/21 4:32AM, Anton Altaparmakov wrote:
> Hi Christoph,
> 
>> On 14 Oct 2021, at 07:28, Christoph Hellwig <hch at lst.de> wrote:
>>
>> On Wed, Oct 13, 2021 at 07:10:13AM +0200, Christoph Hellwig wrote:
>>> I wondered about adding a helper for looking at the size in byte units
>>> to avoid the SECTOR_SHIFT shifts in various places.  But given that
>>> I could not come up with a good name and block devices fundamentally
>>> work in sector size granularity I decided against that.
>>
>> So it seems like the biggest review feedback is that we should have
>> such a helper.  I think the bdev_size name is the worst as size does
>> not imply a particular unit.  bdev_nr_bytes is a little better but I'm
>> not too happy.  Any other suggestions or strong opinions?
> 
> bdev_byte_size() would seem to address your concerns?
> 
> bdev_nr_bytes() would work though - it is analogous to bdev_nr_sectors() after all.
> 
> No strong opinion here but I do agree with you that bdev_size() is a bad choice for sure.  It is bound to cause bugs down the line when people forget what unit it is in.

I don't really mind bdev_size since it's analogous to i_size, but 
bdev_nr_bytes seems good to me.

Shaggy

> Best regards,
> 
> 	Anton
> 


From hch at lst.de  Thu Oct 14 07:52:05 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 14 Oct 2021 16:52:05 +0200
Subject: RFC: decouple block2mtd from block layer internals
Message-ID: <20211014145206.1488967-1-hch@lst.de>

Hi all,

while looking for abuses of ->bd_inode, block2mtd scored high on the list.
This completely UNTESTED patch tries to move it off that and use the proper
file abstraction instead.  Are there any current users of this code that
could give it a spin?




From hch at lst.de  Thu Oct 14 07:52:06 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 14 Oct 2021 16:52:06 +0200
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <20211014145206.1488967-1-hch@lst.de>
References: <20211014145206.1488967-1-hch@lst.de>
Message-ID: <20211014145206.1488967-2-hch@lst.de>

block2mtd is a bit of a mess as it pokes directly into the block layer
internal page cache.  Switch it to use the proper file abstraction
instead.  Note that this contains a small behavior change in that erase
now unconditionally writes all Fs instead of first scanning for them.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/mtd/devices/block2mtd.c | 203 ++++++++------------------------
 1 file changed, 48 insertions(+), 155 deletions(-)

diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index c08721b11642b..ea8ec9956c3e8 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -34,7 +34,7 @@
 /* Info for the block device */
 struct block2mtd_dev {
 	struct list_head list;
-	struct block_device *blkdev;
+	struct file *file;
 	struct mtd_info mtd;
 	struct mutex write_mutex;
 };
@@ -43,58 +43,35 @@ struct block2mtd_dev {
 /* Static info about the MTD, used in cleanup_module */
 static LIST_HEAD(blkmtd_device_list);
 
-
-static struct page *page_read(struct address_space *mapping, pgoff_t index)
-{
-	return read_mapping_page(mapping, index, NULL);
-}
+static u_long allfs[PAGE_SIZE / sizeof(u_long)] = {
+	[0 ... (PAGE_SIZE / sizeof(u_long)) - 1] = -1UL,
+};
 
 /* erase a specified part of the device */
-static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
-{
-	struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
-	struct page *page;
-	pgoff_t index = to >> PAGE_SHIFT;	// page index
-	int pages = len >> PAGE_SHIFT;
-	u_long *p;
-	u_long *max;
-
-	while (pages) {
-		page = page_read(mapping, index);
-		if (IS_ERR(page))
-			return PTR_ERR(page);
-
-		max = page_address(page) + PAGE_SIZE;
-		for (p=page_address(page); p<max; p++)
-			if (*p != -1UL) {
-				lock_page(page);
-				memset(page_address(page), 0xff, PAGE_SIZE);
-				set_page_dirty(page);
-				unlock_page(page);
-				balance_dirty_pages_ratelimited(mapping);
-				break;
-			}
-
-		put_page(page);
-		pages--;
-		index++;
-	}
-	return 0;
-}
 static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 {
 	struct block2mtd_dev *dev = mtd->priv;
-	size_t from = instr->addr;
-	size_t len = instr->len;
-	int err;
+	loff_t end = instr->addr + instr->len;
+	size_t total_len = instr->len;
+	loff_t from = instr->addr;
+	ssize_t ret;
 
 	mutex_lock(&dev->write_mutex);
-	err = _block2mtd_erase(dev, from, len);
+	do {
+		size_t len = min_t(size_t, total_len, PAGE_SIZE);
+
+		ret = kernel_write(dev->file, allfs, len, &from);
+		if (ret < 0)
+			goto fail;
+		total_len -= ret;
+	} while (from < end);
 	mutex_unlock(&dev->write_mutex);
-	if (err)
-		pr_err("erase failed err = %d\n", err);
 
-	return err;
+	return 0;
+
+fail:
+	pr_err("erase failed err = %zd\n", ret);
+	return ret;
 }
 
 
@@ -102,72 +79,12 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
 		size_t *retlen, u_char *buf)
 {
 	struct block2mtd_dev *dev = mtd->priv;
-	struct page *page;
-	pgoff_t index = from >> PAGE_SHIFT;
-	int offset = from & (PAGE_SIZE-1);
-	int cpylen;
-
-	while (len) {
-		if ((offset + len) > PAGE_SIZE)
-			cpylen = PAGE_SIZE - offset;	// multiple pages
-		else
-			cpylen = len;	// this page
-		len = len - cpylen;
-
-		page = page_read(dev->blkdev->bd_inode->i_mapping, index);
-		if (IS_ERR(page))
-			return PTR_ERR(page);
-
-		memcpy(buf, page_address(page) + offset, cpylen);
-		put_page(page);
-
-		if (retlen)
-			*retlen += cpylen;
-		buf += cpylen;
-		offset = 0;
-		index++;
-	}
-	return 0;
-}
+	ssize_t ret;
 
-
-/* write data to the underlying device */
-static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
-		loff_t to, size_t len, size_t *retlen)
-{
-	struct page *page;
-	struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
-	pgoff_t index = to >> PAGE_SHIFT;	// page index
-	int offset = to & ~PAGE_MASK;	// page offset
-	int cpylen;
-
-	while (len) {
-		if ((offset+len) > PAGE_SIZE)
-			cpylen = PAGE_SIZE - offset;	// multiple pages
-		else
-			cpylen = len;			// this page
-		len = len - cpylen;
-
-		page = page_read(mapping, index);
-		if (IS_ERR(page))
-			return PTR_ERR(page);
-
-		if (memcmp(page_address(page)+offset, buf, cpylen)) {
-			lock_page(page);
-			memcpy(page_address(page) + offset, buf, cpylen);
-			set_page_dirty(page);
-			unlock_page(page);
-			balance_dirty_pages_ratelimited(mapping);
-		}
-		put_page(page);
-
-		if (retlen)
-			*retlen += cpylen;
-
-		buf += cpylen;
-		offset = 0;
-		index++;
-	}
+	ret = kernel_read(dev->file, buf, len, &from);
+	if (ret < 0)
+		return ret;
+	*retlen += ret;
 	return 0;
 }
 
@@ -176,14 +93,17 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
 		size_t *retlen, const u_char *buf)
 {
 	struct block2mtd_dev *dev = mtd->priv;
-	int err;
+	ssize_t ret;
 
 	mutex_lock(&dev->write_mutex);
-	err = _block2mtd_write(dev, buf, to, len, retlen);
+	ret = kernel_write(dev->file, buf, len, &to);
+	if (ret > 0) {
+		*retlen += ret;
+		ret = 0;
+	}
 	mutex_unlock(&dev->write_mutex);
-	if (err > 0)
-		err = 0;
-	return err;
+
+	return ret;
 }
 
 
@@ -191,8 +111,8 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
 static void block2mtd_sync(struct mtd_info *mtd)
 {
 	struct block2mtd_dev *dev = mtd->priv;
-	sync_blockdev(dev->blkdev);
-	return;
+
+	vfs_fsync(dev->file, 1);
 }
 
 
@@ -203,10 +123,9 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 
 	kfree(dev->mtd.name);
 
-	if (dev->blkdev) {
-		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
-					0, -1);
-		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
+	if (dev->file) {
+		vfs_fsync(dev->file, 1);
+		fput(dev->file);
 	}
 
 	kfree(dev);
@@ -216,11 +135,6 @@ static void block2mtd_free_device(struct block2mtd_dev *dev)
 static struct block2mtd_dev *add_device(char *devname, int erase_size,
 		int timeout)
 {
-#ifndef MODULE
-	int i;
-#endif
-	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
-	struct block_device *bdev;
 	struct block2mtd_dev *dev;
 	char *name;
 
@@ -231,45 +145,24 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 	if (!dev)
 		return NULL;
 
-	/* Get a handle on the device */
-	bdev = blkdev_get_by_path(devname, mode, dev);
-
-#ifndef MODULE
-	/*
-	 * We might not have the root device mounted at this point.
-	 * Try to resolve the device name by other means.
-	 */
-	for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
-		dev_t devt;
-
-		if (i)
-			/*
-			 * Calling wait_for_device_probe in the first loop
-			 * was not enough, sleep for a bit in subsequent
-			 * go-arounds.
-			 */
-			msleep(1000);
-		wait_for_device_probe();
-
-		devt = name_to_dev_t(devname);
-		if (!devt)
-			continue;
-		bdev = blkdev_get_by_dev(devt, mode, dev);
+	dev->file = filp_open(devname, O_RDWR | O_EXCL, 0);
+	if (IS_ERR(dev->file)) {
+		dev->file = NULL;
+		pr_err("error: cannot open device %s\n", devname);
+		goto err_free_block2mtd;
 	}
-#endif
 
-	if (IS_ERR(bdev)) {
+	if (!S_ISBLK(file_inode(dev->file)->i_mode)) {
 		pr_err("error: cannot open device %s\n", devname);
 		goto err_free_block2mtd;
 	}
-	dev->blkdev = bdev;
 
-	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+	if (MAJOR(file_inode(dev->file)->i_rdev) == MTD_BLOCK_MAJOR) {
 		pr_err("attempting to use an MTD device as a block device\n");
 		goto err_free_block2mtd;
 	}
 
-	if ((long)dev->blkdev->bd_inode->i_size % erase_size) {
+	if ((long)i_size_read(dev->file->f_mapping->host) % erase_size) {
 		pr_err("erasesize must be a divisor of device size\n");
 		goto err_free_block2mtd;
 	}
@@ -284,7 +177,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size,
 
 	dev->mtd.name = name;
 
-	dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
+	dev->mtd.size = i_size_read(dev->file->f_mapping->host) & PAGE_MASK;
 	dev->mtd.erasesize = erase_size;
 	dev->mtd.writesize = 1;
 	dev->mtd.writebufsize = PAGE_SIZE;
-- 
2.30.2



From keescook at chromium.org  Thu Oct 14 08:14:31 2021
From: keescook at chromium.org (Kees Cook)
Date: Thu, 14 Oct 2021 08:14:31 -0700
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <a5eb3c18-deb2-6539-cc24-57e6d5d3500c@oracle.com>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211014062844.GA25448@lst.de>
 <3AB8052D-DD45-478B-85F2-BFBEC1C7E9DF@tuxera.com>
 <a5eb3c18-deb2-6539-cc24-57e6d5d3500c@oracle.com>
Message-ID: <202110140813.44C95229@keescook>

On Thu, Oct 14, 2021 at 08:13:59AM -0500, Dave Kleikamp wrote:
> On 10/14/21 4:32AM, Anton Altaparmakov wrote:
> > Hi Christoph,
> > 
> > > On 14 Oct 2021, at 07:28, Christoph Hellwig <hch at lst.de> wrote:
> > > 
> > > On Wed, Oct 13, 2021 at 07:10:13AM +0200, Christoph Hellwig wrote:
> > > > I wondered about adding a helper for looking at the size in byte units
> > > > to avoid the SECTOR_SHIFT shifts in various places.  But given that
> > > > I could not come up with a good name and block devices fundamentally
> > > > work in sector size granularity I decided against that.
> > > 
> > > So it seems like the biggest review feedback is that we should have
> > > such a helper.  I think the bdev_size name is the worst as size does
> > > not imply a particular unit.  bdev_nr_bytes is a little better but I'm
> > > not too happy.  Any other suggestions or strong opinions?
> > 
> > bdev_byte_size() would seem to address your concerns?
> > 
> > bdev_nr_bytes() would work though - it is analogous to bdev_nr_sectors() after all.
> > 
> > No strong opinion here but I do agree with you that bdev_size() is a bad choice for sure.  It is bound to cause bugs down the line when people forget what unit it is in.
> 
> I don't really mind bdev_size since it's analogous to i_size, but
> bdev_nr_bytes seems good to me.

I much prefer bdev_nr_bytes(), as "size" has no units.

-- 
Kees Cook


From antlists at youngman.org.uk  Thu Oct 14 08:35:49 2021
From: antlists at youngman.org.uk (Wol)
Date: Thu, 14 Oct 2021 16:35:49 +0100
Subject: don't use ->bd_inode to access the block device size
In-Reply-To: <202110140813.44C95229@keescook>
References: <20211013051042.1065752-1-hch@lst.de>
 <20211014062844.GA25448@lst.de>
 <3AB8052D-DD45-478B-85F2-BFBEC1C7E9DF@tuxera.com>
 <a5eb3c18-deb2-6539-cc24-57e6d5d3500c@oracle.com>
 <202110140813.44C95229@keescook>
Message-ID: <e3d2f358-be1a-3413-fdb8-2e86718cde3e@youngman.org.uk>

On 14/10/2021 16:14, Kees Cook wrote:
>> I don't really mind bdev_size since it's analogous to i_size, but
>> bdev_nr_bytes seems good to me.

> I much prefer bdev_nr_bytes(), as "size" has no units.

Does it mean size IN bytes, or size OF A byte? :-)

Cheers,
Wol


From mauro.lima at eclypsium.com  Thu Oct 14 11:54:09 2021
From: mauro.lima at eclypsium.com (Mauro Lima)
Date: Thu, 14 Oct 2021 15:54:09 -0300
Subject: [PATCH v3 0/3] mtd: spi-nor / spi / MFD: Convert intel-spi to SPI
 MEM
In-Reply-To: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
Message-ID: <CAArk9MOscFASjen3=6VmUwkMZooPJ3RqrenNiQ4QVmp_rEoL2Q@mail.gmail.com>

Hi all,

On Wed, Oct 13, 2021 at 8:44 AM Mika Westerberg
<mika.westerberg at linux.intel.com> wrote:
>
> Hi all,
>
> Based on discussion on the patch I sent some time ago here:
>
>   http://lists.infradead.org/pipermail/linux-mtd/2021-June/086867.html
>
> it turns out that the preferred way to deal with the SPI flash controller
> drivers is through SPI MEM which is part of Linux SPI subsystem.
>
> This series does that for the intel-spi driver. This also renames the
> driver to follow the convention used in the SPI subsystem. The first patch
> improves the write protection handling to be slightly more safer. The
> following two patches do the conversion itself. Note the Intel SPI flash
> controller only allows commands such as read, write and so on and it
> internally uses whatever addressing etc. it figured from the SFDP on the
> flash device.
>
> Previous versions of the patch series can be found here:
>
>   v2: https://lore.kernel.org/linux-mtd/20211007112132.30934-1-mika.westerberg at linux.intel.com/
>   v1: https://lore.kernel.org/linux-mtd/20210930100719.2176-1-mika.westerberg at linux.intel.com/
>
> Changes from v2:
>
>   * Added tag from Andy
>   * Check buswidth in intel_spi_supports_mem_op() and return false if octal
>     mode is asked. The Intel controllers support buswidths 1-4 but this is
>     not exposed to software. It figures this itself through SFDP tables.
>   * In case of software sequencer, support same opcodes than we support with
>     the hardware sequencer if found in the opcodes table.
>
> Changes from v1:
>
>   * Arrange dependencies in Kconfig entries the same way in both glue
>     drivers.
>   * Added empty lines between different subsystem includes.
>   * dev_err() to single line
>   * Return intel_spi_sw_cycle() directly in intel_spi_erase().
>   * Drop redundant elses.
>   * Fixed typo in the commit message of the patch 3/3.
>
> Mika Westerberg (3):
>   mtd: spi-nor: intel-spi: Disable write protection only if asked
>   mtd: spi-nor: intel-spi: Convert to SPI MEM
>   Documentation / MTD: Rename the intel-spi driver
>
>  Documentation/driver-api/mtd/index.rst        |   2 +-
>  .../mtd/{intel-spi.rst => spi-intel.rst}      |   8 +-
>  drivers/mfd/lpc_ich.c                         |  59 ++-
>  drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
>  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
>  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
>  drivers/spi/Kconfig                           |  39 ++
>  drivers/spi/Makefile                          |   3 +
>  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  49 ++-
>  .../spi-intel-platform.c}                     |  21 +-
>  .../intel-spi.c => spi/spi-intel.c}           | 357 +++++++++++-------
>  drivers/spi/spi-intel.h                       |  19 +
>  include/linux/mfd/lpc_ich.h                   |   2 +-
>  .../x86/{intel-spi.h => spi-intel.h}          |  12 +-
>  14 files changed, 367 insertions(+), 264 deletions(-)
>  rename Documentation/driver-api/mtd/{intel-spi.rst => spi-intel.rst} (94%)
>  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (84%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (77%)
>  create mode 100644 drivers/spi/spi-intel.h
>  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (64%)
>
> --
> 2.33.0
>
$ ./scripts/checkpatch.pl --file --strict drivers/spi/spi-intel.c
CHECK: Alignment should match open parenthesis
#215: FILE: drivers/spi/spi-intel.c:215:
+ dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x [%c%c]\n",
+ i, base << 12, (limit << 12) | 0xfff,

CHECK: Alignment should match open parenthesis
#232: FILE: drivers/spi/spi-intel.c:232:
+ dev_dbg(ispi->dev, " %02d base: 0x%08x limit: 0x%08x\n",
+ i, base << 12, (limit << 12) | 0xfff);

CHECK: Comparison to NULL could be written "!ispi->sregs"
#378: FILE: drivers/spi/spi-intel.c:378:
+ if (ispi->sregs == NULL && (ispi->swseq_reg || ispi->swseq_erase)) {

CHECK: Blank lines aren't necessary before a close brace '}'
#534: FILE: drivers/spi/spi-intel.c:534:
+
+ }

Beside these checks,
Reviewed-by: Mauro Lima <mauro.lima at eclypsium.com>
Thanks


From richard at nod.at  Thu Oct 14 12:28:19 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 14 Oct 2021 21:28:19 +0200 (CEST)
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <20211014145206.1488967-2-hch@lst.de>
References: <20211014145206.1488967-1-hch@lst.de>
 <20211014145206.1488967-2-hch@lst.de>
Message-ID: <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "hch" <hch at lst.de>
> An: joern at lazybastard.org, "Miquel Raynal" <miquel.raynal at bootlin.com>, "richard" <richard at nod.at>, "Vignesh
> Raghavendra" <vigneshr at ti.com>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>
> Gesendet: Donnerstag, 14. Oktober 2021 16:52:06
> Betreff: [PATCH] mtd/block2mtd: don't poke into block layer internals

> block2mtd is a bit of a mess as it pokes directly into the block layer
> internal page cache.  Switch it to use the proper file abstraction

Nice cleanup! :-)

I guess the cleanup can also be applied to nandsim. While it does not touch
the block layer, it still messes with the page cache.

> instead.  Note that this contains a small behavior change in that erase
> now unconditionally writes all Fs instead of first scanning for them.

Unless you have a strong opinoin I'd like to keep the scanning.
The original use case of block2mtd is using Compact Flash (ATA)
as MTD. Some of this devices are super stupid and I fear the 0xFF scanning
is here to avoid programming 0xFF bytes into the NAND.
Just to be on the safe side...

> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---
> drivers/mtd/devices/block2mtd.c | 203 ++++++++------------------------
> 1 file changed, 48 insertions(+), 155 deletions(-)
> 
> diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
> index c08721b11642b..ea8ec9956c3e8 100644
> --- a/drivers/mtd/devices/block2mtd.c
> +++ b/drivers/mtd/devices/block2mtd.c
> @@ -34,7 +34,7 @@
> /* Info for the block device */
> struct block2mtd_dev {
> 	struct list_head list;
> -	struct block_device *blkdev;
> +	struct file *file;
> 	struct mtd_info mtd;
> 	struct mutex write_mutex;
> };
> @@ -43,58 +43,35 @@ struct block2mtd_dev {
> /* Static info about the MTD, used in cleanup_module */
> static LIST_HEAD(blkmtd_device_list);
> 
> -
> -static struct page *page_read(struct address_space *mapping, pgoff_t index)
> -{
> -	return read_mapping_page(mapping, index, NULL);
> -}
> +static u_long allfs[PAGE_SIZE / sizeof(u_long)] = {
> +	[0 ... (PAGE_SIZE / sizeof(u_long)) - 1] = -1UL,
> +};
> 
> /* erase a specified part of the device */
> -static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
> -{
> -	struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
> -	struct page *page;
> -	pgoff_t index = to >> PAGE_SHIFT;	// page index
> -	int pages = len >> PAGE_SHIFT;
> -	u_long *p;
> -	u_long *max;
> -
> -	while (pages) {
> -		page = page_read(mapping, index);
> -		if (IS_ERR(page))
> -			return PTR_ERR(page);
> -
> -		max = page_address(page) + PAGE_SIZE;
> -		for (p=page_address(page); p<max; p++)
> -			if (*p != -1UL) {
> -				lock_page(page);
> -				memset(page_address(page), 0xff, PAGE_SIZE);
> -				set_page_dirty(page);
> -				unlock_page(page);
> -				balance_dirty_pages_ratelimited(mapping);
> -				break;
> -			}
> -
> -		put_page(page);
> -		pages--;
> -		index++;
> -	}
> -	return 0;
> -}
> static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
> {
> 	struct block2mtd_dev *dev = mtd->priv;
> -	size_t from = instr->addr;
> -	size_t len = instr->len;
> -	int err;
> +	loff_t end = instr->addr + instr->len;
> +	size_t total_len = instr->len;
> +	loff_t from = instr->addr;
> +	ssize_t ret;
> 
> 	mutex_lock(&dev->write_mutex);
> -	err = _block2mtd_erase(dev, from, len);
> +	do {
> +		size_t len = min_t(size_t, total_len, PAGE_SIZE);
> +
> +		ret = kernel_write(dev->file, allfs, len, &from);
> +		if (ret < 0)
> +			goto fail;
> +		total_len -= ret;
> +	} while (from < end);
> 	mutex_unlock(&dev->write_mutex);
> -	if (err)
> -		pr_err("erase failed err = %d\n", err);
> 
> -	return err;
> +	return 0;
> +
> +fail:
> +	pr_err("erase failed err = %zd\n", ret);
> +	return ret;
> }
> 
> 
> @@ -102,72 +79,12 @@ static int block2mtd_read(struct mtd_info *mtd, loff_t
> from, size_t len,
> 		size_t *retlen, u_char *buf)
> {
> 	struct block2mtd_dev *dev = mtd->priv;
> -	struct page *page;
> -	pgoff_t index = from >> PAGE_SHIFT;
> -	int offset = from & (PAGE_SIZE-1);
> -	int cpylen;
> -
> -	while (len) {
> -		if ((offset + len) > PAGE_SIZE)
> -			cpylen = PAGE_SIZE - offset;	// multiple pages
> -		else
> -			cpylen = len;	// this page
> -		len = len - cpylen;
> -
> -		page = page_read(dev->blkdev->bd_inode->i_mapping, index);
> -		if (IS_ERR(page))
> -			return PTR_ERR(page);
> -
> -		memcpy(buf, page_address(page) + offset, cpylen);
> -		put_page(page);
> -
> -		if (retlen)
> -			*retlen += cpylen;
> -		buf += cpylen;
> -		offset = 0;
> -		index++;
> -	}
> -	return 0;
> -}
> +	ssize_t ret;
> 
> -
> -/* write data to the underlying device */
> -static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
> -		loff_t to, size_t len, size_t *retlen)
> -{
> -	struct page *page;
> -	struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
> -	pgoff_t index = to >> PAGE_SHIFT;	// page index
> -	int offset = to & ~PAGE_MASK;	// page offset
> -	int cpylen;
> -
> -	while (len) {
> -		if ((offset+len) > PAGE_SIZE)
> -			cpylen = PAGE_SIZE - offset;	// multiple pages
> -		else
> -			cpylen = len;			// this page
> -		len = len - cpylen;
> -
> -		page = page_read(mapping, index);
> -		if (IS_ERR(page))
> -			return PTR_ERR(page);
> -
> -		if (memcmp(page_address(page)+offset, buf, cpylen)) {
> -			lock_page(page);
> -			memcpy(page_address(page) + offset, buf, cpylen);
> -			set_page_dirty(page);
> -			unlock_page(page);
> -			balance_dirty_pages_ratelimited(mapping);
> -		}
> -		put_page(page);
> -
> -		if (retlen)
> -			*retlen += cpylen;
> -
> -		buf += cpylen;
> -		offset = 0;
> -		index++;
> -	}
> +	ret = kernel_read(dev->file, buf, len, &from);
> +	if (ret < 0)
> +		return ret;
> +	*retlen += ret;
> 	return 0;
> }
> 
> @@ -176,14 +93,17 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to,
> size_t len,
> 		size_t *retlen, const u_char *buf)
> {
> 	struct block2mtd_dev *dev = mtd->priv;
> -	int err;
> +	ssize_t ret;
> 
> 	mutex_lock(&dev->write_mutex);
> -	err = _block2mtd_write(dev, buf, to, len, retlen);
> +	ret = kernel_write(dev->file, buf, len, &to);
> +	if (ret > 0) {
> +		*retlen += ret;
> +		ret = 0;
> +	}
> 	mutex_unlock(&dev->write_mutex);
> -	if (err > 0)
> -		err = 0;
> -	return err;
> +
> +	return ret;
> }
> 
> 
> @@ -191,8 +111,8 @@ static int block2mtd_write(struct mtd_info *mtd, loff_t to,
> size_t len,
> static void block2mtd_sync(struct mtd_info *mtd)
> {
> 	struct block2mtd_dev *dev = mtd->priv;
> -	sync_blockdev(dev->blkdev);
> -	return;
> +
> +	vfs_fsync(dev->file, 1);
> }
> 
> 
> @@ -203,10 +123,9 @@ static void block2mtd_free_device(struct block2mtd_dev
> *dev)
> 
> 	kfree(dev->mtd.name);
> 
> -	if (dev->blkdev) {
> -		invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
> -					0, -1);
> -		blkdev_put(dev->blkdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
> +	if (dev->file) {
> +		vfs_fsync(dev->file, 1);
> +		fput(dev->file);
> 	}
> 
> 	kfree(dev);
> @@ -216,11 +135,6 @@ static void block2mtd_free_device(struct block2mtd_dev
> *dev)
> static struct block2mtd_dev *add_device(char *devname, int erase_size,
> 		int timeout)
> {
> -#ifndef MODULE
> -	int i;
> -#endif
> -	const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL;
> -	struct block_device *bdev;
> 	struct block2mtd_dev *dev;
> 	char *name;
> 
> @@ -231,45 +145,24 @@ static struct block2mtd_dev *add_device(char *devname, int
> erase_size,
> 	if (!dev)
> 		return NULL;
> 
> -	/* Get a handle on the device */
> -	bdev = blkdev_get_by_path(devname, mode, dev);
> -
> -#ifndef MODULE
> -	/*
> -	 * We might not have the root device mounted at this point.
> -	 * Try to resolve the device name by other means.
> -	 */
> -	for (i = 0; IS_ERR(bdev) && i <= timeout; i++) {
> -		dev_t devt;
> -
> -		if (i)
> -			/*
> -			 * Calling wait_for_device_probe in the first loop
> -			 * was not enough, sleep for a bit in subsequent
> -			 * go-arounds.
> -			 */
> -			msleep(1000);
> -		wait_for_device_probe();
> -
> -		devt = name_to_dev_t(devname);
> -		if (!devt)
> -			continue;
> -		bdev = blkdev_get_by_dev(devt, mode, dev);
> +	dev->file = filp_open(devname, O_RDWR | O_EXCL, 0);
> +	if (IS_ERR(dev->file)) {
> +		dev->file = NULL;
> +		pr_err("error: cannot open device %s\n", devname);
> +		goto err_free_block2mtd;
> 	}
> -#endif
> 
> -	if (IS_ERR(bdev)) {
> +	if (!S_ISBLK(file_inode(dev->file)->i_mode)) {

I think we can actually weaken that check to allow regular files too.
Then one can directly use a file as backend. These days people use block2mtd
sometimes with a file backend via a loop device.

What do you think?

Thanks,
//richard

P.s: While reading this driver I found another issue. There is no way to remove an MTD at runtime.
Miquel, what do you think? Shall we limit block2mtd to one MTD?
The current interface via module parameters is horrible.


From zev at bewilderbeest.net  Thu Oct 14 13:39:52 2021
From: zev at bewilderbeest.net (Zev Weiss)
Date: Thu, 14 Oct 2021 13:39:52 -0700
Subject: [PATCH] mtd: core: don't remove debugfs directory if device is in use
Message-ID: <20211014203953.5424-1-zev@bewilderbeest.net>

Previously, if del_mtd_device() failed with -EBUSY due to a non-zero
usecount, a subsequent call to attempt the deletion again would try to
remove a debugfs directory that had already been removed and panic.
With this change the second call can instead proceed safely.

Fixes: e8e3edb95ce6 ("mtd: create per-device and module-scope debugfs entries")
Signed-off-by: Zev Weiss <zev at bewilderbeest.net>
---
 drivers/mtd/mtdcore.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index e22266f63ae9..0a0fca737d43 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -724,8 +724,6 @@ int del_mtd_device(struct mtd_info *mtd)
 
 	mutex_lock(&mtd_table_mutex);
 
-	debugfs_remove_recursive(mtd->dbg.dfs_dir);
-
 	if (idr_find(&mtd_idr, mtd->index) != mtd) {
 		ret = -ENODEV;
 		goto out_error;
@@ -741,6 +739,8 @@ int del_mtd_device(struct mtd_info *mtd)
 		       mtd->index, mtd->name, mtd->usecount);
 		ret = -EBUSY;
 	} else {
+		debugfs_remove_recursive(mtd->dbg.dfs_dir);
+
 		/* Try to remove the NVMEM provider */
 		if (mtd->nvmem)
 			nvmem_unregister(mtd->nvmem);
-- 
2.33.0



From miquel.raynal at bootlin.com  Thu Oct 14 23:13:13 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 08:13:13 +0200
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211009184952.24591-3-paul@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
Message-ID: <20211015081313.60018976@xps13>

Hi Paul,

paul at crapouillou.net wrote on Sat,  9 Oct 2021 20:49:51 +0200:

> Move the function nand_read_page_hwecc_oob_first() (previously
> nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and export it
> as a GPL symbol, so that it can be used by more modules.
> 
> Cc: <stable at vger.kernel.org> # v5.2
> Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
> Signed-off-by: Paul Cercueil <paul at crapouillou.net>
> ---
>  drivers/mtd/nand/raw/davinci_nand.c | 70 +----------------------------
>  drivers/mtd/nand/raw/nand_base.c    | 69 ++++++++++++++++++++++++++++
>  include/linux/mtd/rawnand.h         |  2 +
>  3 files changed, 72 insertions(+), 69 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
> index 89de24d3bb7a..45fec8c192ab 100644
> --- a/drivers/mtd/nand/raw/davinci_nand.c
> +++ b/drivers/mtd/nand/raw/davinci_nand.c
> @@ -371,74 +371,6 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
>  	return corrected;
>  }
>  
> -/**
> - * nand_read_page_hwecc_oob_first - hw ecc, read oob first
> - * @chip: nand chip info structure
> - * @buf: buffer to store read data
> - * @oob_required: caller requires OOB data read to chip->oob_poi
> - * @page: page number to read
> - *
> - * Hardware ECC for large page chips, require OOB to be read first. For this
> - * ECC mode, the write_page method is re-used from ECC_HW. These methods
> - * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
> - * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
> - * the data area, by overwriting the NAND manufacturer bad block markings.
> - */
> -static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
> -						  uint8_t *buf,
> -						  int oob_required, int page)
> -{
> -	struct mtd_info *mtd = nand_to_mtd(chip);
> -	int i, eccsize = chip->ecc.size, ret;
> -	int eccbytes = chip->ecc.bytes;
> -	int eccsteps = chip->ecc.steps;
> -	uint8_t *p = buf;
> -	uint8_t *ecc_code = chip->ecc.code_buf;
> -	unsigned int max_bitflips = 0;
> -
> -	/* Read the OOB area first */
> -	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
> -	if (ret)
> -		return ret;
> -
> -	ret = nand_read_page_op(chip, page, 0, NULL, 0);
> -	if (ret)
> -		return ret;
> -
> -	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
> -					 chip->ecc.total);
> -	if (ret)
> -		return ret;
> -
> -	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
> -		int stat;
> -
> -		chip->ecc.hwctl(chip, NAND_ECC_READ);
> -
> -		ret = nand_read_data_op(chip, p, eccsize, false, false);
> -		if (ret)
> -			return ret;
> -
> -		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
> -		if (stat == -EBADMSG &&
> -		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
> -			/* check for empty pages with bitflips */
> -			stat = nand_check_erased_ecc_chunk(p, eccsize,
> -							   &ecc_code[i],
> -							   eccbytes, NULL, 0,
> -							   chip->ecc.strength);
> -		}
> -
> -		if (stat < 0) {
> -			mtd->ecc_stats.failed++;
> -		} else {
> -			mtd->ecc_stats.corrected += stat;
> -			max_bitflips = max_t(unsigned int, max_bitflips, stat);
> -		}
> -	}
> -	return max_bitflips;
> -}
> -
>  /*----------------------------------------------------------------------*/
>  
>  /* An ECC layout for using 4-bit ECC with small-page flash, storing
> @@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
>  			} else if (chunks == 4 || chunks == 8) {
>  				mtd_set_ooblayout(mtd,
>  						  nand_get_large_page_ooblayout());
> -				chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
> +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
>  			} else {
>  				return -EIO;
>  			}
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..cb5f343b9fa2 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
>  	return max_bitflips;
>  }
>  
> +/**
> + * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC
> + *                                  data read from OOB area
> + * @chip: nand chip info structure
> + * @buf: buffer to store read data
> + * @oob_required: caller requires OOB data read to chip->oob_poi
> + * @page: page number to read
> + *
> + * Hardware ECC for large page chips, require OOB to be read first. For this

requires

With this ECC configuration?

> + * ECC mode, the write_page method is re-used from ECC_HW. These methods

I do not understand this sentence nor the next one about syndrome. I
believe it is related to your engine and should not leak into the core.

> + * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
> + * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
> + * the data area, by overwriting the NAND manufacturer bad block markings.

That's a sentence I don't like. What do you mean exactly?

What "Infix ECC" scheme is?

Do you mean that unlike the syndrome  mode it *does not* overwrite the
BBM ?

> + */
> +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
> +				   int oob_required, int page)
> +{
> +	struct mtd_info *mtd = nand_to_mtd(chip);
> +	int i, eccsize = chip->ecc.size, ret;
> +	int eccbytes = chip->ecc.bytes;
> +	int eccsteps = chip->ecc.steps;
> +	uint8_t *p = buf;
> +	uint8_t *ecc_code = chip->ecc.code_buf;
> +	unsigned int max_bitflips = 0;
> +
> +	/* Read the OOB area first */
> +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
> +	if (ret)
> +		return ret;
> +
> +	ret = nand_read_page_op(chip, page, 0, NULL, 0);

Definitely not, your are requesting the chip to do the read_page
operation twice. You only need a nand_change_read_column I believe.

> +	if (ret)
> +		return ret;
> +
> +	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
> +					 chip->ecc.total);
> +	if (ret)
> +		return ret;
> +
> +	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
> +		int stat;
> +
> +		chip->ecc.hwctl(chip, NAND_ECC_READ);
> +
> +		ret = nand_read_data_op(chip, p, eccsize, false, false);
> +		if (ret)
> +			return ret;
> +
> +		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
> +		if (stat == -EBADMSG &&
> +		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
> +			/* check for empty pages with bitflips */
> +			stat = nand_check_erased_ecc_chunk(p, eccsize,
> +							   &ecc_code[i],
> +							   eccbytes, NULL, 0,
> +							   chip->ecc.strength);
> +		}
> +
> +		if (stat < 0) {
> +			mtd->ecc_stats.failed++;
> +		} else {
> +			mtd->ecc_stats.corrected += stat;
> +			max_bitflips = max_t(unsigned int, max_bitflips, stat);
> +		}
> +	}
> +	return max_bitflips;
> +}
> +EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
> +
>  /**
>   * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
>   * @chip: nand chip info structure
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index b2f9dd3cbd69..5b88cd51fadb 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
>  		      bool force_8bit, bool check_only);
>  int nand_write_data_op(struct nand_chip *chip, const void *buf,
>  		       unsigned int len, bool force_8bit);
> +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
> +				   int oob_required, int page);

You certainly want to add this symbol closer to the other read/write
page helpers?

>  
>  /* Scan and identify a NAND device */
>  int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,


Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Thu Oct 14 23:14:47 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 08:14:47 +0200
Subject: [PATCH 3/3] mtd: rawnand/ingenic: JZ4740 needs 'oob_first' read
 page function
In-Reply-To: <20211009184952.24591-4-paul@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-4-paul@crapouillou.net>
Message-ID: <20211015081447.25836fc7@xps13>

Hi Paul,

paul at crapouillou.net wrote on Sat,  9 Oct 2021 20:49:52 +0200:

> The ECC engine on the JZ4740 SoC requires the ECC data to be read before
> the page; using the default page reading function does not work. Indeed,
> the old JZ4740 NAND driver (removed in 5.4) did use the 'OOB first' flag
> that existed back then.
> 
> Use the newly created nand_read_page_hwecc_oob_first() to address this
> issue.
> 
> This issue was not found when the new ingenic-nand driver was developed,
> most likely because the Device Tree used had the nand-ecc-mode set to
> "hw_oob_first", which seems to not be supported anymore.

I would rename both the boolean and the helper "*_access_oob_first"
which seems more precise.

> 
> Cc: <stable at vger.kernel.org> # v5.2
> Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
> Signed-off-by: Paul Cercueil <paul at crapouillou.net>
> ---
>  drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
> index 0e9d426fe4f2..b18861bdcdc8 100644
> --- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
> +++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
> @@ -32,6 +32,7 @@ struct jz_soc_info {
>  	unsigned long addr_offset;
>  	unsigned long cmd_offset;
>  	const struct mtd_ooblayout_ops *oob_layout;
> +	bool oob_first;
>  };
>  
>  struct ingenic_nand_cs {
> @@ -240,6 +241,9 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip)
>  	if (chip->bbt_options & NAND_BBT_USE_FLASH)
>  		chip->bbt_options |= NAND_BBT_NO_OOB;
>  
> +	if (nfc->soc_info->oob_first)
> +		chip->ecc.read_page = nand_read_page_hwecc_oob_first;
> +
>  	/* For legacy reasons we use a different layout on the qi,lb60 board. */
>  	if (of_machine_is_compatible("qi,lb60"))
>  		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
> @@ -534,6 +538,7 @@ static const struct jz_soc_info jz4740_soc_info = {
>  	.data_offset = 0x00000000,
>  	.cmd_offset = 0x00008000,
>  	.addr_offset = 0x00010000,
> +	.oob_first = true,
>  };
>  
>  static const struct jz_soc_info jz4725b_soc_info = {


Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Thu Oct 14 23:22:06 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 08:22:06 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211011160546.707b737b@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
Message-ID: <20211015082206.244a2316@xps13>

Hi Sean,

boris.brezillon at collabora.com wrote on Mon, 11 Oct 2021 16:05:46 +0200:

> On Mon, 11 Oct 2021 13:52:50 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > Follow-up on discussion in https://lkml.org/lkml/2021/10/4/41
> > 
> > Changes since from rfc v1/v2:
> >  - added access protection for all device access hooks in mtd_info.
> >  - added Suggested-by to [1/3] patch.
> >  - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
> >    from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
> >    to be blamed.
> >  - tested on a kernel with LOCKDEP enabled.
> > 
> > @Miquel: I havn't covered every ioctl, to me it looks like they havn't
> > direct device access.

Yes indeed it looks like they re-use most of the mtdcore.c functions,
so it should be fine.

> > One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> > initialized. Seems cumbersome to have every mtd/nand driver to call
> > init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> > to mtd_set_dev_defaults() before nand_create_bbt()?  
> 
> I have a nasty trick for that one, but I'm not sure Miquel will like it
> (actually, I don't like it either, but it's so simple compared to the
> other options we have that I'm tempted to go for this approach until
> someone has time to invest in a cleaner solution :-)):
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..a9ac2d528a4d 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
>         mtd->_sync = nand_sync;
>         mtd->_lock = nand_lock;
>         mtd->_unlock = nand_unlock;
> -       mtd->_suspend = nand_suspend;
> -       mtd->_resume = nand_resume;
>         mtd->_reboot = nand_shutdown;
>         mtd->_block_isreserved = nand_block_isreserved;
>         mtd->_block_isbad = nand_block_isbad;
> @@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
>         if (ret)
>                 goto err_free_secure_regions;
>  
> +       /*
> +        * Populate the suspend/resume hooks after the BBT has been scanned to
> +        * avoid using the suspend lock and resume waitqueue which are only
> +        * initialized when mtd_device_register() is called.
> +        */
> +       mtd->_suspend = nand_suspend;
> +       mtd->_resume = nand_resume;
>         return 0;

I'm fine with this as long as it is documented for now.

Thanks,
Miqu?l


From hch at lst.de  Thu Oct 14 23:28:09 2021
From: hch at lst.de (hch)
Date: Fri, 15 Oct 2021 08:28:09 +0200
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
References: <20211014145206.1488967-1-hch@lst.de>
 <20211014145206.1488967-2-hch@lst.de>
 <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
Message-ID: <20211015062809.GA29769@lst.de>

On Thu, Oct 14, 2021 at 09:28:19PM +0200, Richard Weinberger wrote:
> > instead.  Note that this contains a small behavior change in that erase
> > now unconditionally writes all Fs instead of first scanning for them.
> 
> Unless you have a strong opinoin I'd like to keep the scanning.
> The original use case of block2mtd is using Compact Flash (ATA)
> as MTD. Some of this devices are super stupid and I fear the 0xFF scanning
> is here to avoid programming 0xFF bytes into the NAND.
> Just to be on the safe side...

Hmm.  Doing the right first is quite a bit of overhead, especially as
unlike the direct page cache access we can't just poke into the page
without copying it.

> I think we can actually weaken that check to allow regular files too.
> Then one can directly use a file as backend. These days people use block2mtd
> sometimes with a file backend via a loop device.

Yes, a file backend will work just fine.

> P.s: While reading this driver I found another issue. There is no way to remove an MTD at runtime.
> Miquel, what do you think? Shall we limit block2mtd to one MTD?
> The current interface via module parameters is horrible.
---end quoted text---


From miquel.raynal at bootlin.com  Thu Oct 14 23:53:54 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 08:53:54 +0200
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <20211015062809.GA29769@lst.de>
References: <20211014145206.1488967-1-hch@lst.de>
 <20211014145206.1488967-2-hch@lst.de>
 <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
 <20211015062809.GA29769@lst.de>
Message-ID: <20211015085354.5f841f64@xps13>

Hi Richard,

hch at lst.de wrote on Fri, 15 Oct 2021 08:28:09 +0200:

> On Thu, Oct 14, 2021 at 09:28:19PM +0200, Richard Weinberger wrote:
> > > instead.  Note that this contains a small behavior change in that erase
> > > now unconditionally writes all Fs instead of first scanning for them.  
> > 
> > Unless you have a strong opinoin I'd like to keep the scanning.
> > The original use case of block2mtd is using Compact Flash (ATA)
> > as MTD. Some of this devices are super stupid and I fear the 0xFF scanning
> > is here to avoid programming 0xFF bytes into the NAND.
> > Just to be on the safe side...  
> 
> Hmm.  Doing the right first is quite a bit of overhead, especially as
> unlike the direct page cache access we can't just poke into the page
> without copying it.
> 
> > I think we can actually weaken that check to allow regular files too.
> > Then one can directly use a file as backend. These days people use block2mtd
> > sometimes with a file backend via a loop device.  
> 
> Yes, a file backend will work just fine.
> 
> > P.s: While reading this driver I found another issue. There is no way to remove an MTD at runtime.
> > Miquel, what do you think? Shall we limit block2mtd to one MTD?
> > The current interface via module parameters is horrible.

I believe if we do this we will someday find someone who *wants*
several block2mtd devices and we'll be back to today's situation.

What about an extra parameter where you provide the mtd device to
remove it? Or perhaps a new interface if block2mtd is actually used
in another pseudo-fs? (like configfs or perhaps debugfs if this is
suitable)

Thanks,
Miqu?l


From boris.brezillon at collabora.com  Thu Oct 14 23:55:11 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Fri, 15 Oct 2021 08:55:11 +0200
Subject: [PATCH 1/3] mtd: core: protect access to MTD devices while in
 suspend
In-Reply-To: <20211011115253.38497-2-sean@geanix.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011115253.38497-2-sean@geanix.com>
Message-ID: <20211015085511.0e2ac916@collabora.com>

On Mon, 11 Oct 2021 13:52:51 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

>  struct mtd_info {
> @@ -476,10 +478,49 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
>  	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
>  }
>  
> +static inline void mtd_start_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);

mtd_start_{access,end}() should only be called on master devices, so I
guess you can drop the mtd_get_master() call and use mtd directly.
Maybe add a WARN_ON_ONCE(mtd != mtd_get_master(mtd)) so we can
easily catch silly mistakes.

> +
> +	/*
> +	 * Don't take the suspend_lock on devices that don't
> +	 * implement the suspend hook. Otherwise, lockdep will
> +	 * complain about nested locks when trying to suspend MTD
> +	 * partitions or MTD devices created by gluebi which are
> +	 * backed by real devices.
> +	 */
> +	if (!master->_suspend)
> +		return;
> +
> +	/*
> +	 * Wait until the device is resumed. Should we have a
> +	 * non-blocking mode here?
> +	 */
> +	while (1) {
> +		down_read(&master->master.suspend_lock);
> +		if (!master->master.suspended)
> +			return;
> +
> +		up_read(&master->master.suspend_lock);
> +		wait_event(master->master.resume_wq, master->master.suspended == 0);
> +	}
> +}
> +
> +static inline void mtd_end_access(struct mtd_info *mtd)
> +{
> +	struct mtd_info *master = mtd_get_master(mtd);
> +
> +	if (!master->_suspend)
> +		return;
> +
> +	up_read(&master->master.suspend_lock);
> +}
> +
>  static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
>  				     loff_t ofs, size_t len)
>  {
>  	struct mtd_info *master = mtd_get_master(mtd);
> +	int ret;
>  
>  	if (!master->_max_bad_blocks)
>  		return -ENOTSUPP;
> @@ -487,8 +528,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
>  	if (mtd->size < (len + ofs) || ofs < 0)
>  		return -EINVAL;
>  
> -	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
> -				       len);
> +	mtd_start_access(mtd);
> +	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
> +				      len);
> +	mtd_end_access(mtd);

Please pass the master to those functions, there's no point walking the
parent chain again in the start/end_access() functions if you already
have the master retrieved in the caller. Oh, and there seems to be a
common pattern here, so maybe it's worth adding those macros:

#define mtd_no_suspend_void_call(master, method, ...) \
	mtd_start_access(master); \
	master->method(master, __VA_ARGS__); \
	mtd_end_access(master);

#define mtd_no_suspend_ret_call(ret, master, method, ...) \
	mtd_start_access(master); \
	ret = master->method(master, __VA_ARGS__); \
	mtd_end_access(master);

I don't really like the helper names, so feel free to propose something
else.

> +
> +	return ret;
>  }
>  



From miquel.raynal at bootlin.com  Fri Oct 15 00:44:50 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 09:44:50 +0200
Subject: [PATCH 1/2] mtd: nand: raw: gpmi: new bch geometry settings
In-Reply-To: <9f4ed2c6-7b3d-4933-2247-541855b800ba@geanix.com>
References: <20210522205136.19465-1-han.xu@nxp.com>
 <13c975bc-b37b-8708-9ac7-acdc62ef7108@geanix.com>
 <20210525191308.jlxqvy7khptbuj4z@umbrella>
 <20210526094136.279976a6@xps13>
 <20210526141700.5gygssig4rnzn6mj@umbrella>
 <20210526173123.1787713b@xps13>
 <20210705104654.gko7ettkilrrosi7@skn-laptop>
 <20210706025001.bqvrdye4v3cidm5v@umbrella>
 <9f4ed2c6-7b3d-4933-2247-541855b800ba@geanix.com>
Message-ID: <20211015094450.6350c630@xps13>

Hi Han,

sean at geanix.com wrote on Tue, 12 Oct 2021 11:15:27 +0200:

> On 06/07/2021 04.50, Han Xu wrote:
> > On 21/07/05 12:46PM, Sean Nyekjaer wrote:  
> >> On Wed, May 26, 2021 at 05:31:23PM +0200, Miquel Raynal wrote:  
> >>> Hi Han,  
> 
> [ ... ]
> 
> >> 
> >> Hi Han,
> >> 
> >> Is this something you are working on? If not I really think we need
> >> to revert the changes to u-boot, to allign vanilla u-boot and
> >> kernel.  
> > 
> > I will send patches for both kernel and u-boot to use legacy bch
> > scheme by default, and add some code to treat few MLC nand chips as
> > corner cases.
> >   
> 
> Have I missed the series patches for this? :)

Yes, this needs to be fixed.

Thanks,
Miqu?l


From zajec5 at gmail.com  Fri Oct 15 01:20:09 2021
From: zajec5 at gmail.com (=?UTF-8?B?UmFmYcWCIE1pxYJlY2tp?=)
Date: Fri, 15 Oct 2021 10:20:09 +0200
Subject: nvmem: Defining cells on mtd created by mtdparts
In-Reply-To: <14722734.oMan5NXi5u@sven-desktop>
References: <18728084.NGlc0Rocea@sven-desktop>
 <14722734.oMan5NXi5u@sven-desktop>
Message-ID: <c28ba2f5-cfd7-aef4-526d-bf0679298b5d@gmail.com>

On 11.10.2021 09:06, Sven Eckelmann wrote:
> On Sunday, 10 October 2021 14:53:13 CEST Sven Eckelmann wrote:
> [...]
>> Since there are most likely more devices out there which use mtdparts, I would
>> guess that there might already be a strategy out there which can be used to
>> define the nvmem-provider for mtdparts defined partitions. At least I saw that
>> Bartosz Golaszewski added all the mtd devices automatically as nvmem provider
>> in c4dfa25ab307 ("mtd: add support for reading MTD devices via the nvmem
>> API"). So there might also be something for nvmem-cells to find the correct
>> mtd instead of relying on the fixed-partitions registration + of_node (which
>> doesn't exist because it comes from mtdparts and not devicetree).
> 
> Ansuel Smith just proposed in OpenWrt [1] a workaround. It basically adds a
> minimal fixed-partitions parser to the mtd cmdlinepart parser (responsible for
> the mtdparts=) that tries to find the matching (size + offset) fixed-partition
> from the devicetree. The code in mtd_device_parse_register
> (add_mtd_partitions -> add_mtd_device -> mtd_nvmem_add) will then
> automatically take care of the rest.

I like the idea of connecting cmdline specified partitions (mtdparts=)
with DT. That will help devices that use DT at least.

One thing I'm not sure about is criteria. Ansuel in his patch
[PATCH] drivers: mtd: parsers: add nvmem support to cmdlinepart
https://gist.github.com/Ansuel/35abba1f5663ea3d9bd8eded01e8d95b
requires a matching name, offset & size.

I guess above may work for partitions that stay static like a
bootloader. What if someone wants to describe more dynamic partition
(firmware?). Should we reduce criteria to allow matching just by a
name?


From miquel.raynal at bootlin.com  Fri Oct 15 01:29:11 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 10:29:11 +0200
Subject: =?UTF-8?B?5Zue5L+hOg==?= [RFC PATCH 09/10] spi: mxic: Add
 support for direct mapping
In-Reply-To: <OF032BE161.2014BA23-ON4825876C.0027CC4D-4825876C.0027D1E7@mxic.com.tw>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-10-miquel.raynal@bootlin.com>
 <OF032BE161.2014BA23-ON4825876C.0027CC4D-4825876C.0027D1E7@mxic.com.tw>
Message-ID: <20211015102911.25732215@xps13>

Hello Jaime,

jaimeliao at mxic.com.tw wrote on Tue, 12 Oct 2021 15:14:56 +0800:

> Hi Miquel
> 
> ZhengxunLi have patch new mxic spi host controller before.
> The patch name as below
> spi: mxic: patch for octal DTR mode support
> Please patch mxic ECC engine base on latest version.

Yes you are right. I didn't rebase my series before sending it, as
mentioned in the cover letter this was just a way to provide this code
publicly as someone from Mediatek needed it (hence, the RFC). I will
soon send a real v1 with the bindings fixed as well.

Thanks,
Miqu?l


From paul at crapouillou.net  Fri Oct 15 01:38:31 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Fri, 15 Oct 2021 09:38:31 +0100
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211015081313.60018976@xps13>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13>
Message-ID: <70G01R.2VROMW06O3O83@crapouillou.net>

Hi Miquel,

Le ven., oct. 15 2021 at 08:13:13 +0200, Miquel Raynal 
<miquel.raynal at bootlin.com> a ?crit :
> Hi Paul,
> 
> paul at crapouillou.net wrote on Sat,  9 Oct 2021 20:49:51 +0200:
> 
>>  Move the function nand_read_page_hwecc_oob_first() (previously
>>  nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and 
>> export it
>>  as a GPL symbol, so that it can be used by more modules.
>> 
>>  Cc: <stable at vger.kernel.org> # v5.2
>>  Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the 
>> JZ4740")
>>  Signed-off-by: Paul Cercueil <paul at crapouillou.net>
>>  ---
>>   drivers/mtd/nand/raw/davinci_nand.c | 70 
>> +----------------------------
>>   drivers/mtd/nand/raw/nand_base.c    | 69 
>> ++++++++++++++++++++++++++++
>>   include/linux/mtd/rawnand.h         |  2 +
>>   3 files changed, 72 insertions(+), 69 deletions(-)
>> 
>>  diff --git a/drivers/mtd/nand/raw/davinci_nand.c 
>> b/drivers/mtd/nand/raw/davinci_nand.c
>>  index 89de24d3bb7a..45fec8c192ab 100644
>>  --- a/drivers/mtd/nand/raw/davinci_nand.c
>>  +++ b/drivers/mtd/nand/raw/davinci_nand.c
>>  @@ -371,74 +371,6 @@ static int nand_davinci_correct_4bit(struct 
>> nand_chip *chip, u_char *data,
>>   	return corrected;
>>   }
>> 
>>  -/**
>>  - * nand_read_page_hwecc_oob_first - hw ecc, read oob first
>>  - * @chip: nand chip info structure
>>  - * @buf: buffer to store read data
>>  - * @oob_required: caller requires OOB data read to chip->oob_poi
>>  - * @page: page number to read
>>  - *
>>  - * Hardware ECC for large page chips, require OOB to be read 
>> first. For this
>>  - * ECC mode, the write_page method is re-used from ECC_HW. These 
>> methods
>>  - * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME 
>> support with
>>  - * multiple ECC steps, follows the "infix ECC" scheme and 
>> reads/writes ECC from
>>  - * the data area, by overwriting the NAND manufacturer bad block 
>> markings.
>>  - */
>>  -static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip 
>> *chip,
>>  -						  uint8_t *buf,
>>  -						  int oob_required, int page)
>>  -{
>>  -	struct mtd_info *mtd = nand_to_mtd(chip);
>>  -	int i, eccsize = chip->ecc.size, ret;
>>  -	int eccbytes = chip->ecc.bytes;
>>  -	int eccsteps = chip->ecc.steps;
>>  -	uint8_t *p = buf;
>>  -	uint8_t *ecc_code = chip->ecc.code_buf;
>>  -	unsigned int max_bitflips = 0;
>>  -
>>  -	/* Read the OOB area first */
>>  -	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, 
>> mtd->oobsize);
>>  -	if (ret)
>>  -		return ret;
>>  -
>>  -	ret = nand_read_page_op(chip, page, 0, NULL, 0);
>>  -	if (ret)
>>  -		return ret;
>>  -
>>  -	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
>>  -					 chip->ecc.total);
>>  -	if (ret)
>>  -		return ret;
>>  -
>>  -	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
>>  -		int stat;
>>  -
>>  -		chip->ecc.hwctl(chip, NAND_ECC_READ);
>>  -
>>  -		ret = nand_read_data_op(chip, p, eccsize, false, false);
>>  -		if (ret)
>>  -			return ret;
>>  -
>>  -		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
>>  -		if (stat == -EBADMSG &&
>>  -		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
>>  -			/* check for empty pages with bitflips */
>>  -			stat = nand_check_erased_ecc_chunk(p, eccsize,
>>  -							   &ecc_code[i],
>>  -							   eccbytes, NULL, 0,
>>  -							   chip->ecc.strength);
>>  -		}
>>  -
>>  -		if (stat < 0) {
>>  -			mtd->ecc_stats.failed++;
>>  -		} else {
>>  -			mtd->ecc_stats.corrected += stat;
>>  -			max_bitflips = max_t(unsigned int, max_bitflips, stat);
>>  -		}
>>  -	}
>>  -	return max_bitflips;
>>  -}
>>  -
>>   
>> /*----------------------------------------------------------------------*/
>> 
>>   /* An ECC layout for using 4-bit ECC with small-page flash, storing
>>  @@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct 
>> nand_chip *chip)
>>   			} else if (chunks == 4 || chunks == 8) {
>>   				mtd_set_ooblayout(mtd,
>>   						  nand_get_large_page_ooblayout());
>>  -				chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
>>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
>>   			} else {
>>   				return -EIO;
>>   			}
>>  diff --git a/drivers/mtd/nand/raw/nand_base.c 
>> b/drivers/mtd/nand/raw/nand_base.c
>>  index 3d6c6e880520..cb5f343b9fa2 100644
>>  --- a/drivers/mtd/nand/raw/nand_base.c
>>  +++ b/drivers/mtd/nand/raw/nand_base.c
>>  @@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct 
>> nand_chip *chip, uint8_t *buf,
>>   	return max_bitflips;
>>   }
>> 
>>  +/**
>>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC
>>  + *                                  data read from OOB area
>>  + * @chip: nand chip info structure
>>  + * @buf: buffer to store read data
>>  + * @oob_required: caller requires OOB data read to chip->oob_poi
>>  + * @page: page number to read
>>  + *
>>  + * Hardware ECC for large page chips, require OOB to be read 
>> first. For this
> 
> requires
> 
> With this ECC configuration?
> 
>>  + * ECC mode, the write_page method is re-used from ECC_HW. These 
>> methods
> 
> I do not understand this sentence nor the next one about syndrome. I
> believe it is related to your engine and should not leak into the 
> core.
> 
>>  + * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME 
>> support with
>>  + * multiple ECC steps, follows the "infix ECC" scheme and 
>> reads/writes ECC from
>>  + * the data area, by overwriting the NAND manufacturer bad block 
>> markings.
> 
> That's a sentence I don't like. What do you mean exactly?
> 
> What "Infix ECC" scheme is?
> 
> Do you mean that unlike the syndrome  mode it *does not* overwrite the
> BBM ?

I don't mean anything. I did not write that comment. I just moved the 
function verbatim with no changes. If something needs to be fixed, then 
it needs to be fixed before/after this patch.

>>  + */
>>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t 
>> *buf,
>>  +				   int oob_required, int page)
>>  +{
>>  +	struct mtd_info *mtd = nand_to_mtd(chip);
>>  +	int i, eccsize = chip->ecc.size, ret;
>>  +	int eccbytes = chip->ecc.bytes;
>>  +	int eccsteps = chip->ecc.steps;
>>  +	uint8_t *p = buf;
>>  +	uint8_t *ecc_code = chip->ecc.code_buf;
>>  +	unsigned int max_bitflips = 0;
>>  +
>>  +	/* Read the OOB area first */
>>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, 
>> mtd->oobsize);
>>  +	if (ret)
>>  +		return ret;
>>  +
>>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);
> 
> Definitely not, your are requesting the chip to do the read_page
> operation twice. You only need a nand_change_read_column I believe.

Again, this code is just being moved around - don't shoot the messenger 
:)

>>  +	if (ret)
>>  +		return ret;
>>  +
>>  +	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
>>  +					 chip->ecc.total);
>>  +	if (ret)
>>  +		return ret;
>>  +
>>  +	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
>>  +		int stat;
>>  +
>>  +		chip->ecc.hwctl(chip, NAND_ECC_READ);
>>  +
>>  +		ret = nand_read_data_op(chip, p, eccsize, false, false);
>>  +		if (ret)
>>  +			return ret;
>>  +
>>  +		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
>>  +		if (stat == -EBADMSG &&
>>  +		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
>>  +			/* check for empty pages with bitflips */
>>  +			stat = nand_check_erased_ecc_chunk(p, eccsize,
>>  +							   &ecc_code[i],
>>  +							   eccbytes, NULL, 0,
>>  +							   chip->ecc.strength);
>>  +		}
>>  +
>>  +		if (stat < 0) {
>>  +			mtd->ecc_stats.failed++;
>>  +		} else {
>>  +			mtd->ecc_stats.corrected += stat;
>>  +			max_bitflips = max_t(unsigned int, max_bitflips, stat);
>>  +		}
>>  +	}
>>  +	return max_bitflips;
>>  +}
>>  +EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
>>  +
>>   /**
>>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome 
>> based page read
>>    * @chip: nand chip info structure
>>  diff --git a/include/linux/mtd/rawnand.h 
>> b/include/linux/mtd/rawnand.h
>>  index b2f9dd3cbd69..5b88cd51fadb 100644
>>  --- a/include/linux/mtd/rawnand.h
>>  +++ b/include/linux/mtd/rawnand.h
>>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, 
>> void *buf, unsigned int len,
>>   		      bool force_8bit, bool check_only);
>>   int nand_write_data_op(struct nand_chip *chip, const void *buf,
>>   		       unsigned int len, bool force_8bit);
>>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t 
>> *buf,
>>  +				   int oob_required, int page);
> 
> You certainly want to add this symbol closer to the other read/write
> page helpers?

Where would that be? The other read/write page helpers are all "static" 
so they don't appear in any header.

Cheers,
-Paul

>> 
>>   /* Scan and identify a NAND device */
>>   int nand_scan_with_ids(struct nand_chip *chip, unsigned int 
>> max_chips,
> 
> 
> Thanks,
> Miqu?l




From miquel.raynal at bootlin.com  Fri Oct 15 01:51:46 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 10:51:46 +0200
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <70G01R.2VROMW06O3O83@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13>
 <70G01R.2VROMW06O3O83@crapouillou.net>
Message-ID: <20211015105146.3d2fbd08@xps13>

Hi Paul,

paul at crapouillou.net wrote on Fri, 15 Oct 2021 09:38:31 +0100:

> Hi Miquel,
> 
> Le ven., oct. 15 2021 at 08:13:13 +0200, Miquel Raynal <miquel.raynal at bootlin.com> a ?crit :
> > Hi Paul,
> > 
> > paul at crapouillou.net wrote on Sat,  9 Oct 2021 20:49:51 +0200:
> >   
> >>  Move the function nand_read_page_hwecc_oob_first() (previously
> >>  nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and >> export it
> >>  as a GPL symbol, so that it can be used by more modules.  
> >> >>  Cc: <stable at vger.kernel.org> # v5.2  
> >>  Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the >> JZ4740")
> >>  Signed-off-by: Paul Cercueil <paul at crapouillou.net>
> >>  ---
> >>   drivers/mtd/nand/raw/davinci_nand.c | 70 >> +----------------------------
> >>   drivers/mtd/nand/raw/nand_base.c    | 69 >> ++++++++++++++++++++++++++++
> >>   include/linux/mtd/rawnand.h         |  2 +
> >>   3 files changed, 72 insertions(+), 69 deletions(-)  
> >> >>  diff --git a/drivers/mtd/nand/raw/davinci_nand.c >> b/drivers/mtd/nand/raw/davinci_nand.c  
> >>  index 89de24d3bb7a..45fec8c192ab 100644
> >>  --- a/drivers/mtd/nand/raw/davinci_nand.c
> >>  +++ b/drivers/mtd/nand/raw/davinci_nand.c
> >>  @@ -371,74 +371,6 @@ static int nand_davinci_correct_4bit(struct >> nand_chip *chip, u_char *data,
> >>   	return corrected;
> >>   }  
> >> >>  -/**  
> >>  - * nand_read_page_hwecc_oob_first - hw ecc, read oob first
> >>  - * @chip: nand chip info structure
> >>  - * @buf: buffer to store read data
> >>  - * @oob_required: caller requires OOB data read to chip->oob_poi
> >>  - * @page: page number to read
> >>  - *
> >>  - * Hardware ECC for large page chips, require OOB to be read >> first. For this
> >>  - * ECC mode, the write_page method is re-used from ECC_HW. These >> methods
> >>  - * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME >> support with
> >>  - * multiple ECC steps, follows the "infix ECC" scheme and >> reads/writes ECC from
> >>  - * the data area, by overwriting the NAND manufacturer bad block >> markings.
> >>  - */
> >>  -static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip >> *chip,
> >>  -						  uint8_t *buf,
> >>  -						  int oob_required, int page)
> >>  -{
> >>  -	struct mtd_info *mtd = nand_to_mtd(chip);
> >>  -	int i, eccsize = chip->ecc.size, ret;
> >>  -	int eccbytes = chip->ecc.bytes;
> >>  -	int eccsteps = chip->ecc.steps;
> >>  -	uint8_t *p = buf;
> >>  -	uint8_t *ecc_code = chip->ecc.code_buf;
> >>  -	unsigned int max_bitflips = 0;
> >>  -
> >>  -	/* Read the OOB area first */
> >>  -	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> mtd->oobsize);
> >>  -	if (ret)
> >>  -		return ret;
> >>  -
> >>  -	ret = nand_read_page_op(chip, page, 0, NULL, 0);
> >>  -	if (ret)
> >>  -		return ret;
> >>  -
> >>  -	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
> >>  -					 chip->ecc.total);
> >>  -	if (ret)
> >>  -		return ret;
> >>  -
> >>  -	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
> >>  -		int stat;
> >>  -
> >>  -		chip->ecc.hwctl(chip, NAND_ECC_READ);
> >>  -
> >>  -		ret = nand_read_data_op(chip, p, eccsize, false, false);
> >>  -		if (ret)
> >>  -			return ret;
> >>  -
> >>  -		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
> >>  -		if (stat == -EBADMSG &&
> >>  -		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
> >>  -			/* check for empty pages with bitflips */
> >>  -			stat = nand_check_erased_ecc_chunk(p, eccsize,
> >>  -							   &ecc_code[i],
> >>  -							   eccbytes, NULL, 0,
> >>  -							   chip->ecc.strength);
> >>  -		}
> >>  -
> >>  -		if (stat < 0) {
> >>  -			mtd->ecc_stats.failed++;
> >>  -		} else {
> >>  -			mtd->ecc_stats.corrected += stat;
> >>  -			max_bitflips = max_t(unsigned int, max_bitflips, stat);
> >>  -		}
> >>  -	}
> >>  -	return max_bitflips;
> >>  -}
> >>  -  
> >>   >> /*----------------------------------------------------------------------  
> */
> >> >>   /* An ECC layout for using 4-bit ECC with small-page flash, storing  
> >>  @@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct >> nand_chip *chip)
> >>   			} else if (chunks == 4 || chunks == 8) {
> >>   				mtd_set_ooblayout(mtd,
> >>   						  nand_get_large_page_ooblayout());
> >>  -				chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
> >>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
> >>   			} else {
> >>   				return -EIO;
> >>   			}
> >>  diff --git a/drivers/mtd/nand/raw/nand_base.c >> b/drivers/mtd/nand/raw/nand_base.c
> >>  index 3d6c6e880520..cb5f343b9fa2 100644
> >>  --- a/drivers/mtd/nand/raw/nand_base.c
> >>  +++ b/drivers/mtd/nand/raw/nand_base.c
> >>  @@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct >> nand_chip *chip, uint8_t *buf,
> >>   	return max_bitflips;
> >>   }  
> >> >>  +/**  
> >>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC
> >>  + *                                  data read from OOB area
> >>  + * @chip: nand chip info structure
> >>  + * @buf: buffer to store read data
> >>  + * @oob_required: caller requires OOB data read to chip->oob_poi
> >>  + * @page: page number to read
> >>  + *
> >>  + * Hardware ECC for large page chips, require OOB to be read >> first. For this  
> > 
> > requires
> > 
> > With this ECC configuration?
> >   
> >>  + * ECC mode, the write_page method is re-used from ECC_HW. These >> methods  
> > 
> > I do not understand this sentence nor the next one about syndrome. I
> > believe it is related to your engine and should not leak into the > core.
> >   
> >>  + * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME >> support with
> >>  + * multiple ECC steps, follows the "infix ECC" scheme and >> reads/writes ECC from
> >>  + * the data area, by overwriting the NAND manufacturer bad block >> markings.  
> > 
> > That's a sentence I don't like. What do you mean exactly?
> > 
> > What "Infix ECC" scheme is?
> > 
> > Do you mean that unlike the syndrome  mode it *does not* overwrite the
> > BBM ?  
> 
> I don't mean anything. I did not write that comment. I just moved the function verbatim with no changes. If something needs to be fixed, then it needs to be fixed before/after this patch.

Well, this comment should be adapted because as-is I don't think it's
wise to move it around.

> 
> >>  + */
> >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t >> *buf,
> >>  +				   int oob_required, int page)
> >>  +{
> >>  +	struct mtd_info *mtd = nand_to_mtd(chip);
> >>  +	int i, eccsize = chip->ecc.size, ret;
> >>  +	int eccbytes = chip->ecc.bytes;
> >>  +	int eccsteps = chip->ecc.steps;
> >>  +	uint8_t *p = buf;
> >>  +	uint8_t *ecc_code = chip->ecc.code_buf;
> >>  +	unsigned int max_bitflips = 0;
> >>  +
> >>  +	/* Read the OOB area first */
> >>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> mtd->oobsize);
> >>  +	if (ret)
> >>  +		return ret;
> >>  +
> >>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);  
> > 
> > Definitely not, your are requesting the chip to do the read_page
> > operation twice. You only need a nand_change_read_column I believe.  
> 
> Again, this code is just being moved around - don't shoot the messenger :)

haha

Well, now you touch the core, so I need to be more careful, and the
code is definitely wrong, so even if we don't move that code off, you
definitely want to fix it in order to improve your performances.

> >>  +	if (ret)
> >>  +		return ret;
> >>  +
> >>  +	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
> >>  +					 chip->ecc.total);
> >>  +	if (ret)
> >>  +		return ret;
> >>  +
> >>  +	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
> >>  +		int stat;
> >>  +
> >>  +		chip->ecc.hwctl(chip, NAND_ECC_READ);
> >>  +
> >>  +		ret = nand_read_data_op(chip, p, eccsize, false, false);
> >>  +		if (ret)
> >>  +			return ret;
> >>  +
> >>  +		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
> >>  +		if (stat == -EBADMSG &&
> >>  +		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
> >>  +			/* check for empty pages with bitflips */
> >>  +			stat = nand_check_erased_ecc_chunk(p, eccsize,
> >>  +							   &ecc_code[i],
> >>  +							   eccbytes, NULL, 0,
> >>  +							   chip->ecc.strength);
> >>  +		}
> >>  +
> >>  +		if (stat < 0) {
> >>  +			mtd->ecc_stats.failed++;
> >>  +		} else {
> >>  +			mtd->ecc_stats.corrected += stat;
> >>  +			max_bitflips = max_t(unsigned int, max_bitflips, stat);
> >>  +		}
> >>  +	}
> >>  +	return max_bitflips;
> >>  +}
> >>  +EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
> >>  +
> >>   /**
> >>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome >> based page read
> >>    * @chip: nand chip info structure
> >>  diff --git a/include/linux/mtd/rawnand.h >> b/include/linux/mtd/rawnand.h
> >>  index b2f9dd3cbd69..5b88cd51fadb 100644
> >>  --- a/include/linux/mtd/rawnand.h
> >>  +++ b/include/linux/mtd/rawnand.h
> >>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, >> void *buf, unsigned int len,
> >>   		      bool force_8bit, bool check_only);
> >>   int nand_write_data_op(struct nand_chip *chip, const void *buf,
> >>   		       unsigned int len, bool force_8bit);
> >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t >> *buf,
> >>  +				   int oob_required, int page);  
> > 
> > You certainly want to add this symbol closer to the other read/write
> > page helpers?  
> 
> Where would that be? The other read/write page helpers are all "static" so they don't appear in any header.

I believe we should keep this header local as long as there are no
other users.


Thanks,
Miqu?l


From paul at crapouillou.net  Fri Oct 15 02:27:08 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Fri, 15 Oct 2021 10:27:08 +0100
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211015105146.3d2fbd08@xps13>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13> <70G01R.2VROMW06O3O83@crapouillou.net>
 <20211015105146.3d2fbd08@xps13>
Message-ID: <89I01R.QTBARVYLTBT02@crapouillou.net>



Le ven., oct. 15 2021 at 10:51:46 +0200, Miquel Raynal 
<miquel.raynal at bootlin.com> a ?crit :
> Hi Paul,
> 
> paul at crapouillou.net wrote on Fri, 15 Oct 2021 09:38:31 +0100:
> 
>>  Hi Miquel,
>> 
>>  Le ven., oct. 15 2021 at 08:13:13 +0200, Miquel Raynal 
>> <miquel.raynal at bootlin.com> a ?crit :
>>  > Hi Paul,
>>  >
>>  > paul at crapouillou.net wrote on Sat,  9 Oct 2021 20:49:51 +0200:
>>  >
>>  >>  Move the function nand_read_page_hwecc_oob_first() (previously
>>  >>  nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and 
>> >> export it
>>  >>  as a GPL symbol, so that it can be used by more modules.
>>  >> >>  Cc: <stable at vger.kernel.org> # v5.2
>>  >>  Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for 
>> the >> JZ4740")
>>  >>  Signed-off-by: Paul Cercueil <paul at crapouillou.net>
>>  >>  ---
>>  >>   drivers/mtd/nand/raw/davinci_nand.c | 70 >> 
>> +----------------------------
>>  >>   drivers/mtd/nand/raw/nand_base.c    | 69 >> 
>> ++++++++++++++++++++++++++++
>>  >>   include/linux/mtd/rawnand.h         |  2 +
>>  >>   3 files changed, 72 insertions(+), 69 deletions(-)
>>  >> >>  diff --git a/drivers/mtd/nand/raw/davinci_nand.c >> 
>> b/drivers/mtd/nand/raw/davinci_nand.c
>>  >>  index 89de24d3bb7a..45fec8c192ab 100644
>>  >>  --- a/drivers/mtd/nand/raw/davinci_nand.c
>>  >>  +++ b/drivers/mtd/nand/raw/davinci_nand.c
>>  >>  @@ -371,74 +371,6 @@ static int 
>> nand_davinci_correct_4bit(struct >> nand_chip *chip, u_char *data,
>>  >>   	return corrected;
>>  >>   }
>>  >> >>  -/**
>>  >>  - * nand_read_page_hwecc_oob_first - hw ecc, read oob first
>>  >>  - * @chip: nand chip info structure
>>  >>  - * @buf: buffer to store read data
>>  >>  - * @oob_required: caller requires OOB data read to 
>> chip->oob_poi
>>  >>  - * @page: page number to read
>>  >>  - *
>>  >>  - * Hardware ECC for large page chips, require OOB to be read 
>> >> first. For this
>>  >>  - * ECC mode, the write_page method is re-used from ECC_HW. 
>> These >> methods
>>  >>  - * read/write ECC from the OOB area, unlike the 
>> ECC_HW_SYNDROME >> support with
>>  >>  - * multiple ECC steps, follows the "infix ECC" scheme and >> 
>> reads/writes ECC from
>>  >>  - * the data area, by overwriting the NAND manufacturer bad 
>> block >> markings.
>>  >>  - */
>>  >>  -static int nand_davinci_read_page_hwecc_oob_first(struct 
>> nand_chip >> *chip,
>>  >>  -						  uint8_t *buf,
>>  >>  -						  int oob_required, int page)
>>  >>  -{
>>  >>  -	struct mtd_info *mtd = nand_to_mtd(chip);
>>  >>  -	int i, eccsize = chip->ecc.size, ret;
>>  >>  -	int eccbytes = chip->ecc.bytes;
>>  >>  -	int eccsteps = chip->ecc.steps;
>>  >>  -	uint8_t *p = buf;
>>  >>  -	uint8_t *ecc_code = chip->ecc.code_buf;
>>  >>  -	unsigned int max_bitflips = 0;
>>  >>  -
>>  >>  -	/* Read the OOB area first */
>>  >>  -	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> 
>> mtd->oobsize);
>>  >>  -	if (ret)
>>  >>  -		return ret;
>>  >>  -
>>  >>  -	ret = nand_read_page_op(chip, page, 0, NULL, 0);
>>  >>  -	if (ret)
>>  >>  -		return ret;
>>  >>  -
>>  >>  -	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, 
>> chip->oob_poi, 0,
>>  >>  -					 chip->ecc.total);
>>  >>  -	if (ret)
>>  >>  -		return ret;
>>  >>  -
>>  >>  -	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += 
>> eccsize) {
>>  >>  -		int stat;
>>  >>  -
>>  >>  -		chip->ecc.hwctl(chip, NAND_ECC_READ);
>>  >>  -
>>  >>  -		ret = nand_read_data_op(chip, p, eccsize, false, false);
>>  >>  -		if (ret)
>>  >>  -			return ret;
>>  >>  -
>>  >>  -		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
>>  >>  -		if (stat == -EBADMSG &&
>>  >>  -		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
>>  >>  -			/* check for empty pages with bitflips */
>>  >>  -			stat = nand_check_erased_ecc_chunk(p, eccsize,
>>  >>  -							   &ecc_code[i],
>>  >>  -							   eccbytes, NULL, 0,
>>  >>  -							   chip->ecc.strength);
>>  >>  -		}
>>  >>  -
>>  >>  -		if (stat < 0) {
>>  >>  -			mtd->ecc_stats.failed++;
>>  >>  -		} else {
>>  >>  -			mtd->ecc_stats.corrected += stat;
>>  >>  -			max_bitflips = max_t(unsigned int, max_bitflips, stat);
>>  >>  -		}
>>  >>  -	}
>>  >>  -	return max_bitflips;
>>  >>  -}
>>  >>  -
>>  >>   >> 
>> /*----------------------------------------------------------------------
>>  */
>>  >> >>   /* An ECC layout for using 4-bit ECC with small-page flash, 
>> storing
>>  >>  @@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct 
>> >> nand_chip *chip)
>>  >>   			} else if (chunks == 4 || chunks == 8) {
>>  >>   				mtd_set_ooblayout(mtd,
>>  >>   						  nand_get_large_page_ooblayout());
>>  >>  -				chip->ecc.read_page = 
>> nand_davinci_read_page_hwecc_oob_first;
>>  >>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
>>  >>   			} else {
>>  >>   				return -EIO;
>>  >>   			}
>>  >>  diff --git a/drivers/mtd/nand/raw/nand_base.c >> 
>> b/drivers/mtd/nand/raw/nand_base.c
>>  >>  index 3d6c6e880520..cb5f343b9fa2 100644
>>  >>  --- a/drivers/mtd/nand/raw/nand_base.c
>>  >>  +++ b/drivers/mtd/nand/raw/nand_base.c
>>  >>  @@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct 
>> >> nand_chip *chip, uint8_t *buf,
>>  >>   	return max_bitflips;
>>  >>   }
>>  >> >>  +/**
>>  >>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read 
>> with ECC
>>  >>  + *                                  data read from OOB area
>>  >>  + * @chip: nand chip info structure
>>  >>  + * @buf: buffer to store read data
>>  >>  + * @oob_required: caller requires OOB data read to 
>> chip->oob_poi
>>  >>  + * @page: page number to read
>>  >>  + *
>>  >>  + * Hardware ECC for large page chips, require OOB to be read 
>> >> first. For this
>>  >
>>  > requires
>>  >
>>  > With this ECC configuration?
>>  >
>>  >>  + * ECC mode, the write_page method is re-used from ECC_HW. 
>> These >> methods
>>  >
>>  > I do not understand this sentence nor the next one about 
>> syndrome. I
>>  > believe it is related to your engine and should not leak into the 
>> > core.
>>  >
>>  >>  + * read/write ECC from the OOB area, unlike the 
>> ECC_HW_SYNDROME >> support with
>>  >>  + * multiple ECC steps, follows the "infix ECC" scheme and >> 
>> reads/writes ECC from
>>  >>  + * the data area, by overwriting the NAND manufacturer bad 
>> block >> markings.
>>  >
>>  > That's a sentence I don't like. What do you mean exactly?
>>  >
>>  > What "Infix ECC" scheme is?
>>  >
>>  > Do you mean that unlike the syndrome  mode it *does not* 
>> overwrite the
>>  > BBM ?
>> 
>>  I don't mean anything. I did not write that comment. I just moved 
>> the function verbatim with no changes. If something needs to be 
>> fixed, then it needs to be fixed before/after this patch.
> 
> Well, this comment should be adapted because as-is I don't think it's
> wise to move it around.

OK.

I think it says that BBM can be overwritten with this configuration, 
but that would be if the OOB layout covers the BBM area.

>> 
>>  >>  + */
>>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, 
>> uint8_t >> *buf,
>>  >>  +				   int oob_required, int page)
>>  >>  +{
>>  >>  +	struct mtd_info *mtd = nand_to_mtd(chip);
>>  >>  +	int i, eccsize = chip->ecc.size, ret;
>>  >>  +	int eccbytes = chip->ecc.bytes;
>>  >>  +	int eccsteps = chip->ecc.steps;
>>  >>  +	uint8_t *p = buf;
>>  >>  +	uint8_t *ecc_code = chip->ecc.code_buf;
>>  >>  +	unsigned int max_bitflips = 0;
>>  >>  +
>>  >>  +	/* Read the OOB area first */
>>  >>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> 
>> mtd->oobsize);
>>  >>  +	if (ret)
>>  >>  +		return ret;
>>  >>  +
>>  >>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);
>>  >
>>  > Definitely not, your are requesting the chip to do the read_page
>>  > operation twice. You only need a nand_change_read_column I 
>> believe.
>> 
>>  Again, this code is just being moved around - don't shoot the 
>> messenger :)
> 
> haha
> 
> Well, now you touch the core, so I need to be more careful, and the
> code is definitely wrong, so even if we don't move that code off, you
> definitely want to fix it in order to improve your performances.

I don't see the read_page being done twice?

There's one read_oob, one read_page, then read_data in the loop.

>>  >>  +	if (ret)
>>  >>  +		return ret;
>>  >>  +
>>  >>  +	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, 
>> chip->oob_poi, 0,
>>  >>  +					 chip->ecc.total);
>>  >>  +	if (ret)
>>  >>  +		return ret;
>>  >>  +
>>  >>  +	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += 
>> eccsize) {
>>  >>  +		int stat;
>>  >>  +
>>  >>  +		chip->ecc.hwctl(chip, NAND_ECC_READ);
>>  >>  +
>>  >>  +		ret = nand_read_data_op(chip, p, eccsize, false, false);
>>  >>  +		if (ret)
>>  >>  +			return ret;
>>  >>  +
>>  >>  +		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
>>  >>  +		if (stat == -EBADMSG &&
>>  >>  +		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
>>  >>  +			/* check for empty pages with bitflips */
>>  >>  +			stat = nand_check_erased_ecc_chunk(p, eccsize,
>>  >>  +							   &ecc_code[i],
>>  >>  +							   eccbytes, NULL, 0,
>>  >>  +							   chip->ecc.strength);
>>  >>  +		}
>>  >>  +
>>  >>  +		if (stat < 0) {
>>  >>  +			mtd->ecc_stats.failed++;
>>  >>  +		} else {
>>  >>  +			mtd->ecc_stats.corrected += stat;
>>  >>  +			max_bitflips = max_t(unsigned int, max_bitflips, stat);
>>  >>  +		}
>>  >>  +	}
>>  >>  +	return max_bitflips;
>>  >>  +}
>>  >>  +EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
>>  >>  +
>>  >>   /**
>>  >>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC 
>> syndrome >> based page read
>>  >>    * @chip: nand chip info structure
>>  >>  diff --git a/include/linux/mtd/rawnand.h >> 
>> b/include/linux/mtd/rawnand.h
>>  >>  index b2f9dd3cbd69..5b88cd51fadb 100644
>>  >>  --- a/include/linux/mtd/rawnand.h
>>  >>  +++ b/include/linux/mtd/rawnand.h
>>  >>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip 
>> *chip, >> void *buf, unsigned int len,
>>  >>   		      bool force_8bit, bool check_only);
>>  >>   int nand_write_data_op(struct nand_chip *chip, const void *buf,
>>  >>   		       unsigned int len, bool force_8bit);
>>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, 
>> uint8_t >> *buf,
>>  >>  +				   int oob_required, int page);
>>  >
>>  > You certainly want to add this symbol closer to the other 
>> read/write
>>  > page helpers?
>> 
>>  Where would that be? The other read/write page helpers are all 
>> "static" so they don't appear in any header.
> 
> I believe we should keep this header local as long as there are no
> other users.

I'll move it to internal.h then.

Cheers,
-Paul




From miquel.raynal at bootlin.com  Fri Oct 15 02:35:15 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 11:35:15 +0200
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <89I01R.QTBARVYLTBT02@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13>
 <70G01R.2VROMW06O3O83@crapouillou.net>
 <20211015105146.3d2fbd08@xps13>
 <89I01R.QTBARVYLTBT02@crapouillou.net>
Message-ID: <20211015113515.7b10a2d5@xps13>

Hi Paul,

> >>  */  
> >>  >> >>   /* An ECC layout for using 4-bit ECC with small-page flash, >> storing  
> >>  >>  @@ -648,7 +580,7 @@ static int davinci_nand_attach_chip(struct >> >> nand_chip *chip)
> >>  >>   			} else if (chunks == 4 || chunks == 8) {
> >>  >>   				mtd_set_ooblayout(mtd,
> >>  >>   						  nand_get_large_page_ooblayout());
> >>  >>  -				chip->ecc.read_page = >> nand_davinci_read_page_hwecc_oob_first;
> >>  >>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
> >>  >>   			} else {
> >>  >>   				return -EIO;
> >>  >>   			}
> >>  >>  diff --git a/drivers/mtd/nand/raw/nand_base.c >> >> b/drivers/mtd/nand/raw/nand_base.c
> >>  >>  index 3d6c6e880520..cb5f343b9fa2 100644
> >>  >>  --- a/drivers/mtd/nand/raw/nand_base.c
> >>  >>  +++ b/drivers/mtd/nand/raw/nand_base.c
> >>  >>  @@ -3160,6 +3160,75 @@ static int nand_read_page_hwecc(struct >> >> nand_chip *chip, uint8_t *buf,
> >>  >>   	return max_bitflips;
> >>  >>   }  
> >>  >> >>  +/**  
> >>  >>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read >> with ECC
> >>  >>  + *                                  data read from OOB area
> >>  >>  + * @chip: nand chip info structure
> >>  >>  + * @buf: buffer to store read data
> >>  >>  + * @oob_required: caller requires OOB data read to >> chip->oob_poi
> >>  >>  + * @page: page number to read
> >>  >>  + *
> >>  >>  + * Hardware ECC for large page chips, require OOB to be read >> >> first. For this  
> >>  >
> >>  > requires
> >>  >
> >>  > With this ECC configuration?
> >>  >  
> >>  >>  + * ECC mode, the write_page method is re-used from ECC_HW. >> These >> methods  
> >>  >
> >>  > I do not understand this sentence nor the next one about >> syndrome. I
> >>  > believe it is related to your engine and should not leak into the >> > core.
> >>  >  
> >>  >>  + * read/write ECC from the OOB area, unlike the >> ECC_HW_SYNDROME >> support with
> >>  >>  + * multiple ECC steps, follows the "infix ECC" scheme and >> >> reads/writes ECC from
> >>  >>  + * the data area, by overwriting the NAND manufacturer bad >> block >> markings.  
> >>  >
> >>  > That's a sentence I don't like. What do you mean exactly?
> >>  >
> >>  > What "Infix ECC" scheme is?
> >>  >
> >>  > Do you mean that unlike the syndrome  mode it *does not* >> overwrite the
> >>  > BBM ?  
> >> >>  I don't mean anything. I did not write that comment. I just moved >> the function verbatim with no changes. If something needs to be >> fixed, then it needs to be fixed before/after this patch.  
> > 
> > Well, this comment should be adapted because as-is I don't think it's
> > wise to move it around.  
> 
> OK.
> 
> I think it says that BBM can be overwritten with this configuration, but that would be if the OOB layout covers the BBM area.

If the ooblayout prevents the BBM to be smatched I'm fine and this
sentence should disappear because it's misleading.

> >> >>  >>  + */  
> >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, >> uint8_t >> *buf,
> >>  >>  +				   int oob_required, int page)
> >>  >>  +{
> >>  >>  +	struct mtd_info *mtd = nand_to_mtd(chip);
> >>  >>  +	int i, eccsize = chip->ecc.size, ret;
> >>  >>  +	int eccbytes = chip->ecc.bytes;
> >>  >>  +	int eccsteps = chip->ecc.steps;
> >>  >>  +	uint8_t *p = buf;
> >>  >>  +	uint8_t *ecc_code = chip->ecc.code_buf;
> >>  >>  +	unsigned int max_bitflips = 0;
> >>  >>  +
> >>  >>  +	/* Read the OOB area first */
> >>  >>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> >> mtd->oobsize);
> >>  >>  +	if (ret)
> >>  >>  +		return ret;
> >>  >>  +
> >>  >>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);  
> >>  >
> >>  > Definitely not, your are requesting the chip to do the read_page
> >>  > operation twice. You only need a nand_change_read_column I >> believe.  
> >> >>  Again, this code is just being moved around - don't shoot the >> messenger :)  
> > 
> > haha
> > 
> > Well, now you touch the core, so I need to be more careful, and the
> > code is definitely wrong, so even if we don't move that code off, you
> > definitely want to fix it in order to improve your performances.  
> 
> I don't see the read_page being done twice?
> 
> There's one read_oob, one read_page, then read_data in the loop.

read_oob and read_page both end up sending READ0 and READSTART so
they do request the chip to perform an internal read twice. You
need this only once. The call to nand_read_page_op() should be a
nand_change_read_column() with no data requested. 

> >>  >>   /**
> >>  >>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC >> syndrome >> based page read
> >>  >>    * @chip: nand chip info structure
> >>  >>  diff --git a/include/linux/mtd/rawnand.h >> >> b/include/linux/mtd/rawnand.h
> >>  >>  index b2f9dd3cbd69..5b88cd51fadb 100644
> >>  >>  --- a/include/linux/mtd/rawnand.h
> >>  >>  +++ b/include/linux/mtd/rawnand.h
> >>  >>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip >> *chip, >> void *buf, unsigned int len,
> >>  >>   		      bool force_8bit, bool check_only);
> >>  >>   int nand_write_data_op(struct nand_chip *chip, const void *buf,
> >>  >>   		       unsigned int len, bool force_8bit);
> >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, >> uint8_t >> *buf,
> >>  >>  +				   int oob_required, int page);  
> >>  >
> >>  > You certainly want to add this symbol closer to the other >> read/write
> >>  > page helpers?  
> >> >>  Where would that be? The other read/write page helpers are all >> "static" so they don't appear in any header.  
> > 
> > I believe we should keep this header local as long as there are no
> > other users.  
> 
> I'll move it to internal.h then.

Why do you want to put it there is there is only one user?

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Fri Oct 15 02:37:41 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 11:37:41 +0200
Subject: [RFC PATCH 06/10] mtd: nand: mxic-ecc: Add Macronix external
 ECC engine support
In-Reply-To: <872348abea7317c6b3d2ed53c8139e0927bb991f.camel@mediatek.com>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-7-miquel.raynal@bootlin.com>
 <872348abea7317c6b3d2ed53c8139e0927bb991f.camel@mediatek.com>
Message-ID: <20211015113741.30712544@xps13>

Hi xiangsheng.hou,

xiangsheng.hou at mediatek.com wrote on Wed, 13 Oct 2021 17:15:49 +0800:

> Hi,
> 
> On Fri, 2021-10-08 at 18:22 +0200, Miquel Raynal wrote:
> > 
> > +static int mxic_ecc_count_biterrs(struct mxic_ecc_engine *eng,
> > struct mtd_info *mtd)
> > +{
> > +	struct device *dev = eng->dev;
> > +	unsigned int max_bf = 0;
> > +	int step;
> > +
> > +	for (step = 0; step < eng->steps; step++) {
> > +		u8 stat = eng->status[step];
> > +
> > +		if (stat == NO_ERR) {
> > +			dev_dbg(dev, "ECC step %d: no error\n", step);
> > +		} else if (stat == ERASED_CHUNK) {
> > +			dev_dbg(dev, "ECC step %d: erased\n", step);
> > +		} else if (stat == UNCORR_ERR || stat > MAX_CORR_ERR) {
> > +			dev_dbg(dev, "ECC step %d: uncorrectable\n",
> > step);
> > +			mtd->ecc_stats.failed++;
> > +		} else {
> > +			dev_dbg(dev, "ECC step %d: %d bits
> > corrected\n",
> > +				step, stat);
> > +			max_bf = max_t(unsigned int, max_bf, stat);
> > +			mtd->ecc_stats.corrected += stat;
> > +		}
> > +	}
> > +
> > +	return max_bf;
> > +}  
> 
> In spinand_mtd_read() function, rely on the return value -EBADMSG to
> check whether ecc failed. Therefore, maybe there also need return this
> value in mxic_ecc_count_biterrs() function when uncorrectable ecc
> error?

True, I'll fix this.

Thanks,
Miqu?l


From paul at crapouillou.net  Fri Oct 15 02:38:00 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Fri, 15 Oct 2021 10:38:00 +0100
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211015113515.7b10a2d5@xps13>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13> <70G01R.2VROMW06O3O83@crapouillou.net>
 <20211015105146.3d2fbd08@xps13> <89I01R.QTBARVYLTBT02@crapouillou.net>
 <20211015113515.7b10a2d5@xps13>
Message-ID: <CRI01R.KF0NPTKK5WYV1@crapouillou.net>

Hi,

Le ven., oct. 15 2021 at 11:35:15 +0200, Miquel Raynal 
<miquel.raynal at bootlin.com> a ?crit :
> Hi Paul,
> 
>>  >>  */
>>  >>  >> >>   /* An ECC layout for using 4-bit ECC with small-page 
>> flash, >> storing
>>  >>  >>  @@ -648,7 +580,7 @@ static int 
>> davinci_nand_attach_chip(struct >> >> nand_chip *chip)
>>  >>  >>   			} else if (chunks == 4 || chunks == 8) {
>>  >>  >>   				mtd_set_ooblayout(mtd,
>>  >>  >>   						  nand_get_large_page_ooblayout());
>>  >>  >>  -				chip->ecc.read_page = >> 
>> nand_davinci_read_page_hwecc_oob_first;
>>  >>  >>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
>>  >>  >>   			} else {
>>  >>  >>   				return -EIO;
>>  >>  >>   			}
>>  >>  >>  diff --git a/drivers/mtd/nand/raw/nand_base.c >> >> 
>> b/drivers/mtd/nand/raw/nand_base.c
>>  >>  >>  index 3d6c6e880520..cb5f343b9fa2 100644
>>  >>  >>  --- a/drivers/mtd/nand/raw/nand_base.c
>>  >>  >>  +++ b/drivers/mtd/nand/raw/nand_base.c
>>  >>  >>  @@ -3160,6 +3160,75 @@ static int 
>> nand_read_page_hwecc(struct >> >> nand_chip *chip, uint8_t *buf,
>>  >>  >>   	return max_bitflips;
>>  >>  >>   }
>>  >>  >> >>  +/**
>>  >>  >>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read 
>> >> with ECC
>>  >>  >>  + *                                  data read from OOB area
>>  >>  >>  + * @chip: nand chip info structure
>>  >>  >>  + * @buf: buffer to store read data
>>  >>  >>  + * @oob_required: caller requires OOB data read to >> 
>> chip->oob_poi
>>  >>  >>  + * @page: page number to read
>>  >>  >>  + *
>>  >>  >>  + * Hardware ECC for large page chips, require OOB to be 
>> read >> >> first. For this
>>  >>  >
>>  >>  > requires
>>  >>  >
>>  >>  > With this ECC configuration?
>>  >>  >
>>  >>  >>  + * ECC mode, the write_page method is re-used from ECC_HW. 
>> >> These >> methods
>>  >>  >
>>  >>  > I do not understand this sentence nor the next one about >> 
>> syndrome. I
>>  >>  > believe it is related to your engine and should not leak into 
>> the >> > core.
>>  >>  >
>>  >>  >>  + * read/write ECC from the OOB area, unlike the >> 
>> ECC_HW_SYNDROME >> support with
>>  >>  >>  + * multiple ECC steps, follows the "infix ECC" scheme and 
>> >> >> reads/writes ECC from
>>  >>  >>  + * the data area, by overwriting the NAND manufacturer bad 
>> >> block >> markings.
>>  >>  >
>>  >>  > That's a sentence I don't like. What do you mean exactly?
>>  >>  >
>>  >>  > What "Infix ECC" scheme is?
>>  >>  >
>>  >>  > Do you mean that unlike the syndrome  mode it *does not* >> 
>> overwrite the
>>  >>  > BBM ?
>>  >> >>  I don't mean anything. I did not write that comment. I just 
>> moved >> the function verbatim with no changes. If something needs 
>> to be >> fixed, then it needs to be fixed before/after this patch.
>>  >
>>  > Well, this comment should be adapted because as-is I don't think 
>> it's
>>  > wise to move it around.
>> 
>>  OK.
>> 
>>  I think it says that BBM can be overwritten with this 
>> configuration, but that would be if the OOB layout covers the BBM 
>> area.
> 
> If the ooblayout prevents the BBM to be smatched I'm fine and this
> sentence should disappear because it's misleading.
> 
>>  >> >>  >>  + */
>>  >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, 
>> >> uint8_t >> *buf,
>>  >>  >>  +				   int oob_required, int page)
>>  >>  >>  +{
>>  >>  >>  +	struct mtd_info *mtd = nand_to_mtd(chip);
>>  >>  >>  +	int i, eccsize = chip->ecc.size, ret;
>>  >>  >>  +	int eccbytes = chip->ecc.bytes;
>>  >>  >>  +	int eccsteps = chip->ecc.steps;
>>  >>  >>  +	uint8_t *p = buf;
>>  >>  >>  +	uint8_t *ecc_code = chip->ecc.code_buf;
>>  >>  >>  +	unsigned int max_bitflips = 0;
>>  >>  >>  +
>>  >>  >>  +	/* Read the OOB area first */
>>  >>  >>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> 
>> >> mtd->oobsize);
>>  >>  >>  +	if (ret)
>>  >>  >>  +		return ret;
>>  >>  >>  +
>>  >>  >>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);
>>  >>  >
>>  >>  > Definitely not, your are requesting the chip to do the 
>> read_page
>>  >>  > operation twice. You only need a nand_change_read_column I >> 
>> believe.
>>  >> >>  Again, this code is just being moved around - don't shoot 
>> the >> messenger :)
>>  >
>>  > haha
>>  >
>>  > Well, now you touch the core, so I need to be more careful, and 
>> the
>>  > code is definitely wrong, so even if we don't move that code off, 
>> you
>>  > definitely want to fix it in order to improve your performances.
>> 
>>  I don't see the read_page being done twice?
>> 
>>  There's one read_oob, one read_page, then read_data in the loop.
> 
> read_oob and read_page both end up sending READ0 and READSTART so
> they do request the chip to perform an internal read twice. You
> need this only once. The call to nand_read_page_op() should be a
> nand_change_read_column() with no data requested.

OK.

> 
>>  >>  >>   /**
>>  >>  >>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC >> 
>> syndrome >> based page read
>>  >>  >>    * @chip: nand chip info structure
>>  >>  >>  diff --git a/include/linux/mtd/rawnand.h >> >> 
>> b/include/linux/mtd/rawnand.h
>>  >>  >>  index b2f9dd3cbd69..5b88cd51fadb 100644
>>  >>  >>  --- a/include/linux/mtd/rawnand.h
>>  >>  >>  +++ b/include/linux/mtd/rawnand.h
>>  >>  >>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct 
>> nand_chip >> *chip, >> void *buf, unsigned int len,
>>  >>  >>   		      bool force_8bit, bool check_only);
>>  >>  >>   int nand_write_data_op(struct nand_chip *chip, const void 
>> *buf,
>>  >>  >>   		       unsigned int len, bool force_8bit);
>>  >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, 
>> >> uint8_t >> *buf,
>>  >>  >>  +				   int oob_required, int page);
>>  >>  >
>>  >>  > You certainly want to add this symbol closer to the other >> 
>> read/write
>>  >>  > page helpers?
>>  >> >>  Where would that be? The other read/write page helpers are 
>> all >> "static" so they don't appear in any header.
>>  >
>>  > I believe we should keep this header local as long as there are no
>>  > other users.
>> 
>>  I'll move it to internal.h then.
> 
> Why do you want to put it there is there is only one user?

But there are two users: davinci_nand.c and (with patch [3/3]) 
ingenic/ingenic_nand_drv.c.

-Paul




From miquel.raynal at bootlin.com  Fri Oct 15 02:44:46 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 11:44:46 +0200
Subject: [PATCH 2/3] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <CRI01R.KF0NPTKK5WYV1@crapouillou.net>
References: <20211009184952.24591-1-paul@crapouillou.net>
 <20211009184952.24591-3-paul@crapouillou.net>
 <20211015081313.60018976@xps13>
 <70G01R.2VROMW06O3O83@crapouillou.net>
 <20211015105146.3d2fbd08@xps13>
 <89I01R.QTBARVYLTBT02@crapouillou.net>
 <20211015113515.7b10a2d5@xps13>
 <CRI01R.KF0NPTKK5WYV1@crapouillou.net>
Message-ID: <20211015114446.6a939367@xps13>

Hi Paul,

paul at crapouillou.net wrote on Fri, 15 Oct 2021 10:38:00 +0100:

> Hi,
> 
> Le ven., oct. 15 2021 at 11:35:15 +0200, Miquel Raynal <miquel.raynal at bootlin.com> a ?crit :
> > Hi Paul,
> >   
> >>  >>  */  
> >>  >>  >> >>   /* An ECC layout for using 4-bit ECC with small-page >> flash, >> storing  
> >>  >>  >>  @@ -648,7 +580,7 @@ static int >> davinci_nand_attach_chip(struct >> >> nand_chip *chip)
> >>  >>  >>   			} else if (chunks == 4 || chunks == 8) {
> >>  >>  >>   				mtd_set_ooblayout(mtd,
> >>  >>  >>   						  nand_get_large_page_ooblayout());
> >>  >>  >>  -				chip->ecc.read_page = >> >> nand_davinci_read_page_hwecc_oob_first;
> >>  >>  >>  +				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
> >>  >>  >>   			} else {
> >>  >>  >>   				return -EIO;
> >>  >>  >>   			}
> >>  >>  >>  diff --git a/drivers/mtd/nand/raw/nand_base.c >> >> >> b/drivers/mtd/nand/raw/nand_base.c
> >>  >>  >>  index 3d6c6e880520..cb5f343b9fa2 100644
> >>  >>  >>  --- a/drivers/mtd/nand/raw/nand_base.c
> >>  >>  >>  +++ b/drivers/mtd/nand/raw/nand_base.c
> >>  >>  >>  @@ -3160,6 +3160,75 @@ static int >> nand_read_page_hwecc(struct >> >> nand_chip *chip, uint8_t *buf,
> >>  >>  >>   	return max_bitflips;
> >>  >>  >>   }  
> >>  >>  >> >>  +/**  
> >>  >>  >>  + * nand_read_page_hwecc_oob_first - Hardware ECC page read >> >> with ECC
> >>  >>  >>  + *                                  data read from OOB area
> >>  >>  >>  + * @chip: nand chip info structure
> >>  >>  >>  + * @buf: buffer to store read data
> >>  >>  >>  + * @oob_required: caller requires OOB data read to >> >> chip->oob_poi
> >>  >>  >>  + * @page: page number to read
> >>  >>  >>  + *
> >>  >>  >>  + * Hardware ECC for large page chips, require OOB to be >> read >> >> first. For this  
> >>  >>  >
> >>  >>  > requires
> >>  >>  >
> >>  >>  > With this ECC configuration?
> >>  >>  >  
> >>  >>  >>  + * ECC mode, the write_page method is re-used from ECC_HW. >> >> These >> methods  
> >>  >>  >
> >>  >>  > I do not understand this sentence nor the next one about >> >> syndrome. I
> >>  >>  > believe it is related to your engine and should not leak into >> the >> > core.
> >>  >>  >  
> >>  >>  >>  + * read/write ECC from the OOB area, unlike the >> >> ECC_HW_SYNDROME >> support with
> >>  >>  >>  + * multiple ECC steps, follows the "infix ECC" scheme and >> >> >> reads/writes ECC from
> >>  >>  >>  + * the data area, by overwriting the NAND manufacturer bad >> >> block >> markings.  
> >>  >>  >
> >>  >>  > That's a sentence I don't like. What do you mean exactly?
> >>  >>  >
> >>  >>  > What "Infix ECC" scheme is?
> >>  >>  >
> >>  >>  > Do you mean that unlike the syndrome  mode it *does not* >> >> overwrite the
> >>  >>  > BBM ?  
> >>  >> >>  I don't mean anything. I did not write that comment. I just >> moved >> the function verbatim with no changes. If something needs >> to be >> fixed, then it needs to be fixed before/after this patch.  
> >>  >
> >>  > Well, this comment should be adapted because as-is I don't think >> it's
> >>  > wise to move it around.  
> >> >>  OK.
> >> >>  I think it says that BBM can be overwritten with this >> configuration, but that would be if the OOB layout covers the BBM >> area.  
> > 
> > If the ooblayout prevents the BBM to be smatched I'm fine and this
> > sentence should disappear because it's misleading.
> >   
> >>  >> >>  >>  + */  
> >>  >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, >> >> uint8_t >> *buf,
> >>  >>  >>  +				   int oob_required, int page)
> >>  >>  >>  +{
> >>  >>  >>  +	struct mtd_info *mtd = nand_to_mtd(chip);
> >>  >>  >>  +	int i, eccsize = chip->ecc.size, ret;
> >>  >>  >>  +	int eccbytes = chip->ecc.bytes;
> >>  >>  >>  +	int eccsteps = chip->ecc.steps;
> >>  >>  >>  +	uint8_t *p = buf;
> >>  >>  >>  +	uint8_t *ecc_code = chip->ecc.code_buf;
> >>  >>  >>  +	unsigned int max_bitflips = 0;
> >>  >>  >>  +
> >>  >>  >>  +	/* Read the OOB area first */
> >>  >>  >>  +	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, >> >> >> mtd->oobsize);
> >>  >>  >>  +	if (ret)
> >>  >>  >>  +		return ret;
> >>  >>  >>  +
> >>  >>  >>  +	ret = nand_read_page_op(chip, page, 0, NULL, 0);  
> >>  >>  >
> >>  >>  > Definitely not, your are requesting the chip to do the >> read_page
> >>  >>  > operation twice. You only need a nand_change_read_column I >> >> believe.  
> >>  >> >>  Again, this code is just being moved around - don't shoot >> the >> messenger :)  
> >>  >
> >>  > haha
> >>  >
> >>  > Well, now you touch the core, so I need to be more careful, and >> the
> >>  > code is definitely wrong, so even if we don't move that code off, >> you
> >>  > definitely want to fix it in order to improve your performances.  
> >> >>  I don't see the read_page being done twice?
> >> >>  There's one read_oob, one read_page, then read_data in the loop.  
> > 
> > read_oob and read_page both end up sending READ0 and READSTART so
> > they do request the chip to perform an internal read twice. You
> > need this only once. The call to nand_read_page_op() should be a
> > nand_change_read_column() with no data requested.  
> 
> OK.
> 
> >   
> >>  >>  >>   /**
> >>  >>  >>    * nand_read_page_syndrome - [REPLACEABLE] hardware ECC >> >> syndrome >> based page read
> >>  >>  >>    * @chip: nand chip info structure
> >>  >>  >>  diff --git a/include/linux/mtd/rawnand.h >> >> >> b/include/linux/mtd/rawnand.h
> >>  >>  >>  index b2f9dd3cbd69..5b88cd51fadb 100644
> >>  >>  >>  --- a/include/linux/mtd/rawnand.h
> >>  >>  >>  +++ b/include/linux/mtd/rawnand.h
> >>  >>  >>  @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct >> nand_chip >> *chip, >> void *buf, unsigned int len,
> >>  >>  >>   		      bool force_8bit, bool check_only);
> >>  >>  >>   int nand_write_data_op(struct nand_chip *chip, const void >> *buf,
> >>  >>  >>   		       unsigned int len, bool force_8bit);
> >>  >>  >>  +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, >> >> uint8_t >> *buf,
> >>  >>  >>  +				   int oob_required, int page);  
> >>  >>  >
> >>  >>  > You certainly want to add this symbol closer to the other >> >> read/write
> >>  >>  > page helpers?  
> >>  >> >>  Where would that be? The other read/write page helpers are >> all >> "static" so they don't appear in any header.  
> >>  >
> >>  > I believe we should keep this header local as long as there are no
> >>  > other users.  
> >> >>  I'll move it to internal.h then.  
> > 
> > Why do you want to put it there is there is only one user?  
> 
> But there are two users: davinci_nand.c and (with patch [3/3]) ingenic/ingenic_nand_drv.c.

Oh right I missed that :)

Then please add two preparation patches which:
- fixes the comment (please reword it completely)
- avoid the double reading

And keep the location where you moved it (including the header) as-is.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Fri Oct 15 03:16:31 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:16:31 +0200
Subject: [GIT PULL] mtd: Fixes for 5.15-rc6
Message-ID: <20211015121631.2d9fa93c@xps13>

Hello Linus,

This is a very small MTD fixes PR for the next -rc.

Thanks,
Miqu?l


The following changes since commit 6880fa6c56601bb8ed59df6c30fd390cc5f6dd8f:

  Linux 5.15-rc1 (2021-09-12 16:28:37 -0700)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git tags/mtd/fixes-for-5.15-rc6

for you to fetch changes up to f60f5741002b9fde748cff65fd09bd6222c5db0c:

  mtd: rawnand: qcom: Update code word value for raw read (2021-09-14 19:36:00 +0200)

----------------------------------------------------------------
Raw NAND controller driver change:
* Qcom: Update code word value for raw reads (QPIC v2+)

----------------------------------------------------------------
Md Sadre Alam (1):
      mtd: rawnand: qcom: Update code word value for raw read

 drivers/mtd/nand/raw/qcom_nandc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:07 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:07 +0200
Subject: [PATCH] mtd: core: don't remove debugfs directory if device is in
 use
In-Reply-To: <20211014203953.5424-1-zev@bewilderbeest.net>
Message-ID: <20211015103107.948869-1-miquel.raynal@bootlin.com>

On Thu, 2021-10-14 at 20:39:52 UTC, Zev Weiss wrote:
> Previously, if del_mtd_device() failed with -EBUSY due to a non-zero
> usecount, a subsequent call to attempt the deletion again would try to
> remove a debugfs directory that had already been removed and panic.
> With this change the second call can instead proceed safely.
> 
> Fixes: e8e3edb95ce6 ("mtd: create per-device and module-scope debugfs entries")
> Signed-off-by: Zev Weiss <zev at bewilderbeest.net>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:16 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:16 +0200
Subject: [PATCH] MAINTAINERS: Update the devicetree documentation path of
 hyperbus
In-Reply-To: <20211014110614.3320-1-caihuoqing@baidu.com>
Message-ID: <20211015103116.948934-1-miquel.raynal@bootlin.com>

On Thu, 2021-10-14 at 11:06:14 UTC, Cai Huoqing wrote:
> Change the devicetree documentation path
> to "Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml"
> since 'cypress,hyperflash.txt' and 'ti,am654-hbmc.txt' have
> been converted to 'ti,am654-hbmc.yaml'.
> 
> Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:21 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:21 +0200
Subject: [PATCH v3 2/2] mtd: block2mtd: add support for an optional custom
 MTD label
In-Reply-To: <20211009060955.552636-3-troglobit@gmail.com>
Message-ID: <20211015103121.948998-1-miquel.raynal@bootlin.com>

On Sat, 2021-10-09 at 06:09:55 UTC, Joachim Wiberg wrote:
> This patch adds support for an optional MTD label for mtd2block emulated
> MTD devices.  Useful when, e.g., testing device images using Qemu.
> 
> The following line in /etc/fstab can then be used to mount a file system
> regardless if running on an embedded system, or emulated with block2mtd:
> 
>     mtd:Config  /mnt    jffs2   noatime,nodiratime      0    0
> 
> Kernel command line syntax in the emulated case:
> 
>     block2mtd.block2mtd=/dev/sda,,Config
> 
> Notice the ',,' it is the optional erase_size, which like before this
> patch, defaults to PAGE_SIZE when omitted.  Hence the strlen() check.
> 
> Signed-off-by: Joachim Wiberg <troglobit at gmail.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:25 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:25 +0200
Subject: [PATCH v3 1/2] mtd: block2mtd: minor refactor to avoid hard coded
 constant
In-Reply-To: <20211009060955.552636-2-troglobit@gmail.com>
Message-ID: <20211015103125.949063-1-miquel.raynal@bootlin.com>

On Sat, 2021-10-09 at 06:09:54 UTC, Joachim Wiberg wrote:
> Signed-off-by: Joachim Wiberg <troglobit at gmail.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:30 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:30 +0200
Subject: [PATCH] [RFC] mtd: fixup CFI on ixp4xx
In-Reply-To: <20210927141045.1597593-1-arnd@kernel.org>
Message-ID: <20211015103130.949127-1-miquel.raynal@bootlin.com>

On Mon, 2021-09-27 at 14:10:37 UTC, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd at arndb.de>
> 
> drivers/mtd/maps/ixp4xx.c requires MTD_CFI_BE_BYTE_SWAP to be set
> in order to compile.
> 
> drivers/mtd/maps/ixp4xx.c:57:4: error: #error CONFIG_MTD_CFI_BE_BYTE_SWAP required
> 
> This patch avoids the #error output by enforcing the policy in
> Kconfig. Not sure if this is the right approach, but it helps doing
> randconfig builds.
> 
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> Acked-by: Linus Walleij <linus.walleij at linaro.org>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:40 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:40 +0200
Subject: [PATCH v2] mtd: rawnand: arasan: Prevent an unsupported
 configuration
In-Reply-To: <20211008163640.1753821-1-miquel.raynal@bootlin.com>
Message-ID: <20211015103140.949192-1-miquel.raynal@bootlin.com>

On Fri, 2021-10-08 at 16:36:40 UTC, Miquel Raynal wrote:
> Under the following conditions:
> * after rounding up by 4 the number of bytes to transfer (this is
>   related to the controller's internal constraints),
> * if this (rounded) amount of data is situated beyond the end of the
>   device,
> * and only in NV-DDR mode,
> the Arasan NAND controller timeouts.
> 
> This currently can happen in a particular helper used when picking
> software ECC algorithms. Let's prevent this situation by refusing to use
> the NV-DDR interface with software engines.
> 
> Fixes: 4edde6031458 ("mtd: rawnand: arasan: Support NV-DDR interface")
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:46 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:46 +0200
Subject: [PATCH] MAINTAINERS: Add entry for Qualcomm NAND controller driver
In-Reply-To: <20211004123926.53462-1-manivannan.sadhasivam@linaro.org>
Message-ID: <20211015103146.949256-1-miquel.raynal@bootlin.com>

On Mon, 2021-10-04 at 12:39:26 UTC, Manivannan Sadhasivam wrote:
> Since I maintain the dt-binding for this controller, I'm stepping
> forward to maintain the driver also.
> 
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam at linaro.org>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:50 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:50 +0200
Subject: [PATCH] mtd: rawnand: hynix: Add support for H27UCG8T2ETR-BC MLC
 NAND
In-Reply-To: <20210930162402.344-1-macroalpha82@gmail.com>
Message-ID: <20211015103150.949320-1-miquel.raynal@bootlin.com>

On Thu, 2021-09-30 at 16:24:02 UTC, Chris Morgan wrote:
> From: Chris Morgan <macromorgan at hotmail.com>
> 
> Add support for the H27UCG8T2ETR-BC MLC NAND. The NAND is used widely
> in the NTC CHIP, is an MLC type NAND, and is 8GB in size. Neither
> JEDEC nor ONFI detection identifies it correctly, so the ID is added
> to the nand_ids.c file. Additionally, per the datasheet this NAND
> appears to use the same paired pages scheme as the Toshiba
> TC58TEG5DCLTA00 (dist3), so add support for that to enable use in
> SLC emulation mode.
> 
> Tested on a NTC CHIP the device is able to write to a ubifs formatted
> partition, and then have U-Boot (with proposed patches) boot from a
> kernel located on that ubifs formatted partition.
> 
> Signed-off-by: Chris Morgan <macromorgan at hotmail.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next, thanks.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:31:55 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:31:55 +0200
Subject: [PATCH 9/9] mtd: rawnand: xway: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20210928222258.199726-10-miquel.raynal@bootlin.com>
Message-ID: <20211015103155.949385-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:48 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: d525914b5bd8 ("mtd: rawnand: xway: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Cc: Jan Hoffmann <jan at 3e8.eu>
> Cc: Kestrel seventyfour <kestrelseventyfour at gmail.com>
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> Tested-by: Jan Hoffmann <jan at 3e8.eu>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:00 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:00 +0200
Subject: [PATCH 8/9] mtd: rawnand: socrates: Keep the driver compatible
 with on-die ECC engines
In-Reply-To: <20210928222258.199726-9-miquel.raynal@bootlin.com>
Message-ID: <20211015103200.949449-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:47 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: b36bf0a0fe5d ("mtd: rawnand: socrates: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:04 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:04 +0200
Subject: [PATCH 7/9] mtd: rawnand: plat_nand: Keep the driver compatible
 with on-die ECC engines
In-Reply-To: <20210928222258.199726-8-miquel.raynal@bootlin.com>
Message-ID: <20211015103204.949513-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:46 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: 612e048e6aab ("mtd: rawnand: plat_nand: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:10 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:10 +0200
Subject: [PATCH 6/9] mtd: rawnand: pasemi: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20210928222258.199726-7-miquel.raynal@bootlin.com>
Message-ID: <20211015103210.949577-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:45 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: 8fc6f1f042b2 ("mtd: rawnand: pasemi: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:14 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:14 +0200
Subject: [PATCH 5/9] mtd: rawnand: orion: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20210928222258.199726-6-miquel.raynal@bootlin.com>
Message-ID: <20211015103214.949641-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:44 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: 553508cec2e8 ("mtd: rawnand: orion: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:18 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:18 +0200
Subject: [PATCH 4/9] mtd: rawnand: mpc5121: Keep the driver compatible
 with on-die ECC engines
In-Reply-To: <20210928222258.199726-5-miquel.raynal@bootlin.com>
Message-ID: <20211015103218.949705-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:43 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: 6dd09f775b72 ("mtd: rawnand: mpc5121: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:23 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:23 +0200
Subject: [PATCH 3/9] mtd: rawnand: gpio: Keep the driver compatible with
 on-die ECC engines
In-Reply-To: <20210928222258.199726-4-miquel.raynal@bootlin.com>
Message-ID: <20211015103223.949769-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:42 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: f6341f6448e0 ("mtd: rawnand: gpio: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:28 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:28 +0200
Subject: [PATCH 2/9] mtd: rawnand: au1550nd: Keep the driver compatible
 with on-die ECC engines
In-Reply-To: <20210928222258.199726-3-miquel.raynal@bootlin.com>
Message-ID: <20211015103228.949834-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:41 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: dbffc8ccdf3a ("mtd: rawnand: au1550: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:34 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:34 +0200
Subject: [PATCH 1/9] mtd: rawnand: ams-delta: Keep the driver compatible
 with on-die ECC engines
In-Reply-To: <20210928222258.199726-2-miquel.raynal@bootlin.com>
Message-ID: <20211015103234.949898-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:22:40 UTC, Miquel Raynal wrote:
> Following the introduction of the generic ECC engine infrastructure, it
> was necessary to reorganize the code and move the ECC configuration in
> the ->attach_chip() hook. Failing to do that properly lead to a first
> series of fixes supposed to stabilize the situation. Unfortunately, this
> only fixed the use of software ECC engines, preventing any other kind of
> engine to be used, including on-die ones.
> 
> It is now time to (finally) fix the situation by ensuring that we still
> provide a default (eg. software ECC) but will still support different
> ECC engines such as on-die ECC engines if properly described in the
> device tree.
> 
> There are no changes needed on the core side in order to do this, but we
> just need to leverage the logic there which allows:
> 1- a subsystem default (set to Host engines in the raw NAND world)
> 2- a driver specific default (here set to software ECC engines)
> 3- any type of engine requested by the user (ie. described in the DT)
> 
> As the raw NAND subsystem has not yet been fully converted to the ECC
> engine infrastructure, in order to provide a default ECC engine for this
> driver we need to set chip->ecc.engine_type *before* calling
> nand_scan(). During the initialization step, the core will consider this
> entry as the default engine for this driver. This value may of course
> be overloaded by the user if the usual DT properties are provided.
> 
> Fixes: 59d93473323a ("mtd: rawnand: ams-delta: Move the ECC initialization to ->attach_chip()")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:39 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:39 +0200
Subject: [PATCH 8/8] Revert "mtd: rawnand: cs553x: Fix external use of SW
 Hamming ECC helper"
In-Reply-To: <20210928221507.199198-9-miquel.raynal@bootlin.com>
Message-ID: <20211015103239.949962-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:07 UTC, Miquel Raynal wrote:
> This reverts commit 56a8d3fd1f342d10ee7b27e9ac0f4d00b5fbb91c.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:44 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:44 +0200
Subject: [PATCH 7/8] Revert "mtd: rawnand: lpc32xx_slc: Fix external use
 of SW Hamming ECC helper"
In-Reply-To: <20210928221507.199198-8-miquel.raynal@bootlin.com>
Message-ID: <20211015103244.950026-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:06 UTC, Miquel Raynal wrote:
> This reverts commit c4b7d7c480d607e4f52d310d9d16b194868d0917.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:51 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:51 +0200
Subject: [PATCH 6/8] Revert "mtd: rawnand: ndfc: Fix external use of SW
 Hamming ECC helper"
In-Reply-To: <20210928221507.199198-7-miquel.raynal@bootlin.com>
Message-ID: <20211015103251.950095-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:05 UTC, Miquel Raynal wrote:
> This reverts commit 3e09c0252501829b14b10f14e1982aaab77d0b80.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:32:55 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:32:55 +0200
Subject: [PATCH 5/8] Revert "mtd: rawnand: sharpsl: Fix external use of SW
 Hamming ECC helper"
In-Reply-To: <20210928221507.199198-6-miquel.raynal@bootlin.com>
Message-ID: <20211015103255.950159-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:04 UTC, Miquel Raynal wrote:
> This reverts commit 46fcb57e6b7283533ebf8ba17a6bd30fa88bdc9f.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:33:02 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:33:02 +0200
Subject: [PATCH 4/8] Revert "mtd: rawnand: tmio: Fix external use of SW
 Hamming ECC helper"
In-Reply-To: <20210928221507.199198-5-miquel.raynal@bootlin.com>
Message-ID: <20211015103302.950223-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:03 UTC, Miquel Raynal wrote:
> This reverts commit 6a4c5ada577467a5f79e06f2c5e69c09983c22fb.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:33:06 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:33:06 +0200
Subject: [PATCH 3/8] Revert "mtd: rawnand: txx9ndfmc: Fix external use of
 SW Hamming ECC helper"
In-Reply-To: <20210928221507.199198-4-miquel.raynal@bootlin.com>
Message-ID: <20211015103306.950290-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:02 UTC, Miquel Raynal wrote:
> This reverts commit 3d227a0b0ce319edbff6fd0d8af4d66689e477cc.
> 
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> The implementation of the rawnand_ecc_sw_* helpers has now been enhanced
> to support both cases, when the ECC object is instantiated and when it is
> not. This way, we can still use the existing and exported rawnand
> helpers while avoiding the need for each driver to declare its own
> helper, thus this fix from [2] can now be safely reverted.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:33:13 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:33:13 +0200
Subject: [PATCH 2/8] mtd: rawnand: Let callers use the bare Hamming helpers
In-Reply-To: <20210928221507.199198-3-miquel.raynal@bootlin.com>
Message-ID: <20211015103313.950354-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:01 UTC, Miquel Raynal wrote:
> Before the introduction of the ECC framework infrastructure, many
> drivers used the ->calculate/correct() Hamming helpers directly. The
> point of this framework was to avoid this kind of hackish calls and use a
> proper and generic API but it is true that in certain cases, drivers
> still need to use these helpers in order to do ECC computations on
> behalf of their limited hardware.
> 
> Right after the introduction of the ECC engine core introduction, it was
> spotted that it was not possible to use the shiny rawnand software ECC
> helpers so easily because an ECC engine object should have been
> allocated and initialized first. While this works well in most cases,
> for these drivers just leveraging the power of a single helper in
> conjunction with some pretty old and limited hardware, it did not fit.
> 
> The idea back then was to declare intermediate helpers which would make
> use of the exported software ECC engine bare functions while keeping the
> rawnand layer compatibility. As there was already functions with the
> rawnand_sw_hamming_ prefix it was decided to declare new local helpers
> for this purpose in each driver needing one.
> 
> Besides being far from optimal, this design choice was blamed by Linus
> when he pulled the "fixes" pull request [1] so that is why now it is
> time to clean this mess up.
> 
> Enhancing the implementation of the rawnand_ecc_sw_* helpers to support
> both cases, when the ECC object is instantiated and when it is not is a
> quite elegant way to solve this situation. This way, we can still use
> the existing and exported rawnand helpers while avoiding the need for
> each driver to declare its own helper.
> 
> Following this change, most of the fixes sent in [2] can now be safely
> reverted. Only the fsmc fix will need to be kept because there is
> actually something specific to the driver to do in its ->correct()
> helper.
> 
> [1] https://lore.kernel.org/lkml/CAHk-=wh_ZHF685Fni8V9is17mj=pFisUaZ_0=gq6nbK+ZcyQmg at mail.gmail.com/
> [2] https://lore.kernel.org/linux-mtd/20210413161840.345208-1-miquel.raynal at bootlin.com/
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From miquel.raynal at bootlin.com  Fri Oct 15 03:33:18 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Fri, 15 Oct 2021 12:33:18 +0200
Subject: [PATCH 1/8] mtd: rawnand: fsmc: Fix use of SM ORDER
In-Reply-To: <20210928221507.199198-2-miquel.raynal@bootlin.com>
Message-ID: <20211015103318.950418-1-miquel.raynal@bootlin.com>

On Tue, 2021-09-28 at 22:15:00 UTC, Miquel Raynal wrote:
> The introduction of the generic ECC engine API lead to a number of
> changes in various drivers which broke some of them. Here is a typical
> example: I expected the SM_ORDER option to be handled by the Hamming ECC
> engine internals. Problem: the fsmc driver does not instantiate (yet) a
> real ECC engine object so we had to use a 'bare' ECC helper instead of
> the shiny rawnand functions. However, when not intializing this engine
> properly and using the bare helpers, we do not get the SM ORDER feature
> handled automatically. It looks like this was lost in the process so
> let's ensure we use the right SM ORDER now.
> 
> Fixes: ad9ffdce4539 ("mtd: rawnand: fsmc: Fix external use of SW Hamming ECC helper")
> Cc: stable at vger.kernel.org
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>

Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next.

Miquel


From pr-tracker-bot at kernel.org  Fri Oct 15 07:35:10 2021
From: pr-tracker-bot at kernel.org (pr-tracker-bot at kernel.org)
Date: Fri, 15 Oct 2021 14:35:10 +0000
Subject: [GIT PULL] mtd: Fixes for 5.15-rc6
In-Reply-To: <20211015121631.2d9fa93c@xps13>
References: <20211015121631.2d9fa93c@xps13>
Message-ID: <163430851025.21069.13663451040102869717.pr-tracker-bot@kernel.org>

The pull request you sent on Fri, 15 Oct 2021 12:16:31 +0200:

> git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git tags/mtd/fixes-for-5.15-rc6

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/9e795d94deafd007bd6702679a02b82facc6e7ea

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


From zev at bewilderbeest.net  Fri Oct 15 11:50:48 2021
From: zev at bewilderbeest.net (Zev Weiss)
Date: Fri, 15 Oct 2021 11:50:48 -0700
Subject: [PATCH] mtd: core: clear out unregistered devices a bit more
Message-ID: <20211015185049.3318-1-zev@bewilderbeest.net>

This allows an MTD device that has been unregistered to be easily
re-registered later without triggering spurious "already registered"
warnings in mtd_device_parse_register() and add_mtd_device().

Signed-off-by: Zev Weiss <zev at bewilderbeest.net>
---
 drivers/mtd/mtdcore.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 153229198947..0a0fca737d43 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -747,6 +747,9 @@ int del_mtd_device(struct mtd_info *mtd)
 
 		device_unregister(&mtd->dev);
 
+		/* Clear dev so mtd can be safely re-registered later if desired */
+		memset(&mtd->dev, 0, sizeof(mtd->dev));
+
 		idr_remove(&mtd_idr, mtd->index);
 		of_node_put(mtd_get_of_node(mtd));
 
@@ -1018,8 +1021,10 @@ int mtd_device_unregister(struct mtd_info *master)
 {
 	int err;
 
-	if (master->_reboot)
+	if (master->_reboot) {
 		unregister_reboot_notifier(&master->reboot_notifier);
+		memset(&master->reboot_notifier, 0, sizeof(master->reboot_notifier));
+	}
 
 	if (master->otp_user_nvmem)
 		nvmem_unregister(master->otp_user_nvmem);
-- 
2.33.0



From michael at amarulasolutions.com  Fri Oct 15 13:05:41 2021
From: michael at amarulasolutions.com (Michael Trimarchi)
Date: Fri, 15 Oct 2021 22:05:41 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20210201161433.0c4ff0e3@xps13>
References: <00b31833-69ba-42c5-57c9-37fa1f70efc5@kernel.org>
 <20190812093129.75888dad@collabora.com>
 <a47792dc-b19f-8af3-8748-5a21fb63271e@kernel.org>
 <CAOf5uwmPzCU8WFRQ1tQBdN7OVGZZ9SvdAG0YqVAyxmA1zwtUhg@mail.gmail.com>
 <2e9e1f1c-ee57-425d-1791-70c66de52637@kernel.org>
 <CAOf5uwm93+ARf=_BckjMar1tpeBs6YHeUwORj5cyhFfvu5fNWQ@mail.gmail.com>
 <20210201151335.210af8ca@xps13>
 <CAOf5uwkivHhMX_mPJymBZxQge_wc4K1p_1S3gsQYHPV40aaj3w@mail.gmail.com>
 <CAOf5uwnXB-2xXXXxvH9Fo3ngscccA5Hv7iNTbUYRNFs_iLGJqw@mail.gmail.com>
 <20210201161433.0c4ff0e3@xps13>
Message-ID: <20211015200541.GA55401@panicking>

Hi

On Mon, Feb 01, 2021 at 04:14:33PM +0100, Miquel Raynal wrote:
> Hi Michael,
> 
> Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> Mon, 1 Feb 2021 16:08:23 +0100:
> 
> > Hi
> > 
> > On Mon, Feb 1, 2021 at 3:32 PM Michael Nazzareno Trimarchi
> > <michael at amarulasolutions.com> wrote:
> > >
> > > Hi
> > >
> > > On Mon, Feb 1, 2021 at 3:13 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:  
> > > >
> > > > Hi Michael,
> > > >
> > > > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > > > Sat, 30 Jan 2021 10:41:29 +0100:
> > > >  
> > > > > Hi Miquel
> > > > >
> > > > > commit f8e6ad14388067f91b26d044185d95623fbc9535
> > > > > Author: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > Date:   Fri Jan 29 08:46:53 2021 +0100
> > > > >
> > > > >     mtd: nand: Calculate the clock before enable it
> > > > >
> > > > >     Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> > > > >     Change-Id: I79b0da39de0a9b32ea0b002fa200d7f44d4f8ce7
> > > > >
> > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > index 322a008290e5..0bca52b3bc8f 100644
> > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > @@ -377,6 +377,7 @@ static void gpmi_nfc_compute_timings(struct
> > > > > gpmi_nand_data *this,
> > > > >                                      const struct nand_sdr_timings *sdr)
> > > > >  {
> > > > >         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > > +       struct resources *r = &this->resources;
> > > > >         unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
> > > > >         unsigned int period_ps, reference_period_ps;
> > > > >         unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
> > > > > @@ -440,6 +441,8 @@ static void gpmi_nfc_compute_timings(struct
> > > > > gpmi_nand_data *this,
> > > > >                 hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
> > > > >                               BM_GPMI_CTRL1_DLL_ENABLE |
> > > > >                               (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
> > > > > +
> > > > > +       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > >  }
> > > > >
> > > > >  void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > @@ -449,8 +452,6 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > >         void __iomem *gpmi_regs = r->gpmi_regs;
> > > > >         unsigned int dll_wait_time_us;
> > > > >
> > > > > -       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > -
> > > > >         writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > >         writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > >
> > > > > Right now I have this change applied and seems fine. That is the only
> > > > > difference I get. Clock is apply a bit earlier that when is enabled
> > > > > it.  
> > > >
> > > > This is very interesting. So this would mean the issue you are
> > > > experiencing comes from the clock driver which kind of returns too
> > > > early from clk_set_rate()? Could you report this to the clk ML/NXP clk
> > > > maintainers and keep us in copy? If it is as global as it sounds, we
> > > > might not be the only ones affected.
> > > >  
> > >
> > > The imx28 is broken too, so it's a general problem. I need to trace it down
> > > I have a reverting for lts but it\s not the way to go
> > >  
> > 
> > For imx28 you ask to set the rate to 22Mhz but you don't care about the clock
> > that you get back. You get back 12Mhz because the base clock is 24 Mhz and seems
> > that it can not get the point. You need to check if the clock
> > requested is in range or ask
> > for set_rate_clk_min to avoid to have somenthing lower. Then for
> > imx6ull because is sporadic
> > I think that is more connected to the clk_set_rate and when you change
> > the register. Can not be a
> > setting time?
> 
> So, if I understand correctly, we face two different problems:
> - imx6*: seems like a clock issue regarding the clock settlement
> - imx28: actual NAND driver issue (does not check the validity of the
>   new frequency). This should be handled properly in
>   ->setup_interface().
>

Somenthing like this? Not compile/tested

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 4d08e4ab5c1b..cc8146ab1b78 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -644,7 +644,7 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
  *         RDN_DELAY = -----------------------     {3}
  *                           RP
  */
-static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
+static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
 				     const struct nand_sdr_timings *sdr)
 {
 	struct gpmi_nfc_hardware_timing *hw = &this->hw;
@@ -656,6 +656,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
 	int sample_delay_ps, sample_delay_factor;
 	u16 busy_timeout_cycles;
 	u8 wrn_dly_sel;
+	long clk_rate;
 
 	if (sdr->tRC_min >= 30000) {
 		/* ONFI non-EDO modes [0-3] */
@@ -671,6 +672,10 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
 		wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
 	}
 
+	clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
+	if (clk_rate < hw->clk_rate || clk_rate <= 0)
+		return -ENOTSUPP;
+
 	/* SDR core timings are given in picoseconds */
 	period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
 
@@ -746,6 +751,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
 {
 	struct gpmi_nand_data *this = nand_get_controller_data(chip);
 	const struct nand_sdr_timings *sdr;
+	int ret = 0;
 
 	/* Retrieve required NAND timings */
 	sdr = nand_get_sdr_timings(conf);
@@ -761,11 +767,11 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
 		return 0;
 
 	/* Do the actual derivation of the controller timings */
-	gpmi_nfc_compute_timings(this, sdr);
-
-	this->hw.must_apply_timings = true;
+	ret = gpmi_nfc_compute_timings(this, sdr);
+	if (!ret)
+		this->hw.must_apply_timings = true;
 
-	return 0;
+	return ret;
 }
 
 /* Clears a BCH interrupt. */
> Thanks,
> Miqu?l


From michael at amarulasolutions.com  Fri Oct 15 13:12:50 2021
From: michael at amarulasolutions.com (Michael Nazzareno Trimarchi)
Date: Fri, 15 Oct 2021 22:12:50 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211015200541.GA55401@panicking>
References: <00b31833-69ba-42c5-57c9-37fa1f70efc5@kernel.org>
 <20190812093129.75888dad@collabora.com>
 <a47792dc-b19f-8af3-8748-5a21fb63271e@kernel.org>
 <CAOf5uwmPzCU8WFRQ1tQBdN7OVGZZ9SvdAG0YqVAyxmA1zwtUhg@mail.gmail.com>
 <2e9e1f1c-ee57-425d-1791-70c66de52637@kernel.org>
 <CAOf5uwm93+ARf=_BckjMar1tpeBs6YHeUwORj5cyhFfvu5fNWQ@mail.gmail.com>
 <20210201151335.210af8ca@xps13>
 <CAOf5uwkivHhMX_mPJymBZxQge_wc4K1p_1S3gsQYHPV40aaj3w@mail.gmail.com>
 <CAOf5uwnXB-2xXXXxvH9Fo3ngscccA5Hv7iNTbUYRNFs_iLGJqw@mail.gmail.com>
 <20210201161433.0c4ff0e3@xps13> <20211015200541.GA55401@panicking>
Message-ID: <CAOf5uw=26LZ9O9zqovo6enwRnA6DE398M4fqj_jKsKfShOLNUQ@mail.gmail.com>

Hi

On Fri, Oct 15, 2021 at 10:05 PM Michael Trimarchi
<michael at amarulasolutions.com> wrote:
>
> Hi
>
> On Mon, Feb 01, 2021 at 04:14:33PM +0100, Miquel Raynal wrote:
> > Hi Michael,
> >
> > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > Mon, 1 Feb 2021 16:08:23 +0100:
> >
> > > Hi
> > >
> > > On Mon, Feb 1, 2021 at 3:32 PM Michael Nazzareno Trimarchi
> > > <michael at amarulasolutions.com> wrote:
> > > >
> > > > Hi
> > > >
> > > > On Mon, Feb 1, 2021 at 3:13 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> > > > >
> > > > > Hi Michael,
> > > > >
> > > > > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > > > > Sat, 30 Jan 2021 10:41:29 +0100:
> > > > >
> > > > > > Hi Miquel
> > > > > >
> > > > > > commit f8e6ad14388067f91b26d044185d95623fbc9535
> > > > > > Author: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > Date:   Fri Jan 29 08:46:53 2021 +0100
> > > > > >
> > > > > >     mtd: nand: Calculate the clock before enable it
> > > > > >
> > > > > >     Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > >     Change-Id: I79b0da39de0a9b32ea0b002fa200d7f44d4f8ce7
> > > > > >
> > > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > index 322a008290e5..0bca52b3bc8f 100644
> > > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > @@ -377,6 +377,7 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > gpmi_nand_data *this,
> > > > > >                                      const struct nand_sdr_timings *sdr)
> > > > > >  {
> > > > > >         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > > > +       struct resources *r = &this->resources;
> > > > > >         unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
> > > > > >         unsigned int period_ps, reference_period_ps;
> > > > > >         unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
> > > > > > @@ -440,6 +441,8 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > gpmi_nand_data *this,
> > > > > >                 hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
> > > > > >                               BM_GPMI_CTRL1_DLL_ENABLE |
> > > > > >                               (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
> > > > > > +
> > > > > > +       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > >  }
> > > > > >
> > > > > >  void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > @@ -449,8 +452,6 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > >         void __iomem *gpmi_regs = r->gpmi_regs;
> > > > > >         unsigned int dll_wait_time_us;
> > > > > >
> > > > > > -       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > -
> > > > > >         writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > > >         writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > > >
> > > > > > Right now I have this change applied and seems fine. That is the only
> > > > > > difference I get. Clock is apply a bit earlier that when is enabled
> > > > > > it.
> > > > >
> > > > > This is very interesting. So this would mean the issue you are
> > > > > experiencing comes from the clock driver which kind of returns too
> > > > > early from clk_set_rate()? Could you report this to the clk ML/NXP clk
> > > > > maintainers and keep us in copy? If it is as global as it sounds, we
> > > > > might not be the only ones affected.
> > > > >
> > > >
> > > > The imx28 is broken too, so it's a general problem. I need to trace it down
> > > > I have a reverting for lts but it\s not the way to go
> > > >
> > >
> > > For imx28 you ask to set the rate to 22Mhz but you don't care about the clock
> > > that you get back. You get back 12Mhz because the base clock is 24 Mhz and seems
> > > that it can not get the point. You need to check if the clock
> > > requested is in range or ask
> > > for set_rate_clk_min to avoid to have somenthing lower. Then for
> > > imx6ull because is sporadic
> > > I think that is more connected to the clk_set_rate and when you change
> > > the register. Can not be a
> > > setting time?
> >
> > So, if I understand correctly, we face two different problems:
> > - imx6*: seems like a clock issue regarding the clock settlement
> > - imx28: actual NAND driver issue (does not check the validity of the
> >   new frequency). This should be handled properly in
> >   ->setup_interface().
> >
>
> Somenthing like this? Not compile/tested
>
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 4d08e4ab5c1b..cc8146ab1b78 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -644,7 +644,7 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
>   *         RDN_DELAY = -----------------------     {3}
>   *                           RP
>   */
> -static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> +static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>                                      const struct nand_sdr_timings *sdr)
>  {
>         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> @@ -656,6 +656,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>         int sample_delay_ps, sample_delay_factor;
>         u16 busy_timeout_cycles;
>         u8 wrn_dly_sel;
> +       long clk_rate;
>
>         if (sdr->tRC_min >= 30000) {
>                 /* ONFI non-EDO modes [0-3] */
> @@ -671,6 +672,10 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>                 wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
>         }
>
> +       clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
> +       if (clk_rate < hw->clk_rate || clk_rate <= 0)
> +               return -ENOTSUPP;
> +
>         /* SDR core timings are given in picoseconds */
>         period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);

Not sure here or:

period_ps = div_u64((u64)NSEC_PER_SEC * 1000, clk_rate);

Michael

>
> @@ -746,6 +751,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
>  {
>         struct gpmi_nand_data *this = nand_get_controller_data(chip);
>         const struct nand_sdr_timings *sdr;
> +       int ret = 0;
>
>         /* Retrieve required NAND timings */
>         sdr = nand_get_sdr_timings(conf);
> @@ -761,11 +767,11 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
>                 return 0;
>
>         /* Do the actual derivation of the controller timings */
> -       gpmi_nfc_compute_timings(this, sdr);
> -
> -       this->hw.must_apply_timings = true;
> +       ret = gpmi_nfc_compute_timings(this, sdr);
> +       if (!ret)
> +               this->hw.must_apply_timings = true;
>
> -       return 0;
> +       return ret;
>  }
>
>  /* Clears a BCH interrupt. */
> > Thanks,
> > Miqu?l


From mcgrof at kernel.org  Fri Oct 15 16:30:20 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:20 -0700
Subject: [PATCH 1/9] scsi/sd: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-2-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

As with the error handling for device_add() we follow the same
logic and just put the device so that cleanup is done via the
scsi_disk_release().

Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/scsi/sd.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a646d27df681..d69f2e626e76 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3457,7 +3457,13 @@ static int sd_probe(struct device *dev)
 		pm_runtime_set_autosuspend_delay(dev,
 			sdp->host->hostt->rpm_autosuspend_delay);
 	}
-	device_add_disk(dev, gd, NULL);
+
+	error = device_add_disk(dev, gd, NULL);
+	if (error) {
+		put_device(&sdkp->dev);
+		goto out;
+	}
+
 	if (sdkp->capacity)
 		sd_dif_config_host(sdkp);
 
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:23 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:23 -0700
Subject: [PATCH 4/9] bcache: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-5-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

This driver doesn't do any unwinding with blk_cleanup_disk()
even on errors after add_disk() and so we follow that
tradition.

Acked-by: Coly Li <colyli at suse.de>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/md/bcache/super.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index f2874c77ff79..f0c32cdd6594 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1082,7 +1082,9 @@ int bch_cached_dev_run(struct cached_dev *dc)
 		closure_sync(&cl);
 	}
 
-	add_disk(d->disk);
+	ret = add_disk(d->disk);
+	if (ret)
+		goto out;
 	bd_link_disk_holder(dc->bdev, dc->disk.disk);
 	/*
 	 * won't show up in the uevent file, use udevadm monitor -e instead
@@ -1534,10 +1536,11 @@ static void flash_dev_flush(struct closure *cl)
 
 static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
 {
+	int err = -ENOMEM;
 	struct bcache_device *d = kzalloc(sizeof(struct bcache_device),
 					  GFP_KERNEL);
 	if (!d)
-		return -ENOMEM;
+		goto err_ret;
 
 	closure_init(&d->cl, NULL);
 	set_closure_fn(&d->cl, flash_dev_flush, system_wq);
@@ -1551,9 +1554,12 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
 	bcache_device_attach(d, c, u - c->uuids);
 	bch_sectors_dirty_init(d);
 	bch_flash_dev_request_init(d);
-	add_disk(d->disk);
+	err = add_disk(d->disk);
+	if (err)
+		goto err;
 
-	if (kobject_add(&d->kobj, &disk_to_dev(d->disk)->kobj, "bcache"))
+	err = kobject_add(&d->kobj, &disk_to_dev(d->disk)->kobj, "bcache");
+	if (err)
 		goto err;
 
 	bcache_device_link(d, c, "volume");
@@ -1567,7 +1573,8 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)
 	return 0;
 err:
 	kobject_put(&d->kobj);
-	return -ENOMEM;
+err_ret:
+	return err;
 }
 
 static int flash_devs_run(struct cache_set *c)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:25 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:25 -0700
Subject: [PATCH 6/9] m68k/emu/nfblock: add error handling support for
 add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-7-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Reviewed-by: Geert Uytterhoeven <geert at linux-m68k.org>
Acked-by: Geert Uytterhoeven <geert at linux-m68k.org>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 arch/m68k/emu/nfblock.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/m68k/emu/nfblock.c b/arch/m68k/emu/nfblock.c
index 9a8394e96388..4de5a6087034 100644
--- a/arch/m68k/emu/nfblock.c
+++ b/arch/m68k/emu/nfblock.c
@@ -100,6 +100,7 @@ static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
 {
 	struct nfhd_device *dev;
 	int dev_id = id - NFHD_DEV_OFFSET;
+	int err = -ENOMEM;
 
 	pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id,
 		blocks, bsize);
@@ -130,16 +131,20 @@ static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
 	sprintf(dev->disk->disk_name, "nfhd%u", dev_id);
 	set_capacity(dev->disk, (sector_t)blocks * (bsize / 512));
 	blk_queue_logical_block_size(dev->disk->queue, bsize);
-	add_disk(dev->disk);
+	err = add_disk(dev->disk);
+	if (err)
+		goto out_cleanup_disk;
 
 	list_add_tail(&dev->list, &nfhd_list);
 
 	return 0;
 
+out_cleanup_disk:
+	blk_cleanup_disk(dev->disk);
 free_dev:
 	kfree(dev);
 out:
-	return -ENOMEM;
+	return err;
 }
 
 static int __init nfhd_init(void)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:22 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:22 -0700
Subject: [PATCH 3/9] dm: add add_disk() error handling
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-4-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

There are two calls to dm_setup_md_queue() which can fail then,
one on dm_early_create() and we can easily see that the error path
there calls dm_destroy in the error path. The other use case is on
the ioctl table_load case. If that fails userspace needs to call
the DM_DEV_REMOVE_CMD to cleanup the state - similar to any other
failure.

Reviewed-by: Hannes Reinecke <hare at suse.de>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/md/dm.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 245fa4153306..6d3265ed37c0 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -2086,7 +2086,9 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t)
 	if (r)
 		return r;
 
-	add_disk(md->disk);
+	r = add_disk(md->disk);
+	if (r)
+		return r;
 
 	r = dm_sysfs_init(md);
 	if (r) {
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:24 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:24 -0700
Subject: [PATCH 5/9] xen-blkfront: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-6-mcgrof@kernel.org>

We never checked for errors on device_add_disk() as this function
returned void. Now that this is fixed, use the shiny new error
handling. The function xlvbd_alloc_gendisk() typically does the
unwinding on error on allocating the disk and creating the tag,
but since all that error handling was stuffed inside
xlvbd_alloc_gendisk() we must repeat the tag free'ing as well.

We set the info->rq to NULL to ensure blkif_free() doesn't crash
on blk_mq_stop_hw_queues() on device_add_disk() error as the queue
will be long gone by then.

Reviewed-by: Juergen Gross <jgross at suse.com>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/xen-blkfront.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index df0deb927760..8e3983e456f3 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2386,7 +2386,13 @@ static void blkfront_connect(struct blkfront_info *info)
 	for_each_rinfo(info, rinfo, i)
 		kick_pending_request_queues(rinfo);
 
-	device_add_disk(&info->xbdev->dev, info->gd, NULL);
+	err = device_add_disk(&info->xbdev->dev, info->gd, NULL);
+	if (err) {
+		blk_cleanup_disk(info->gd);
+		blk_mq_free_tag_set(&info->tag_set);
+		info->rq = NULL;
+		goto fail;
+	}
 
 	info->is_ready = 1;
 	return;
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:26 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:26 -0700
Subject: [PATCH 7/9] um/drivers/ubd_kern: add error handling support for
 add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-8-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

ubd_disk_register() never returned an error, so just fix
that now and let the caller handle the error condition.

Reviewed-by: Gabriel Krisman Bertazi <krisman at collabora.com>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 arch/um/drivers/ubd_kern.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index fefd343412c7..69d2d0049a61 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -855,8 +855,8 @@ static const struct attribute_group *ubd_attr_groups[] = {
 	NULL,
 };
 
-static void ubd_disk_register(int major, u64 size, int unit,
-			      struct gendisk *disk)
+static int ubd_disk_register(int major, u64 size, int unit,
+			     struct gendisk *disk)
 {
 	disk->major = major;
 	disk->first_minor = unit << UBD_SHIFT;
@@ -873,7 +873,7 @@ static void ubd_disk_register(int major, u64 size, int unit,
 
 	disk->private_data = &ubd_devs[unit];
 	disk->queue = ubd_devs[unit].queue;
-	device_add_disk(&ubd_devs[unit].pdev.dev, disk, ubd_attr_groups);
+	return device_add_disk(&ubd_devs[unit].pdev.dev, disk, ubd_attr_groups);
 }
 
 #define ROUND_BLOCK(n) ((n + (SECTOR_SIZE - 1)) & (-SECTOR_SIZE))
@@ -920,10 +920,15 @@ static int ubd_add(int n, char **error_out)
 	blk_queue_write_cache(ubd_dev->queue, true, false);
 	blk_queue_max_segments(ubd_dev->queue, MAX_SG);
 	blk_queue_segment_boundary(ubd_dev->queue, PAGE_SIZE - 1);
-	ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, disk);
+	err = ubd_disk_register(UBD_MAJOR, ubd_dev->size, n, disk);
+	if (err)
+		goto out_cleanup_disk;
+
 	ubd_gendisk[n] = disk;
 	return 0;
 
+out_cleanup_disk:
+	blk_cleanup_disk(disk);
 out_cleanup_tags:
 	blk_mq_free_tag_set(&ubd_dev->tag_set);
 out:
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:28 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:28 -0700
Subject: [PATCH 9/9] mtd: add add_disk() error handling
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-10-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Acked-by: Miquel Raynal <miquel.raynal at bootlin.com>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/mtd/mtd_blkdevs.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index b8ae1ec14e17..4eaba6f4ec68 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -384,7 +384,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	if (new->readonly)
 		set_disk_ro(gd, 1);
 
-	device_add_disk(&new->mtd->dev, gd, NULL);
+	ret = device_add_disk(&new->mtd->dev, gd, NULL);
+	if (ret)
+		goto out_cleanup_disk;
 
 	if (new->disk_attributes) {
 		ret = sysfs_create_group(&disk_to_dev(gd)->kobj,
@@ -393,6 +395,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	}
 	return 0;
 
+out_cleanup_disk:
+	blk_cleanup_disk(new->disk);
 out_free_tag_set:
 	blk_mq_free_tag_set(new->tag_set);
 out_kfree_tag_set:
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:27 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:27 -0700
Subject: [PATCH 8/9] rnbd: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-9-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Acked-by: Jack Wang <jinpu.wang at ionos.com>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/rnbd/rnbd-clt.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/block/rnbd/rnbd-clt.c b/drivers/block/rnbd/rnbd-clt.c
index 5864c9b46cb9..3b78dc55a9a2 100644
--- a/drivers/block/rnbd/rnbd-clt.c
+++ b/drivers/block/rnbd/rnbd-clt.c
@@ -1384,8 +1384,10 @@ static void setup_request_queue(struct rnbd_clt_dev *dev)
 	blk_queue_write_cache(dev->queue, dev->wc, dev->fua);
 }
 
-static void rnbd_clt_setup_gen_disk(struct rnbd_clt_dev *dev, int idx)
+static int rnbd_clt_setup_gen_disk(struct rnbd_clt_dev *dev, int idx)
 {
+	int err;
+
 	dev->gd->major		= rnbd_client_major;
 	dev->gd->first_minor	= idx << RNBD_PART_BITS;
 	dev->gd->minors		= 1 << RNBD_PART_BITS;
@@ -1410,7 +1412,11 @@ static void rnbd_clt_setup_gen_disk(struct rnbd_clt_dev *dev, int idx)
 
 	if (!dev->rotational)
 		blk_queue_flag_set(QUEUE_FLAG_NONROT, dev->queue);
-	add_disk(dev->gd);
+	err = add_disk(dev->gd);
+	if (err)
+		blk_cleanup_disk(dev->gd);
+
+	return err;
 }
 
 static int rnbd_client_setup_device(struct rnbd_clt_dev *dev)
@@ -1426,8 +1432,7 @@ static int rnbd_client_setup_device(struct rnbd_clt_dev *dev)
 	rnbd_init_mq_hw_queues(dev);
 
 	setup_request_queue(dev);
-	rnbd_clt_setup_gen_disk(dev, idx);
-	return 0;
+	return rnbd_clt_setup_gen_disk(dev, idx);
 }
 
 static struct rnbd_clt_dev *init_dev(struct rnbd_clt_session *sess,
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:19 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:19 -0700
Subject: [PATCH 0/9] block: reviewed add_disk() error handling set
Message-ID: <20211015233028.2167651-1-mcgrof@kernel.org>

Jens,

I had last split up patches into 7 groups, but at this point now
most changes are merged except a few more drivers. Instead of creating
a new patch set for each of the 7 groups I'm creating 3 new groups of
patches now:

  * This set, for which we already have an Acked-by or Reviewed-by tag,
    it would be nice to get clarification of driver maintainers want
    these to go through you or if a the maintainers want to pick these
    changes up themselves.

  * A second set will deal with patches which have no reviews done for
    them yet 

  * The last set deals with the __register_blkdev() change and the
    __must_check change which ensures we don't let in new drivers
    which don't deal with error handling.

If you're a maintainer of any of the below patches and wish for them to
go through Jens' tree directly now would be a good time to say so or
you can just pick the patch up yourself.

Luis Chamberlain (9):
  scsi/sd: add error handling support for add_disk()
  scsi/sr: add error handling support for add_disk()
  dm: add add_disk() error handling
  bcache: add error handling support for add_disk()
  xen-blkfront: add error handling support for add_disk()
  m68k/emu/nfblock: add error handling support for add_disk()
  um/drivers/ubd_kern: add error handling support for add_disk()
  rnbd: add error handling support for add_disk()
  mtd: add add_disk() error handling

 arch/m68k/emu/nfblock.c       |  9 +++++++--
 arch/um/drivers/ubd_kern.c    | 13 +++++++++----
 drivers/block/rnbd/rnbd-clt.c | 13 +++++++++----
 drivers/block/xen-blkfront.c  |  8 +++++++-
 drivers/md/bcache/super.c     | 17 ++++++++++++-----
 drivers/md/dm.c               |  4 +++-
 drivers/mtd/mtd_blkdevs.c     |  6 +++++-
 drivers/scsi/sd.c             |  8 +++++++-
 drivers/scsi/sr.c             |  7 ++++++-
 9 files changed, 65 insertions(+), 20 deletions(-)

-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:30:21 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:30:21 -0700
Subject: [PATCH 2/9] scsi/sr: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <20211015233028.2167651-3-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Just put the cdrom kref and have the unwinding be done by
sr_kref_release().

Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/scsi/sr.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 115f7ef7a5de..4e5515848fa6 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -728,7 +728,12 @@ static int sr_probe(struct device *dev)
 	dev_set_drvdata(dev, cd);
 	disk->flags |= GENHD_FL_REMOVABLE;
 	sr_revalidate_disk(cd);
-	device_add_disk(&sdev->sdev_gendev, disk, NULL);
+
+	error = device_add_disk(&sdev->sdev_gendev, disk, NULL);
+	if (error) {
+		kref_put(&cd->kref, sr_kref_release);
+		goto fail;
+	}
 
 	sdev_printk(KERN_DEBUG, sdev,
 		    "Attached scsi CD-ROM %s\n", cd->cdi.name);
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:10 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:10 -0700
Subject: [PATCH 04/13] nvdimm/btt: use goto error labels on btt_blk_init()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-5-mcgrof@kernel.org>

This will make it easier to share common error paths.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvdimm/btt.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 29cc7325e890..23ee8c005db5 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1520,10 +1520,11 @@ static int btt_blk_init(struct btt *btt)
 {
 	struct nd_btt *nd_btt = btt->nd_btt;
 	struct nd_namespace_common *ndns = nd_btt->ndns;
+	int rc = -ENOMEM;
 
 	btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE);
 	if (!btt->btt_disk)
-		return -ENOMEM;
+		goto out;
 
 	nvdimm_namespace_disk_name(ndns, btt->btt_disk->disk_name);
 	btt->btt_disk->first_minor = 0;
@@ -1535,19 +1536,23 @@ static int btt_blk_init(struct btt *btt)
 	blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue);
 
 	if (btt_meta_size(btt)) {
-		int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
-
-		if (rc) {
-			blk_cleanup_disk(btt->btt_disk);
-			return rc;
-		}
+		rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
+		if (rc)
+			goto out_cleanup_disk;
 	}
+
 	set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
 	device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
+
 	btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
 	nvdimm_check_and_set_ro(btt->btt_disk);
 
 	return 0;
+
+out_cleanup_disk:
+	blk_cleanup_disk(btt->btt_disk);
+out:
+	return rc;
 }
 
 static void btt_blk_cleanup(struct btt *btt)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:19 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:19 -0700
Subject: [PATCH 13/13] mtd/ubi/block: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-14-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/mtd/ubi/block.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index e003b4b44ffa..062e6c2c45f5 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -447,12 +447,18 @@ int ubiblock_create(struct ubi_volume_info *vi)
 	list_add_tail(&dev->list, &ubiblock_devices);
 
 	/* Must be the last step: anyone can call file ops from now on */
-	add_disk(dev->gd);
+	ret = add_disk(dev->gd);
+	if (ret)
+		goto out_destroy_wq;
+
 	dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
 		 dev->ubi_num, dev->vol_id, vi->name);
 	mutex_unlock(&devices_mutex);
 	return 0;
 
+out_destroy_wq:
+	list_del(&dev->list);
+	destroy_workqueue(dev->wq);
 out_remove_minor:
 	idr_remove(&ubiblock_minor_idr, gd->first_minor);
 out_cleanup_disk:
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:07 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:07 -0700
Subject: [PATCH 01/13] block/brd: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-2-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/brd.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 530b31240203..6065f493876f 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -372,6 +372,7 @@ static int brd_alloc(int i)
 	struct brd_device *brd;
 	struct gendisk *disk;
 	char buf[DISK_NAME_LEN];
+	int err = -ENOMEM;
 
 	mutex_lock(&brd_devices_mutex);
 	list_for_each_entry(brd, &brd_devices, brd_list) {
@@ -422,16 +423,20 @@ static int brd_alloc(int i)
 	/* Tell the block layer that this is not a rotational device */
 	blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
 	blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
-	add_disk(disk);
+	err = add_disk(disk);
+	if (err)
+		goto out_cleanup_disk;
 
 	return 0;
 
+out_cleanup_disk:
+	blk_cleanup_disk(disk);
 out_free_dev:
 	mutex_lock(&brd_devices_mutex);
 	list_del(&brd->brd_list);
 	mutex_unlock(&brd_devices_mutex);
 	kfree(brd);
-	return -ENOMEM;
+	return err;
 }
 
 static void brd_probe(dev_t dev)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:11 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:11 -0700
Subject: [PATCH 05/13] nvdimm/btt: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-6-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvdimm/btt.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 23ee8c005db5..57b921c5fbb5 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1542,7 +1542,9 @@ static int btt_blk_init(struct btt *btt)
 	}
 
 	set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
-	device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
+	rc = device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
+	if (rc)
+		goto out_cleanup_disk;
 
 	btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
 	nvdimm_check_and_set_ro(btt->btt_disk);
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:12 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:12 -0700
Subject: [PATCH 06/13] nvdimm/blk: avoid calling del_gendisk() on early
 failures
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-7-mcgrof@kernel.org>

If nd_integrity_init() fails we'd get del_gendisk() called,
but that's not correct as we should only call that if we're
done with device_add_disk(). Fix this by providing unwinding
prior to the devm call being registered and moving the devm
registration to the very end.

This should fix calling del_gendisk() if nd_integrity_init()
fails. I only spotted this issue through code inspection. It
does not fix any real world bug.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvdimm/blk.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 088d3dd6f6fa..591fa1f86f1e 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -240,6 +240,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
 	resource_size_t available_disk_size;
 	struct gendisk *disk;
 	u64 internal_nlba;
+	int rc;
 
 	internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk));
 	available_disk_size = internal_nlba * nsblk_sector_size(nsblk);
@@ -256,20 +257,26 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
 	blk_queue_logical_block_size(disk->queue, nsblk_sector_size(nsblk));
 	blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
 
-	if (devm_add_action_or_reset(dev, nd_blk_release_disk, disk))
-		return -ENOMEM;
-
 	if (nsblk_meta_size(nsblk)) {
-		int rc = nd_integrity_init(disk, nsblk_meta_size(nsblk));
+		rc = nd_integrity_init(disk, nsblk_meta_size(nsblk));
 
 		if (rc)
-			return rc;
+			goto out_before_devm_err;
 	}
 
 	set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
 	device_add_disk(dev, disk, NULL);
+
+	/* nd_blk_release_disk() is called if this fails */
+	if (devm_add_action_or_reset(dev, nd_blk_release_disk, disk))
+		return -ENOMEM;
+
 	nvdimm_check_and_set_ro(disk);
 	return 0;
+
+out_before_devm_err:
+	blk_cleanup_disk(disk);
+	return rc;
 }
 
 static int nd_blk_probe(struct device *dev)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:06 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:06 -0700
Subject: [PATCH 00/13] block: add_disk() error handling stragglers
Message-ID: <20211015235219.2191207-1-mcgrof@kernel.org>

This patch set consists of al the straggler drivers for which we have
have no patch reviews done for yet. I'd like to ask for folks to please
consider chiming in, specially if you're the maintainer for the driver.
Additionally if you can specify if you'll take the patch in yourself or
if you want Jens to take it, that'd be great too.

Luis Chamberlain (13):
  block/brd: add error handling support for add_disk()
  nvme-multipath: add error handling support for add_disk()
  nvdimm/btt: do not call del_gendisk() if not needed
  nvdimm/btt: use goto error labels on btt_blk_init()
  nvdimm/btt: add error handling support for add_disk()
  nvdimm/blk: avoid calling del_gendisk() on early failures
  nvdimm/blk: add error handling support for add_disk()
  zram: add error handling support for add_disk()
  z2ram: add error handling support for add_disk()
  ps3disk: add error handling support for add_disk()
  ps3vram: add error handling support for add_disk()
  block/sunvdc: add error handling support for add_disk()
  mtd/ubi/block: add error handling support for add_disk()

 drivers/block/brd.c           |  9 +++++++--
 drivers/block/ps3disk.c       |  8 ++++++--
 drivers/block/ps3vram.c       |  7 ++++++-
 drivers/block/sunvdc.c        | 14 +++++++++++---
 drivers/block/z2ram.c         |  7 +++++--
 drivers/block/zram/zram_drv.c |  6 +++++-
 drivers/mtd/ubi/block.c       |  8 +++++++-
 drivers/nvdimm/blk.c          | 21 +++++++++++++++------
 drivers/nvdimm/btt.c          | 24 +++++++++++++++---------
 drivers/nvme/host/multipath.c | 14 ++++++++++++--
 10 files changed, 89 insertions(+), 29 deletions(-)

-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:13 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:13 -0700
Subject: [PATCH 07/13] nvdimm/blk: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-8-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Since nvdimm/blk uses devm we just need to move the devm
registration towards the end. And in hindsight, that seems
to also provide a fix given del_gendisk() should not be
called unless the disk was already added via add_disk().
The probably of that issue happening is low though, like
OOM while calling devm_add_action(), so the fix is minor.

We manually unwind in case of add_disk() failure prior
to the devm registration.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvdimm/blk.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/nvdimm/blk.c b/drivers/nvdimm/blk.c
index 591fa1f86f1e..9f1eb41404ac 100644
--- a/drivers/nvdimm/blk.c
+++ b/drivers/nvdimm/blk.c
@@ -265,7 +265,9 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
 	}
 
 	set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
-	device_add_disk(dev, disk, NULL);
+	rc = device_add_disk(dev, disk, NULL);
+	if (rc)
+		goto out_before_devm_err;
 
 	/* nd_blk_release_disk() is called if this fails */
 	if (devm_add_action_or_reset(dev, nd_blk_release_disk, disk))
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:09 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:09 -0700
Subject: [PATCH 03/13] nvdimm/btt: do not call del_gendisk() if not needed
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-4-mcgrof@kernel.org>

We know we don't need del_gendisk() if we haven't added
the disk, so just skip it. This should fix a bug on older
kernels, as del_gendisk() became able to deal with
disks not added only recently, after the patch titled
"block: add flag for add_disk() completion notation".

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvdimm/btt.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index 52de60b7adee..29cc7325e890 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1538,7 +1538,6 @@ static int btt_blk_init(struct btt *btt)
 		int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
 
 		if (rc) {
-			del_gendisk(btt->btt_disk);
 			blk_cleanup_disk(btt->btt_disk);
 			return rc;
 		}
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:18 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:18 -0700
Subject: [PATCH 12/13] block/sunvdc: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-13-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

We re-use the same free tag call, so we also add a label for
that as well.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/sunvdc.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
index 4d4bb810c2ae..6f45a53f7cbf 100644
--- a/drivers/block/sunvdc.c
+++ b/drivers/block/sunvdc.c
@@ -826,8 +826,8 @@ static int probe_disk(struct vdc_port *port)
 	if (IS_ERR(g)) {
 		printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
 		       port->vio.name);
-		blk_mq_free_tag_set(&port->tag_set);
-		return PTR_ERR(g);
+		err = PTR_ERR(g);
+		goto out_free_tag;
 	}
 
 	port->disk = g;
@@ -879,9 +879,17 @@ static int probe_disk(struct vdc_port *port)
 	       port->vdisk_size, (port->vdisk_size >> (20 - 9)),
 	       port->vio.ver.major, port->vio.ver.minor);
 
-	device_add_disk(&port->vio.vdev->dev, g, NULL);
+	err = device_add_disk(&port->vio.vdev->dev, g, NULL);
+	if (err)
+		goto out_cleanup_disk;
 
 	return 0;
+
+out_cleanup_disk:
+	blk_cleanup_disk(g);
+out_free_tag:
+	blk_mq_free_tag_set(&port->tag_set);
+	return err;
 }
 
 static struct ldc_channel_config vdc_ldc_cfg = {
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:17 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:17 -0700
Subject: [PATCH 11/13] ps3vram: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-12-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/ps3vram.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index c7b19e128b03..af2a0d09c598 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -755,9 +755,14 @@ static int ps3vram_probe(struct ps3_system_bus_device *dev)
 	dev_info(&dev->core, "%s: Using %llu MiB of GPU memory\n",
 		 gendisk->disk_name, get_capacity(gendisk) >> 11);
 
-	device_add_disk(&dev->core, gendisk, NULL);
+	error = device_add_disk(&dev->core, gendisk, NULL);
+	if (error)
+		goto out_cleanup_disk;
+
 	return 0;
 
+out_cleanup_disk:
+	blk_cleanup_disk(gendisk);
 out_cache_cleanup:
 	remove_proc_entry(DEVICE_NAME, NULL);
 	ps3vram_cache_cleanup(dev);
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:15 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:15 -0700
Subject: [PATCH 09/13] z2ram: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-10-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling. Only the disk is cleaned up inside
z2ram_register_disk() as the caller deals with the rest.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/z2ram.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 4eef218108c6..ccc52c935faf 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -318,6 +318,7 @@ static const struct blk_mq_ops z2_mq_ops = {
 static int z2ram_register_disk(int minor)
 {
 	struct gendisk *disk;
+	int err;
 
 	disk = blk_mq_alloc_disk(&tag_set, NULL);
 	if (IS_ERR(disk))
@@ -333,8 +334,10 @@ static int z2ram_register_disk(int minor)
 		sprintf(disk->disk_name, "z2ram");
 
 	z2ram_gendisk[minor] = disk;
-	add_disk(disk);
-	return 0;
+	err = add_disk(disk);
+	if (err)
+		blk_cleanup_disk(disk);
+	return err;
 }
 
 static int __init z2_init(void)
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:16 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:16 -0700
Subject: [PATCH 10/13] ps3disk: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-11-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/ps3disk.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 8d51efbe045d..3054adf77460 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -467,9 +467,13 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
 		 gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
 		 get_capacity(gendisk) >> 11);
 
-	device_add_disk(&dev->sbd.core, gendisk, NULL);
-	return 0;
+	error = device_add_disk(&dev->sbd.core, gendisk, NULL);
+	if (error)
+		goto fail_cleanup_disk;
 
+	return 0;
+fail_cleanup_disk:
+	blk_cleanup_disk(gendisk);
 fail_free_tag_set:
 	blk_mq_free_tag_set(&priv->tag_set);
 fail_teardown:
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:14 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:14 -0700
Subject: [PATCH 08/13] zram: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-9-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/block/zram/zram_drv.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 0a9309a2ef54..bdbded107e6b 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1983,7 +1983,9 @@ static int zram_add(void)
 		blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
 
 	blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
-	device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
+	ret = device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
+	if (ret)
+		goto out_cleanup_disk;
 
 	strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
 
@@ -1991,6 +1993,8 @@ static int zram_add(void)
 	pr_info("Added device: %s\n", zram->disk->disk_name);
 	return device_id;
 
+out_cleanup_disk:
+	blk_cleanup_disk(zram->disk);
 out_free_idr:
 	idr_remove(&zram_index_idr, device_id);
 out_free_dev:
-- 
2.30.2



From mcgrof at kernel.org  Fri Oct 15 16:52:08 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Fri, 15 Oct 2021 16:52:08 -0700
Subject: [PATCH 02/13] nvme-multipath: add error handling support for
 add_disk()
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <20211015235219.2191207-3-mcgrof@kernel.org>

We never checked for errors on add_disk() as this function
returned void. Now that this is fixed, use the shiny new
error handling.

Since we now can tell for sure when a disk was added, move
setting the bit NVME_NSHEAD_DISK_LIVE only when we did
add the disk successfully.

Nothing to do here as the cleanup is done elsewhere. We take
care and use test_and_set_bit() because it is protects against
two nvme paths simultaneously calling device_add_disk() on the
same namespace head.

Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
---
 drivers/nvme/host/multipath.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index e8ccdd398f78..022837f7be41 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -496,13 +496,23 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)
 static void nvme_mpath_set_live(struct nvme_ns *ns)
 {
 	struct nvme_ns_head *head = ns->head;
+	int rc;
 
 	if (!head->disk)
 		return;
 
+	/*
+	 * test_and_set_bit() is used because it is protecting against two nvme
+	 * paths simultaneously calling device_add_disk() on the same namespace
+	 * head.
+	 */
 	if (!test_and_set_bit(NVME_NSHEAD_DISK_LIVE, &head->flags)) {
-		device_add_disk(&head->subsys->dev, head->disk,
-				nvme_ns_id_attr_groups);
+		rc = device_add_disk(&head->subsys->dev, head->disk,
+				     nvme_ns_id_attr_groups);
+		if (rc) {
+			clear_bit(NVME_NSHEAD_DISK_LIVE, &ns->flags);
+			return;
+		}
 		nvme_add_ns_head_cdev(head);
 	}
 
-- 
2.30.2



From kbusch at kernel.org  Fri Oct 15 17:01:18 2021
From: kbusch at kernel.org (Keith Busch)
Date: Fri, 15 Oct 2021 18:01:18 -0600
Subject: [PATCH 02/13] nvme-multipath: add error handling support for
 add_disk()
In-Reply-To: <20211015235219.2191207-3-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-3-mcgrof@kernel.org>
Message-ID: <20211016000118.GA50317@C02WT3WMHTD6>

On Fri, Oct 15, 2021 at 04:52:08PM -0700, Luis Chamberlain wrote:
> We never checked for errors on add_disk() as this function
> returned void. Now that this is fixed, use the shiny new
> error handling.
> 
> Since we now can tell for sure when a disk was added, move
> setting the bit NVME_NSHEAD_DISK_LIVE only when we did
> add the disk successfully.
> 
> Nothing to do here as the cleanup is done elsewhere. We take
> care and use test_and_set_bit() because it is protects against
> two nvme paths simultaneously calling device_add_disk() on the
> same namespace head.

Looks good, thank you.

Reviewed-by: Keith Busch <kbusch at kernel.org>


From dan.j.williams at intel.com  Fri Oct 15 17:13:48 2021
From: dan.j.williams at intel.com (Dan Williams)
Date: Fri, 15 Oct 2021 17:13:48 -0700
Subject: [PATCH 06/13] nvdimm/blk: avoid calling del_gendisk() on early
 failures
In-Reply-To: <20211015235219.2191207-7-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-7-mcgrof@kernel.org>
Message-ID: <CAPcyv4j+xLT=5RUodHWgnPjNq6t5OcmX1oM2zK2ML0U+OS_16Q@mail.gmail.com>

On Fri, Oct 15, 2021 at 4:53 PM Luis Chamberlain <mcgrof at kernel.org> wrote:
>
> If nd_integrity_init() fails we'd get del_gendisk() called,
> but that's not correct as we should only call that if we're
> done with device_add_disk(). Fix this by providing unwinding
> prior to the devm call being registered and moving the devm
> registration to the very end.
>
> This should fix calling del_gendisk() if nd_integrity_init()
> fails. I only spotted this issue through code inspection. It
> does not fix any real world bug.
>

Just fyi, I'm preparing patches to delete this driver completely as it
is unused by any shipping platform. I hope to get that removal into
v5.16.


From hch at lst.de  Fri Oct 15 21:39:36 2021
From: hch at lst.de (Christoph Hellwig)
Date: Sat, 16 Oct 2021 06:39:36 +0200
Subject: [PATCH 02/13] nvme-multipath: add error handling support for
 add_disk()
In-Reply-To: <20211015235219.2191207-3-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-3-mcgrof@kernel.org>
Message-ID: <20211016043936.GB27339@lst.de>

Thanks,

applied to nvme-5.16.


From paul at crapouillou.net  Sat Oct 16 06:22:24 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat, 16 Oct 2021 14:22:24 +0100
Subject: [PATCH v2 1/5] mtd: rawnand/davinci: Don't calculate ECC when reading
 page
Message-ID: <20211016132228.40254-1-paul@crapouillou.net>

The function nand_davinci_read_page_hwecc_oob_first() does read the ECC
data from the OOB area. Therefore it does not need to calculate the ECC
as it is already available.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 118da9944e3b..89de24d3bb7a 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -394,7 +394,6 @@ static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 	int eccsteps = chip->ecc.steps;
 	uint8_t *p = buf;
 	uint8_t *ecc_code = chip->ecc.code_buf;
-	uint8_t *ecc_calc = chip->ecc.calc_buf;
 	unsigned int max_bitflips = 0;
 
 	/* Read the OOB area first */
@@ -420,8 +419,6 @@ static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 		if (ret)
 			return ret;
 
-		chip->ecc.calculate(chip, p, &ecc_calc[i]);
-
 		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
 		if (stat == -EBADMSG &&
 		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
-- 
2.33.0



From paul at crapouillou.net  Sat Oct 16 06:22:25 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat, 16 Oct 2021 14:22:25 +0100
Subject: [PATCH v2 2/5] mtd: rawnand/davinci: Avoid duplicated page read
In-Reply-To: <20211016132228.40254-1-paul@crapouillou.net>
References: <20211016132228.40254-1-paul@crapouillou.net>
Message-ID: <20211016132228.40254-2-paul@crapouillou.net>

The function nand_davinci_read_page_hwecc_oob_first() first reads the
OOB data, extracts the ECC information, programs the ECC hardware before
reading the actual data in a loop.

Right after the OOB data was read, it called nand_read_page_op() to
reset the read cursor to the beginning of the page. This caused the
first page to be read twice: in that call, and later in the loop.

Address that issue by changing the call to nand_read_page_op() to
nand_change_read_column_op(), which will only reset the read cursor.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 89de24d3bb7a..2e6a0c1671be 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -401,7 +401,8 @@ static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 	if (ret)
 		return ret;
 
-	ret = nand_read_page_op(chip, page, 0, NULL, 0);
+	/* Move read cursor to start of page */
+	ret = nand_change_read_column_op(chip, 0, NULL, 0, false);
 	if (ret)
 		return ret;
 
-- 
2.33.0



From paul at crapouillou.net  Sat Oct 16 06:22:26 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat, 16 Oct 2021 14:22:26 +0100
Subject: [PATCH v2 3/5] mtd: rawnand/davinci: Rewrite function description
In-Reply-To: <20211016132228.40254-1-paul@crapouillou.net>
References: <20211016132228.40254-1-paul@crapouillou.net>
Message-ID: <20211016132228.40254-3-paul@crapouillou.net>

The original comment that describes the function
nand_davinci_read_page_hwecc_oob_first() is very obscure and it is hard
to understand what it is for.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 2e6a0c1671be..fe2511cdcae3 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -372,17 +372,15 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
 }
 
 /**
- * nand_read_page_hwecc_oob_first - hw ecc, read oob first
+ * nand_davinci_read_page_hwecc_oob_first - Hardware ECC page read with ECC
+ *                                          data read from OOB area
  * @chip: nand chip info structure
  * @buf: buffer to store read data
  * @oob_required: caller requires OOB data read to chip->oob_poi
  * @page: page number to read
  *
- * Hardware ECC for large page chips, require OOB to be read first. For this
- * ECC mode, the write_page method is re-used from ECC_HW. These methods
- * read/write ECC from the OOB area, unlike the ECC_HW_SYNDROME support with
- * multiple ECC steps, follows the "infix ECC" scheme and reads/writes ECC from
- * the data area, by overwriting the NAND manufacturer bad block markings.
+ * Hardware ECC for large page chips, which requires the ECC data to be
+ * extracted from the OOB before the actual data is read.
  */
 static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
 						  uint8_t *buf,
-- 
2.33.0



From paul at crapouillou.net  Sat Oct 16 06:22:27 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat, 16 Oct 2021 14:22:27 +0100
Subject: [PATCH v2 4/5] mtd: rawnand: Export nand_read_page_hwecc_oob_first()
In-Reply-To: <20211016132228.40254-1-paul@crapouillou.net>
References: <20211016132228.40254-1-paul@crapouillou.net>
Message-ID: <20211016132228.40254-4-paul@crapouillou.net>

Move the function nand_read_page_hwecc_oob_first() (previously
nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and export it
as a GPL symbol, so that it can be used by more modules.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/davinci_nand.c | 69 +----------------------------
 drivers/mtd/nand/raw/nand_base.c    | 67 ++++++++++++++++++++++++++++
 include/linux/mtd/rawnand.h         |  2 +
 3 files changed, 70 insertions(+), 68 deletions(-)

diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index fe2511cdcae3..45fec8c192ab 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -371,73 +371,6 @@ static int nand_davinci_correct_4bit(struct nand_chip *chip, u_char *data,
 	return corrected;
 }
 
-/**
- * nand_davinci_read_page_hwecc_oob_first - Hardware ECC page read with ECC
- *                                          data read from OOB area
- * @chip: nand chip info structure
- * @buf: buffer to store read data
- * @oob_required: caller requires OOB data read to chip->oob_poi
- * @page: page number to read
- *
- * Hardware ECC for large page chips, which requires the ECC data to be
- * extracted from the OOB before the actual data is read.
- */
-static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip,
-						  uint8_t *buf,
-						  int oob_required, int page)
-{
-	struct mtd_info *mtd = nand_to_mtd(chip);
-	int i, eccsize = chip->ecc.size, ret;
-	int eccbytes = chip->ecc.bytes;
-	int eccsteps = chip->ecc.steps;
-	uint8_t *p = buf;
-	uint8_t *ecc_code = chip->ecc.code_buf;
-	unsigned int max_bitflips = 0;
-
-	/* Read the OOB area first */
-	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
-	if (ret)
-		return ret;
-
-	/* Move read cursor to start of page */
-	ret = nand_change_read_column_op(chip, 0, NULL, 0, false);
-	if (ret)
-		return ret;
-
-	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
-					 chip->ecc.total);
-	if (ret)
-		return ret;
-
-	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-		int stat;
-
-		chip->ecc.hwctl(chip, NAND_ECC_READ);
-
-		ret = nand_read_data_op(chip, p, eccsize, false, false);
-		if (ret)
-			return ret;
-
-		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
-		if (stat == -EBADMSG &&
-		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
-			/* check for empty pages with bitflips */
-			stat = nand_check_erased_ecc_chunk(p, eccsize,
-							   &ecc_code[i],
-							   eccbytes, NULL, 0,
-							   chip->ecc.strength);
-		}
-
-		if (stat < 0) {
-			mtd->ecc_stats.failed++;
-		} else {
-			mtd->ecc_stats.corrected += stat;
-			max_bitflips = max_t(unsigned int, max_bitflips, stat);
-		}
-	}
-	return max_bitflips;
-}
-
 /*----------------------------------------------------------------------*/
 
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -647,7 +580,7 @@ static int davinci_nand_attach_chip(struct nand_chip *chip)
 			} else if (chunks == 4 || chunks == 8) {
 				mtd_set_ooblayout(mtd,
 						  nand_get_large_page_ooblayout());
-				chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first;
+				chip->ecc.read_page = nand_read_page_hwecc_oob_first;
 			} else {
 				return -EIO;
 			}
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..113a2e9f43b1 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -3160,6 +3160,73 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf,
 	return max_bitflips;
 }
 
+/**
+ * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC
+ *                                  data read from OOB area
+ * @chip: nand chip info structure
+ * @buf: buffer to store read data
+ * @oob_required: caller requires OOB data read to chip->oob_poi
+ * @page: page number to read
+ *
+ * Hardware ECC for large page chips, which requires the ECC data to be
+ * extracted from the OOB before the actual data is read.
+ */
+int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
+				   int oob_required, int page)
+{
+	struct mtd_info *mtd = nand_to_mtd(chip);
+	int i, eccsize = chip->ecc.size, ret;
+	int eccbytes = chip->ecc.bytes;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *ecc_code = chip->ecc.code_buf;
+	unsigned int max_bitflips = 0;
+
+	/* Read the OOB area first */
+	ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize);
+	if (ret)
+		return ret;
+
+	/* Move read cursor to start of page */
+	ret = nand_change_read_column_op(chip, 0, NULL, 0, false);
+	if (ret)
+		return ret;
+
+	ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
+					 chip->ecc.total);
+	if (ret)
+		return ret;
+
+	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+		int stat;
+
+		chip->ecc.hwctl(chip, NAND_ECC_READ);
+
+		ret = nand_read_data_op(chip, p, eccsize, false, false);
+		if (ret)
+			return ret;
+
+		stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL);
+		if (stat == -EBADMSG &&
+		    (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) {
+			/* check for empty pages with bitflips */
+			stat = nand_check_erased_ecc_chunk(p, eccsize,
+							   &ecc_code[i],
+							   eccbytes, NULL, 0,
+							   chip->ecc.strength);
+		}
+
+		if (stat < 0) {
+			mtd->ecc_stats.failed++;
+		} else {
+			mtd->ecc_stats.corrected += stat;
+			max_bitflips = max_t(unsigned int, max_bitflips, stat);
+		}
+	}
+	return max_bitflips;
+}
+EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first);
+
 /**
  * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
  * @chip: nand chip info structure
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..5b88cd51fadb 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
 		      bool force_8bit, bool check_only);
 int nand_write_data_op(struct nand_chip *chip, const void *buf,
 		       unsigned int len, bool force_8bit);
+int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf,
+				   int oob_required, int page);
 
 /* Scan and identify a NAND device */
 int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,
-- 
2.33.0



From paul at crapouillou.net  Sat Oct 16 06:22:28 2021
From: paul at crapouillou.net (Paul Cercueil)
Date: Sat, 16 Oct 2021 14:22:28 +0100
Subject: [PATCH v2 5/5] mtd: rawnand/ingenic: JZ4740 needs 'oob_first' read
 page function
In-Reply-To: <20211016132228.40254-1-paul@crapouillou.net>
References: <20211016132228.40254-1-paul@crapouillou.net>
Message-ID: <20211016132228.40254-5-paul@crapouillou.net>

The ECC engine on the JZ4740 SoC requires the ECC data to be read before
the page; using the default page reading function does not work. Indeed,
the old JZ4740 NAND driver (removed in 5.4) did use the 'OOB first' flag
that existed back then.

Use the newly created nand_read_page_hwecc_oob_first() to address this
issue.

This issue was not found when the new ingenic-nand driver was developed,
most likely because the Device Tree used had the nand-ecc-mode set to
"hw_oob_first", which seems to not be supported anymore.

Cc: <stable at vger.kernel.org> # v5.2
Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740")
Signed-off-by: Paul Cercueil <paul at crapouillou.net>
---
 drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
index 0e9d426fe4f2..b18861bdcdc8 100644
--- a/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
+++ b/drivers/mtd/nand/raw/ingenic/ingenic_nand_drv.c
@@ -32,6 +32,7 @@ struct jz_soc_info {
 	unsigned long addr_offset;
 	unsigned long cmd_offset;
 	const struct mtd_ooblayout_ops *oob_layout;
+	bool oob_first;
 };
 
 struct ingenic_nand_cs {
@@ -240,6 +241,9 @@ static int ingenic_nand_attach_chip(struct nand_chip *chip)
 	if (chip->bbt_options & NAND_BBT_USE_FLASH)
 		chip->bbt_options |= NAND_BBT_NO_OOB;
 
+	if (nfc->soc_info->oob_first)
+		chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+
 	/* For legacy reasons we use a different layout on the qi,lb60 board. */
 	if (of_machine_is_compatible("qi,lb60"))
 		mtd_set_ooblayout(mtd, &qi_lb60_ooblayout_ops);
@@ -534,6 +538,7 @@ static const struct jz_soc_info jz4740_soc_info = {
 	.data_offset = 0x00000000,
 	.cmd_offset = 0x00008000,
 	.addr_offset = 0x00010000,
+	.oob_first = true,
 };
 
 static const struct jz_soc_info jz4725b_soc_info = {
-- 
2.33.0



From martin.petersen at oracle.com  Sat Oct 16 19:51:48 2021
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Sat, 16 Oct 2021 22:51:48 -0400
Subject: [PATCH 1/9] scsi/sd: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-2-mcgrof@kernel.org> (Luis Chamberlain's
 message of "Fri, 15 Oct 2021 16:30:20 -0700")
References: <20211015233028.2167651-1-mcgrof@kernel.org>
 <20211015233028.2167651-2-mcgrof@kernel.org>
Message-ID: <yq1bl3ofjo5.fsf@ca-mkp.ca.oracle.com>


Luis,

> We never checked for errors on add_disk() as this function returned
> void. Now that this is fixed, use the shiny new error handling.
>
> As with the error handling for device_add() we follow the same logic
> and just put the device so that cleanup is done via the
> scsi_disk_release().

Acked-by: Martin K. Petersen <martin.petersen at oracle.com>

-- 
Martin K. Petersen	Oracle Linux Engineering


From martin.petersen at oracle.com  Sat Oct 16 19:53:47 2021
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Sat, 16 Oct 2021 22:53:47 -0400
Subject: [PATCH 2/9] scsi/sr: add error handling support for add_disk()
In-Reply-To: <20211015233028.2167651-3-mcgrof@kernel.org> (Luis Chamberlain's
 message of "Fri, 15 Oct 2021 16:30:21 -0700")
References: <20211015233028.2167651-1-mcgrof@kernel.org>
 <20211015233028.2167651-3-mcgrof@kernel.org>
Message-ID: <yq15ytwfjkp.fsf@ca-mkp.ca.oracle.com>


Luis,

> We never checked for errors on add_disk() as this function returned
> void. Now that this is fixed, use the shiny new error handling.
>
> Just put the cdrom kref and have the unwinding be done by
> sr_kref_release().

Acked-by: Martin K. Petersen <martin.petersen at oracle.com>

-- 
Martin K. Petersen	Oracle Linux Engineering


From geoff at infradead.org  Sun Oct 17 08:26:33 2021
From: geoff at infradead.org (Geoff Levand)
Date: Sun, 17 Oct 2021 08:26:33 -0700
Subject: [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <a31970d6-8631-9d9d-a36f-8f4fcebfb1e6@infradead.org>

Hi Luis,

On 10/15/21 4:52 PM, Luis Chamberlain wrote:
> This patch set consists of al the straggler drivers for which we have
> have no patch reviews done for yet. I'd like to ask for folks to please
> consider chiming in, specially if you're the maintainer for the driver.
> Additionally if you can specify if you'll take the patch in yourself or
> if you want Jens to take it, that'd be great too.

Do you have a git repo with the patch set applied that I can use to test with?

Thanks.

-Geoff


From jaimeliao at mxic.com.tw  Sun Oct 17 18:42:39 2021
From: jaimeliao at mxic.com.tw (jaimeliao at mxic.com.tw)
Date: Mon, 18 Oct 2021 09:42:39 +0800
Subject: =?Big5?B?pl6rSDogUmU6IFtSRkMgUEFUQ0ggMDMvMTBdIGR0LWJpbmRpbmdzOiB2ZW5kb3It?=
 =?Big5?B?cHJlZml4ZXM6IFVwZGF0ZSBNYWNyb25peCBwcmVmaXg=?=
In-Reply-To: <YWC8jgI74FgTudSD@robh.at.kernel.org>
References: <20211008162228.1753083-1-miquel.raynal@bootlin.com>
 <20211008162228.1753083-4-miquel.raynal@bootlin.com>
 <YWC8jgI74FgTudSD@robh.at.kernel.org>
Message-ID: <OF9A15BF2B.E4A73AE9-ON48258772.00093984-48258772.00096628@mxic.com.tw>


Hi Rob

> 
> Re: [RFC PATCH 03/10] dt-bindings: vendor-prefixes: Update Macronix 
prefix
> 
> On Fri, Oct 08, 2021 at 06:22:21PM +0200, Miquel Raynal wrote:
> > When looking at compatible prefixes, Macronix is sometimes referred as
> > mxicy:
> > - mxicy,mx25r1635f
> > - mxicy,mx25u6435f
> > - mxicy,mx25v8035f
> > - mxicy,mx25f0a-spi
> > and sometimes as mxic:
> > - mxic,multi-itfc-v009-nand-controller
> > - mxic,enable-randomizer-otp
> > 
> > It looks like the more up-to-date way is mxic so declare this prefix 
and
> > mark the other one as deprecated.
> 
> mxicy is more widely used with flash parts. There's not a single dts 
> file with 'mxic' which only seems to be some nand controller.
Yes, you are right.

Hi Miquel

Please keep using "mxicy,*" consistently for the compatible property, 
thanks.

> 
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> > ---
> >  Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-
> prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > index b868cefc7c55..013a87850cd5 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > @@ -758,8 +758,11 @@ patternProperties:
> >      description: Mundo Reader S.L.
> >    "^murata,.*":
> >      description: Murata Manufacturing Co., Ltd.
> > +  "^mxic,.*":
> > +    description: Macronix International Co., Ltd.
> >    "^mxicy,.*":
> >      description: Macronix International Co., Ltd.
> > +    deprecated: true
> >    "^myir,.*":
> >      description: MYIR Tech Limited
> >    "^national,.*":
> > -- 
> > 2.27.0
> > 
> > 


CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information 
and/or personal data, which is protected by applicable laws. Please be 
reminded that duplication, disclosure, distribution, or use of this e-mail 
(and/or its attachments) or any part thereof is prohibited. If you receive 
this e-mail in error, please notify us immediately and delete this mail as 
well as its attachment(s) from your system. In addition, please be 
informed that collection, processing, and/or use of personal data is 
prohibited unless expressly permitted by personal data protection laws. 
Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



============================================================================

CONFIDENTIALITY NOTE:

This e-mail and any attachments may contain confidential information and/or personal data, which is protected by applicable laws. Please be reminded that duplication, disclosure, distribution, or use of this e-mail (and/or its attachments) or any part thereof is prohibited. If you receive this e-mail in error, please notify us immediately and delete this mail as well as its attachment(s) from your system. In addition, please be informed that collection, processing, and/or use of personal data is prohibited unless expressly permitted by personal data protection laws. Thank you for your attention and cooperation.

Macronix International Co., Ltd.

=====================================================================



From chaitanyak at nvidia.com  Sun Oct 17 22:34:12 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Mon, 18 Oct 2021 05:34:12 +0000
Subject: [PATCH 02/13] nvme-multipath: add error handling support for
 add_disk()
In-Reply-To: <20211015235219.2191207-3-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-3-mcgrof@kernel.org>
Message-ID: <f312b3a4-3ab4-9897-877b-458c3eed2dd8@nvidia.com>

On 10/15/21 16:52, Luis Chamberlain wrote:
> We never checked for errors on add_disk() as this function
> returned void. Now that this is fixed, use the shiny new
> error handling.
> 
> Since we now can tell for sure when a disk was added, move
> setting the bit NVME_NSHEAD_DISK_LIVE only when we did
> add the disk successfully.
> 
> Nothing to do here as the cleanup is done elsewhere. We take
> care and use test_and_set_bit() because it is protects against
> two nvme paths simultaneously calling device_add_disk() on the
> same namespace head.
> 
> Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>


Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>




From miquel.raynal at bootlin.com  Mon Oct 18 00:19:19 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 18 Oct 2021 09:19:19 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211015200541.GA55401@panicking>
References: <00b31833-69ba-42c5-57c9-37fa1f70efc5@kernel.org>
 <20190812093129.75888dad@collabora.com>
 <a47792dc-b19f-8af3-8748-5a21fb63271e@kernel.org>
 <CAOf5uwmPzCU8WFRQ1tQBdN7OVGZZ9SvdAG0YqVAyxmA1zwtUhg@mail.gmail.com>
 <2e9e1f1c-ee57-425d-1791-70c66de52637@kernel.org>
 <CAOf5uwm93+ARf=_BckjMar1tpeBs6YHeUwORj5cyhFfvu5fNWQ@mail.gmail.com>
 <20210201151335.210af8ca@xps13>
 <CAOf5uwkivHhMX_mPJymBZxQge_wc4K1p_1S3gsQYHPV40aaj3w@mail.gmail.com>
 <CAOf5uwnXB-2xXXXxvH9Fo3ngscccA5Hv7iNTbUYRNFs_iLGJqw@mail.gmail.com>
 <20210201161433.0c4ff0e3@xps13> <20211015200541.GA55401@panicking>
Message-ID: <20211018091919.08cf589a@xps13>

Hi Michael,

michael at amarulasolutions.com wrote on Fri, 15 Oct 2021 22:05:41 +0200:

> Hi
> 
> On Mon, Feb 01, 2021 at 04:14:33PM +0100, Miquel Raynal wrote:
> > Hi Michael,
> > 
> > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > Mon, 1 Feb 2021 16:08:23 +0100:
> >   
> > > Hi
> > > 
> > > On Mon, Feb 1, 2021 at 3:32 PM Michael Nazzareno Trimarchi
> > > <michael at amarulasolutions.com> wrote:  
> > > >
> > > > Hi
> > > >
> > > > On Mon, Feb 1, 2021 at 3:13 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:    
> > > > >
> > > > > Hi Michael,
> > > > >
> > > > > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > > > > Sat, 30 Jan 2021 10:41:29 +0100:
> > > > >    
> > > > > > Hi Miquel
> > > > > >
> > > > > > commit f8e6ad14388067f91b26d044185d95623fbc9535
> > > > > > Author: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > Date:   Fri Jan 29 08:46:53 2021 +0100
> > > > > >
> > > > > >     mtd: nand: Calculate the clock before enable it
> > > > > >
> > > > > >     Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > >     Change-Id: I79b0da39de0a9b32ea0b002fa200d7f44d4f8ce7
> > > > > >
> > > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > index 322a008290e5..0bca52b3bc8f 100644
> > > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > @@ -377,6 +377,7 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > gpmi_nand_data *this,
> > > > > >                                      const struct nand_sdr_timings *sdr)
> > > > > >  {
> > > > > >         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > > > +       struct resources *r = &this->resources;
> > > > > >         unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
> > > > > >         unsigned int period_ps, reference_period_ps;
> > > > > >         unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
> > > > > > @@ -440,6 +441,8 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > gpmi_nand_data *this,
> > > > > >                 hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
> > > > > >                               BM_GPMI_CTRL1_DLL_ENABLE |
> > > > > >                               (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
> > > > > > +
> > > > > > +       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > >  }
> > > > > >
> > > > > >  void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > @@ -449,8 +452,6 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > >         void __iomem *gpmi_regs = r->gpmi_regs;
> > > > > >         unsigned int dll_wait_time_us;
> > > > > >
> > > > > > -       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > -
> > > > > >         writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > > >         writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > > >
> > > > > > Right now I have this change applied and seems fine. That is the only
> > > > > > difference I get. Clock is apply a bit earlier that when is enabled
> > > > > > it.    
> > > > >
> > > > > This is very interesting. So this would mean the issue you are
> > > > > experiencing comes from the clock driver which kind of returns too
> > > > > early from clk_set_rate()? Could you report this to the clk ML/NXP clk
> > > > > maintainers and keep us in copy? If it is as global as it sounds, we
> > > > > might not be the only ones affected.
> > > > >    
> > > >
> > > > The imx28 is broken too, so it's a general problem. I need to trace it down
> > > > I have a reverting for lts but it\s not the way to go
> > > >    
> > > 
> > > For imx28 you ask to set the rate to 22Mhz but you don't care about the clock
> > > that you get back. You get back 12Mhz because the base clock is 24 Mhz and seems
> > > that it can not get the point. You need to check if the clock
> > > requested is in range or ask
> > > for set_rate_clk_min to avoid to have somenthing lower. Then for
> > > imx6ull because is sporadic
> > > I think that is more connected to the clk_set_rate and when you change
> > > the register. Can not be a
> > > setting time?  
> > 
> > So, if I understand correctly, we face two different problems:
> > - imx6*: seems like a clock issue regarding the clock settlement
> > - imx28: actual NAND driver issue (does not check the validity of the
> >   new frequency). This should be handled properly in  
> >   ->setup_interface().  
> >  
> 
> Somenthing like this? Not compile/tested
> 
> diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> index 4d08e4ab5c1b..cc8146ab1b78 100644
> --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> @@ -644,7 +644,7 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
>   *         RDN_DELAY = -----------------------     {3}
>   *                           RP
>   */
> -static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> +static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>  				     const struct nand_sdr_timings *sdr)
>  {
>  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> @@ -656,6 +656,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>  	int sample_delay_ps, sample_delay_factor;
>  	u16 busy_timeout_cycles;
>  	u8 wrn_dly_sel;
> +	long clk_rate;
>  
>  	if (sdr->tRC_min >= 30000) {
>  		/* ONFI non-EDO modes [0-3] */
> @@ -671,6 +672,10 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
>  		wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
>  	}
>  
> +	clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
> +	if (clk_rate < hw->clk_rate || clk_rate <= 0)
> +		return -ENOTSUPP;

I believe clk_rate < hw->clk_rate will always match cases where
clk_rate <= 0 ?

The check looks very strict though. Will it even pass on i.MX6? Perhaps
we could verify something like a 10% error which might grab all the
erroneous situations?

	if (abs(clk_rate - hw->clk_rate) > (hw->clk_rate / 10))
		return -ENOTSUPP;

> +
>  	/* SDR core timings are given in picoseconds */
>  	period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
>  
> @@ -746,6 +751,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
>  {
>  	struct gpmi_nand_data *this = nand_get_controller_data(chip);
>  	const struct nand_sdr_timings *sdr;
> +	int ret = 0;
>  
>  	/* Retrieve required NAND timings */
>  	sdr = nand_get_sdr_timings(conf);
> @@ -761,11 +767,11 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
>  		return 0;
>  
>  	/* Do the actual derivation of the controller timings */
> -	gpmi_nfc_compute_timings(this, sdr);
> -
> -	this->hw.must_apply_timings = true;
> +	ret = gpmi_nfc_compute_timings(this, sdr);
> +	if (!ret)
> +		this->hw.must_apply_timings = true;
>  
> -	return 0;
> +	return ret;
>  }
>  
>  /* Clears a BCH interrupt. */
> > Thanks,
> > Miqu?l  

Otherwise looks good, thanks!

Miqu?l


From michael at amarulasolutions.com  Mon Oct 18 00:33:25 2021
From: michael at amarulasolutions.com (Michael Nazzareno Trimarchi)
Date: Mon, 18 Oct 2021 09:33:25 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <20211018091919.08cf589a@xps13>
References: <00b31833-69ba-42c5-57c9-37fa1f70efc5@kernel.org>
 <20190812093129.75888dad@collabora.com>
 <a47792dc-b19f-8af3-8748-5a21fb63271e@kernel.org>
 <CAOf5uwmPzCU8WFRQ1tQBdN7OVGZZ9SvdAG0YqVAyxmA1zwtUhg@mail.gmail.com>
 <2e9e1f1c-ee57-425d-1791-70c66de52637@kernel.org>
 <CAOf5uwm93+ARf=_BckjMar1tpeBs6YHeUwORj5cyhFfvu5fNWQ@mail.gmail.com>
 <20210201151335.210af8ca@xps13>
 <CAOf5uwkivHhMX_mPJymBZxQge_wc4K1p_1S3gsQYHPV40aaj3w@mail.gmail.com>
 <CAOf5uwnXB-2xXXXxvH9Fo3ngscccA5Hv7iNTbUYRNFs_iLGJqw@mail.gmail.com>
 <20210201161433.0c4ff0e3@xps13> <20211015200541.GA55401@panicking>
 <20211018091919.08cf589a@xps13>
Message-ID: <CAOf5uwk8o_m6FJwnRtkGqhkTQZh-3b3FJoc_OnnQq6JdBPPKLg@mail.gmail.com>

Hi


On Mon, Oct 18, 2021 at 9:19 AM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
>
> Hi Michael,
>
> michael at amarulasolutions.com wrote on Fri, 15 Oct 2021 22:05:41 +0200:
>
> > Hi
> >
> > On Mon, Feb 01, 2021 at 04:14:33PM +0100, Miquel Raynal wrote:
> > > Hi Michael,
> > >
> > > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > > Mon, 1 Feb 2021 16:08:23 +0100:
> > >
> > > > Hi
> > > >
> > > > On Mon, Feb 1, 2021 at 3:32 PM Michael Nazzareno Trimarchi
> > > > <michael at amarulasolutions.com> wrote:
> > > > >
> > > > > Hi
> > > > >
> > > > > On Mon, Feb 1, 2021 at 3:13 PM Miquel Raynal <miquel.raynal at bootlin.com> wrote:
> > > > > >
> > > > > > Hi Michael,
> > > > > >
> > > > > > Michael Nazzareno Trimarchi <michael at amarulasolutions.com> wrote on
> > > > > > Sat, 30 Jan 2021 10:41:29 +0100:
> > > > > >
> > > > > > > Hi Miquel
> > > > > > >
> > > > > > > commit f8e6ad14388067f91b26d044185d95623fbc9535
> > > > > > > Author: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > > Date:   Fri Jan 29 08:46:53 2021 +0100
> > > > > > >
> > > > > > >     mtd: nand: Calculate the clock before enable it
> > > > > > >
> > > > > > >     Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > >     Change-Id: I79b0da39de0a9b32ea0b002fa200d7f44d4f8ce7
> > > > > > >
> > > > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > index 322a008290e5..0bca52b3bc8f 100644
> > > > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > @@ -377,6 +377,7 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > > gpmi_nand_data *this,
> > > > > > >                                      const struct nand_sdr_timings *sdr)
> > > > > > >  {
> > > > > > >         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > > > > +       struct resources *r = &this->resources;
> > > > > > >         unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
> > > > > > >         unsigned int period_ps, reference_period_ps;
> > > > > > >         unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
> > > > > > > @@ -440,6 +441,8 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > > gpmi_nand_data *this,
> > > > > > >                 hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
> > > > > > >                               BM_GPMI_CTRL1_DLL_ENABLE |
> > > > > > >                               (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
> > > > > > > +
> > > > > > > +       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > >  }
> > > > > > >
> > > > > > >  void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > > @@ -449,8 +452,6 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > >         void __iomem *gpmi_regs = r->gpmi_regs;
> > > > > > >         unsigned int dll_wait_time_us;
> > > > > > >
> > > > > > > -       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > > -
> > > > > > >         writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > > > >         writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > > > >
> > > > > > > Right now I have this change applied and seems fine. That is the only
> > > > > > > difference I get. Clock is apply a bit earlier that when is enabled
> > > > > > > it.
> > > > > >
> > > > > > This is very interesting. So this would mean the issue you are
> > > > > > experiencing comes from the clock driver which kind of returns too
> > > > > > early from clk_set_rate()? Could you report this to the clk ML/NXP clk
> > > > > > maintainers and keep us in copy? If it is as global as it sounds, we
> > > > > > might not be the only ones affected.
> > > > > >
> > > > >
> > > > > The imx28 is broken too, so it's a general problem. I need to trace it down
> > > > > I have a reverting for lts but it\s not the way to go
> > > > >
> > > >
> > > > For imx28 you ask to set the rate to 22Mhz but you don't care about the clock
> > > > that you get back. You get back 12Mhz because the base clock is 24 Mhz and seems
> > > > that it can not get the point. You need to check if the clock
> > > > requested is in range or ask
> > > > for set_rate_clk_min to avoid to have somenthing lower. Then for
> > > > imx6ull because is sporadic
> > > > I think that is more connected to the clk_set_rate and when you change
> > > > the register. Can not be a
> > > > setting time?
> > >
> > > So, if I understand correctly, we face two different problems:
> > > - imx6*: seems like a clock issue regarding the clock settlement
> > > - imx28: actual NAND driver issue (does not check the validity of the
> > >   new frequency). This should be handled properly in
> > >   ->setup_interface().
> > >
> >
> > Somenthing like this? Not compile/tested
> >
> > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > index 4d08e4ab5c1b..cc8146ab1b78 100644
> > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > @@ -644,7 +644,7 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
> >   *         RDN_DELAY = -----------------------     {3}
> >   *                           RP
> >   */
> > -static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> > +static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> >                                    const struct nand_sdr_timings *sdr)
> >  {
> >       struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > @@ -656,6 +656,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> >       int sample_delay_ps, sample_delay_factor;
> >       u16 busy_timeout_cycles;
> >       u8 wrn_dly_sel;
> > +     long clk_rate;
> >
> >       if (sdr->tRC_min >= 30000) {
> >               /* ONFI non-EDO modes [0-3] */
> > @@ -671,6 +672,10 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> >               wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
> >       }
> >
> > +     clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
> > +     if (clk_rate < hw->clk_rate || clk_rate <= 0)
> > +             return -ENOTSUPP;
>
> I believe clk_rate < hw->clk_rate will always match cases where
> clk_rate <= 0 ?
>
> The check looks very strict though. Will it even pass on i.MX6? Perhaps
> we could verify something like a 10% error which might grab all the
> erroneous situations?

According to what I read the clk is the min that we can accept. So any clock
from EDO4 to EDO5 should be ok. My concern is that calculation. I need to read
it properly. I don't think that put 10% or any will help us, until we
now that is possible or not.

I will even anyway put a warning

Michael

>
>         if (abs(clk_rate - hw->clk_rate) > (hw->clk_rate / 10))
>                 return -ENOTSUPP;
>
> > +
> >       /* SDR core timings are given in picoseconds */
> >       period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
> >
> > @@ -746,6 +751,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> >  {
> >       struct gpmi_nand_data *this = nand_get_controller_data(chip);
> >       const struct nand_sdr_timings *sdr;
> > +     int ret = 0;
> >
> >       /* Retrieve required NAND timings */
> >       sdr = nand_get_sdr_timings(conf);
> > @@ -761,11 +767,11 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> >               return 0;
> >
> >       /* Do the actual derivation of the controller timings */
> > -     gpmi_nfc_compute_timings(this, sdr);
> > -
> > -     this->hw.must_apply_timings = true;
> > +     ret = gpmi_nfc_compute_timings(this, sdr);
> > +     if (!ret)
> > +             this->hw.must_apply_timings = true;
> >
> > -     return 0;
> > +     return ret;
> >  }
> >
> >  /* Clears a BCH interrupt. */
> > > Thanks,
> > > Miqu?l
>
> Otherwise looks good, thanks!
>
> Miqu?l



--
Michael Nazzareno Trimarchi
Co-Founder & Chief Executive Officer
M. +39 347 913 2170
michael at amarulasolutions.com
__________________________________

Amarula Solutions BV
Joop Geesinkweg 125, 1114 AB, Amsterdam, NL
T. +31 (0)85 111 9172
info at amarulasolutions.com
www.amarulasolutions.com


From miquel.raynal at bootlin.com  Mon Oct 18 00:43:08 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Mon, 18 Oct 2021 09:43:08 +0200
Subject: GPMI iMX6ull timeout on DMA
In-Reply-To: <CAOf5uwk8o_m6FJwnRtkGqhkTQZh-3b3FJoc_OnnQq6JdBPPKLg@mail.gmail.com>
References: <00b31833-69ba-42c5-57c9-37fa1f70efc5@kernel.org>
 <20190812093129.75888dad@collabora.com>
 <a47792dc-b19f-8af3-8748-5a21fb63271e@kernel.org>
 <CAOf5uwmPzCU8WFRQ1tQBdN7OVGZZ9SvdAG0YqVAyxmA1zwtUhg@mail.gmail.com>
 <2e9e1f1c-ee57-425d-1791-70c66de52637@kernel.org>
 <CAOf5uwm93+ARf=_BckjMar1tpeBs6YHeUwORj5cyhFfvu5fNWQ@mail.gmail.com>
 <20210201151335.210af8ca@xps13>
 <CAOf5uwkivHhMX_mPJymBZxQge_wc4K1p_1S3gsQYHPV40aaj3w@mail.gmail.com>
 <CAOf5uwnXB-2xXXXxvH9Fo3ngscccA5Hv7iNTbUYRNFs_iLGJqw@mail.gmail.com>
 <20210201161433.0c4ff0e3@xps13> <20211015200541.GA55401@panicking>
 <20211018091919.08cf589a@xps13>
 <CAOf5uwk8o_m6FJwnRtkGqhkTQZh-3b3FJoc_OnnQq6JdBPPKLg@mail.gmail.com>
Message-ID: <20211018094308.07cf3943@xps13>

Hi Michael,

> > > > > > > > commit f8e6ad14388067f91b26d044185d95623fbc9535
> > > > > > > > Author: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > > > Date:   Fri Jan 29 08:46:53 2021 +0100
> > > > > > > >
> > > > > > > >     mtd: nand: Calculate the clock before enable it
> > > > > > > >
> > > > > > > >     Signed-off-by: Michael Trimarchi <michael at amarulasolutions.com>
> > > > > > > >     Change-Id: I79b0da39de0a9b32ea0b002fa200d7f44d4f8ce7
> > > > > > > >
> > > > > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > > index 322a008290e5..0bca52b3bc8f 100644
> > > > > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-lib.c
> > > > > > > > @@ -377,6 +377,7 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > > > gpmi_nand_data *this,
> > > > > > > >                                      const struct nand_sdr_timings *sdr)
> > > > > > > >  {
> > > > > > > >         struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > > > > > +       struct resources *r = &this->resources;
> > > > > > > >         unsigned int dll_threshold_ps = this->devdata->max_chain_delay;
> > > > > > > >         unsigned int period_ps, reference_period_ps;
> > > > > > > >         unsigned int data_setup_cycles, data_hold_cycles, addr_setup_cycles;
> > > > > > > > @@ -440,6 +441,8 @@ static void gpmi_nfc_compute_timings(struct
> > > > > > > > gpmi_nand_data *this,
> > > > > > > >                 hw->ctrl1n |= BF_GPMI_CTRL1_RDN_DELAY(sample_delay_factor) |
> > > > > > > >                               BM_GPMI_CTRL1_DLL_ENABLE |
> > > > > > > >                               (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD : 0);
> > > > > > > > +
> > > > > > > > +       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > > >  }
> > > > > > > >
> > > > > > > >  void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > > > @@ -449,8 +452,6 @@ void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > > > >         void __iomem *gpmi_regs = r->gpmi_regs;
> > > > > > > >         unsigned int dll_wait_time_us;
> > > > > > > >
> > > > > > > > -       clk_set_rate(r->clock[0], hw->clk_rate);
> > > > > > > > -
> > > > > > > >         writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > > > > >         writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > > > > >
> > > > > > > > Right now I have this change applied and seems fine. That is the only
> > > > > > > > difference I get. Clock is apply a bit earlier that when is enabled
> > > > > > > > it.  
> > > > > > >
> > > > > > > This is very interesting. So this would mean the issue you are
> > > > > > > experiencing comes from the clock driver which kind of returns too
> > > > > > > early from clk_set_rate()? Could you report this to the clk ML/NXP clk
> > > > > > > maintainers and keep us in copy? If it is as global as it sounds, we
> > > > > > > might not be the only ones affected.
> > > > > > >  
> > > > > >
> > > > > > The imx28 is broken too, so it's a general problem. I need to trace it down
> > > > > > I have a reverting for lts but it\s not the way to go
> > > > > >  
> > > > >
> > > > > For imx28 you ask to set the rate to 22Mhz but you don't care about the clock
> > > > > that you get back. You get back 12Mhz because the base clock is 24 Mhz and seems
> > > > > that it can not get the point. You need to check if the clock
> > > > > requested is in range or ask
> > > > > for set_rate_clk_min to avoid to have somenthing lower. Then for
> > > > > imx6ull because is sporadic
> > > > > I think that is more connected to the clk_set_rate and when you change
> > > > > the register. Can not be a
> > > > > setting time?  
> > > >
> > > > So, if I understand correctly, we face two different problems:
> > > > - imx6*: seems like a clock issue regarding the clock settlement
> > > > - imx28: actual NAND driver issue (does not check the validity of the
> > > >   new frequency). This should be handled properly in  
> > > >   ->setup_interface().  
> > > >  
> > >
> > > Somenthing like this? Not compile/tested
> > >
> > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > index 4d08e4ab5c1b..cc8146ab1b78 100644
> > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > @@ -644,7 +644,7 @@ static int bch_set_geometry(struct gpmi_nand_data *this)
> > >   *         RDN_DELAY = -----------------------     {3}
> > >   *                           RP
> > >   */
> > > -static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> > > +static int gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> > >                                    const struct nand_sdr_timings *sdr)
> > >  {
> > >       struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > @@ -656,6 +656,7 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> > >       int sample_delay_ps, sample_delay_factor;
> > >       u16 busy_timeout_cycles;
> > >       u8 wrn_dly_sel;
> > > +     long clk_rate;
> > >
> > >       if (sdr->tRC_min >= 30000) {
> > >               /* ONFI non-EDO modes [0-3] */
> > > @@ -671,6 +672,10 @@ static void gpmi_nfc_compute_timings(struct gpmi_nand_data *this,
> > >               wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY;
> > >       }
> > >
> > > +     clk_rate = clk_round_rate(r->clock[0], hw->clk_rate);
> > > +     if (clk_rate < hw->clk_rate || clk_rate <= 0)
> > > +             return -ENOTSUPP;  
> >
> > I believe clk_rate < hw->clk_rate will always match cases where
> > clk_rate <= 0 ?
> >
> > The check looks very strict though. Will it even pass on i.MX6? Perhaps
> > we could verify something like a 10% error which might grab all the
> > erroneous situations?  
> 
> According to what I read the clk is the min that we can accept. So any clock
> from EDO4 to EDO5 should be ok. My concern is that calculation. I need to read
> it properly. I don't think that put 10% or any will help us, until we
> now that is possible or not.

10% was for the example, what I mean is that it is very common to
request a clock to run at 100MHz and to read it at eg. 93MHz. Your
check won't pass in this case and we cannot get the necessary test
coverage in order to ensure that we won't break working boards.

The thing is, if the calculation are made using hw->clk_rate we will
always get the register values wrong anyway and in this case it's true
that only experience will tell us if such a clock works or not.
However, if the calculations are made with clk_rate instead, it is
likely that we will get more accurate timings which very likely will
work. So perhaps the right solution would be to use the real clock rate
instead than refusing clock rates which do not match our strict
expectations?


> >
> >         if (abs(clk_rate - hw->clk_rate) > (hw->clk_rate / 10))
> >                 return -ENOTSUPP;
> >  
> > > +
> > >       /* SDR core timings are given in picoseconds */
> > >       period_ps = div_u64((u64)NSEC_PER_SEC * 1000, hw->clk_rate);
> > >
> > > @@ -746,6 +751,7 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > >  {
> > >       struct gpmi_nand_data *this = nand_get_controller_data(chip);
> > >       const struct nand_sdr_timings *sdr;
> > > +     int ret = 0;
> > >
> > >       /* Retrieve required NAND timings */
> > >       sdr = nand_get_sdr_timings(conf);
> > > @@ -761,11 +767,11 @@ static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > >               return 0;
> > >
> > >       /* Do the actual derivation of the controller timings */
> > > -     gpmi_nfc_compute_timings(this, sdr);
> > > -
> > > -     this->hw.must_apply_timings = true;
> > > +     ret = gpmi_nfc_compute_timings(this, sdr);
> > > +     if (!ret)
> > > +             this->hw.must_apply_timings = true;
> > >
> > > -     return 0;
> > > +     return ret;
> > >  }
> > >
> > >  /* Clears a BCH interrupt. */  
> > > > Thanks,
> > > > Miqu?l  
> >
> > Otherwise looks good, thanks!
> >
> > Miqu?l  
> 

Thanks,
Miqu?l


From mcgrof at kernel.org  Mon Oct 18 09:15:53 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Mon, 18 Oct 2021 09:15:53 -0700
Subject: [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <a31970d6-8631-9d9d-a36f-8f4fcebfb1e6@infradead.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <a31970d6-8631-9d9d-a36f-8f4fcebfb1e6@infradead.org>
Message-ID: <YW2duaTqf3qUbTIm@bombadil.infradead.org>

On Sun, Oct 17, 2021 at 08:26:33AM -0700, Geoff Levand wrote:
> Hi Luis,
> 
> On 10/15/21 4:52 PM, Luis Chamberlain wrote:
> > This patch set consists of al the straggler drivers for which we have
> > have no patch reviews done for yet. I'd like to ask for folks to please
> > consider chiming in, specially if you're the maintainer for the driver.
> > Additionally if you can specify if you'll take the patch in yourself or
> > if you want Jens to take it, that'd be great too.
> 
> Do you have a git repo with the patch set applied that I can use to test with?

Sure, although the second to last patch is in a state of flux given
the ataflop driver currently is broken and so we're seeing how to fix
that first:

https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git/log/?h=20211011-for-axboe-add-disk-error-handling

  Luis


From mcgrof at kernel.org  Mon Oct 18 13:31:53 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Mon, 18 Oct 2021 13:31:53 -0700
Subject: [PATCH 1/9] scsi/sd: add error handling support for add_disk()
In-Reply-To: <yq1bl3ofjo5.fsf@ca-mkp.ca.oracle.com>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
 <20211015233028.2167651-2-mcgrof@kernel.org>
 <yq1bl3ofjo5.fsf@ca-mkp.ca.oracle.com>
Message-ID: <YW3ZuQv1qpIXkd5b@bombadil.infradead.org>

On Sat, Oct 16, 2021 at 10:51:48PM -0400, Martin K. Petersen wrote:
> 
> Luis,
> 
> > We never checked for errors on add_disk() as this function returned
> > void. Now that this is fixed, use the shiny new error handling.
> >
> > As with the error handling for device_add() we follow the same logic
> > and just put the device so that cleanup is done via the
> > scsi_disk_release().
> 
> Acked-by: Martin K. Petersen <martin.petersen at oracle.com>

Thanks, would you like Jens to pick this up and the other scsi/sr patch
or are you taking it through your tree?

  Luis


From martin.petersen at oracle.com  Mon Oct 18 19:52:44 2021
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Mon, 18 Oct 2021 22:52:44 -0400
Subject: [PATCH 1/9] scsi/sd: add error handling support for add_disk()
In-Reply-To: <YW3ZuQv1qpIXkd5b@bombadil.infradead.org> (Luis Chamberlain's
 message of "Mon, 18 Oct 2021 13:31:53 -0700")
References: <20211015233028.2167651-1-mcgrof@kernel.org>
 <20211015233028.2167651-2-mcgrof@kernel.org>
 <yq1bl3ofjo5.fsf@ca-mkp.ca.oracle.com>
 <YW3ZuQv1qpIXkd5b@bombadil.infradead.org>
Message-ID: <yq1pms1d8w4.fsf@ca-mkp.ca.oracle.com>


Luis,

> Thanks, would you like Jens to pick this up and the other scsi/sr patch
> or are you taking it through your tree?

Didn't think I had the relevant add_disk() patch in my baseline tree but
it turns out I do. So I queued them up.

Thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering


From hch at lst.de  Mon Oct 18 22:53:09 2021
From: hch at lst.de (hch)
Date: Tue, 19 Oct 2021 07:53:09 +0200
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
References: <20211014145206.1488967-1-hch@lst.de>
 <20211014145206.1488967-2-hch@lst.de>
 <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
Message-ID: <20211019055309.GA20805@lst.de>

On Thu, Oct 14, 2021 at 09:28:19PM +0200, Richard Weinberger wrote:
> > instead.  Note that this contains a small behavior change in that erase
> > now unconditionally writes all Fs instead of first scanning for them.
> 
> Unless you have a strong opinoin I'd like to keep the scanning.
> The original use case of block2mtd is using Compact Flash (ATA)
> as MTD. Some of this devices are super stupid and I fear the 0xFF scanning
> is here to avoid programming 0xFF bytes into the NAND.
> Just to be on the safe side...

I played with keeping the scanning, but it really is a mess.  Shouldn't
the higher layers (ubi, jffs2, etc) know what has already been erased?

Btw, Joerns address bounces.  Does anyone knw if he still wants to
maintain block2mtd and has a new address or if he should be removed from
the maintainers list?


From Tudor.Ambarus at microchip.com  Tue Oct 19 03:15:30 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Tue, 19 Oct 2021 10:15:30 +0000
Subject: [PATCH] mtd: spi-nor: Enable locking for n25q128a13
In-Reply-To: <20210628211729.3625017-1-jonathan.lemon@gmail.com>
References: <20210628211729.3625017-1-jonathan.lemon@gmail.com>
Message-ID: <bef07b81-d1c5-0788-2b57-6f2edaf345e0@microchip.com>

On 6/29/21 12:17 AM, Jonathan Lemon wrote:
> As 4bit block protection patchset for some micron models are merged,
> n25q128a13 also uses 4 bit Block Protection scheme, so enable locking
> for it. Tested it on n25q128a13, the locking functions work well.
> 
> Signed-off-by: Jonathan Lemon <jonathan.lemon at gmail.com>
> ---
>  drivers/mtd/spi-nor/micron-st.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Applied, thanks.

From Tudor.Ambarus at microchip.com  Tue Oct 19 03:16:18 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Tue, 19 Oct 2021 10:16:18 +0000
Subject: [PATCH v2] mtd: spi-nor: hisi-sfc: Remove excessive
 clk_disable_unprepare()
In-Reply-To: <20210709144529.31379-1-novikov@ispras.ru>
References: <20210709144529.31379-1-novikov@ispras.ru>
Message-ID: <94539db8-e6d7-fd1e-46f1-af3ff1525685@microchip.com>

On 7/9/21 5:45 PM, Evgeny Novikov wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> hisi_spi_nor_probe() invokes clk_disable_unprepare() on all paths after
> successful call of clk_prepare_enable(). Besides, the clock is enabled by
> hispi_spi_nor_prep() and disabled by hispi_spi_nor_unprep(). So at remove
> time it is not possible to have the clock enabled. The patch removes
> excessive clk_disable_unprepare() from hisi_spi_nor_remove().
> 
> Found by Linux Driver Verification project (linuxtesting.org).
> 
> Fixes: e523f11141bd ("mtd: spi-nor: add hisilicon spi-nor flash controller driver")
> Signed-off-by: Evgeny Novikov <novikov at ispras.ru>
> Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
> ---
> v2: Fix notes from Pratyush Yadav:
>     - Describe better why clock disabling is not necessary at remove time.
>     - Add tag Fixes.
> ---
>  drivers/mtd/spi-nor/controllers/hisi-sfc.c | 1 -
>  1 file changed, 1 deletion(-)
> 

Applied, thanks.

From Tudor.Ambarus at microchip.com  Tue Oct 19 03:16:51 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Tue, 19 Oct 2021 10:16:51 +0000
Subject: [PATCH] mtd: spi-nor: hisi-sfc: Make use of the helper function
 devm_platform_ioremap_resource_byname()
In-Reply-To: <20210901074259.9683-1-caihuoqing@baidu.com>
References: <20210901074259.9683-1-caihuoqing@baidu.com>
Message-ID: <b01790b1-20c7-f016-8bce-af5b00cda683@microchip.com>

On 9/1/21 10:42 AM, Cai Huoqing wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Use the devm_platform_ioremap_resource_byname() helper instead of
> calling platform_get_resource_byname() and devm_ioremap_resource()
> separately
> 
> Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>
> ---
>  drivers/mtd/spi-nor/controllers/hisi-sfc.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)
> 

Applied, thanks.

From Tudor.Ambarus at microchip.com  Tue Oct 19 03:17:25 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Tue, 19 Oct 2021 10:17:25 +0000
Subject: [PATCH] mtd: spi-nor: nxp-spifi: Make use of the helper function
 devm_platform_ioremap_resource_byname()
In-Reply-To: <20210901074307.9733-1-caihuoqing@baidu.com>
References: <20210901074307.9733-1-caihuoqing@baidu.com>
Message-ID: <79991ede-709b-9897-094c-4ac8eea39054@microchip.com>

On 9/1/21 10:43 AM, Cai Huoqing wrote:
> Use the devm_platform_ioremap_resource_byname() helper instead of
> calling platform_get_resource_byname() and devm_ioremap_resource()
> separately
> 
> Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>
> ---
>  drivers/mtd/spi-nor/controllers/nxp-spifi.c | 7 ++-----
>  1 file changed, 2 insertions(+), 5 deletions(-)

Applied, thanks.

From mcgrof at kernel.org  Tue Oct 19 09:06:39 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Tue, 19 Oct 2021 09:06:39 -0700
Subject: [PATCH 06/13] nvdimm/blk: avoid calling del_gendisk() on early
 failures
In-Reply-To: <CAPcyv4j+xLT=5RUodHWgnPjNq6t5OcmX1oM2zK2ML0U+OS_16Q@mail.gmail.com>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-7-mcgrof@kernel.org>
 <CAPcyv4j+xLT=5RUodHWgnPjNq6t5OcmX1oM2zK2ML0U+OS_16Q@mail.gmail.com>
Message-ID: <YW7tDx/kXvg00T3O@bombadil.infradead.org>

On Fri, Oct 15, 2021 at 05:13:48PM -0700, Dan Williams wrote:
> On Fri, Oct 15, 2021 at 4:53 PM Luis Chamberlain <mcgrof at kernel.org> wrote:
> >
> > If nd_integrity_init() fails we'd get del_gendisk() called,
> > but that's not correct as we should only call that if we're
> > done with device_add_disk(). Fix this by providing unwinding
> > prior to the devm call being registered and moving the devm
> > registration to the very end.
> >
> > This should fix calling del_gendisk() if nd_integrity_init()
> > fails. I only spotted this issue through code inspection. It
> > does not fix any real world bug.
> >
> 
> Just fyi, I'm preparing patches to delete this driver completely as it
> is unused by any shipping platform. I hope to get that removal into
> v5.16.

I'll remove this from my queue, any chance you can review the changes
for nvdimm/btt?

  Luis


From p.yadav at ti.com  Tue Oct 19 10:26:25 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Tue, 19 Oct 2021 22:56:25 +0530
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
Message-ID: <20211019172623.hi5c4i274bv3lnqw@ti.com>

On 04/10/21 03:18AM, Tudor.Ambarus at microchip.com wrote:
> On 8/17/21 3:16 PM, Pratyush Yadav wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 27/07/21 07:52AM, Tudor Ambarus wrote:
> >> Get rid of flash_info flags that indicate settings which can be
> >> discovered when parsing SFDP. It will be clearer who sets what,
> >> and we'll restrict the flash settings that a developer can choose to
> >> only settings that are not SFDP discoverable.
> >>
> >> Whether a flash supports 4byte opcodes or not, is discoverable when
> >> parsing the optional 4-byte address instruction table. Flashes that
> >> do not support the 4bait SFDP table should set the SNOR_F_4B_OPCODES
> >> flag in the late_init() call. Flashes that define the 4bait SFDP table
> >> but gets it wrong, should set the flag in a post_sfdp fixup hook.
> > 
> > I like the idea, not so much the execution. More on this below.
> > 
> >>
> >> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> >> ---
> >>  drivers/mtd/spi-nor/core.c       |  3 ---
> >>  drivers/mtd/spi-nor/core.h       | 32 ++++++++++++++++----------------
> >>  drivers/mtd/spi-nor/gigadevice.c |  7 ++++---
> >>  drivers/mtd/spi-nor/issi.c       | 12 ++++++------
> >>  drivers/mtd/spi-nor/macronix.c   | 18 ++++++++++--------
> >>  drivers/mtd/spi-nor/micron-st.c  | 22 +++++++++++++---------
> >>  drivers/mtd/spi-nor/spansion.c   | 12 ++++++------
> >>  7 files changed, 55 insertions(+), 51 deletions(-)
> >>
> >> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >> index 6a8617346764..240d5c31af88 100644
> >> --- a/drivers/mtd/spi-nor/core.c
> >> +++ b/drivers/mtd/spi-nor/core.c
> >> @@ -3204,9 +3204,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
> >>       if (ret)
> >>               return ret;
> >>
> >> -     if (info->flags & SPI_NOR_4B_OPCODES)
> >> -             nor->flags |= SNOR_F_4B_OPCODES;
> >> -
> >>       if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
> >>               nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
> >>
> >> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> >> index 625f4eed75f1..dfdc51a26cad 100644
> >> --- a/drivers/mtd/spi-nor/core.h
> >> +++ b/drivers/mtd/spi-nor/core.h
> >> @@ -348,40 +348,36 @@ struct flash_info {
> >>                                        * S3AN flashes have specific opcode to
> >>                                        * read the status register.
> >>                                        */
> >> -#define SPI_NOR_4B_OPCODES   BIT(11) /*
> >> -                                      * Use dedicated 4byte address op codes
> >> -                                      * to support memory size above 128Mib.
> >> -                                      */
> >> -#define NO_CHIP_ERASE                BIT(12) /* Chip does not support chip erase */
> >> -#define SPI_NOR_SKIP_SFDP    BIT(13) /* Skip parsing of SFDP tables */
> >> -#define USE_CLSR             BIT(14) /* use CLSR command */
> >> -#define SPI_NOR_OCTAL_READ   BIT(15) /* Flash supports Octal Read */
> >> -#define SPI_NOR_TB_SR_BIT6   BIT(16) /*
> >> +#define NO_CHIP_ERASE                BIT(11) /* Chip does not support chip erase */
> >> +#define SPI_NOR_SKIP_SFDP    BIT(12) /* Skip parsing of SFDP tables */
> >> +#define USE_CLSR             BIT(13) /* use CLSR command */
> >> +#define SPI_NOR_OCTAL_READ   BIT(14) /* Flash supports Octal Read */
> >> +#define SPI_NOR_TB_SR_BIT6   BIT(15) /*
> >>                                        * Top/Bottom (TB) is bit 6 of
> >>                                        * status register. Must be used with
> >>                                        * SPI_NOR_HAS_TB.
> >>                                        */
> >> -#define SPI_NOR_4BIT_BP              BIT(17) /*
> >> +#define SPI_NOR_4BIT_BP              BIT(16) /*
> >>                                        * Flash SR has 4 bit fields (BP0-3)
> >>                                        * for block protection.
> >>                                        */
> >> -#define SPI_NOR_BP3_SR_BIT6  BIT(18) /*
> >> +#define SPI_NOR_BP3_SR_BIT6  BIT(17) /*
> >>                                        * BP3 is bit 6 of status register.
> >>                                        * Must be used with SPI_NOR_4BIT_BP.
> >>                                        */
> >> -#define SPI_NOR_OCTAL_DTR_READ       BIT(19) /* Flash supports octal DTR Read. */
> >> -#define SPI_NOR_OCTAL_DTR_PP BIT(20) /* Flash supports Octal DTR Page Program */
> >> -#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(21) /*
> >> +#define SPI_NOR_OCTAL_DTR_READ       BIT(18) /* Flash supports octal DTR Read. */
> >> +#define SPI_NOR_OCTAL_DTR_PP BIT(19) /* Flash supports Octal DTR Page Program */
> >> +#define SPI_NOR_IO_MODE_EN_VOLATILE  BIT(20) /*
> >>                                                * Flash enables the best
> >>                                                * available I/O mode via a
> >>                                                * volatile bit.
> >>                                                */
> >> -#define SPI_NOR_SWP_IS_VOLATILE      BIT(22) /*
> >> +#define SPI_NOR_SWP_IS_VOLATILE      BIT(21) /*
> >>                                        * Flash has volatile software write
> >>                                        * protection bits. Usually these will
> >>                                        * power-up in a write-protected state.
> >>                                        */
> >> -#define SPI_NOR_PARSE_SFDP   BIT(23) /*
> >> +#define SPI_NOR_PARSE_SFDP   BIT(22) /*
> >>                                        * Flash initialized based on the SFDP
> >>                                        * tables.
> >>                                        */
> >> @@ -569,4 +565,8 @@ static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
> >>       return mtd->priv;
> >>  }
> >>
> >> +static inline void snor_f_4b_opcodes(struct spi_nor *nor)
> > 
> > Maybe snor_set_f_4b_opcodes()?
> 
> snor_f comes from SPI NOR Flags I guess, so probably snor_f_set_4b_opcodes if we're
> going this path.

Makes sense to me.

> 
> > 
> >> +{
> >> +     nor->flags |= SNOR_F_4B_OPCODES;
> >> +}
> >>  #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
> >> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
> >> index 447d84bb2128..ff523fe734ef 100644
> >> --- a/drivers/mtd/spi-nor/gigadevice.c
> >> +++ b/drivers/mtd/spi-nor/gigadevice.c
> >> @@ -47,9 +47,10 @@ static const struct flash_info gigadevice_parts[] = {
> >>                          SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
> >>       { "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
> >>                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                        SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK |
> >> -                        SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
> >> -             .fixups = &gd25q256_fixups },
> >> +                        SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
> >> +                        SPI_NOR_TB_SR_BIT6)
> >> +             .fixups = &gd25q256_fixups,
> >> +             .late_init = snor_f_4b_opcodes, },
> >>  };
> >>
> >>  const struct spi_nor_manufacturer spi_nor_gigadevice = {
> >> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
> >> index 1e5bb5408b68..aeff8f60cbae 100644
> >> --- a/drivers/mtd/spi-nor/issi.c
> >> +++ b/drivers/mtd/spi-nor/issi.c
> >> @@ -45,9 +45,9 @@ static const struct flash_info issi_parts[] = {
> >>       { "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
> >>                            SECT_4K | SPI_NOR_DUAL_READ) },
> >>       { "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
> >> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                          SPI_NOR_4B_OPCODES)
> >> -             .fixups = &is25lp256_fixups },
> >> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .fixups = &is25lp256_fixups,
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
> >>                            SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> >>       { "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
> >> @@ -55,9 +55,9 @@ static const struct flash_info issi_parts[] = {
> >>       { "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
> >>                            SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> >>       { "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
> >> -                         SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                         SPI_NOR_4B_OPCODES)
> >> -             .fixups = &is25lp256_fixups },
> >> +                         SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .fixups = &is25lp256_fixups,
> >> +             .late_init = snor_f_4b_opcodes, },
> >>
> >>       /* PMC */
> >>       { "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
> >> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> >> index fba85efafb47..9709eb68b613 100644
> >> --- a/drivers/mtd/spi-nor/macronix.c
> >> +++ b/drivers/mtd/spi-nor/macronix.c
> >> @@ -105,29 +105,31 @@ static const struct flash_info macronix_parts[] = {
> >>       { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
> >>                             SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >>               .fixups = &mx25l25635_fixups },
> >> -     { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
> >> -                           SECT_4K | SPI_NOR_4B_OPCODES) },
> >> +     { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024,
> >>                             SECT_4K | SPI_NOR_DUAL_READ |
> >> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                           SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
> >>                             SECT_4K | SPI_NOR_DUAL_READ |
> >>                             SPI_NOR_QUAD_READ) },
> >>       { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> >>       { "mx66l51235f", INFO(0xc2201a, 0, 64 * 1024, 1024,
> >> -                           SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                           SPI_NOR_4B_OPCODES) },
> >> +                           SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
> >>                             SECT_4K | SPI_NOR_DUAL_READ |
> >> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                           SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048,
> >>                             SECT_4K | SPI_NOR_DUAL_READ |
> >>                             SPI_NOR_QUAD_READ) },
> >>       { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
> >>                             SPI_NOR_QUAD_READ) },
> >>       { "mx66u2g45g",  INFO(0xc2253c, 0, 64 * 1024, 4096,
> >> -                           SECT_4K | SPI_NOR_DUAL_READ |
> >> -                           SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                           SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>  };
> >>
> >>  static void macronix_default_init(struct spi_nor *nor)
> >> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> >> index c224e59820a1..72cc4673bf88 100644
> >> --- a/drivers/mtd/spi-nor/micron-st.c
> >> +++ b/drivers/mtd/spi-nor/micron-st.c
> >> @@ -121,13 +121,13 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
> >>  static const struct flash_info micron_parts[] = {
> >>       { "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
> >>                              SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
> >> -                            SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ |
> >> -                            SPI_NOR_OCTAL_DTR_PP |
> >> +                            SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP |
> >>                              SPI_NOR_IO_MODE_EN_VOLATILE)
> >> -       .fixups = &mt35xu512aba_fixups},
> >> +       .fixups = &mt35xu512aba_fixups,
> >> +       .late_init = snor_f_4b_opcodes, },
> > 
> > This flash populated the 4BAIT table, so you can simply drop the flag.
> 
> I'll do this in a dedicated patch, I'll need your tested-by tag.

Okay, let's keep that for a separate series. I will do a conversion 
series for the flashes I have on hand once this series is merged.

> 
> > No need for the late_init().
> > 
> > This makes me think that many other flashes might also have the 4BAIT
> > table but the developers chose to add this flag here since at that time
> > the norm was to populate all flash capabilities. I think we could be
> > able to drop many more .late_init like this. But unfortunately someone
> > needs to do the hard work of checking each flash, and most flash
> > datasheets don't even list the SFDP contents.
> > 
> > So while I think in the ideal world we would go check each flash, I
> > think this is an acceptable compromise. Let's not let perfection be the
> > enemy of good.
> 
> The patch doesn't change how the code works now. If some flashes can drop
> some flags, we can drop them in dedicated patches.

Yes, agreed.

> 
> > 
> > While we are on this topic, I find this a bit "ugly". Having to set
> > late_init() for setting these flags for each flash is not exactly very
> > clean or readable. I don't know how the future will look like, but if
> > each flash/family needs its own late_init() to set some flags, it won't
> > be very readable. We seem to be trading one type of complexity for
> > another. I dunno which is the lesser evil though...
> 
> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
> the late_init() function to see what's there. As you saw, late_init() can be
> used for tweaking flash's parameters, settings and methods, not just NOR flags,
> so I would expect that this hook to be present among flashes that don't define
> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
> the hook will be there anyway.
> 
> This patch opens the door on how we could handle the flash_info flags. All flash_info
> flags that can be determined when parsing SFDP can be removed and use for flashes that
> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
> 1/ flashes with SFDP will set the flags as:
> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> 2/ flashes without SFDP:
> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
> and a late_init() for SNOR_F equivalents of flash_info flags from
> spi_nor_info_init_params()
> 3/ flashes that collide, one with SFDP and the other without:
> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> and a late_init() for SNOR_F equivalents of flash_info flags from
> spi_nor_info_init_params(), that will be used for the flash without SFDP.
> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> and a late_init() for SNOR_F equivalents of flash_info flags from
> spi_nor_info_init_params(), that will be used for the flash without SFDP.

To me it looks like you can separate these flags into three classes:

  1. Whether to parse SFDP or not.
  2. Flags that can't be discovered via SFDP.
  3. Flags that can be discovered by SFDP ideally but can't be 
     discovered for this particular flash because either SFDP is missing 
     or the table for this flag is missing.

With your series, flags from 1 and 2 are populated via .flags in 
flash_info and the ones from 3 are populated via late_init().

Why can't we have 3 different fields for these 3 different flags? In 
flash_info, we can set .parse_sfdp to true/false to indicate SFDP 
support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable 
flags. And we can set .fixup_flags = A | B | C (can probably pick a 
better name) for the flags that your series sets through late_init().

This way, you have a clear separation between the three and they are all 
clearly visible in the flash entry itself.

The only case where this might run into trouble is when a SFDP flash has 
a collision with a non-SFDP flash and they both need different 
fixup_flags. But I supposed that is a problem even if you use 
late_init() so it certainly doesn't make anything worse.

I have not given this extensive thought, but it seems to make sense to 
me, and I feel that it would make the flow easier to follow. Thoughts? 
Am I missing something?

> 
> Let me know what you think or if I missed something.
> 
> Cheers,
> ta
> 
> > 
> >>       { "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
> >> -                         SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
> >> -                         SPI_NOR_4B_OPCODES) },
> >> +                         SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ)
> >> +       .late_init = snor_f_4b_opcodes, },
> >>  };
> >>
> >>  static const struct flash_info st_parts[] = {
> >> @@ -149,25 +149,29 @@ static const struct flash_info st_parts[] = {
> >>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
> >>       { "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
> >>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> >> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                            SPI_NOR_QUAD_READ)
> >> +       .late_init = snor_f_4b_opcodes, },
> >>       { "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
> >>                             USE_FSR | SPI_NOR_DUAL_READ |
> >>                             SPI_NOR_QUAD_READ) },
> >>       { "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
> >>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> >> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                            SPI_NOR_QUAD_READ)
> >> +       .late_init = snor_f_4b_opcodes, },
> >>       { "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512,
> >>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
> >>       { "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
> >>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> >> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                            SPI_NOR_QUAD_READ)
> >> +       .late_init = snor_f_4b_opcodes, },
> >>       { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024,
> >>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
> >>                             SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
> >>                             SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
> >>       { "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
> >>                              SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
> >> -                            SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> >> +                            SPI_NOR_QUAD_READ)
> >> +       .late_init = snor_f_4b_opcodes, },
> >>       { "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024,
> >>                             SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
> >>                             SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
> >> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> >> index aad7170768b4..af10833f56d8 100644
> >> --- a/drivers/mtd/spi-nor/spansion.c
> >> +++ b/drivers/mtd/spi-nor/spansion.c
> >> @@ -259,14 +259,14 @@ static const struct flash_info spansion_parts[] = {
> >>       { "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16,
> >>                            SECT_4K | SPI_NOR_DUAL_READ) },
> >>       { "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128,
> >> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                          SPI_NOR_4B_OPCODES) },
> >> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256,
> >> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                          SPI_NOR_4B_OPCODES) },
> >> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512,
> >> -                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> -                          SPI_NOR_4B_OPCODES) },
> >> +                          SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> >> +             .late_init = snor_f_4b_opcodes, },
> >>       { "cy15x104q",  INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1,
> >>                             SPI_NOR_NO_ERASE) },
> >>       { "s28hs512t",   INFO(0x345b1a,      0, 256 * 1024, 256,
> >> --
> >> 2.25.1
> >>
> > 
> > --
> > Regards,
> > Pratyush Yadav
> > Texas Instruments Inc.
> > 
> 

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From sean at geanix.com  Tue Oct 19 11:08:00 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 19 Oct 2021 20:08:00 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211015082206.244a2316@xps13>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
Message-ID: <20211019180800.3v7emokse6lkpjvk@skn-laptop>

On Fri, Oct 15, 2021 at 08:22:06AM +0200, Miquel Raynal wrote:
> Hi Sean,
> 
> boris.brezillon at collabora.com wrote on Mon, 11 Oct 2021 16:05:46 +0200:
> 
> > On Mon, 11 Oct 2021 13:52:50 +0200

[ ... ]

> 
> > > One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> > > initialized. Seems cumbersome to have every mtd/nand driver to call
> > > init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> > > to mtd_set_dev_defaults() before nand_create_bbt()?  
> > 
> > I have a nasty trick for that one, but I'm not sure Miquel will like it
> > (actually, I don't like it either, but it's so simple compared to the
> > other options we have that I'm tempted to go for this approach until
> > someone has time to invest in a cleaner solution :-)):
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..a9ac2d528a4d 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         mtd->_sync = nand_sync;
> >         mtd->_lock = nand_lock;
> >         mtd->_unlock = nand_unlock;
> > -       mtd->_suspend = nand_suspend;
> > -       mtd->_resume = nand_resume;
> >         mtd->_reboot = nand_shutdown;
> >         mtd->_block_isreserved = nand_block_isreserved;
> >         mtd->_block_isbad = nand_block_isbad;
> > @@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         if (ret)
> >                 goto err_free_secure_regions;
> >  
> > +       /*
> > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > +        * avoid using the suspend lock and resume waitqueue which are only
> > +        * initialized when mtd_device_register() is called.
> > +        */
> > +       mtd->_suspend = nand_suspend;
> > +       mtd->_resume = nand_resume;
> >         return 0;
> 
> I'm fine with this as long as it is documented for now.
> 

Hi Boris and Miquel,

gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
suspend resume hooks :(
Guess there is other drivers that does the same thing...

I have looked in the history and tried to blame gpmi-nand.c, but I can't
see the reason to why NAND_SKIP_BBTSCAN is set.

I have tested Boris' hack with this diff (and it seems to work):

diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index 4d08e4ab5c1b..ec7f44d630b6 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -2073,8 +2073,6 @@ static int gpmi_nand_attach_chip(struct nand_chip *chip)
 	if (ret)
 		return ret;
 
-	chip->options |= NAND_SKIP_BBTSCAN;
-
 	return 0;
 }
 
@@ -2460,9 +2459,6 @@ static int gpmi_nand_init(struct gpmi_nand_data *this)
 		goto err_out;
 
 	ret = nand_boot_init(this);
-	if (ret)
-		goto err_nand_cleanup;
-	ret = nand_create_bbt(chip);
 	if (ret)
 		goto err_nand_cleanup;
 

Do I miss something?

/Sean


From patrice.chotard at foss.st.com  Tue Oct 19 23:50:00 2021
From: patrice.chotard at foss.st.com (patrice.chotard at foss.st.com)
Date: Wed, 20 Oct 2021 08:50:00 +0200
Subject: dt-bindings: treewide: Update @st.com email address to @foss.st.com
Message-ID: <20211020065000.21312-1-patrice.chotard@foss.st.com>

From: Patrice Chotard <patrice.chotard at foss.st.com>

Not all @st.com email address are concerned, only people who have
a specific @foss.st.com email will see their entry updated.
For some people, who left the company, remove their email.

Signed-off-by: Patrice Chotard <patrice.chotard at foss.st.com>
---
 Documentation/devicetree/bindings/arm/sti.yaml                | 2 +-
 Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml     | 4 ++--
 .../devicetree/bindings/arm/stm32/st,stm32-syscon.yaml        | 4 ++--
 Documentation/devicetree/bindings/arm/stm32/stm32.yaml        | 2 +-
 Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml  | 2 +-
 Documentation/devicetree/bindings/crypto/st,stm32-crc.yaml    | 2 +-
 Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml   | 2 +-
 Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml   | 2 +-
 .../devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml  | 2 +-
 .../devicetree/bindings/display/panel/orisetech,otm8009a.yaml | 2 +-
 .../devicetree/bindings/display/panel/raydium,rm68200.yaml    | 2 +-
 Documentation/devicetree/bindings/display/st,stm32-dsi.yaml   | 4 ++--
 Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml  | 4 ++--
 Documentation/devicetree/bindings/dma/st,stm32-dma.yaml       | 2 +-
 Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml    | 2 +-
 Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml      | 2 +-
 .../devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml       | 3 +--
 Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml       | 2 +-
 .../devicetree/bindings/iio/adc/sigma-delta-modulator.yaml    | 2 +-
 Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml   | 2 +-
 .../devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml       | 4 ++--
 Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml   | 2 +-
 .../bindings/interrupt-controller/st,stm32-exti.yaml          | 4 ++--
 Documentation/devicetree/bindings/mailbox/st,stm32-ipcc.yaml  | 4 ++--
 Documentation/devicetree/bindings/media/st,stm32-cec.yaml     | 3 +--
 Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml    | 2 +-
 .../bindings/memory-controllers/st,stm32-fmc2-ebi.yaml        | 2 +-
 Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml   | 2 +-
 Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml    | 3 +--
 Documentation/devicetree/bindings/mfd/st,stmfx.yaml           | 2 +-
 Documentation/devicetree/bindings/mfd/st,stpmic1.yaml         | 2 +-
 Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml | 2 +-
 Documentation/devicetree/bindings/net/snps,dwmac.yaml         | 2 +-
 Documentation/devicetree/bindings/net/stm32-dwmac.yaml        | 4 ++--
 Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml   | 2 +-
 Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml  | 2 +-
 .../devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml         | 2 +-
 .../devicetree/bindings/regulator/st,stm32-booster.yaml       | 2 +-
 .../devicetree/bindings/regulator/st,stm32-vrefbuf.yaml       | 2 +-
 .../devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml    | 2 +-
 .../devicetree/bindings/remoteproc/st,stm32-rproc.yaml        | 4 ++--
 Documentation/devicetree/bindings/rng/st,stm32-rng.yaml       | 2 +-
 Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml       | 2 +-
 Documentation/devicetree/bindings/serial/st,stm32-uart.yaml   | 2 +-
 Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml   | 2 +-
 Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml     | 2 +-
 Documentation/devicetree/bindings/sound/st,stm32-sai.yaml     | 2 +-
 Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml | 2 +-
 Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml      | 4 ++--
 Documentation/devicetree/bindings/spi/st,stm32-spi.yaml       | 4 ++--
 .../devicetree/bindings/thermal/st,stm32-thermal.yaml         | 2 +-
 Documentation/devicetree/bindings/timer/st,stm32-timer.yaml   | 3 ++-
 Documentation/devicetree/bindings/usb/st,stusb160x.yaml       | 2 +-
 Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml | 4 ++--
 54 files changed, 67 insertions(+), 69 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/sti.yaml b/Documentation/devicetree/bindings/arm/sti.yaml
index b1f28d16d3fb..a41cd8764885 100644
--- a/Documentation/devicetree/bindings/arm/sti.yaml
+++ b/Documentation/devicetree/bindings/arm/sti.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: ST STi Platforms Device Tree Bindings
 
 maintainers:
-  - Patrice Chotard <patrice.chotard at st.com>
+  - Patrice Chotard <patrice.chotard at foss.st.com>
 
 properties:
   $nodename:
diff --git a/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml b/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml
index 8e711bd202fd..ecb28e90fd11 100644
--- a/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/st,mlahb.yaml
@@ -7,8 +7,8 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: STMicroelectronics STM32 ML-AHB interconnect bindings
 
 maintainers:
-  - Fabien Dessenne <fabien.dessenne at st.com>
-  - Arnaud Pouliquen <arnaud.pouliquen at st.com>
+  - Fabien Dessenne <fabien.dessenne at foss.st.com>
+  - Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
 
 description: |
   These bindings describe the STM32 SoCs ML-AHB interconnect bus which connects
diff --git a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
index 149afb5df5af..6f846d69c5e1 100644
--- a/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/st,stm32-syscon.yaml
@@ -7,8 +7,8 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: STMicroelectronics STM32 Platforms System Controller bindings
 
 maintainers:
-  - Alexandre Torgue <alexandre.torgue at st.com>
-  - Christophe Roullier <christophe.roullier at st.com>
+  - Alexandre Torgue <alexandre.torgue at foss.st.com>
+  - Christophe Roullier <christophe.roullier at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index 9a77ab74be99..e33fbb62b430 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Platforms Device Tree Bindings
 
 maintainers:
-  - Alexandre Torgue <alexandre.torgue at st.com>
+  - Alexandre Torgue <alexandre.torgue at foss.st.com>
 
 properties:
   $nodename:
diff --git a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml
index 8b1ecb2ecdd5..a0ae4867ed27 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml
+++ b/Documentation/devicetree/bindings/clock/st,stm32mp1-rcc.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Reset Clock Controller Binding
 
 maintainers:
-  - Gabriel Fernandez <gabriel.fernandez at st.com>
+  - Gabriel Fernandez <gabriel.fernandez at foss.st.com>
 
 description: |
   The RCC IP is both a reset and a clock controller.
diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-crc.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-crc.yaml
index cee624c14f07..b72e4858f9aa 100644
--- a/Documentation/devicetree/bindings/crypto/st,stm32-crc.yaml
+++ b/Documentation/devicetree/bindings/crypto/st,stm32-crc.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 CRC bindings
 
 maintainers:
-  - Lionel Debieve <lionel.debieve at st.com>
+  - Lionel Debieve <lionel.debieve at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml
index a4574552502a..ed23bf94a8e0 100644
--- a/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml
+++ b/Documentation/devicetree/bindings/crypto/st,stm32-cryp.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 CRYP bindings
 
 maintainers:
-  - Lionel Debieve <lionel.debieve at st.com>
+  - Lionel Debieve <lionel.debieve at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
index 6dd658f0912c..10ba94792d95 100644
--- a/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
+++ b/Documentation/devicetree/bindings/crypto/st,stm32-hash.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 HASH bindings
 
 maintainers:
-  - Lionel Debieve <lionel.debieve at st.com>
+  - Lionel Debieve <lionel.debieve at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml
index 3c3e51af154b..11fd68a70dca 100644
--- a/Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/snps,dw-mipi-dsi.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Synopsys DesignWare MIPI DSI host controller
 
 maintainers:
-  - Philippe CORNU <philippe.cornu at st.com>
+  - Philippe CORNU <philippe.cornu at foss.st.com>
 
 description: |
   This document defines device tree properties for the Synopsys DesignWare MIPI
diff --git a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
index 4b6dda6dbc0f..17cbd0ad32bf 100644
--- a/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
+++ b/Documentation/devicetree/bindings/display/panel/orisetech,otm8009a.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Orise Tech OTM8009A 3.97" 480x800 TFT LCD panel (MIPI-DSI video mode)
 
 maintainers:
-  - Philippe CORNU <philippe.cornu at st.com>
+  - Philippe CORNU <philippe.cornu at foss.st.com>
 
 description: |
              The Orise Tech OTM8009A is a 3.97" 480x800 TFT LCD panel connected using
diff --git a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
index 39477793d289..e8ce2315631a 100644
--- a/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
+++ b/Documentation/devicetree/bindings/display/panel/raydium,rm68200.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Raydium Semiconductor Corporation RM68200 5.5" 720p MIPI-DSI TFT LCD panel
 
 maintainers:
-  - Philippe CORNU <philippe.cornu at st.com>
+  - Philippe CORNU <philippe.cornu at foss.st.com>
 
 description: |
   The Raydium Semiconductor Corporation RM68200 is a 5.5" 720x1280 TFT LCD
diff --git a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml
index ed310bbe3afe..ce1ef93cce93 100644
--- a/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/st,stm32-dsi.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 DSI host controller
 
 maintainers:
-  - Philippe Cornu <philippe.cornu at st.com>
-  - Yannick Fertre <yannick.fertre at st.com>
+  - Philippe Cornu <philippe.cornu at foss.st.com>
+  - Yannick Fertre <yannick.fertre at foss.st.com>
 
 description:
   The STMicroelectronics STM32 DSI controller uses the Synopsys DesignWare MIPI-DSI host controller.
diff --git a/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml b/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
index 4ae3d75492d3..01e2da23790b 100644
--- a/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
+++ b/Documentation/devicetree/bindings/display/st,stm32-ltdc.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 lcd-tft display controller
 
 maintainers:
-  - Philippe Cornu <philippe.cornu at st.com>
-  - Yannick Fertre <yannick.fertre at st.com>
+  - Philippe Cornu <philippe.cornu at foss.st.com>
+  - Yannick Fertre <yannick.fertre at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
index 4bf676fd25dc..55faab6a468e 100644
--- a/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
+++ b/Documentation/devicetree/bindings/dma/st,stm32-dma.yaml
@@ -50,7 +50,7 @@ description: |
 
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 allOf:
   - $ref: "dma-controller.yaml#"
diff --git a/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml b/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
index c8d2b51d8410..f751796531c9 100644
--- a/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
+++ b/Documentation/devicetree/bindings/dma/st,stm32-dmamux.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 DMA MUX (DMA request router) bindings
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 allOf:
   - $ref: "dma-router.yaml#"
diff --git a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml
index c30be840be1c..87b4afd2cf62 100644
--- a/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml
+++ b/Documentation/devicetree/bindings/dma/st,stm32-mdma.yaml
@@ -50,7 +50,7 @@ description: |
        if no HW ack signal is used by the MDMA client
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 allOf:
   - $ref: "dma-controller.yaml#"
diff --git a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml
index 47cf9c8d97e9..b18c616035a8 100644
--- a/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml
+++ b/Documentation/devicetree/bindings/hwlock/st,stm32-hwspinlock.yaml
@@ -7,8 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Hardware Spinlock bindings
 
 maintainers:
-  - Benjamin Gaignard <benjamin.gaignard at st.com>
-  - Fabien Dessenne <fabien.dessenne at st.com>
+  - Fabien Dessenne <fabien.dessenne at foss.st.com>
 
 properties:
   "#hwlock-cells":
diff --git a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
index d747f4990ad8..c07289a643d8 100644
--- a/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/st,stm32-i2c.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: I2C controller embedded in STMicroelectronics STM32 I2C platform
 
 maintainers:
-  - Pierre-Yves MORDRET <pierre-yves.mordret at st.com>
+  - Pierre-Yves MORDRET <pierre-yves.mordret at foss.st.com>
 
 allOf:
   - $ref: /schemas/i2c/i2c-controller.yaml#
diff --git a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml
index a390343d0c2a..2287697f1f61 100644
--- a/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/sigma-delta-modulator.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Device-Tree bindings for sigma delta modulator
 
 maintainers:
-  - Arnaud Pouliquen <arnaud.pouliquen at st.com>
+  - Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
index a58334c3bb76..a055c78cc047 100644
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-adc.yaml
@@ -19,7 +19,7 @@ description: |
   Each STM32 ADC block can have up to 3 ADC instances.
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
index 733351dee252..7c260f209687 100644
--- a/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 DFSDM ADC device driver
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
-  - Olivier Moysan <olivier.moysan at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
+  - Olivier Moysan <olivier.moysan at foss.st.com>
 
 description: |
   STM32 DFSDM ADC is a sigma delta analog-to-digital converter dedicated to
diff --git a/Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml b/Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml
index 393f7005941a..6adeda4087fc 100644
--- a/Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/st,stm32-dac.yaml
@@ -15,7 +15,7 @@ description: |
   current.
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml
index 6d3e68eb2e8b..d19c881b4abc 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STM32 External Interrupt Controller Device Tree Bindings
 
 maintainers:
-  - Alexandre Torgue <alexandre.torgue at st.com>
-  - Ludovic Barre <ludovic.barre at st.com>
+  - Alexandre Torgue <alexandre.torgue at foss.st.com>
+  - Ludovic Barre <ludovic.barre at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mailbox/st,stm32-ipcc.yaml b/Documentation/devicetree/bindings/mailbox/st,stm32-ipcc.yaml
index b15da9ba90b2..8eb4bf52ea27 100644
--- a/Documentation/devicetree/bindings/mailbox/st,stm32-ipcc.yaml
+++ b/Documentation/devicetree/bindings/mailbox/st,stm32-ipcc.yaml
@@ -13,8 +13,8 @@ description:
   channels (N) can be read from a dedicated register.
 
 maintainers:
-  - Fabien Dessenne <fabien.dessenne at st.com>
-  - Arnaud Pouliquen <arnaud.pouliquen at st.com>
+  - Fabien Dessenne <fabien.dessenne at foss.st.com>
+  - Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/media/st,stm32-cec.yaml b/Documentation/devicetree/bindings/media/st,stm32-cec.yaml
index d75019c093a4..77144cc6f7db 100644
--- a/Documentation/devicetree/bindings/media/st,stm32-cec.yaml
+++ b/Documentation/devicetree/bindings/media/st,stm32-cec.yaml
@@ -7,8 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 CEC bindings
 
 maintainers:
-  - Benjamin Gaignard <benjamin.gaignard at st.com>
-  - Yannick Fertre <yannick.fertre at st.com>
+  - Yannick Fertre <yannick.fertre at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
index 41e1d0cd80e5..9c1262a276b5 100644
--- a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
+++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Digital Camera Memory Interface (DCMI) binding
 
 maintainers:
-  - Hugues Fruchet <hugues.fruchet at st.com>
+  - Hugues Fruchet <hugues.fruchet at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
index cba74205846a..6b516d3895af 100644
--- a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
@@ -19,7 +19,7 @@ description: |
   Select. The FMC2 performs only one access at a time to an external device.
 
 maintainers:
-  - Christophe Kerello <christophe.kerello at st.com>
+  - Christophe Kerello <christophe.kerello at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
index 8bcea8dd7d90..ec7f0190f46e 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
@@ -17,7 +17,7 @@ description: |
      - simple counter from IN1 input signal.
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
index dace35362a7a..10b330d42901 100644
--- a/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
@@ -17,8 +17,7 @@ description: |
       programmable prescaler.
 
 maintainers:
-  - Benjamin Gaignard <benjamin.gaignard at st.com>
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
index 19e9afb385ac..b2a4e4aa7ff6 100644
--- a/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stmfx.yaml
@@ -12,7 +12,7 @@ description: ST Multi-Function eXpander (STMFX) is a slave controller using I2C
                through VDD) and resistive touchscreen controller.
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml
index 305123e74a58..426658ad81d4 100644
--- a/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml
+++ b/Documentation/devicetree/bindings/mfd/st,stpmic1.yaml
@@ -9,7 +9,7 @@ title: STMicroelectonics STPMIC1 Power Management IC bindings
 description: STMicroelectronics STPMIC1 Power Management IC
 
 maintainers:
-  - pascal Paillet <p.paillet at st.com>
+  - pascal Paillet <p.paillet at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
index 29c5ef24ac6a..eab8ea3da1fa 100644
--- a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics Flexible Memory Controller 2 (FMC2) Bindings
 
 maintainers:
-  - Christophe Kerello <christophe.kerello at st.com>
+  - Christophe Kerello <christophe.kerello at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index 42689b7d03a2..a5c55127cc44 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Synopsys DesignWare MAC Device Tree Bindings
 
 maintainers:
-  - Alexandre Torgue <alexandre.torgue at st.com>
+  - Alexandre Torgue <alexandre.torgue at foss.st.com>
   - Giuseppe Cavallaro <peppe.cavallaro at st.com>
   - Jose Abreu <joabreu at synopsys.com>
 
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.yaml b/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
index d3f05d5934d5..577f4e284425 100644
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
@@ -8,8 +8,8 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: STMicroelectronics STM32 / MCU DWMAC glue layer controller
 
 maintainers:
-  - Alexandre Torgue <alexandre.torgue at st.com>
-  - Christophe Roullier <christophe.roullier at st.com>
+  - Alexandre Torgue <alexandre.torgue at foss.st.com>
+  - Christophe Roullier <christophe.roullier at foss.st.com>
 
 description:
   This file documents platform glue layer for stmmac.
diff --git a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
index 0b80ce22a2f8..a48c8fa56bce 100644
--- a/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
+++ b/Documentation/devicetree/bindings/nvmem/st,stm32-romem.yaml
@@ -13,7 +13,7 @@ description: |
   internal vref (VREFIN_CAL), unique device ID...
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 allOf:
   - $ref: "nvmem.yaml#"
diff --git a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml
index 3329f1d33a4f..7bae8dff3ef6 100644
--- a/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml
+++ b/Documentation/devicetree/bindings/phy/phy-stm32-usbphyc.yaml
@@ -24,7 +24,7 @@ description:
   |_ UTMI switch_______|          OTG controller
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index dfee6d38a701..ac88e01ec430 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STM32 GPIO and Pin Mux/Config controller
 
 maintainers:
-  - Alexandre TORGUE <alexandre.torgue at st.com>
+  - Alexandre TORGUE <alexandre.torgue at foss.st.com>
 
 description: |
   STMicroelectronics's STM32 MCUs intregrate a GPIO and Pin mux/config hardware
diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml
index 9f1c70381b82..df0191b1ceba 100644
--- a/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml
+++ b/Documentation/devicetree/bindings/regulator/st,stm32-booster.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 booster for ADC analog input switches bindings
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 description: |
   Some STM32 devices embed a 3.3V booster supplied by Vdda, that can be used
diff --git a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml
index 3cd4a254e4cb..836d4156d54c 100644
--- a/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml
+++ b/Documentation/devicetree/bindings/regulator/st,stm32-vrefbuf.yaml
@@ -12,7 +12,7 @@ description: |
   components through the dedicated VREF+ pin.
 
 maintainers:
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 allOf:
   - $ref: "regulator.yaml#"
diff --git a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
index e6322bc3e447..bd07b9c81570 100644
--- a/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
+++ b/Documentation/devicetree/bindings/regulator/st,stm32mp1-pwr-reg.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STM32MP1 PWR voltage regulators
 
 maintainers:
-  - Pascal Paillet <p.paillet at st.com>
+  - Pascal Paillet <p.paillet at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
index 1e6225677e00..b587c97c282b 100644
--- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
@@ -11,8 +11,8 @@ description:
   boots firmwares on the ST32MP family chipset.
 
 maintainers:
-  - Fabien Dessenne <fabien.dessenne at st.com>
-  - Arnaud Pouliquen <arnaud.pouliquen at st.com>
+  - Fabien Dessenne <fabien.dessenne at foss.st.com>
+  - Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
index 82bb2e97e889..9a6e4eaf4d3c 100644
--- a/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
+++ b/Documentation/devicetree/bindings/rng/st,stm32-rng.yaml
@@ -11,7 +11,7 @@ description: |
   IP and is fully separated from other crypto functions.
 
 maintainers:
-  - Lionel Debieve <lionel.debieve at st.com>
+  - Lionel Debieve <lionel.debieve at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
index 5456604b1c14..2359f541b770 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Real Time Clock Bindings
 
 maintainers:
-  - Gabriel Fernandez <gabriel.fernandez at st.com>
+  - Gabriel Fernandez <gabriel.fernandez at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
index f50f4ca893a0..333dc42722d2 100644
--- a/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/st,stm32-uart.yaml
@@ -5,7 +5,7 @@ $id: http://devicetree.org/schemas/serial/st,stm32-uart.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 maintainers:
-  - Erwan Le Ray <erwan.leray at st.com>
+  - Erwan Le Ray <erwan.leray at foss.st.com>
 
 title: STMicroelectronics STM32 USART bindings
 
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
index 0d87e2c86a42..963a871e74da 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: CS42L51 audio codec DT bindings
 
 maintainers:
-  - Olivier Moysan <olivier.moysan at st.com>
+  - Olivier Moysan <olivier.moysan at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
index 6feb5a09c184..d3966ae04ad0 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 SPI/I2S Controller
 
 maintainers:
-  - Olivier Moysan <olivier.moysan at st.com>
+  - Olivier Moysan <olivier.moysan at foss.st.com>
 
 description:
   The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
index f97132400bb6..1538d11ce9a8 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Serial Audio Interface (SAI)
 
 maintainers:
-  - Olivier Moysan <olivier.moysan at st.com>
+  - Olivier Moysan <olivier.moysan at foss.st.com>
 
 description:
   The SAI interface (Serial Audio Interface) offers a wide set of audio
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
index b7f7dc452231..837e830c47ac 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 S/PDIF receiver (SPDIFRX)
 
 maintainers:
-  - Olivier Moysan <olivier.moysan at st.com>
+  - Olivier Moysan <olivier.moysan at foss.st.com>
 
 description: |
   The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
diff --git a/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml
index 983c4e54c0be..6ec6f556182f 100644
--- a/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml
+++ b/Documentation/devicetree/bindings/spi/st,stm32-qspi.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Quad Serial Peripheral Interface (QSPI) bindings
 
 maintainers:
-  - Christophe Kerello <christophe.kerello at st.com>
-  - Patrice Chotard <patrice.chotard at st.com>
+  - Christophe Kerello <christophe.kerello at foss.st.com>
+  - Patrice Chotard <patrice.chotard at foss.st.com>
 
 allOf:
   - $ref: "spi-controller.yaml#"
diff --git a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
index 2d9af4c506bb..3d64bed266ac 100644
--- a/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/st,stm32-spi.yaml
@@ -13,8 +13,8 @@ description: |
   from 4 to 32-bit data size.
 
 maintainers:
-  - Erwan Leray <erwan.leray at st.com>
-  - Fabrice Gasnier <fabrice.gasnier at st.com>
+  - Erwan Leray <erwan.leray at foss.st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
 
 allOf:
   - $ref: "spi-controller.yaml#"
diff --git a/Documentation/devicetree/bindings/thermal/st,stm32-thermal.yaml b/Documentation/devicetree/bindings/thermal/st,stm32-thermal.yaml
index c0f59c56003d..bee41cff5142 100644
--- a/Documentation/devicetree/bindings/thermal/st,stm32-thermal.yaml
+++ b/Documentation/devicetree/bindings/thermal/st,stm32-thermal.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 digital thermal sensor (DTS) binding
 
 maintainers:
-  - David Hernandez Sanchez <david.hernandezsanchez at st.com>
+  - Pascal Paillet <p.paillet at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/timer/st,stm32-timer.yaml b/Documentation/devicetree/bindings/timer/st,stm32-timer.yaml
index 176aa3c9baf8..937aa8a56366 100644
--- a/Documentation/devicetree/bindings/timer/st,stm32-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/st,stm32-timer.yaml
@@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 general-purpose 16 and 32 bits timers bindings
 
 maintainers:
-  - Benjamin Gaignard <benjamin.gaignard at st.com>
+  - Fabrice Gasnier <fabrice.gasnier at foss.st.com>
+  - Patrice Chotard <patrice.chotard at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/usb/st,stusb160x.yaml b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
index 9a51efa9d101..ead1571e0e43 100644
--- a/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
+++ b/Documentation/devicetree/bindings/usb/st,stusb160x.yaml
@@ -7,7 +7,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: STMicroelectronics STUSB160x Type-C controller bindings
 
 maintainers:
-  - Amelie Delaunay <amelie.delaunay at st.com>
+  - Amelie Delaunay <amelie.delaunay at foss.st.com>
 
 properties:
   compatible:
diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml
index 481bf91f988a..39736449ba64 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.yaml
@@ -7,8 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: STMicroelectronics STM32 Independent WatchDoG (IWDG) bindings
 
 maintainers:
-  - Yannick Fertre <yannick.fertre at st.com>
-  - Christophe Roullier <christophe.roullier at st.com>
+  - Yannick Fertre <yannick.fertre at foss.st.com>
+  - Christophe Roullier <christophe.roullier at foss.st.com>
 
 allOf:
   - $ref: "watchdog.yaml#"
-- 
2.17.1



From boris.brezillon at collabora.com  Tue Oct 19 23:52:50 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 08:52:50 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211019180800.3v7emokse6lkpjvk@skn-laptop>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
Message-ID: <20211020085250.030ef244@collabora.com>

On Tue, 19 Oct 2021 20:08:00 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Fri, Oct 15, 2021 at 08:22:06AM +0200, Miquel Raynal wrote:
> > Hi Sean,
> > 
> > boris.brezillon at collabora.com wrote on Mon, 11 Oct 2021 16:05:46 +0200:
> >   
> > > On Mon, 11 Oct 2021 13:52:50 +0200  
> 
> [ ... ]
> 
> >   
> > > > One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> > > > initialized. Seems cumbersome to have every mtd/nand driver to call
> > > > init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> > > > to mtd_set_dev_defaults() before nand_create_bbt()?    
> > > 
> > > I have a nasty trick for that one, but I'm not sure Miquel will like it
> > > (actually, I don't like it either, but it's so simple compared to the
> > > other options we have that I'm tempted to go for this approach until
> > > someone has time to invest in a cleaner solution :-)):
> > > 
> > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > index 3d6c6e880520..a9ac2d528a4d 100644
> > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> > >         mtd->_sync = nand_sync;
> > >         mtd->_lock = nand_lock;
> > >         mtd->_unlock = nand_unlock;
> > > -       mtd->_suspend = nand_suspend;
> > > -       mtd->_resume = nand_resume;
> > >         mtd->_reboot = nand_shutdown;
> > >         mtd->_block_isreserved = nand_block_isreserved;
> > >         mtd->_block_isbad = nand_block_isbad;
> > > @@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
> > >         if (ret)
> > >                 goto err_free_secure_regions;
> > >  
> > > +       /*
> > > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > > +        * avoid using the suspend lock and resume waitqueue which are only
> > > +        * initialized when mtd_device_register() is called.
> > > +        */
> > > +       mtd->_suspend = nand_suspend;
> > > +       mtd->_resume = nand_resume;
> > >         return 0;  
> > 
> > I'm fine with this as long as it is documented for now.
> >   
> 
> Hi Boris and Miquel,
> 
> gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> suspend resume hooks :(
> Guess there is other drivers that does the same thing...

This should fix the issue:

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..c92b17f66994 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
        mtd->_sync = nand_sync;
        mtd->_lock = nand_lock;
        mtd->_unlock = nand_unlock;
-       mtd->_suspend = nand_suspend;
-       mtd->_resume = nand_resume;
        mtd->_reboot = nand_shutdown;
        mtd->_block_isreserved = nand_block_isreserved;
        mtd->_block_isbad = nand_block_isbad;
@@ -6262,13 +6260,21 @@ static int nand_scan_tail(struct nand_chip *chip)
 
        /* Check, if we should skip the bad block table scan */
        if (chip->options & NAND_SKIP_BBTSCAN)
-               return 0;
+               goto out;
 
        /* Build bad block table */
        ret = nand_create_bbt(chip);
        if (ret)
                goto err_free_secure_regions;
 
+out:
+       /*
+        * Populate the suspend/resume hooks after the BBT has been scanned to
+        * avoid using the suspend lock and resume waitqueue which are only
+        * initialized when mtd_device_register() is called.
+        */
+       mtd->_suspend = nand_suspend;
+       mtd->_resume = nand_resume;
        return 0;
 
 err_free_secure_regions:


From boris.brezillon at collabora.com  Wed Oct 20 00:00:58 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 09:00:58 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020085250.030ef244@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
Message-ID: <20211020090058.58af1087@collabora.com>

On Wed, 20 Oct 2021 08:52:50 +0200
Boris Brezillon <boris.brezillon at collabora.com> wrote:

> On Tue, 19 Oct 2021 20:08:00 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Fri, Oct 15, 2021 at 08:22:06AM +0200, Miquel Raynal wrote:  
> > > Hi Sean,
> > > 
> > > boris.brezillon at collabora.com wrote on Mon, 11 Oct 2021 16:05:46 +0200:
> > >     
> > > > On Mon, 11 Oct 2021 13:52:50 +0200    
> > 
> > [ ... ]
> >   
> > >     
> > > > > One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> > > > > initialized. Seems cumbersome to have every mtd/nand driver to call
> > > > > init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> > > > > to mtd_set_dev_defaults() before nand_create_bbt()?      
> > > > 
> > > > I have a nasty trick for that one, but I'm not sure Miquel will like it
> > > > (actually, I don't like it either, but it's so simple compared to the
> > > > other options we have that I'm tempted to go for this approach until
> > > > someone has time to invest in a cleaner solution :-)):
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > > index 3d6c6e880520..a9ac2d528a4d 100644
> > > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> > > >         mtd->_sync = nand_sync;
> > > >         mtd->_lock = nand_lock;
> > > >         mtd->_unlock = nand_unlock;
> > > > -       mtd->_suspend = nand_suspend;
> > > > -       mtd->_resume = nand_resume;
> > > >         mtd->_reboot = nand_shutdown;
> > > >         mtd->_block_isreserved = nand_block_isreserved;
> > > >         mtd->_block_isbad = nand_block_isbad;
> > > > @@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
> > > >         if (ret)
> > > >                 goto err_free_secure_regions;
> > > >  
> > > > +       /*
> > > > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > > > +        * avoid using the suspend lock and resume waitqueue which are only
> > > > +        * initialized when mtd_device_register() is called.
> > > > +        */
> > > > +       mtd->_suspend = nand_suspend;
> > > > +       mtd->_resume = nand_resume;
> > > >         return 0;    
> > > 
> > > I'm fine with this as long as it is documented for now.
> > >     
> > 
> > Hi Boris and Miquel,
> > 
> > gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> > suspend resume hooks :(
> > Guess there is other drivers that does the same thing...  
> 
> This should fix the issue:
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..c92b17f66994 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
>         mtd->_sync = nand_sync;
>         mtd->_lock = nand_lock;
>         mtd->_unlock = nand_unlock;
> -       mtd->_suspend = nand_suspend;
> -       mtd->_resume = nand_resume;
>         mtd->_reboot = nand_shutdown;
>         mtd->_block_isreserved = nand_block_isreserved;
>         mtd->_block_isbad = nand_block_isbad;
> @@ -6262,13 +6260,21 @@ static int nand_scan_tail(struct nand_chip *chip)
>  
>         /* Check, if we should skip the bad block table scan */
>         if (chip->options & NAND_SKIP_BBTSCAN)
> -               return 0;
> +               goto out;
>  
>         /* Build bad block table */
>         ret = nand_create_bbt(chip);
>         if (ret)
>                 goto err_free_secure_regions;
>  
> +out:
> +       /*
> +        * Populate the suspend/resume hooks after the BBT has been scanned to
> +        * avoid using the suspend lock and resume waitqueue which are only
> +        * initialized when mtd_device_register() is called.
> +        */
> +       mtd->_suspend = nand_suspend;
> +       mtd->_resume = nand_resume;
>         return 0;
>  
>  err_free_secure_regions:

Actually, this version is even cleaner:

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..98c39b7f6279 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
        mtd->_sync = nand_sync;
        mtd->_lock = nand_lock;
        mtd->_unlock = nand_unlock;
-       mtd->_suspend = nand_suspend;
-       mtd->_resume = nand_resume;
        mtd->_reboot = nand_shutdown;
        mtd->_block_isreserved = nand_block_isreserved;
        mtd->_block_isbad = nand_block_isbad;
@@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
                goto err_free_interface_config;
 
        /* Check, if we should skip the bad block table scan */
-       if (chip->options & NAND_SKIP_BBTSCAN)
-               return 0;
-
-       /* Build bad block table */
-       ret = nand_create_bbt(chip);
-       if (ret)
-               goto err_free_secure_regions;
+       if (chip->options & NAND_SKIP_BBTSCAN) {
+               /* Build bad block table */
+               ret = nand_create_bbt(chip);
+               if (ret)
+                       goto err_free_secure_regions;
+       }
 
+       /*
+        * Populate the suspend/resume hooks after the BBT has been scanned to
+        * avoid using the suspend lock and resume waitqueue which are only
+        * initialized when mtd_device_register() is called.
+        */
+       mtd->_suspend = nand_suspend;
+       mtd->_resume = nand_resume;
        return 0;
 
 err_free_secure_regions:


From miquel.raynal at bootlin.com  Wed Oct 20 00:12:28 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 09:12:28 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020090058.58af1087@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
Message-ID: <20211020091228.136fde6e@xps13>

Hi Boris,

boris.brezillon at collabora.com wrote on Wed, 20 Oct 2021 09:00:58 +0200:

> On Wed, 20 Oct 2021 08:52:50 +0200
> Boris Brezillon <boris.brezillon at collabora.com> wrote:
> 
> > On Tue, 19 Oct 2021 20:08:00 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > On Fri, Oct 15, 2021 at 08:22:06AM +0200, Miquel Raynal wrote:    
> > > > Hi Sean,
> > > > 
> > > > boris.brezillon at collabora.com wrote on Mon, 11 Oct 2021 16:05:46 +0200:
> > > >       
> > > > > On Mon, 11 Oct 2021 13:52:50 +0200      
> > > 
> > > [ ... ]
> > >     
> > > >       
> > > > > > One (small) issue still present. gpmi_nand.c uses the rwsem before it's
> > > > > > initialized. Seems cumbersome to have every mtd/nand driver to call
> > > > > > init_waitqueue_head() and init_rwsem(). Could we somehow move the call
> > > > > > to mtd_set_dev_defaults() before nand_create_bbt()?        
> > > > > 
> > > > > I have a nasty trick for that one, but I'm not sure Miquel will like it
> > > > > (actually, I don't like it either, but it's so simple compared to the
> > > > > other options we have that I'm tempted to go for this approach until
> > > > > someone has time to invest in a cleaner solution :-)):
> > > > > 
> > > > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > > > index 3d6c6e880520..a9ac2d528a4d 100644
> > > > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > > > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> > > > >         mtd->_sync = nand_sync;
> > > > >         mtd->_lock = nand_lock;
> > > > >         mtd->_unlock = nand_unlock;
> > > > > -       mtd->_suspend = nand_suspend;
> > > > > -       mtd->_resume = nand_resume;
> > > > >         mtd->_reboot = nand_shutdown;
> > > > >         mtd->_block_isreserved = nand_block_isreserved;
> > > > >         mtd->_block_isbad = nand_block_isbad;
> > > > > @@ -6269,6 +6267,13 @@ static int nand_scan_tail(struct nand_chip *chip)
> > > > >         if (ret)
> > > > >                 goto err_free_secure_regions;
> > > > >  
> > > > > +       /*
> > > > > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > > > > +        * avoid using the suspend lock and resume waitqueue which are only
> > > > > +        * initialized when mtd_device_register() is called.
> > > > > +        */
> > > > > +       mtd->_suspend = nand_suspend;
> > > > > +       mtd->_resume = nand_resume;
> > > > >         return 0;      
> > > > 
> > > > I'm fine with this as long as it is documented for now.
> > > >       
> > > 
> > > Hi Boris and Miquel,
> > > 
> > > gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> > > suspend resume hooks :(
> > > Guess there is other drivers that does the same thing...    
> > 
> > This should fix the issue:
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..c92b17f66994 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         mtd->_sync = nand_sync;
> >         mtd->_lock = nand_lock;
> >         mtd->_unlock = nand_unlock;
> > -       mtd->_suspend = nand_suspend;
> > -       mtd->_resume = nand_resume;
> >         mtd->_reboot = nand_shutdown;
> >         mtd->_block_isreserved = nand_block_isreserved;
> >         mtd->_block_isbad = nand_block_isbad;
> > @@ -6262,13 +6260,21 @@ static int nand_scan_tail(struct nand_chip *chip)
> >  
> >         /* Check, if we should skip the bad block table scan */
> >         if (chip->options & NAND_SKIP_BBTSCAN)
> > -               return 0;
> > +               goto out;
> >  
> >         /* Build bad block table */
> >         ret = nand_create_bbt(chip);
> >         if (ret)
> >                 goto err_free_secure_regions;
> >  
> > +out:
> > +       /*
> > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > +        * avoid using the suspend lock and resume waitqueue which are only
> > +        * initialized when mtd_device_register() is called.
> > +        */
> > +       mtd->_suspend = nand_suspend;
> > +       mtd->_resume = nand_resume;
> >         return 0;
> >  
> >  err_free_secure_regions:  
> 
> Actually, this version is even cleaner:
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..98c39b7f6279 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
>         mtd->_sync = nand_sync;
>         mtd->_lock = nand_lock;
>         mtd->_unlock = nand_unlock;
> -       mtd->_suspend = nand_suspend;
> -       mtd->_resume = nand_resume;
>         mtd->_reboot = nand_shutdown;
>         mtd->_block_isreserved = nand_block_isreserved;
>         mtd->_block_isbad = nand_block_isbad;
> @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
>                 goto err_free_interface_config;
>  
>         /* Check, if we should skip the bad block table scan */
> -       if (chip->options & NAND_SKIP_BBTSCAN)
> -               return 0;
> -
> -       /* Build bad block table */
> -       ret = nand_create_bbt(chip);
> -       if (ret)
> -               goto err_free_secure_regions;
> +       if (chip->options & NAND_SKIP_BBTSCAN) {
> +               /* Build bad block table */
> +               ret = nand_create_bbt(chip);
> +               if (ret)
> +                       goto err_free_secure_regions;
> +       }

Nice idea.

>  
> +       /*
> +        * Populate the suspend/resume hooks after the BBT has been scanned to
> +        * avoid using the suspend lock and resume waitqueue which are only
> +        * initialized when mtd_device_register() is called.
> +        */
> +       mtd->_suspend = nand_suspend;
> +       mtd->_resume = nand_resume;
>         return 0;
>  
>  err_free_secure_regions:

Cheers,
Miqu?l


From sean at geanix.com  Wed Oct 20 00:12:35 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 09:12:35 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020090058.58af1087@collabora.com>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
Message-ID: <20211020071235.in3omswo2jqrahrd@skn-laptop>

On Wed, Oct 20, 2021 at 09:00:58AM +0200, Boris Brezillon wrote:
> On Wed, 20 Oct 2021 08:52:50 +0200
> Boris Brezillon <boris.brezillon at collabora.com> wrote:
> 

[ ... ]
> > > 
> > > Hi Boris and Miquel,
> > > 
> > > gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> > > suspend resume hooks :(
> > > Guess there is other drivers that does the same thing...  
> 
> Actually, this version is even cleaner:
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..98c39b7f6279 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
>         mtd->_sync = nand_sync;
>         mtd->_lock = nand_lock;
>         mtd->_unlock = nand_unlock;
> -       mtd->_suspend = nand_suspend;
> -       mtd->_resume = nand_resume;
>         mtd->_reboot = nand_shutdown;
>         mtd->_block_isreserved = nand_block_isreserved;
>         mtd->_block_isbad = nand_block_isbad;
> @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
>                 goto err_free_interface_config;
>  
>         /* Check, if we should skip the bad block table scan */
> -       if (chip->options & NAND_SKIP_BBTSCAN)
> -               return 0;
> -
> -       /* Build bad block table */
> -       ret = nand_create_bbt(chip);
> -       if (ret)
> -               goto err_free_secure_regions;
> +       if (chip->options & NAND_SKIP_BBTSCAN) {
> +               /* Build bad block table */
> +               ret = nand_create_bbt(chip);
> +               if (ret)
> +                       goto err_free_secure_regions;
> +       }
>  
> +       /*
> +        * Populate the suspend/resume hooks after the BBT has been scanned to
> +        * avoid using the suspend lock and resume waitqueue which are only
> +        * initialized when mtd_device_register() is called.
> +        */
> +       mtd->_suspend = nand_suspend;
> +       mtd->_resume = nand_resume;
>         return 0;
>  
>  err_free_secure_regions:

Why is the gpmi-nand.c and other drivers set NAND_SKIP_BBTSCAN and then
call nand_create_bbt() directly?

To me it looks like legacy leftover...

/Sean


From miquel.raynal at bootlin.com  Wed Oct 20 00:23:31 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 09:23:31 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020071235.in3omswo2jqrahrd@skn-laptop>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
 <20211020071235.in3omswo2jqrahrd@skn-laptop>
Message-ID: <20211020092331.68e46e16@xps13>

Hi Sean,

sean at geanix.com wrote on Wed, 20 Oct 2021 09:12:35 +0200:

> On Wed, Oct 20, 2021 at 09:00:58AM +0200, Boris Brezillon wrote:
> > On Wed, 20 Oct 2021 08:52:50 +0200
> > Boris Brezillon <boris.brezillon at collabora.com> wrote:
> >   
> 
> [ ... ]
> > > > 
> > > > Hi Boris and Miquel,
> > > > 
> > > > gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> > > > suspend resume hooks :(
> > > > Guess there is other drivers that does the same thing...    
> > 
> > Actually, this version is even cleaner:
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..98c39b7f6279 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         mtd->_sync = nand_sync;
> >         mtd->_lock = nand_lock;
> >         mtd->_unlock = nand_unlock;
> > -       mtd->_suspend = nand_suspend;
> > -       mtd->_resume = nand_resume;
> >         mtd->_reboot = nand_shutdown;
> >         mtd->_block_isreserved = nand_block_isreserved;
> >         mtd->_block_isbad = nand_block_isbad;
> > @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
> >                 goto err_free_interface_config;
> >  
> >         /* Check, if we should skip the bad block table scan */
> > -       if (chip->options & NAND_SKIP_BBTSCAN)
> > -               return 0;
> > -
> > -       /* Build bad block table */
> > -       ret = nand_create_bbt(chip);
> > -       if (ret)
> > -               goto err_free_secure_regions;
> > +       if (chip->options & NAND_SKIP_BBTSCAN) {
> > +               /* Build bad block table */
> > +               ret = nand_create_bbt(chip);
> > +               if (ret)
> > +                       goto err_free_secure_regions;
> > +       }
> >  
> > +       /*
> > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > +        * avoid using the suspend lock and resume waitqueue which are only
> > +        * initialized when mtd_device_register() is called.
> > +        */
> > +       mtd->_suspend = nand_suspend;
> > +       mtd->_resume = nand_resume;
> >         return 0;
> >  
> >  err_free_secure_regions:  
> 
> Why is the gpmi-nand.c and other drivers set NAND_SKIP_BBTSCAN and then
> call nand_create_bbt() directly?
> 
> To me it looks like legacy leftover...

It is...

885d71e5838f ("mtd: gpmi: fix the NULL pointer") added this flag to
avoid a NULL pointer dereference on chip->buffer->databuf on mx23,
which IIRC does not exist anymore.

I believe we could get rid of it. But anyway, I like the "cleanup"
proposed by Boris so IMHO you can add these two patches to the series.

Thanks,
Miqu?l


From sean at geanix.com  Wed Oct 20 00:23:52 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 09:23:52 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020091228.136fde6e@xps13>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
 <20211020091228.136fde6e@xps13>
Message-ID: <20211020072352.7fnano7wm5l4bfi6@skn-laptop>

On Wed, Oct 20, 2021 at 09:12:28AM +0200, Miquel Raynal wrote:
> > 
> > Actually, this version is even cleaner:
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..98c39b7f6279 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         mtd->_sync = nand_sync;
> >         mtd->_lock = nand_lock;
> >         mtd->_unlock = nand_unlock;
> > -       mtd->_suspend = nand_suspend;
> > -       mtd->_resume = nand_resume;
> >         mtd->_reboot = nand_shutdown;
> >         mtd->_block_isreserved = nand_block_isreserved;
> >         mtd->_block_isbad = nand_block_isbad;
> > @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
> >                 goto err_free_interface_config;
> >  
> >         /* Check, if we should skip the bad block table scan */
> > -       if (chip->options & NAND_SKIP_BBTSCAN)
> > -               return 0;
> > -
> > -       /* Build bad block table */
> > -       ret = nand_create_bbt(chip);
> > -       if (ret)
> > -               goto err_free_secure_regions;
> > +       if (chip->options & NAND_SKIP_BBTSCAN) {
> > +               /* Build bad block table */
> > +               ret = nand_create_bbt(chip);
> > +               if (ret)
> > +                       goto err_free_secure_regions;
> > +       }
> 
> Nice idea.
> 
> >  
> > +       /*
> > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > +        * avoid using the suspend lock and resume waitqueue which are only
> > +        * initialized when mtd_device_register() is called.
> > +        */
> > +       mtd->_suspend = nand_suspend;
> > +       mtd->_resume = nand_resume;
> >         return 0;
> >  
> >  err_free_secure_regions:

Could be a nice idea, but it doesn't work...
gpmi-nand.c calls nand_create_bbt() after this have run ;)

/Sean


From boris.brezillon at collabora.com  Wed Oct 20 00:30:07 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 09:30:07 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020071235.in3omswo2jqrahrd@skn-laptop>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
 <20211020071235.in3omswo2jqrahrd@skn-laptop>
Message-ID: <20211020093007.0edb4ee4@collabora.com>

On Wed, 20 Oct 2021 09:12:35 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Wed, Oct 20, 2021 at 09:00:58AM +0200, Boris Brezillon wrote:
> > On Wed, 20 Oct 2021 08:52:50 +0200
> > Boris Brezillon <boris.brezillon at collabora.com> wrote:
> >   
> 
> [ ... ]
> > > > 
> > > > Hi Boris and Miquel,
> > > > 
> > > > gpmi-nand.c sets NAND_SKIP_BBTSCAN so we won't get there and populate
> > > > suspend resume hooks :(
> > > > Guess there is other drivers that does the same thing...    
> > 
> > Actually, this version is even cleaner:
> > 
> > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > index 3d6c6e880520..98c39b7f6279 100644
> > --- a/drivers/mtd/nand/raw/nand_base.c
> > +++ b/drivers/mtd/nand/raw/nand_base.c
> > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> >         mtd->_sync = nand_sync;
> >         mtd->_lock = nand_lock;
> >         mtd->_unlock = nand_unlock;
> > -       mtd->_suspend = nand_suspend;
> > -       mtd->_resume = nand_resume;
> >         mtd->_reboot = nand_shutdown;
> >         mtd->_block_isreserved = nand_block_isreserved;
> >         mtd->_block_isbad = nand_block_isbad;
> > @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
> >                 goto err_free_interface_config;
> >  
> >         /* Check, if we should skip the bad block table scan */
> > -       if (chip->options & NAND_SKIP_BBTSCAN)
> > -               return 0;
> > -
> > -       /* Build bad block table */
> > -       ret = nand_create_bbt(chip);
> > -       if (ret)
> > -               goto err_free_secure_regions;
> > +       if (chip->options & NAND_SKIP_BBTSCAN) {
> > +               /* Build bad block table */
> > +               ret = nand_create_bbt(chip);
> > +               if (ret)
> > +                       goto err_free_secure_regions;
> > +       }
> >  
> > +       /*
> > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > +        * avoid using the suspend lock and resume waitqueue which are only
> > +        * initialized when mtd_device_register() is called.
> > +        */
> > +       mtd->_suspend = nand_suspend;
> > +       mtd->_resume = nand_resume;
> >         return 0;
> >  
> >  err_free_secure_regions:  
> 
> Why is the gpmi-nand.c and other drivers set NAND_SKIP_BBTSCAN and then
> call nand_create_bbt() directly?

Dunno, but there's a nand_boot_init() call between the nand_scan() and
nand_create_bbt() calls, so I guess it has to do with something done in
this function...

> 
> To me it looks like legacy leftover...

If I were you, I wouldn't take the risk to change that in the same
patch series. The suspend/resume changes are already quite invasive,
so let's try to keep it as small/simple as possible.


From richard at nod.at  Wed Oct 20 00:43:28 2021
From: richard at nod.at (Richard Weinberger)
Date: Wed, 20 Oct 2021 09:43:28 +0200
Subject: [PATCH] MAINTAINERS: Remove joern@lazybastard.org
Message-ID: <20211020074328.20072-1-richard@nod.at>

Joern's mail bounces and nobody knows where to find thim
these days.
So remove him from MAINTAINERS.

Cc: hch at lst.de
Signed-off-by: Richard Weinberger <richard at nod.at>
---
 MAINTAINERS | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 0590fe14b3bc..08e005468b11 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3318,12 +3318,6 @@ F:	include/linux/blk*
 F:	kernel/trace/blktrace.c
 F:	lib/sbitmap.c
 
-BLOCK2MTD DRIVER
-M:	Joern Engel <joern at lazybastard.org>
-L:	linux-mtd at lists.infradead.org
-S:	Maintained
-F:	drivers/mtd/devices/block2mtd.c
-
 BLUETOOTH DRIVERS
 M:	Marcel Holtmann <marcel at holtmann.org>
 M:	Johan Hedberg <johan.hedberg at gmail.com>
@@ -14734,12 +14728,6 @@ F:	include/net/phonet/
 F:	include/uapi/linux/phonet.h
 F:	net/phonet/
 
-PHRAM MTD DRIVER
-M:	Joern Engel <joern at lazybastard.org>
-L:	linux-mtd at lists.infradead.org
-S:	Maintained
-F:	drivers/mtd/devices/phram.c
-
 PICOLCD HID DRIVER
 M:	Bruno Pr?mont <bonbons at linux-vserver.org>
 L:	linux-input at vger.kernel.org
-- 
2.26.2



From krzysztof.kozlowski at canonical.com  Wed Oct 20 00:45:02 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Wed, 20 Oct 2021 09:45:02 +0200
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <20211020065000.21312-1-patrice.chotard@foss.st.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
Message-ID: <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>

On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
> From: Patrice Chotard <patrice.chotard at foss.st.com>
> 
> Not all @st.com email address are concerned, only people who have
> a specific @foss.st.com email will see their entry updated.
> For some people, who left the company, remove their email.
> 

Please split simple address change from maintainer updates (removal,
addition).

Also would be nice to see here explained *why* are you doing this.

Best regards,
Krzysztof


From boris.brezillon at collabora.com  Wed Oct 20 00:47:41 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 09:47:41 +0200
Subject: [PATCH 0/3] mtd: core: protect access to mtd devices while in
 suspend
In-Reply-To: <20211020072352.7fnano7wm5l4bfi6@skn-laptop>
References: <20211011115253.38497-1-sean@geanix.com>
 <20211011160546.707b737b@collabora.com>
 <20211015082206.244a2316@xps13>
 <20211019180800.3v7emokse6lkpjvk@skn-laptop>
 <20211020085250.030ef244@collabora.com>
 <20211020090058.58af1087@collabora.com>
 <20211020091228.136fde6e@xps13>
 <20211020072352.7fnano7wm5l4bfi6@skn-laptop>
Message-ID: <20211020094741.027a118d@collabora.com>

On Wed, 20 Oct 2021 09:23:52 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Wed, Oct 20, 2021 at 09:12:28AM +0200, Miquel Raynal wrote:
> > > 
> > > Actually, this version is even cleaner:
> > > 
> > > diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> > > index 3d6c6e880520..98c39b7f6279 100644
> > > --- a/drivers/mtd/nand/raw/nand_base.c
> > > +++ b/drivers/mtd/nand/raw/nand_base.c
> > > @@ -6222,8 +6222,6 @@ static int nand_scan_tail(struct nand_chip *chip)
> > >         mtd->_sync = nand_sync;
> > >         mtd->_lock = nand_lock;
> > >         mtd->_unlock = nand_unlock;
> > > -       mtd->_suspend = nand_suspend;
> > > -       mtd->_resume = nand_resume;
> > >         mtd->_reboot = nand_shutdown;
> > >         mtd->_block_isreserved = nand_block_isreserved;
> > >         mtd->_block_isbad = nand_block_isbad;
> > > @@ -6261,14 +6259,20 @@ static int nand_scan_tail(struct nand_chip *chip)
> > >                 goto err_free_interface_config;
> > >  
> > >         /* Check, if we should skip the bad block table scan */
> > > -       if (chip->options & NAND_SKIP_BBTSCAN)
> > > -               return 0;
> > > -
> > > -       /* Build bad block table */
> > > -       ret = nand_create_bbt(chip);
> > > -       if (ret)
> > > -               goto err_free_secure_regions;
> > > +       if (chip->options & NAND_SKIP_BBTSCAN) {
> > > +               /* Build bad block table */
> > > +               ret = nand_create_bbt(chip);
> > > +               if (ret)
> > > +                       goto err_free_secure_regions;
> > > +       }  
> > 
> > Nice idea.
> >   
> > >  
> > > +       /*
> > > +        * Populate the suspend/resume hooks after the BBT has been scanned to
> > > +        * avoid using the suspend lock and resume waitqueue which are only
> > > +        * initialized when mtd_device_register() is called.
> > > +        */
> > > +       mtd->_suspend = nand_suspend;
> > > +       mtd->_resume = nand_resume;
> > >         return 0;
> > >  
> > >  err_free_secure_regions:  
> 
> Could be a nice idea, but it doesn't work...
> gpmi-nand.c calls nand_create_bbt() after this have run ;)

Er, indeed. Can you try with this instead:

diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index b7ad030225f8..548647bd27a4 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -1397,8 +1397,28 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
  */
 int nand_create_bbt(struct nand_chip *this)
 {
+       struct mtd_info *mtd = nand_to_mtd(this)
+       int (*suspend) (struct mtd_info *) = mtd->_suspend;
+       int (*resume) (struct mtd_info *) = mtd->_resume;
        int ret;
 
+       /*
+        * The BBT scan logic use the MTD helpers before the MTD layer had a
+        * chance to initialize the device, and that leads to issues when
+        * accessing the uninitialized suspend lock. Let's temporarily set the
+        * suspend/resume hooks to NULL to skip the lock acquire/release step.
+        *
+        * FIXME: This is an ugly hack, so please don't copy this pattern to
+        * other MTD implementations. The proper fix would be to implement a
+        * generic BBT scan logic at the NAND level that's not using any of the
+        * MTD helpers to access pages. We also might consider doing a two
+        * step initialization at the MTD level (mtd_device_init() +
+        * mtd_device_register()) so some of the fields are initialized
+        * early.
+        */
+       mtd->_suspend = NULL;
+       mtd->_resume = NULL;
+
        /* Is a flash based bad block table requested? */
        if (this->bbt_options & NAND_BBT_USE_FLASH) {
                /* Use the default pattern descriptors */
@@ -1422,7 +1442,13 @@ int nand_create_bbt(struct nand_chip *this)
                        return ret;
        }
 
-       return nand_scan_bbt(this, this->badblock_pattern);
+       ret = nand_scan_bbt(this, this->badblock_pattern);
+
+       /* Restore the suspend/resume hooks. */
+       mtd->_suspend = suspend;
+       mtd->_resume = resume;
+
+       return ret;
 }
 EXPORT_SYMBOL(nand_create_bbt);
 


From p.yadav at ti.com  Wed Oct 20 01:06:03 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Wed, 20 Oct 2021 13:36:03 +0530
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211013114432.31352-3-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
Message-ID: <20211020080601.c2uxccl3zaa557b2@ti.com>

On 13/10/21 02:44PM, Mika Westerberg wrote:
> The preferred way to implement SPI-NOR controller drivers is through SPI
> subsubsystem utilizing the SPI MEM core functions. This converts the
> Intel SPI flash controller driver over the SPI MEM by moving the driver
> from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> SPI MEM functions. The driver name will be changed from intel-spi to
> spi-intel to match the convention used in the SPI subsystem.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> ---
>  drivers/mtd/spi-nor/controllers/Kconfig       |  36 --
>  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
>  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
>  drivers/spi/Kconfig                           |  39 +++
>  drivers/spi/Makefile                          |   3 +
>  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
>  .../spi-intel-platform.c}                     |  21 +-
>  .../intel-spi.c => spi/spi-intel.c}           | 316 +++++++++++-------
>  drivers/spi/spi-intel.h                       |  19 ++
>  include/linux/mfd/lpc_ich.h                   |   2 +-
>  .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
>  11 files changed, 266 insertions(+), 220 deletions(-)
>  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (79%)
>  create mode 100644 drivers/spi/spi-intel.h
>  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)
> 
[...]
> +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> +				      const struct spi_mem_op *op)
> +{
> +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> +
> +	if (op->cmd.dtr)
> +		return false;
> +
> +	/*
> +	 * The Intel controller supports widths up to 4 but it handles
> +	 * them automatically and does not expose them to software. Here
> +	 * we accept anything up to 4.
> +	 */
> +	if (op->cmd.buswidth > 4 ||
> +	    (op->addr.nbytes && op->addr.buswidth > 4) ||
> +	    (op->dummy.nbytes && op->dummy.buswidth > 4))

Also need to check data buswidth here?

Other than this,

Acked-by: Pratyush Yadav <p.yadav at ti.com>

> +		return false;
> +
> +	if (ispi->swseq_reg && ispi->locked) {
> +		int i;
> +
> +		/* Check if it is in the locked opcodes list */
> +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> +			if (ispi->opcodes[i] == op->cmd.opcode)
> +				goto check_opcode;
>  		}
>  
> -		return 0;
> +		return false;
>  	}
>  
> -	/* Not needed with HW sequencer erase, make sure it is cleared */
> -	ispi->atomic_preopcode = 0;
> +check_opcode:
> +	switch (op->cmd.opcode) {
> +	case SPINOR_OP_RDID:
> +	case SPINOR_OP_RDSR:
> +	case SPINOR_OP_WRSR:
> +		return true;
>  
> -	while (len > 0) {
> -		writel(offs, ispi->base + FADDR);
> +	case SPINOR_OP_READ:
> +	case SPINOR_OP_READ_FAST:
> +	case SPINOR_OP_READ_4B:
> +	case SPINOR_OP_READ_FAST_4B:
> +		return true;
>  
> -		val = readl(ispi->base + HSFSTS_CTL);
> -		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> -		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> -		val |= cmd;
> -		val |= HSFSTS_CTL_FGO;
> -		writel(val, ispi->base + HSFSTS_CTL);
> +	case SPINOR_OP_PP:
> +	case SPINOR_OP_PP_4B:
> +	case SPINOR_OP_WREN:
> +	case SPINOR_OP_WRDI:
> +		return true;
>  
> -		ret = intel_spi_wait_hw_busy(ispi);
> -		if (ret)
> -			return ret;
> +	case SPINOR_OP_SE:
> +	case SPINOR_OP_SE_4B:
> +		return ispi->erase_64k;
>  
> -		status = readl(ispi->base + HSFSTS_CTL);
> -		if (status & HSFSTS_CTL_FCERR)
> -			return -EIO;
> -		else if (status & HSFSTS_CTL_AEL)
> -			return -EACCES;
> +	case SPINOR_OP_BE_4K:
> +	case SPINOR_OP_BE_4K_4B:
> +		return true;
> +	}
>  
> -		offs += erase_size;
> -		len -= erase_size;
> +	return false;
> +}
> +
[...]

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From sean at geanix.com  Wed Oct 20 01:45:30 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 10:45:30 +0200
Subject: [PATCH v2 0/4] mtd: core: protect access to mtd devices while in
 suspend
Message-ID: <20211020084534.2472305-1-sean@geanix.com>

Follow-up on discussion in:
https://lkml.org/lkml/2021/10/4/41
https://lkml.org/lkml/2021/10/11/435

Changes since v1:
 - removed __mtd_suspend/__mtd_resume functions as they are not used by
   mtdconcat anymore.
 - only master mtd_info is used for mtd_{start,end}_access(). Warn if we
   got mtd's.
 - added Boris patch for using uninitialized _suspend/_resume hooks when
   bbt scanning
 - mtdconcat uses device _suspend/_resume hooks
 - I don't really like the macro proposal from Boris
   mtd_no_suspend_void_call()/mtd_no_suspend_ret_call() I think they
   make the code complex to read and the macro's doesn't fit every
   where anyway...

Changes since from rfc v1/v2:
 - added access protection for all device access hooks in mtd_info.
 - added Suggested-by to [1/3] patch.
 - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
   from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
   to be blamed.
 - tested on a kernel with LOCKDEP enabled.

Sean Nyekjaer (4):
  mtd: rawnand: nand_bbt: hide suspend/resume hooks while scanning bbt
  mtd: core: protect access to MTD devices while in suspend
  mtd: rawnand: remove suspended check
  mtd: mtdconcat: add suspend lock handling

 drivers/mtd/mtdconcat.c          |   7 +-
 drivers/mtd/mtdcore.c            | 131 +++++++++++++++++++++++++++----
 drivers/mtd/nand/raw/nand_base.c |  52 +++---------
 drivers/mtd/nand/raw/nand_bbt.c  |  28 ++++++-
 include/linux/mtd/mtd.h          |  81 +++++++++++++++----
 include/linux/mtd/rawnand.h      |   5 +-
 6 files changed, 227 insertions(+), 77 deletions(-)

-- 
2.33.0



From sean at geanix.com  Wed Oct 20 01:45:31 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 10:45:31 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume hooks
 while scanning bbt
In-Reply-To: <20211020084534.2472305-1-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
Message-ID: <20211020084534.2472305-2-sean@geanix.com>

From: Boris Brezillon <boris.brezillon at collabora.com>

The BBT scan logic use the MTD helpers before the MTD layer had a
chance to initialize the device, and that leads to issues when
accessing the uninitialized suspend lock. Let's temporarily set the
suspend/resume hooks to NULL to skip the lock acquire/release step.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Tested-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_bbt.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index b7ad030225f8..93d385703469 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -1397,8 +1397,28 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
  */
 int nand_create_bbt(struct nand_chip *this)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
+	int (*suspend) (struct mtd_info *) = mtd->_suspend;
+	void (*resume) (struct mtd_info *) = mtd->_resume;
 	int ret;
 
+	/*
+	 * The BBT scan logic use the MTD helpers before the MTD layer had a
+	 * chance to initialize the device, and that leads to issues when
+	 * accessing the uninitialized suspend lock. Let's temporarily set the
+	 * suspend/resume hooks to NULL to skip the lock acquire/release step.
+	 *
+	 * FIXME: This is an ugly hack, so please don't copy this pattern to
+	 * other MTD implementations. The proper fix would be to implement a
+	 * generic BBT scan logic at the NAND level that's not using any of the
+	 * MTD helpers to access pages. We also might consider doing a two
+	 * step initialization at the MTD level (mtd_device_init() +
+	 * mtd_device_register()) so some of the fields are initialized
+	 * early.
+	 */
+	mtd->_suspend = NULL;
+	mtd->_resume = NULL;
+
 	/* Is a flash based bad block table requested? */
 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
 		/* Use the default pattern descriptors */
@@ -1422,7 +1442,13 @@ int nand_create_bbt(struct nand_chip *this)
 			return ret;
 	}
 
-	return nand_scan_bbt(this, this->badblock_pattern);
+	ret = nand_scan_bbt(this, this->badblock_pattern);
+
+	/* Restore the suspend/resume hooks. */
+	mtd->_suspend = suspend;
+	mtd->_resume = resume;
+
+	return ret;
 }
 EXPORT_SYMBOL(nand_create_bbt);
 
-- 
2.33.0



From sean at geanix.com  Wed Oct 20 01:45:33 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 10:45:33 +0200
Subject: [PATCH v2 3/4] mtd: rawnand: remove suspended check
In-Reply-To: <20211020084534.2472305-1-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
Message-ID: <20211020084534.2472305-4-sean@geanix.com>

Access is protected in upper MTD layer when MTD devices are suspended.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_base.c | 52 ++++++++------------------------
 include/linux/mtd/rawnand.h      |  5 +--
 2 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..aa2874ae3c4a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  * @chip: NAND chip structure
  *
  * Lock the device and its controller for exclusive access
- *
- * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
 	mutex_lock(&chip->controller->lock);
-
-	return 0;
 }
 
 /**
@@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
-
+		nand_get_device(chip);
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
 	}
@@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4345,13 +4332,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	int ret = 0;
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 	if (nand_region_is_secured(chip, instr->addr, instr->len))
 		return -EIO;
 
-	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	/* Grab the lock */
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 	pr_debug("%s: called\n", __func__);
 
-	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	/* Grab the lock */
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
 	mutex_lock(&chip->lock);
 	if (chip->ops.suspend)
 		ret = chip->ops.suspend(chip);
-	if (!ret)
-		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
+
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		if (chip->ops.resume)
-			chip->ops.resume(chip);
-		chip->suspended = 0;
-	} else {
-		pr_err("%s called for a chip which is not in suspended state\n",
-			__func__);
-	}
+	if (chip->ops.resume)
+		chip->ops.resume(chip);
 	mutex_unlock(&chip->lock);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..1198a6548912 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1237,9 +1237,7 @@ struct nand_secure_region {
  * @pagecache.page: Page number currently in the cache. -1 means no page is
  *                  currently cached
  * @buf_align: Minimum buffer alignment required by a platform
- * @lock: Lock protecting the suspended field. Also used to serialize accesses
- *        to the NAND device
- * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @lock: Lock to serialize accesses to the NAND device
  * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
  *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
  *          NAND Controller drivers should not modify this value, but they're
@@ -1293,7 +1291,6 @@ struct nand_chip {
 
 	/* Internals */
 	struct mutex lock;
-	unsigned int suspended : 1;
 	int cur_cs;
 	int read_retries;
 	struct nand_secure_region *secure_regions;
-- 
2.33.0



From sean at geanix.com  Wed Oct 20 01:45:32 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 10:45:32 +0200
Subject: [PATCH v2 2/4] mtd: core: protect access to MTD devices while in
 suspend
In-Reply-To: <20211020084534.2472305-1-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
Message-ID: <20211020084534.2472305-3-sean@geanix.com>

Prevent accessing the devices while in a suspended state. Also
prevent suspending a device which is still currently in use.

Commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") allows the
rawnand layer to return errors rather than waiting in a blocking wait.

Tested on a iMX6ULL.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdcore.c   | 131 ++++++++++++++++++++++++++++++++++------
 include/linux/mtd/mtd.h |  81 ++++++++++++++++++++-----
 2 files changed, 181 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 153229198947..310d1f86a77b 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -777,6 +777,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
 	INIT_LIST_HEAD(&mtd->partitions);
 	mutex_init(&mtd->master.partitions_lock);
 	mutex_init(&mtd->master.chrdev_lock);
+	init_waitqueue_head(&mtd->master.resume_wq);
+	init_rwsem(&mtd->master.suspend_lock);
 }
 
 static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
@@ -1257,6 +1259,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	ledtrig_mtd_activity();
 
+	mtd_start_access(master);
+
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) {
 		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
 				master->erasesize;
@@ -1278,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 		}
 	}
 
+	mtd_end_access(master);
+
 	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase);
@@ -1289,6 +1295,7 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	      void **virt, resource_size_t *phys)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	*virt = NULL;
@@ -1301,8 +1308,12 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	if (!len)
 		return 0;
 
+	mtd_start_access(master);
 	from = mtd_get_master_ofs(mtd, from);
-	return master->_point(master, from, len, retlen, virt, phys);
+	ret = master->_point(master, from, len, retlen, virt, phys);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_point);
 
@@ -1310,6 +1321,7 @@ EXPORT_SYMBOL_GPL(mtd_point);
 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unpoint)
 		return -EOPNOTSUPP;
@@ -1317,7 +1329,12 @@ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
-	return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+
+	mtd_start_access(master);
+	ret =  master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unpoint);
 
@@ -1372,6 +1389,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_read_oob_std handles mtd access protection */
 	ret = mtd_read_oob(mtd, from, &ops);
 	*retlen = ops.retlen;
 
@@ -1388,6 +1406,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_write_oob_std handles mtd access protection */
 	ret = mtd_write_oob(mtd, to, &ops);
 	*retlen = ops.retlen;
 
@@ -1406,6 +1425,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 		    const u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_panic_write)
@@ -1419,8 +1439,12 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	if (!master->oops_panic_write)
 		master->oops_panic_write = true;
 
-	return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
-				    retlen, buf);
+	mtd_start_access(master);
+	ret = master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
+				   retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
@@ -1464,11 +1488,13 @@ static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
 	int ret;
 
 	from = mtd_get_master_ofs(mtd, from);
+	mtd_start_access(master);
 	if (master->_read_oob)
 		ret = master->_read_oob(master, from, ops);
 	else
 		ret = master->_read(master, from, ops->len, &ops->retlen,
 				    ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1480,11 +1506,13 @@ static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
 	int ret;
 
 	to = mtd_get_master_ofs(mtd, to);
+	mtd_start_access(master);
 	if (master->_write_oob)
 		ret = master->_write_oob(master, to, ops);
 	else
 		ret = master->_write(master, to, ops->len, &ops->retlen,
 				     ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1576,7 +1604,6 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 		ret_code = mtd_read_oob_std(mtd, from, ops);
 
 	mtd_update_ecc_stats(mtd, master, &old_stats);
-
 	/*
 	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
 	 * similar to mtd->_read(), returning a non-negative integer
@@ -1615,7 +1642,9 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		return mtd_io_emulated_slc(mtd, to, false, ops);
 
-	return mtd_write_oob_std(mtd, to, ops);
+	ret = mtd_write_oob_std(mtd, to, ops);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_write_oob);
 
@@ -1992,12 +2021,18 @@ int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_fact_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_fact_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_get_fact_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
 
@@ -2005,13 +2040,19 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_fact_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_fact_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_fact_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
 
@@ -2019,12 +2060,18 @@ int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_user_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_user_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret =  master->_get_user_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
 
@@ -2032,13 +2079,19 @@ int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_user_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_user_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
 
@@ -2053,7 +2106,11 @@ int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
+
+	mtd_start_access(master);
 	ret = master->_write_user_prot_reg(master, to, len, retlen, buf);
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
@@ -2068,24 +2125,36 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_lock_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_lock_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
 
 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_erase_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_erase_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_erase_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 
@@ -2093,6 +2162,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock)
 		return -EOPNOTSUPP;
@@ -2106,13 +2176,18 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock);
 
 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unlock)
 		return -EOPNOTSUPP;
@@ -2126,13 +2201,18 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unlock);
 
 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_is_locked)
 		return -EOPNOTSUPP;
@@ -2146,13 +2226,18 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
 
 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2162,13 +2247,18 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isreserved);
 
 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2178,7 +2268,11 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
 
@@ -2197,7 +2291,10 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
+	mtd_start_access(master);
 	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..5c7d8de2d900 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -231,6 +231,8 @@ struct mtd_master {
 	struct mutex partitions_lock;
 	struct mutex chrdev_lock;
 	unsigned int suspended : 1;
+	wait_queue_head_t resume_wq;
+	struct rw_semaphore suspend_lock;
 };
 
 struct mtd_info {
@@ -476,10 +478,47 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
 }
 
+static inline void mtd_start_access(struct mtd_info *master)
+{
+	WARN_ON_ONCE(master != mtd_get_master(master));
+
+	/*
+	 * Don't take the suspend_lock on devices that don't
+	 * implement the suspend hook. Otherwise, lockdep will
+	 * complain about nested locks when trying to suspend MTD
+	 * partitions or MTD devices created by gluebi which are
+	 * backed by real devices.
+	 */
+	if (!master->_suspend)
+		return;
+
+	/*
+	 * Wait until the device is resumed. Should we have a
+	 * non-blocking mode here?
+	 */
+	while (1) {
+		down_read(&master->master.suspend_lock);
+		if (!master->master.suspended)
+			return;
+
+		up_read(&master->master.suspend_lock);
+		wait_event(master->master.resume_wq, master->master.suspended == 0);
+	}
+}
+
+static inline void mtd_end_access(struct mtd_info *master)
+{
+	if (!master->_suspend)
+		return;
+
+	up_read(&master->master.suspend_lock);
+}
+
 static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 				     loff_t ofs, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_max_bad_blocks)
 		return -ENOTSUPP;
@@ -487,8 +526,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 	if (mtd->size < (len + ofs) || ofs < 0)
 		return -EINVAL;
 
-	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
-				       len);
+	mtd_start_access(master);
+	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
+				      len);
+	mtd_end_access(master);
+
+	return ret;
 }
 
 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
@@ -546,30 +589,40 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
-	int ret;
-
-	if (master->master.suspended)
-		return 0;
+	int ret = 0;
 
-	ret = master->_suspend ? master->_suspend(master) : 0;
-	if (ret)
+	if (!master->_suspend)
 		return ret;
 
-	master->master.suspended = 1;
-	return 0;
+	down_write(&master->master.suspend_lock);
+	if (!master->master.suspended) {
+		ret = master->_suspend(master);
+		if (!ret)
+			master->master.suspended = 1;
+	}
+	up_write(&master->master.suspend_lock);
+
+	return ret;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 
-	if (!master->master.suspended)
+	if (!master->_suspend)
 		return;
 
-	if (master->_resume)
-		master->_resume(master);
+	down_write(&master->master.suspend_lock);
+	if (master->master.suspended) {
+		if (master->_resume)
+			master->_resume(master);
+
+		master->master.suspended = 0;
 
-	master->master.suspended = 0;
+		/* The MTD dev has been resumed, wake up all waiters. */
+		wake_up_all(&master->master.resume_wq);
+	}
+	up_write(&master->master.suspend_lock);
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
-- 
2.33.0



From sean at geanix.com  Wed Oct 20 01:45:34 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 10:45:34 +0200
Subject: [PATCH v2 4/4] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211020084534.2472305-1-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
Message-ID: <20211020084534.2472305-5-sean@geanix.com>

Use MTD hooks to control suspend/resume of MTD devices.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdconcat.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index f685a581df48..1ec36890118f 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -566,9 +566,11 @@ static int concat_suspend(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		if ((rc = mtd_suspend(subdev)) < 0)
+		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
+		if (rc < 0)
 			return rc;
 	}
+
 	return rc;
 }
 
@@ -579,7 +581,8 @@ static void concat_resume(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		mtd_resume(subdev);
+		if (subdev->_resume)
+			subdev->_resume(subdev);
 	}
 }
 
-- 
2.33.0



From boris.brezillon at collabora.com  Wed Oct 20 01:53:26 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 10:53:26 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume
 hooks while scanning bbt
In-Reply-To: <20211020084534.2472305-2-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-2-sean@geanix.com>
Message-ID: <20211020105326.0dca864a@collabora.com>

On Wed, 20 Oct 2021 10:45:31 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> From: Boris Brezillon <boris.brezillon at collabora.com>
> 
> The BBT scan logic use the MTD helpers before the MTD layer had a
> chance to initialize the device, and that leads to issues when
> accessing the uninitialized suspend lock. Let's temporarily set the
> suspend/resume hooks to NULL to skip the lock acquire/release step.
> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Tested-by: Sean Nyekjaer <sean at geanix.com>

It's missing our Signed-off-by tags.

> ---
>  drivers/mtd/nand/raw/nand_bbt.c | 28 +++++++++++++++++++++++++++-
>  1 file changed, 27 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
> index b7ad030225f8..93d385703469 100644
> --- a/drivers/mtd/nand/raw/nand_bbt.c
> +++ b/drivers/mtd/nand/raw/nand_bbt.c
> @@ -1397,8 +1397,28 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
>   */
>  int nand_create_bbt(struct nand_chip *this)
>  {
> +	struct mtd_info *mtd = nand_to_mtd(this);
> +	int (*suspend) (struct mtd_info *) = mtd->_suspend;
> +	void (*resume) (struct mtd_info *) = mtd->_resume;
>  	int ret;
>  
> +	/*
> +	 * The BBT scan logic use the MTD helpers before the MTD layer had a
> +	 * chance to initialize the device, and that leads to issues when
> +	 * accessing the uninitialized suspend lock. Let's temporarily set the
> +	 * suspend/resume hooks to NULL to skip the lock acquire/release step.
> +	 *
> +	 * FIXME: This is an ugly hack, so please don't copy this pattern to
> +	 * other MTD implementations. The proper fix would be to implement a
> +	 * generic BBT scan logic at the NAND level that's not using any of the
> +	 * MTD helpers to access pages. We also might consider doing a two
> +	 * step initialization at the MTD level (mtd_device_init() +
> +	 * mtd_device_register()) so some of the fields are initialized
> +	 * early.
> +	 */
> +	mtd->_suspend = NULL;
> +	mtd->_resume = NULL;
> +
>  	/* Is a flash based bad block table requested? */
>  	if (this->bbt_options & NAND_BBT_USE_FLASH) {
>  		/* Use the default pattern descriptors */
> @@ -1422,7 +1442,13 @@ int nand_create_bbt(struct nand_chip *this)
>  			return ret;
>  	}
>  
> -	return nand_scan_bbt(this, this->badblock_pattern);
> +	ret = nand_scan_bbt(this, this->badblock_pattern);
> +
> +	/* Restore the suspend/resume hooks. */
> +	mtd->_suspend = suspend;
> +	mtd->_resume = resume;
> +
> +	return ret;
>  }
>  EXPORT_SYMBOL(nand_create_bbt);
>  



From boris.brezillon at collabora.com  Wed Oct 20 01:55:47 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 10:55:47 +0200
Subject: [PATCH v2 4/4] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211020084534.2472305-5-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-5-sean@geanix.com>
Message-ID: <20211020105547.23ed9324@collabora.com>

On Wed, 20 Oct 2021 10:45:34 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Use MTD hooks to control suspend/resume of MTD devices.

Please explain in great details why this is needed.

> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>

This patch should be moved earlier (before 'mtd: core: protect access to
MTD devices while in suspend') in the series.

> ---
>  drivers/mtd/mtdconcat.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> index f685a581df48..1ec36890118f 100644
> --- a/drivers/mtd/mtdconcat.c
> +++ b/drivers/mtd/mtdconcat.c
> @@ -566,9 +566,11 @@ static int concat_suspend(struct mtd_info *mtd)
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		if ((rc = mtd_suspend(subdev)) < 0)
> +		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
> +		if (rc < 0)
>  			return rc;

Same here, you need a fat comment explaining why mtd_suspend() is not
used.

>  	}
> +
>  	return rc;
>  }
>  
> @@ -579,7 +581,8 @@ static void concat_resume(struct mtd_info *mtd)
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		mtd_resume(subdev);
> +		if (subdev->_resume)
> +			subdev->_resume(subdev);

Ditto.

>  	}
>  }
>  



From boris.brezillon at collabora.com  Wed Oct 20 01:57:43 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 10:57:43 +0200
Subject: [PATCH v2 3/4] mtd: rawnand: remove suspended check
In-Reply-To: <20211020084534.2472305-4-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-4-sean@geanix.com>
Message-ID: <20211020105743.225d97f4@collabora.com>

On Wed, 20 Oct 2021 10:45:33 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> Access is protected in upper MTD layer when MTD devices are suspended.

I think it deserves more explanation.

> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")

This patch doesn't fix anything, things have been fixed in 'mtd: core:
protect access to MTD devices while in suspend'. It's just a cleanup on
top of it.

> Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
>  drivers/mtd/nand/raw/nand_base.c | 52 ++++++++------------------------
>  include/linux/mtd/rawnand.h      |  5 +--
>  2 files changed, 14 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index 3d6c6e880520..aa2874ae3c4a 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
>   * @chip: NAND chip structure
>   *
>   * Lock the device and its controller for exclusive access
> - *
> - * Return: -EBUSY if the chip has been suspended, 0 otherwise
>   */
> -static int nand_get_device(struct nand_chip *chip)
> +static void nand_get_device(struct nand_chip *chip)
>  {
>  	mutex_lock(&chip->lock);
> -	if (chip->suspended) {
> -		mutex_unlock(&chip->lock);
> -		return -EBUSY;
> -	}
>  	mutex_lock(&chip->controller->lock);
> -
> -	return 0;
>  }
>  
>  /**
> @@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
>  		nand_erase_nand(chip, &einfo, 0);
>  
>  		/* Write bad block marker to OOB */
> -		ret = nand_get_device(chip);
> -		if (ret)
> -			return ret;
> -
> +		nand_get_device(chip);
>  		ret = nand_markbad_bbm(chip, ofs);
>  		nand_release_device(chip);
>  	}
> @@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
>  	    ops->mode != MTD_OPS_RAW)
>  		return -ENOTSUPP;
>  
> -	ret = nand_get_device(chip);
> -	if (ret)
> -		return ret;
> +	nand_get_device(chip);
>  
>  	if (!ops->datbuf)
>  		ret = nand_do_read_oob(chip, from, ops);
> @@ -4345,13 +4332,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
>  			  struct mtd_oob_ops *ops)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
> -	int ret;
> +	int ret = 0;
>  
>  	ops->retlen = 0;
>  
> -	ret = nand_get_device(chip);
> -	if (ret)
> -		return ret;
> +	nand_get_device(chip);
>  
>  	switch (ops->mode) {
>  	case MTD_OPS_PLACE_OOB:
> @@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
>  	if (nand_region_is_secured(chip, instr->addr, instr->len))
>  		return -EIO;
>  
> -	/* Grab the lock and see if the device is available */
> -	ret = nand_get_device(chip);
> -	if (ret)
> -		return ret;
> +	/* Grab the lock */
> +	nand_get_device(chip);
>  
>  	/* Shift to get first page */
>  	page = (int)(instr->addr >> chip->page_shift);
> @@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
>  
>  	pr_debug("%s: called\n", __func__);
>  
> -	/* Grab the lock and see if the device is available */
> -	WARN_ON(nand_get_device(chip));
> +	/* Grab the lock */
> +	nand_get_device(chip);
>  	/* Release it and go back */
>  	nand_release_device(chip);
>  }
> @@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
>  	int ret;
>  
>  	/* Select the NAND device */
> -	ret = nand_get_device(chip);
> -	if (ret)
> -		return ret;
> +	nand_get_device(chip);
>  
>  	nand_select_target(chip, chipnr);
>  
> @@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
>  	mutex_lock(&chip->lock);
>  	if (chip->ops.suspend)
>  		ret = chip->ops.suspend(chip);
> -	if (!ret)
> -		chip->suspended = 1;
>  	mutex_unlock(&chip->lock);
>  
>  	return ret;
> @@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  
> +
>  	mutex_lock(&chip->lock);
> -	if (chip->suspended) {
> -		if (chip->ops.resume)
> -			chip->ops.resume(chip);
> -		chip->suspended = 0;
> -	} else {
> -		pr_err("%s called for a chip which is not in suspended state\n",
> -			__func__);
> -	}
> +	if (chip->ops.resume)
> +		chip->ops.resume(chip);
>  	mutex_unlock(&chip->lock);
>  }
>  
> diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
> index b2f9dd3cbd69..1198a6548912 100644
> --- a/include/linux/mtd/rawnand.h
> +++ b/include/linux/mtd/rawnand.h
> @@ -1237,9 +1237,7 @@ struct nand_secure_region {
>   * @pagecache.page: Page number currently in the cache. -1 means no page is
>   *                  currently cached
>   * @buf_align: Minimum buffer alignment required by a platform
> - * @lock: Lock protecting the suspended field. Also used to serialize accesses
> - *        to the NAND device
> - * @suspended: Set to 1 when the device is suspended, 0 when it's not
> + * @lock: Lock to serialize accesses to the NAND device
>   * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
>   *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
>   *          NAND Controller drivers should not modify this value, but they're
> @@ -1293,7 +1291,6 @@ struct nand_chip {
>  
>  	/* Internals */
>  	struct mutex lock;
> -	unsigned int suspended : 1;
>  	int cur_cs;
>  	int read_retries;
>  	struct nand_secure_region *secure_regions;



From sean at geanix.com  Wed Oct 20 02:01:32 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 11:01:32 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume hooks
 while scanning bbt
In-Reply-To: <20211020105326.0dca864a@collabora.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-2-sean@geanix.com>
 <20211020105326.0dca864a@collabora.com>
Message-ID: <20211020090132.zuxojg6cnwsm4dwg@skn-laptop>

On Wed, Oct 20, 2021 at 10:53:26AM +0200, Boris Brezillon wrote:
> On Wed, 20 Oct 2021 10:45:31 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > From: Boris Brezillon <boris.brezillon at collabora.com>
> > 
> > The BBT scan logic use the MTD helpers before the MTD layer had a
> > chance to initialize the device, and that leads to issues when
> > accessing the uninitialized suspend lock. Let's temporarily set the
> > suspend/resume hooks to NULL to skip the lock acquire/release step.
> > 
> > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > Tested-by: Sean Nyekjaer <sean at geanix.com>
> 
> It's missing our Signed-off-by tags.
> 

Patch is from you ;)
If you are okay with it, I will add your Signed-off-by tag.

/Sean


From boris.brezillon at collabora.com  Wed Oct 20 02:03:03 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 11:03:03 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume
 hooks while scanning bbt
In-Reply-To: <20211020090132.zuxojg6cnwsm4dwg@skn-laptop>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-2-sean@geanix.com>
 <20211020105326.0dca864a@collabora.com>
 <20211020090132.zuxojg6cnwsm4dwg@skn-laptop>
Message-ID: <20211020110303.6f21c057@collabora.com>

On Wed, 20 Oct 2021 11:01:32 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

> On Wed, Oct 20, 2021 at 10:53:26AM +0200, Boris Brezillon wrote:
> > On Wed, 20 Oct 2021 10:45:31 +0200
> > Sean Nyekjaer <sean at geanix.com> wrote:
> >   
> > > From: Boris Brezillon <boris.brezillon at collabora.com>
> > > 
> > > The BBT scan logic use the MTD helpers before the MTD layer had a
> > > chance to initialize the device, and that leads to issues when
> > > accessing the uninitialized suspend lock. Let's temporarily set the
> > > suspend/resume hooks to NULL to skip the lock acquire/release step.
> > > 
> > > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > > Tested-by: Sean Nyekjaer <sean at geanix.com>  
> > 
> > It's missing our Signed-off-by tags.
> >   
> 
> Patch is from you ;)
> If you are okay with it, I will add your Signed-off-by tag.

You should add both (mine and yours).



From miquel.raynal at bootlin.com  Wed Oct 20 02:12:06 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 11:12:06 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume
 hooks while scanning bbt
In-Reply-To: <20211020110303.6f21c057@collabora.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-2-sean@geanix.com>
 <20211020105326.0dca864a@collabora.com>
 <20211020090132.zuxojg6cnwsm4dwg@skn-laptop>
 <20211020110303.6f21c057@collabora.com>
Message-ID: <20211020111206.342bd9d5@xps13>

Hi Boris,

boris.brezillon at collabora.com wrote on Wed, 20 Oct 2021 11:03:03 +0200:

> On Wed, 20 Oct 2021 11:01:32 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > On Wed, Oct 20, 2021 at 10:53:26AM +0200, Boris Brezillon wrote:  
> > > On Wed, 20 Oct 2021 10:45:31 +0200
> > > Sean Nyekjaer <sean at geanix.com> wrote:
> > >     
> > > > From: Boris Brezillon <boris.brezillon at collabora.com>
> > > > 
> > > > The BBT scan logic use the MTD helpers before the MTD layer had a
> > > > chance to initialize the device, and that leads to issues when
> > > > accessing the uninitialized suspend lock. Let's temporarily set the
> > > > suspend/resume hooks to NULL to skip the lock acquire/release step.
> > > > 
> > > > Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
> > > > Tested-by: Sean Nyekjaer <sean at geanix.com>    
> > > 
> > > It's missing our Signed-off-by tags.
> > >     
> > 
> > Patch is from you ;)
> > If you are okay with it, I will add your Signed-off-by tag.  
> 
> You should add both (mine and yours).

And put the one matching the author (Boris') before the other (yours).


From boris.brezillon at collabora.com  Wed Oct 20 02:13:47 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 11:13:47 +0200
Subject: [PATCH v2 2/4] mtd: core: protect access to MTD devices while
 in suspend
In-Reply-To: <20211020084534.2472305-3-sean@geanix.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-3-sean@geanix.com>
Message-ID: <20211020111347.627159a2@collabora.com>

On Wed, 20 Oct 2021 10:45:32 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

>  static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
> @@ -1257,6 +1259,8 @@ int mtd_erase(struct mtd_info *mtd, sruct erase_info *instr)
>  
>  	ledtrig_mtd_activity();
>  
> +	mtd_start_access(master);
> +
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) {
>  		adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) *
>  				master->erasesize;
> @@ -1278,6 +1282,8 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
>  		}
>  	}
>  
> +	mtd_end_access(master);
> +

The section covered in mtd_erase() is too broad. Put the start/end
calls around the ->_erase() call.

>  	return ret;
>  }



> @@ -1576,7 +1604,6 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
>  		ret_code = mtd_read_oob_std(mtd, from, ops);
>  
>  	mtd_update_ecc_stats(mtd, master, &old_stats);
> -

Unrelated line removal. Please drop this change.

>  	/*
>  	 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
>  	 * similar to mtd->_read(), returning a non-negative integer
> @@ -1615,7 +1642,9 @@ int mtd_write_oob(struct mtd_info *mtd, loff_t to,
>  	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
>  		return mtd_io_emulated_slc(mtd, to, false, ops);
>  
> -	return mtd_write_oob_std(mtd, to, ops);
> +	ret = mtd_write_oob_std(mtd, to, ops);
> +
> +	return ret;

Ditto, you can keep the 'return mtd_write_oob_std(mtd, to, ops);' here.

>  }
>  EXPORT_SYMBOL_GPL(mtd_write_oob);


> +static inline void mtd_start_access(struct mtd_info *master)
> +{
> +	WARN_ON_ONCE(master != mtd_get_master(master));
> +
> +	/*
> +	 * Don't take the suspend_lock on devices that don't
> +	 * implement the suspend hook. Otherwise, lockdep will
> +	 * complain about nested locks when trying to suspend MTD
> +	 * partitions or MTD devices created by gluebi which are
> +	 * backed by real devices.
> +	 */
> +	if (!master->_suspend)
> +		return;
> +
> +	/*
> +	 * Wait until the device is resumed. Should we have a
> +	 * non-blocking mode here?
> +	 */
> +	while (1) {
> +		down_read(&master->master.suspend_lock);
> +		if (!master->master.suspended)
> +			return;
> +
> +		up_read(&master->master.suspend_lock);
> +		wait_event(master->master.resume_wq, master->master.suspended == 0);

Please keep the tests consistent:

		wait_event(master->master.resume_wq, !master->master.suspended);

> +	}
> +}
> +


From sean at geanix.com  Wed Oct 20 02:14:19 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Wed, 20 Oct 2021 11:14:19 +0200
Subject: [PATCH v2 3/4] mtd: rawnand: remove suspended check
In-Reply-To: <20211020105743.225d97f4@collabora.com>
References: <20211020084534.2472305-1-sean@geanix.com>
 <20211020084534.2472305-4-sean@geanix.com>
 <20211020105743.225d97f4@collabora.com>
Message-ID: <20211020091419.2ufd4modeopmpxsp@skn-laptop>

On Wed, Oct 20, 2021 at 10:57:43AM +0200, Boris Brezillon wrote:
> On Wed, 20 Oct 2021 10:45:33 +0200
> Sean Nyekjaer <sean at geanix.com> wrote:
> 
> > Access is protected in upper MTD layer when MTD devices are suspended.
> 
> I think it deserves more explanation.
> 

Access is protected in upper MTD layer when MTD devices are suspended.

Commit ("mtd: core: protect access to MTD devices while in suspend")
introduces access protection, so it's safe to remove suspended checks.


From boris.brezillon at collabora.com  Wed Oct 20 02:41:53 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 11:41:53 +0200
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211013114432.31352-3-mika.westerberg@linux.intel.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
Message-ID: <20211020114153.0f99c5df@collabora.com>

On Wed, 13 Oct 2021 14:44:31 +0300
Mika Westerberg <mika.westerberg at linux.intel.com> wrote:

> The preferred way to implement SPI-NOR controller drivers is through SPI
> subsubsystem utilizing the SPI MEM core functions. This converts the
> Intel SPI flash controller driver over the SPI MEM by moving the driver
> from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> SPI MEM functions. The driver name will be changed from intel-spi to
> spi-intel to match the convention used in the SPI subsystem.
> 

I skimmed over the driver changes, and I'm skeptical about this "let's
convert all spi-nor controller drivers into spi-mem drivers even if
they don't fit the spi-mem model" strategy. Clearly, the intel
controller is much more limited than any other spi-mem controller (I
mean feature-wise not perf-wise of course). The fact that you have to
check the opcode to decide whether the operation is supported or not,
or the way you deduce when to issue an erase vs a regular read/write is
kind of hack-ish. Not saying we shouldn't support this case in spi-mem,
but it should at least be done in a more controlled way. Maybe with an
explicit array of supported spi_mem operations, and driver specific
hooks for each of these operations so anything falling outside is
clearly identified and rejected (we have this sort of things in the raw
NAND framework).

> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> ---

> +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> +				      const struct spi_mem_op *op)
> +{
> +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> +
> +	if (op->cmd.dtr)
> +		return false;
> +
> +	/*
> +	 * The Intel controller supports widths up to 4 but it handles
> +	 * them automatically and does not expose them to software. Here
> +	 * we accept anything up to 4.
> +	 */
> +	if (op->cmd.buswidth > 4 ||
> +	    (op->addr.nbytes && op->addr.buswidth > 4) ||
> +	    (op->dummy.nbytes && op->dummy.buswidth > 4))
> +		return false;
> +
> +	if (ispi->swseq_reg && ispi->locked) {
> +		int i;
> +
> +		/* Check if it is in the locked opcodes list */
> +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> +			if (ispi->opcodes[i] == op->cmd.opcode)
> +				goto check_opcode;
>  		}
>  
> -		return 0;
> +		return false;
>  	}
>  
> -	/* Not needed with HW sequencer erase, make sure it is cleared */
> -	ispi->atomic_preopcode = 0;
> +check_opcode:
> +	switch (op->cmd.opcode) {
> +	case SPINOR_OP_RDID:
> +	case SPINOR_OP_RDSR:
> +	case SPINOR_OP_WRSR:
> +		return true;

Ouch. I hate how spi-nor specific stuff leak into the supposedly
spi-mem generic driver. Now if we want to allow such specialization, we
should at least make sure the whole operation is consistent instead of
checking the opcode, address, dummy and data cycles separately.

>  
> -	while (len > 0) {
> -		writel(offs, ispi->base + FADDR);
> +	case SPINOR_OP_READ:
> +	case SPINOR_OP_READ_FAST:
> +	case SPINOR_OP_READ_4B:
> +	case SPINOR_OP_READ_FAST_4B:
> +		return true;
>  
> -		val = readl(ispi->base + HSFSTS_CTL);
> -		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> -		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> -		val |= cmd;
> -		val |= HSFSTS_CTL_FGO;
> -		writel(val, ispi->base + HSFSTS_CTL);
> +	case SPINOR_OP_PP:
> +	case SPINOR_OP_PP_4B:
> +	case SPINOR_OP_WREN:
> +	case SPINOR_OP_WRDI:
> +		return true;
>  
> -		ret = intel_spi_wait_hw_busy(ispi);
> -		if (ret)
> -			return ret;
> +	case SPINOR_OP_SE:
> +	case SPINOR_OP_SE_4B:
> +		return ispi->erase_64k;
>  
> -		status = readl(ispi->base + HSFSTS_CTL);
> -		if (status & HSFSTS_CTL_FCERR)
> -			return -EIO;
> -		else if (status & HSFSTS_CTL_AEL)
> -			return -EACCES;
> +	case SPINOR_OP_BE_4K:
> +	case SPINOR_OP_BE_4K_4B:
> +		return true;
> +	}
>  
> -		offs += erase_size;
> -		len -= erase_size;
> +	return false;
> +}
> +
> +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
> +{
> +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> +	size_t nbytes = op->data.nbytes;
> +	u8 opcode = op->cmd.opcode;
> +
> +	if (op->addr.nbytes) {
> +		if  (op->data.dir == SPI_MEM_DATA_IN)
> +			return intel_spi_read(ispi, op->addr.val, nbytes,
> +					      op->data.buf.in);
> +		if (op->data.dir == SPI_MEM_DATA_OUT)
> +			return intel_spi_write(ispi, op->addr.val, nbytes,
> +					       op->data.buf.out);
> +		if (op->data.dir == SPI_MEM_NO_DATA)
> +			return intel_spi_erase(ispi, opcode, op->addr.val);

That's risky IMHO, how can you be sure that NO_DATA means erase? Again,
it looks like the whole operation should be checked, not just the data
field.

> +	} else {
> +		if  (op->data.dir == SPI_MEM_DATA_IN)
> +			return intel_spi_read_reg(ispi, opcode, op->data.buf.in,
> +						  nbytes);
> +		if (op->data.dir == SPI_MEM_DATA_OUT)
> +			return intel_spi_write_reg(ispi, opcode, op->data.buf.out,
> +						   nbytes);
> +		if (op->data.dir == SPI_MEM_NO_DATA)
> +			return intel_spi_write_reg(ispi, opcode, NULL, 0);
>  	}
>  
> -	return 0;
> +	return -EINVAL;
> +}
> +


From Tudor.Ambarus at microchip.com  Wed Oct 20 02:55:47 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Wed, 20 Oct 2021 09:55:47 +0000
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <20211019172623.hi5c4i274bv3lnqw@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
 <20211019172623.hi5c4i274bv3lnqw@ti.com>
Message-ID: <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>

On 10/19/21 8:26 PM, Pratyush Yadav wrote:
>>> While we are on this topic, I find this a bit "ugly". Having to set
>>> late_init() for setting these flags for each flash is not exactly very
>>> clean or readable. I don't know how the future will look like, but if
>>> each flash/family needs its own late_init() to set some flags, it won't
>>> be very readable. We seem to be trading one type of complexity for
>>> another. I dunno which is the lesser evil though...
>> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
>> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
>> the late_init() function to see what's there. As you saw, late_init() can be
>> used for tweaking flash's parameters, settings and methods, not just NOR flags,
>> so I would expect that this hook to be present among flashes that don't define
>> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
>> the hook will be there anyway.
>>
>> This patch opens the door on how we could handle the flash_info flags. All flash_info
>> flags that can be determined when parsing SFDP can be removed and use for flashes that
>> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
>> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
>> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
>> 1/ flashes with SFDP will set the flags as:
>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> 2/ flashes without SFDP:
>> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> spi_nor_info_init_params()
>> 3/ flashes that collide, one with SFDP and the other without:
>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
> To me it looks like you can separate these flags into three classes:
> 
>   1. Whether to parse SFDP or not.
>   2. Flags that can't be discovered via SFDP.
>   3. Flags that can be discovered by SFDP ideally but can't be
>      discovered for this particular flash because either SFDP is missing
>      or the table for this flag is missing.

These are the flash_info flags, indeed. Apart of these there are the SNOR_F flags
which are set either statically (one sets a flash_info flag equivalent when
declaring the flash), or dynamically when parsing SFDP. Check
SPI_NOR_4B_OPCODES and SNOR_F_4B_OPCODES for example.

> 
> With your series, flags from 1 and 2 are populated via .flags in
> flash_info and the ones from 3 are populated via late_init().

My proposal was to get rid of the flash_info flags from the 3rd category that you
described, and set the SNOR_F equivalents in a late_init() hook. This way we also
control when the SNOR_F equivalents are set, late in the init call. But this can
be achieved with your proposal as well, let's see.

> 
> Why can't we have 3 different fields for these 3 different flags? In
> flash_info, we can set .parse_sfdp to true/false to indicate SFDP
> support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable
> flags. And we can set .fixup_flags = A | B | C (can probably pick a
> better name) for the flags that your series sets through late_init().
> 
> This way, you have a clear separation between the three and they are all
> clearly visible in the flash entry itself.

The downside that I see with this is that we extend the flash_info struct with new
fields and the spi-nor.o's size will increase whether the fields are used or not,
as we have lots of flash_info entries. This reminds me that probably I should have
put the late_init() hook inside const struct spi_nor_fixups. Anyway, we can avoid
increasing the size with some flash_info flags masks. We use the same flash_info flags
entry, but we introduce some masks, to separate the type of flags. Something like:
SPI_NOR_PARSE_SFDP |
	NON_SFDP_FLAGS(SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_SWP_IS_VOLATILE)
these are for category 1 and 2 in your description

or
SPI_NOR_SKIP_SFDP | SFDP_FLAGS(SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
for categories 1 and 3 in your description

but you can end up with flags like:
SPI_NOR_SKIP_SFDP | SFDP_FLAGS() | NON_SFDP_FLAGS()


> 
> The only case where this might run into trouble is when a SFDP flash has
> a collision with a non-SFDP flash and they both need different
> fixup_flags. But I supposed that is a problem even if you use

we can probably solve this by putting the minimum supported flags by both
and fill the rest in fixup hooks after we determine which flash is which.

> late_init() so it certainly doesn't make anything worse.

yes, this is a different topic.

> 
> I have not given this extensive thought, but it seems to make sense to
> me, and I feel that it would make the flow easier to follow. Thoughts?

Both approaches are fine. Your method keeps all flags in one place but duplicates
the setting of flags, you'll have "if flash_info flag, set SNOR_F flag".
Mine gets rid of the SFDP flash_info flags and directly sets SNOR_F equivalents
with the detriment of introducing fixup hooks at flash declaration. Can we involve
Michael and Vignesh to get their preference so that we come to an agreement and move
forward?

Thanks for the review, Pratyush.
Cheers,
ta

From maz at kernel.org  Wed Oct 20 04:39:11 2021
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 20 Oct 2021 12:39:11 +0100
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
Message-ID: <878ryoc4dc.wl-maz@kernel.org>

On Wed, 20 Oct 2021 08:45:02 +0100,
Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> wrote:
> 
> On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
> > From: Patrice Chotard <patrice.chotard at foss.st.com>
> > 
> > Not all @st.com email address are concerned, only people who have
> > a specific @foss.st.com email will see their entry updated.
> > For some people, who left the company, remove their email.
> > 
> 
> Please split simple address change from maintainer updates (removal,
> addition).
> 
> Also would be nice to see here explained *why* are you doing this.

And why this can't be done with a single update to .mailmap, like
anyone else does.

	M.

-- 
Without deviation from the norm, progress is not possible.


From p.yadav at ti.com  Wed Oct 20 04:59:15 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Wed, 20 Oct 2021 17:29:15 +0530
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211020114153.0f99c5df@collabora.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
 <20211020114153.0f99c5df@collabora.com>
Message-ID: <20211020115913.uzo3ogkmrltnb26y@ti.com>

On 20/10/21 11:41AM, Boris Brezillon wrote:
> On Wed, 13 Oct 2021 14:44:31 +0300
> Mika Westerberg <mika.westerberg at linux.intel.com> wrote:
> 
> > The preferred way to implement SPI-NOR controller drivers is through SPI
> > subsubsystem utilizing the SPI MEM core functions. This converts the
> > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > SPI MEM functions. The driver name will be changed from intel-spi to
> > spi-intel to match the convention used in the SPI subsystem.
> > 
> 
> I skimmed over the driver changes, and I'm skeptical about this "let's
> convert all spi-nor controller drivers into spi-mem drivers even if
> they don't fit the spi-mem model" strategy. Clearly, the intel
> controller is much more limited than any other spi-mem controller (I
> mean feature-wise not perf-wise of course). The fact that you have to
> check the opcode to decide whether the operation is supported or not,
> or the way you deduce when to issue an erase vs a regular read/write is
> kind of hack-ish. Not saying we shouldn't support this case in spi-mem,
> but it should at least be done in a more controlled way. Maybe with an
> explicit array of supported spi_mem operations, and driver specific
> hooks for each of these operations so anything falling outside is
> clearly identified and rejected (we have this sort of things in the raw
> NAND framework).

I am curious about how we can solve this. Any pointers to 
functions/drivers in raw NAND framework that follow this model?

[...]

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From boris.brezillon at collabora.com  Wed Oct 20 05:13:57 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Wed, 20 Oct 2021 14:13:57 +0200
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211020115913.uzo3ogkmrltnb26y@ti.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
 <20211020114153.0f99c5df@collabora.com>
 <20211020115913.uzo3ogkmrltnb26y@ti.com>
Message-ID: <20211020141357.3559ca95@collabora.com>

On Wed, 20 Oct 2021 17:29:15 +0530
Pratyush Yadav <p.yadav at ti.com> wrote:

> On 20/10/21 11:41AM, Boris Brezillon wrote:
> > On Wed, 13 Oct 2021 14:44:31 +0300
> > Mika Westerberg <mika.westerberg at linux.intel.com> wrote:
> >   
> > > The preferred way to implement SPI-NOR controller drivers is through SPI
> > > subsubsystem utilizing the SPI MEM core functions. This converts the
> > > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > > SPI MEM functions. The driver name will be changed from intel-spi to
> > > spi-intel to match the convention used in the SPI subsystem.
> > >   
> > 
> > I skimmed over the driver changes, and I'm skeptical about this "let's
> > convert all spi-nor controller drivers into spi-mem drivers even if
> > they don't fit the spi-mem model" strategy. Clearly, the intel
> > controller is much more limited than any other spi-mem controller (I
> > mean feature-wise not perf-wise of course). The fact that you have to
> > check the opcode to decide whether the operation is supported or not,
> > or the way you deduce when to issue an erase vs a regular read/write is
> > kind of hack-ish. Not saying we shouldn't support this case in spi-mem,
> > but it should at least be done in a more controlled way. Maybe with an
> > explicit array of supported spi_mem operations, and driver specific
> > hooks for each of these operations so anything falling outside is
> > clearly identified and rejected (we have this sort of things in the raw
> > NAND framework).  
> 
> I am curious about how we can solve this. Any pointers to 
> functions/drivers in raw NAND framework that follow this model?

It's not quite what you'd need, but nand_op_parser_pattern follows the
same philosophy: describe a pattern and attach a hook to be executed
when this pattern is found. Then you pass this pattern table to a helper
that tries to match the operation against the supported patterns. If it
finds one that matches, the operation is reported as supported and/or
executed, otherwise it's rejected.

In this particular case, the pattern must be very specific:

* matching opcode
* matching direction
* matching number of address cycles
* matching number of dummy cycles?
* max/min number of data cycles?


From miquel.raynal at bootlin.com  Wed Oct 20 05:18:55 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 14:18:55 +0200
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211020115913.uzo3ogkmrltnb26y@ti.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
 <20211020114153.0f99c5df@collabora.com>
 <20211020115913.uzo3ogkmrltnb26y@ti.com>
Message-ID: <20211020141855.75f0314d@xps13>

Hi Pratyush,

p.yadav at ti.com wrote on Wed, 20 Oct 2021 17:29:15 +0530:

> On 20/10/21 11:41AM, Boris Brezillon wrote:
> > On Wed, 13 Oct 2021 14:44:31 +0300
> > Mika Westerberg <mika.westerberg at linux.intel.com> wrote:
> >   
> > > The preferred way to implement SPI-NOR controller drivers is through SPI
> > > subsubsystem utilizing the SPI MEM core functions. This converts the
> > > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > > SPI MEM functions. The driver name will be changed from intel-spi to
> > > spi-intel to match the convention used in the SPI subsystem.
> > >   
> > 
> > I skimmed over the driver changes, and I'm skeptical about this "let's
> > convert all spi-nor controller drivers into spi-mem drivers even if
> > they don't fit the spi-mem model" strategy. Clearly, the intel
> > controller is much more limited than any other spi-mem controller (I
> > mean feature-wise not perf-wise of course). The fact that you have to
> > check the opcode to decide whether the operation is supported or not,
> > or the way you deduce when to issue an erase vs a regular read/write is
> > kind of hack-ish. Not saying we shouldn't support this case in spi-mem,
> > but it should at least be done in a more controlled way. Maybe with an
> > explicit array of supported spi_mem operations, and driver specific
> > hooks for each of these operations so anything falling outside is
> > clearly identified and rejected (we have this sort of things in the raw
> > NAND framework).  
> 
> I am curious about how we can solve this. Any pointers to 
> functions/drivers in raw NAND framework that follow this model?

->exec_op() should be implemented by controller drivers, there is a
check_only flag to verify that the operation is supported by the
controller, the entire operation is provided so that the controller
driver knows exactly where we are going and does not try to guess
anything. There is also a parser in the core that allows
"complicated"/"constrained" drivers to just give a number of patterns
they support and the parser will do the job of finding how the
operation should be split.

I believe this was what Boris referred to. If not, please correct me.

Thanks,
Miqu?l


From miquel.raynal at bootlin.com  Wed Oct 20 07:27:52 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:52 +0200
Subject: [PATCH 01/18] dt-bindings: mtd: nand-controller: Fix the reg property
 description
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-2-miquel.raynal@bootlin.com>

The reg property of a NAND device always references the chip-select(s).
The ready/busy lines are described in the nand-rb property. I believe
this was a harmless copy/paste error during the conversion to yaml.

Fixes: 212e49693592 ("dt-bindings: mtd: Add YAML schemas for the generic NAND options")
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 Documentation/devicetree/bindings/mtd/nand-controller.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index bd217e6f5018..811f03978fc6 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -55,7 +55,7 @@ patternProperties:
     properties:
       reg:
         description:
-          Contains the native Ready/Busy IDs.
+          Contains the chip-select IDs.
 
       nand-ecc-engine:
         allOf:
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:51 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:51 +0200
Subject: [PATCH 00/18] External ECC engines & Macronix support
Message-ID: <20211020142809.349347-1-miquel.raynal@bootlin.com>

Hello all,

This series is now stable and brings support for external/modular ECC
engines, and let SPI controller using the ECC framework.

As a first example, Macronix ECC engine can be used as an
external engine (takes the data, proceeds to the calculations, writes
back the ECC bytes) or as a pipelined engine doing on-the-fly
calculations (which is very common in the raw NAND world).

In the device tree, the ECC engine should be described as a separated DT
node. Then:
* external case: the flash node should provide a nand-ecc-engine
  property pointing to the ECC engine node.
* pipelined case: the flash node should provide a nand-ecc-engine
  property pointing to the SPI controller, itself with another
  nand-ecc-engine property pointing at the ECC engine node.

This series comes with a bunch of improvements on the binding side as
well.

Cheers,
Miqu?l

Changes since the RFC:
* Rebased on top of v5.15-rc1.
* Fixed the dirmap configuration.
* Added the various tags received.
* Fixed the bindings as reported by the robots.
* Fixed the return value of the helper counting bitflips.
* Included a fix from Jaime Liao in the external pattern logic.
* Added the yaml conversion of Macronix SPI controller description.
* Added the yaml conversion of the SPI-NAND description.
* Created a nand-chip.yaml file to share properties between SPI-NAND and
  raw NAND.

Mason Yang (1):
  mtd: spinand: macronix: Use random program load

Miquel Raynal (17):
  dt-bindings: mtd: nand-controller: Fix the reg property description
  dt-bindings: mtd: nand-controller: Fix a comment in the examples
  dt-bindings: mtd: nand-chip: Create a NAND chip description
  dt-bindings: mtd: spi-nand: Convert spi-nand description file to yaml
  dt-bindings: vendor-prefixes: Clarify Macronix prefix
  dt-bindings: spi: mxic: The interrupt property is not mandatory
  dt-bindings: spi: mxic: Convert to yaml
  dt-bindings: mtd: Describe Macronix NAND ECC engine
  dt-bindings: spi: mxic: Document the nand-ecc-engine property
  mtd: nand: ecc: Add infrastructure to support hardware engines
  mtd: nand: mxic-ecc: Add Macronix external ECC engine support
  mtd: nand: mxic-ecc: Support SPI pipelined mode
  spi: mxic: Fix the transmit path
  spi: mxic: Create a helper to configure the controller before an
    operation
  spi: mxic: Create a helper to ease the start of an operation
  spi: mxic: Add support for direct mapping
  spi: mxic: Add support for pipelined ECC operations

 .../bindings/mtd/mxicy,nand-ecc-engine.yaml   |  77 ++
 .../devicetree/bindings/mtd/nand-chip.yaml    |  71 ++
 .../bindings/mtd/nand-controller.yaml         |  57 +-
 .../devicetree/bindings/mtd/spi-nand.txt      |   5 -
 .../devicetree/bindings/mtd/spi-nand.yaml     |  27 +
 .../bindings/spi/mxicy,mx25f0a-spi.yaml       |  73 ++
 .../devicetree/bindings/spi/spi-mxic.txt      |  34 -
 .../devicetree/bindings/vendor-prefixes.yaml  |   3 +
 drivers/mtd/nand/Kconfig                      |   6 +
 drivers/mtd/nand/Makefile                     |   1 +
 drivers/mtd/nand/core.c                       |  10 +-
 drivers/mtd/nand/ecc-mxic.c                   | 799 ++++++++++++++++++
 drivers/mtd/nand/ecc.c                        |  89 ++
 drivers/mtd/nand/spi/macronix.c               |   2 +-
 drivers/spi/spi-mxic.c                        | 328 +++++--
 include/linux/mtd/nand-ecc-mxic.h             |  36 +
 include/linux/mtd/nand.h                      |  11 +
 17 files changed, 1483 insertions(+), 146 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml
 create mode 100644 Documentation/devicetree/bindings/mtd/nand-chip.yaml
 delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml
 create mode 100644 Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
 delete mode 100644 Documentation/devicetree/bindings/spi/spi-mxic.txt
 create mode 100644 drivers/mtd/nand/ecc-mxic.c
 create mode 100644 include/linux/mtd/nand-ecc-mxic.h

-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:53 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:53 +0200
Subject: [PATCH 02/18] dt-bindings: mtd: nand-controller: Fix a comment in the
 examples
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-3-miquel.raynal@bootlin.com>

The controller properties should be in the controller 'parent' node,
while properties in the children nodes are specific to the NAND
*chip*. This error was already present during the yaml conversion.

Fixes: 2d472aba15ff ("mtd: nand: document the NAND controller/NAND chip DT representation")
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 Documentation/devicetree/bindings/mtd/nand-controller.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index 811f03978fc6..5cd144a9ec99 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -184,7 +184,7 @@ examples:
         nand-use-soft-ecc-engine;
         nand-ecc-algo = "bch";
 
-        /* controller specific properties */
+        /* NAND chip specific properties */
       };
 
       nand at 1 {
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:54 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:54 +0200
Subject: [PATCH 03/18] dt-bindings: mtd: nand-chip: Create a NAND chip
 description
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-4-miquel.raynal@bootlin.com>

Move the NAND chip description out of the NAND controller file. Indeed,
a subsequent part of the properties supported by a raw NAND chip are
also supported by SPI-NAND chips. So let's create a generic NAND chip
description which will be pulled by nand-controller.yaml and later by
spi-nand.yaml as well.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../devicetree/bindings/mtd/nand-chip.yaml    | 71 +++++++++++++++++++
 .../bindings/mtd/nand-controller.yaml         | 53 ++------------
 2 files changed, 75 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mtd/nand-chip.yaml

diff --git a/Documentation/devicetree/bindings/mtd/nand-chip.yaml b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
new file mode 100644
index 000000000000..1f230a3ee27d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/nand-chip.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NAND Chip and NAND Controller Generic Binding
+
+maintainers:
+  - Miquel Raynal <miquel.raynal at bootlin.com>
+
+description: |
+  This file covers the generic description of a NAND chip. It implies that the
+  bus interface should not be taken into account: both raw NAND devices and
+  SPI-NAND devices are concerned by this description.
+
+properties:
+  reg:
+    description:
+      Contains the chip-select IDs.
+
+  nand-ecc-engine:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: |
+      A phandle on the hardware ECC engine if any. There are
+      basically three possibilities:
+      1/ The ECC engine is part of the NAND controller, in this
+      case the phandle should reference the parent node.
+      2/ The ECC engine is part of the NAND part (on-die), in this
+      case the phandle should reference the node itself.
+      3/ The ECC engine is external, in this case the phandle should
+      reference the specific ECC engine node.
+
+  nand-use-soft-ecc-engine:
+    type: boolean
+    description: Use a software ECC engine.
+
+  nand-no-ecc-engine:
+    type: boolean
+    description: Do not use any ECC correction.
+
+  nand-ecc-algo:
+    description:
+      Desired ECC algorithm.
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [hamming, bch, rs]
+
+  nand-ecc-strength:
+    description:
+      Maximum number of bits that can be corrected per ECC step.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 1
+
+  nand-ecc-step-size:
+    description:
+      Number of data bytes covered by a single ECC step.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 1
+
+  secure-regions:
+    $ref: /schemas/types.yaml#/definitions/uint64-matrix
+    description:
+      Regions in the NAND chip which are protected using a secure element
+      like Trustzone. This property contains the start address and size of
+      the secure regions present.
+
+required:
+  - reg
+
+additionalProperties: false
diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index 5cd144a9ec99..44825dc95412 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -52,32 +52,15 @@ properties:
 patternProperties:
   "^nand@[a-f0-9]$":
     type: object
+
+    allOf:
+      - $ref: "nand-chip.yaml#"
+
     properties:
       reg:
         description:
           Contains the chip-select IDs.
 
-      nand-ecc-engine:
-        allOf:
-          - $ref: /schemas/types.yaml#/definitions/phandle
-        description: |
-          A phandle on the hardware ECC engine if any. There are
-          basically three possibilities:
-          1/ The ECC engine is part of the NAND controller, in this
-          case the phandle should reference the parent node.
-          2/ The ECC engine is part of the NAND part (on-die), in this
-          case the phandle should reference the node itself.
-          3/ The ECC engine is external, in this case the phandle should
-          reference the specific ECC engine node.
-
-      nand-use-soft-ecc-engine:
-        type: boolean
-        description: Use a software ECC engine.
-
-      nand-no-ecc-engine:
-        type: boolean
-        description: Do not use any ECC correction.
-
       nand-ecc-placement:
         allOf:
           - $ref: /schemas/types.yaml#/definitions/string
@@ -88,12 +71,6 @@ patternProperties:
           known to be stored in the OOB area, or "interleaved" if ECC
           bytes will be interleaved with regular data in the main area.
 
-      nand-ecc-algo:
-        description:
-          Desired ECC algorithm.
-        $ref: /schemas/types.yaml#/definitions/string
-        enum: [hamming, bch, rs]
-
       nand-bus-width:
         description:
           Bus width to the NAND chip
@@ -112,18 +89,6 @@ patternProperties:
           find Bad Block Markers (BBM). These markers will help to
           build a volatile BBT in RAM.
 
-      nand-ecc-strength:
-        description:
-          Maximum number of bits that can be corrected per ECC step.
-        $ref: /schemas/types.yaml#/definitions/uint32
-        minimum: 1
-
-      nand-ecc-step-size:
-        description:
-          Number of data bytes covered by a single ECC step.
-        $ref: /schemas/types.yaml#/definitions/uint32
-        minimum: 1
-
       nand-ecc-maximize:
         $ref: /schemas/types.yaml#/definitions/flag
         description:
@@ -154,13 +119,6 @@ patternProperties:
           Ready/Busy pins. Active state refers to the NAND ready state and
           should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted.
 
-      secure-regions:
-        $ref: /schemas/types.yaml#/definitions/uint64-matrix
-        description:
-          Regions in the NAND chip which are protected using a secure element
-          like Trustzone. This property contains the start address and size of
-          the secure regions present.
-
     required:
       - reg
 
@@ -181,9 +139,6 @@ examples:
 
       nand at 0 {
         reg = <0>; /* Native CS */
-        nand-use-soft-ecc-engine;
-        nand-ecc-algo = "bch";
-
         /* NAND chip specific properties */
       };
 
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:55 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:55 +0200
Subject: [PATCH 04/18] dt-bindings: mtd: spi-nand: Convert spi-nand
 description file to yaml
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-5-miquel.raynal@bootlin.com>

Let's get rid of spi-nand.txt by converting it to yaml schema. While at
converting this file, let's actually pull all the generic properties
from nand-chip.yaml which might apply to a SPI-NAND chip.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../devicetree/bindings/mtd/spi-nand.txt      |  5 ----
 .../devicetree/bindings/mtd/spi-nand.yaml     | 27 +++++++++++++++++++
 2 files changed, 27 insertions(+), 5 deletions(-)
 delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
 create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml

diff --git a/Documentation/devicetree/bindings/mtd/spi-nand.txt b/Documentation/devicetree/bindings/mtd/spi-nand.txt
deleted file mode 100644
index 8b51f3b6d55c..000000000000
--- a/Documentation/devicetree/bindings/mtd/spi-nand.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-SPI NAND flash
-
-Required properties:
-- compatible: should be "spi-nand"
-- reg: should encode the chip-select line used to access the NAND chip
diff --git a/Documentation/devicetree/bindings/mtd/spi-nand.yaml b/Documentation/devicetree/bindings/mtd/spi-nand.yaml
new file mode 100644
index 000000000000..19ac57dcffc3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/spi-nand.yaml
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/spi-nand.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SPI-NAND flash device tree bindings
+
+maintainers:
+  - Miquel Raynal <miquel.raynal at bootlin.com>
+
+allOf:
+  - $ref: "nand-chip.yaml#"
+
+properties:
+  compatible:
+    const: spi-nand
+
+  reg:
+    maxItems: 1
+    description: Encode the chip-select line on the SPI bus
+
+required:
+  - compatible
+  - reg
+
+unevaluatedProperties: false
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:56 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:56 +0200
Subject: [PATCH 05/18] dt-bindings: vendor-prefixes: Clarify Macronix prefix
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-6-miquel.raynal@bootlin.com>

When looking at compatible prefixes, Macronix is sometimes referred as
"mxicy":
- mxicy,mx25r1635f
- mxicy,mx25u6435f
- mxicy,mx25v8035f
- mxicy,mx25f0a-spi
and sometimes as "mxic":
- mxic,multi-itfc-v009-nand-controller
- mxic,enable-randomizer-otp

The oldest prefix that is also the one preferred by Macronix engineers
is "mxicy", so document the other one and mark it deprecated.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index a867f7102c35..93d65dc3746c 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -774,6 +774,9 @@ patternProperties:
     description: Mundo Reader S.L.
   "^murata,.*":
     description: Murata Manufacturing Co., Ltd.
+  "^mxic,.*":
+    description: Macronix International Co., Ltd.
+    deprecated: true
   "^mxicy,.*":
     description: Macronix International Co., Ltd.
   "^myir,.*":
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:57 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:57 +0200
Subject: [PATCH 06/18] dt-bindings: spi: mxic: The interrupt property is not
 mandatory
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-7-miquel.raynal@bootlin.com>

The interrupt property is not mandatory at all, this property should not
be part of the required properties list, so move it into the optional
properties list.

Fixes: 326e5c8d4a87 ("dt-binding: spi: Document Macronix controller bindings")
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 Documentation/devicetree/bindings/spi/spi-mxic.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/spi/spi-mxic.txt b/Documentation/devicetree/bindings/spi/spi-mxic.txt
index 529f2dab2648..7bcbb229b78b 100644
--- a/Documentation/devicetree/bindings/spi/spi-mxic.txt
+++ b/Documentation/devicetree/bindings/spi/spi-mxic.txt
@@ -8,11 +8,13 @@ Required properties:
 - reg: should contain 2 entries, one for the registers and one for the direct
        mapping area
 - reg-names: should contain "regs" and "dirmap"
-- interrupts: interrupt line connected to the SPI controller
 - clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
 - clocks: should contain 3 entries for the "ps_clk", "send_clk" and
 	  "send_dly_clk" clocks
 
+Optional properties:
+- interrupts: interrupt line connected to the SPI controller
+
 Example:
 
 	spi at 43c30000 {
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:58 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:58 +0200
Subject: [PATCH 07/18] dt-bindings: spi: mxic: Convert to yaml
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-8-miquel.raynal@bootlin.com>

Straightforward conversion from regular text to yaml schema of the
Macronix SPI controller DT bindings.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../bindings/spi/mxicy,mx25f0a-spi.yaml       | 67 +++++++++++++++++++
 .../devicetree/bindings/spi/spi-mxic.txt      | 36 ----------
 2 files changed, 67 insertions(+), 36 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
 delete mode 100644 Documentation/devicetree/bindings/spi/spi-mxic.txt

diff --git a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
new file mode 100644
index 000000000000..4036c14fc533
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/mxicy,mx25f0a-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Macronix SPI controller device tree bindings
+
+maintainers:
+  - Miquel Raynal <miquel.raynal at bootlin.com>
+
+allOf:
+  - $ref: "spi-controller.yaml#"
+
+properties:
+  compatible:
+    const: mxicy,mx25f0a-spi
+
+  reg:
+    minItems: 2
+    maxItems: 2
+
+  reg-names:
+    items:
+      - const: regs
+      - const: dirmap
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    minItems: 3
+    maxItems: 3
+
+  clock-names:
+    items:
+      - const: send_clk
+      - const: send_dly_clk
+      - const: ps_clk
+
+  "#address-cells":
+    const: 1
+  "#size-cells":
+    const: 0
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+  - clock-names
+  - "#address-cells"
+  - "#size-cells"
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    spi at 43c30000 {
+      compatible = "mxicy,mx25f0a-spi";
+      reg = <0x43c30000 0x10000>, <0xa0000000 0x20000000>;
+      reg-names = "regs", "dirmap";
+      clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 18>;
+      clock-names = "send_clk", "send_dly_clk", "ps_clk";
+      #address-cells = <1>;
+      #size-cells = <0>;
+    };
diff --git a/Documentation/devicetree/bindings/spi/spi-mxic.txt b/Documentation/devicetree/bindings/spi/spi-mxic.txt
deleted file mode 100644
index 7bcbb229b78b..000000000000
--- a/Documentation/devicetree/bindings/spi/spi-mxic.txt
+++ /dev/null
@@ -1,36 +0,0 @@
-Macronix SPI controller Device Tree Bindings
---------------------------------------------
-
-Required properties:
-- compatible: should be "mxicy,mx25f0a-spi"
-- #address-cells: should be 1
-- #size-cells: should be 0
-- reg: should contain 2 entries, one for the registers and one for the direct
-       mapping area
-- reg-names: should contain "regs" and "dirmap"
-- clock-names: should contain "ps_clk", "send_clk" and "send_dly_clk"
-- clocks: should contain 3 entries for the "ps_clk", "send_clk" and
-	  "send_dly_clk" clocks
-
-Optional properties:
-- interrupts: interrupt line connected to the SPI controller
-
-Example:
-
-	spi at 43c30000 {
-		compatible = "mxicy,mx25f0a-spi";
-		reg = <0x43c30000 0x10000>, <0xa0000000 0x20000000>;
-		reg-names = "regs", "dirmap";
-		clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 18>;
-		clock-names = "send_clk", "send_dly_clk", "ps_clk";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		flash at 0 {
-			compatible = "jedec,spi-nor";
-			reg = <0>;
-			spi-max-frequency = <25000000>;
-			spi-tx-bus-width = <4>;
-			spi-rx-bus-width = <4>;
-		};
-	};
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:27:59 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:27:59 +0200
Subject: [PATCH 08/18] dt-bindings: mtd: Describe Macronix NAND ECC engine
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-9-miquel.raynal@bootlin.com>

Describe Macronix NAND ECC engine. This engine may be used as an
external engine or can be pipelined with either a raw NAND controller or
a SPI controller. Both hardware designs with a SPI controller are shown
in the examples.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../bindings/mtd/mxicy,nand-ecc-engine.yaml   | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml

diff --git a/Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml b/Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml
new file mode 100644
index 000000000000..804479999ccb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/mxicy,nand-ecc-engine.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Macronix NAND ECC engine device tree bindings
+
+maintainers:
+  - Miquel Raynal <miquel.raynal at bootlin.com>
+
+properties:
+  compatible:
+    const: mxicy,nand-ecc-engine-rev3
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    /* External configuration */
+    spi_controller0: spi at 43c30000 {
+        compatible = "mxicy,mx25f0a-spi";
+        reg = <0x43c30000 0x10000>, <0xa0000000 0x4000000>;
+        reg-names = "regs", "dirmap";
+        clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
+        clock-names = "send_clk", "send_dly_clk", "ps_clk";
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        flash at 0 {
+            compatible = "spi-nand";
+            reg = <0>;
+            nand-ecc-engine = <&ecc_engine0>;
+        };
+    };
+
+    ecc_engine0: ecc at 43c40000 {
+        compatible = "mxicy,nand-ecc-engine-rev3";
+        reg = <0x43c40000 0x10000>;
+    };
+
+  - |
+    /* Pipelined configuration */
+    spi_controller1: spi at 43c30000 {
+        compatible = "mxicy,mx25f0a-spi";
+        reg = <0x43c30000 0x10000>, <0xa0000000 0x4000000>;
+        reg-names = "regs", "dirmap";
+        clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 15>;
+        clock-names = "send_clk", "send_dly_clk", "ps_clk";
+        #address-cells = <1>;
+        #size-cells = <0>;
+        nand-ecc-engine = <&ecc_engine1>;
+
+        flash at 0 {
+            compatible = "spi-nand";
+            reg = <0>;
+            nand-ecc-engine = <&spi_controller1>;
+        };
+    };
+
+    ecc_engine1: ecc at 43c40000 {
+        compatible = "mxicy,nand-ecc-engine-rev3";
+        reg = <0x43c40000 0x10000>;
+    };
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:00 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:00 +0200
Subject: [PATCH 09/18] dt-bindings: spi: mxic: Document the nand-ecc-engine
 property
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-10-miquel.raynal@bootlin.com>

This SPI controller supports interacting with an external ECC
engine. The nand-ecc-engine property already exist in the NAND world but
also applies to SPI controller nodes which have external correction
capabilities like Macronix's.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 .../devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml          | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
index 4036c14fc533..01618a77627d 100644
--- a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
+++ b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
@@ -43,6 +43,12 @@ properties:
   "#size-cells":
     const: 0
 
+  nand-ecc-engine:
+    allOf:
+      - $ref: /schemas/types.yaml#/definitions/phandle
+    description: NAND ECC engine used by the SPI controller in order to perform
+      on-the-fly correction when using a SPI-NAND memory.
+
 required:
   - compatible
   - reg
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:01 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:01 +0200
Subject: [PATCH 10/18] mtd: spinand: macronix: Use random program load
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-11-miquel.raynal@bootlin.com>

From: Mason Yang <masonccyang at mxic.com.tw>

Macronix SPI-NAND chips might benefit from an external ECC
engine. Such an engine might need to access random columns, thus needing
to use random commands (0x84 instead of 0x02).

Signed-off-by: Mason Yang <masonccyang at mxic.com.tw>
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/spi/macronix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c
index 3f31f1381a62..dce835132a1e 100644
--- a/drivers/mtd/nand/spi/macronix.c
+++ b/drivers/mtd/nand/spi/macronix.c
@@ -20,7 +20,7 @@ static SPINAND_OP_VARIANTS(read_cache_variants,
 
 static SPINAND_OP_VARIANTS(write_cache_variants,
 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
-		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
 static SPINAND_OP_VARIANTS(update_cache_variants,
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:02 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:02 +0200
Subject: [PATCH 11/18] mtd: nand: ecc: Add infrastructure to support hardware
 engines
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-12-miquel.raynal@bootlin.com>

Add the necessary helpers to register/unregister hardware ECC engines
that will be called from ECC engine drivers.

Also add helpers to get the right engine from the user
perspective. Keep a reference of the in use ECC engine in order to
prevent modules to be unloaded. Put the reference when the engine gets
retired.

A static list of hardware (only) ECC engines is setup to keep track of
the registered engines.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/core.c  | 10 +++--
 drivers/mtd/nand/ecc.c   | 89 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h | 11 +++++
 3 files changed, 107 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index df9646685c91..5628bd410f7e 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -232,7 +232,9 @@ static int nanddev_get_ecc_engine(struct nand_device *nand)
 		nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
+		if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
 		break;
 	default:
 		pr_err("Missing ECC engine type\n");
@@ -252,7 +254,7 @@ static int nanddev_put_ecc_engine(struct nand_device *nand)
 {
 	switch (nand->ecc.ctx.conf.engine_type) {
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand_ecc_put_on_host_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_NONE:
 	case NAND_ECC_ENGINE_TYPE_SOFT:
@@ -297,7 +299,9 @@ int nanddev_ecc_engine_init(struct nand_device *nand)
 	/* Look for the ECC engine to use */
 	ret = nanddev_get_ecc_engine(nand);
 	if (ret) {
-		pr_err("No ECC engine found\n");
+		if (ret != -EPROBE_DEFER)
+			pr_err("No ECC engine found\n");
+
 		return ret;
 	}
 
diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
index 6c43dfda01d4..3aa56c990d11 100644
--- a/drivers/mtd/nand/ecc.c
+++ b/drivers/mtd/nand/ecc.c
@@ -96,6 +96,12 @@
 #include <linux/module.h>
 #include <linux/mtd/nand.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+
+static LIST_HEAD(on_host_hw_engines);
+static DEFINE_MUTEX(on_host_hw_engines_mutex);
 
 /**
  * nand_ecc_init_ctx - Init the ECC engine context
@@ -611,6 +617,89 @@ struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand)
 }
 EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine);
 
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	struct nand_ecc_engine *item;
+
+	if (!engine)
+		return -ENOTSUPP;
+
+	/* Prevent multiple registrations of one engine */
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item == engine)
+			return 0;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_add_tail(&engine->node, &on_host_hw_engines);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_register_on_host_hw_engine);
+
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	if (!engine)
+		return -ENOTSUPP;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_del(&engine->node);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_unregister_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev)
+{
+	struct nand_ecc_engine *item;
+
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item->dev == dev)
+			return item;
+
+	return NULL;
+}
+EXPORT_SYMBOL(nand_ecc_match_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand)
+{
+	struct nand_ecc_engine *engine = NULL;
+	struct device *dev = &nand->mtd.dev;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	if (list_empty(&on_host_hw_engines))
+		return NULL;
+
+	/* Check for an explicit nand-ecc-engine property */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (np) {
+		pdev = of_find_device_by_node(np);
+		if (!pdev)
+			return ERR_PTR(-EPROBE_DEFER);
+
+		engine = nand_ecc_match_on_host_hw_engine(&pdev->dev);
+		platform_device_put(pdev);
+		of_node_put(np);
+
+		if (!engine)
+			return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	if (engine)
+		get_device(engine->dev);
+
+	return engine;
+}
+EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine);
+
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand)
+{
+	put_device(nand->ecc.engine->dev);
+}
+EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal at bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 32fc7edf65b3..5ffd3e359515 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -265,10 +265,16 @@ struct nand_ecc_engine_ops {
 
 /**
  * struct nand_ecc_engine - ECC engine abstraction for NAND devices
+ * @dev: Host device
+ * @node: Private field for registration time
  * @ops: ECC engine operations
+ * @priv: Private data
  */
 struct nand_ecc_engine {
+	struct device *dev;
+	struct list_head node;
 	struct nand_ecc_engine_ops *ops;
+	void *priv;
 };
 
 void of_get_nand_ecc_user_config(struct nand_device *nand);
@@ -279,8 +285,13 @@ 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);
 bool nand_ecc_is_strong_enough(struct nand_device *nand);
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine);
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine);
 struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
 struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev);
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand);
 
 #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING)
 struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:03 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:03 +0200
Subject: [PATCH 12/18] mtd: nand: mxic-ecc: Add Macronix external ECC engine
 support
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-13-miquel.raynal@bootlin.com>

Some SPI-NAND chips do not support on-die ECC. For these chips,
correction must apply on the SPI controller end. In order to avoid
doing all the calculations by software, Macronix provides a specific
engine that can offload the intensive work.

Add Macronix ECC engine support, this engine can work in conjunction
with a SPI controller and a raw NAND controller, it can be pipelined
or external and supports linear and syndrome layouts.

Right now the simplest configuration is supported: SPI controller
external and linear ECC engine.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/Kconfig    |   6 +
 drivers/mtd/nand/Makefile   |   1 +
 drivers/mtd/nand/ecc-mxic.c | 657 ++++++++++++++++++++++++++++++++++++
 3 files changed, 664 insertions(+)
 create mode 100644 drivers/mtd/nand/ecc-mxic.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index b40455234cbd..8431292ff49d 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -46,6 +46,12 @@ config MTD_NAND_ECC_SW_BCH
 	  ECC codes. They are used with NAND devices requiring more than 1 bit
 	  of error correction.
 
+config MTD_NAND_ECC_MXIC
+	bool "Macronix external hardware ECC engine"
+	select MTD_NAND_ECC
+	help
+	  This enables support for the hardware ECC engine from Macronix.
+
 endmenu
 
 endmenu
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1c0b46960eb1..a4e6b7ae0614 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -10,3 +10,4 @@ obj-y	+= spi/
 nandcore-$(CONFIG_MTD_NAND_ECC) += ecc.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_HAMMING) += ecc-sw-hamming.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_BCH) += ecc-sw-bch.o
+nandcore-$(CONFIG_MTD_NAND_ECC_MXIC) += ecc-mxic.o
diff --git a/drivers/mtd/nand/ecc-mxic.c b/drivers/mtd/nand/ecc-mxic.c
new file mode 100644
index 000000000000..d9b251ab9201
--- /dev/null
+++ b/drivers/mtd/nand/ecc-mxic.c
@@ -0,0 +1,657 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Support for Macronix external hardware ECC engine for NAND devices, also
+ * called DPE for Data Processing Engine.
+ *
+ * Copyright ? 2019 Macronix
+ * Author: Miquel Raynal <miquel.raynal at bootlin.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* DPE Configuration */
+#define DP_CONFIG 0x00
+#define   ECC_EN BIT(0)
+#define   ECC_TYP(idx) (((idx) << 3) & GENMASK(6, 3))
+/* DPE Interrupt Status */
+#define INTRPT_STS 0x04
+#define   TRANS_CMPLT BIT(0)
+#define   SDMA_MAIN BIT(1)
+#define   SDMA_SPARE BIT(2)
+#define   ECC_ERR BIT(3)
+#define   TO_SPARE BIT(4)
+#define   TO_MAIN BIT(5)
+/* DPE Interrupt Status Enable */
+#define INTRPT_STS_EN 0x08
+/* DPE Interrupt Signal Enable */
+#define INTRPT_SIG_EN 0x0C
+/* Host Controller Configuration */
+#define HC_CONFIG 0x10
+#define   MEM2MEM BIT(4) /* TRANS_TYP_IO in the spec */
+#define   ECC_PACKED 0 /* LAYOUT_TYP_INTEGRATED in the spec */
+#define   ECC_INTERLEAVED BIT(2) /* LAYOUT_TYP_DISTRIBUTED in the spec */
+#define   BURST_TYP_FIXED 0
+#define   BURST_TYP_INCREASING BIT(0)
+/* Host Controller Slave Address */
+#define HC_SLV_ADDR 0x14
+/* ECC Chunk Size */
+#define CHUNK_SIZE 0x20
+/* Main Data Size */
+#define MAIN_SIZE 0x24
+/* Spare Data Size */
+#define SPARE_SIZE 0x28
+#define   META_SZ(reg) ((reg) & GENMASK(7, 0))
+#define   PARITY_SZ(reg) (((reg) & GENMASK(15, 8)) >> 8)
+#define   RSV_SZ(reg) (((reg) & GENMASK(23, 16)) >> 16)
+#define   SPARE_SZ(reg) ((reg) >> 24)
+/* ECC Chunk Count */
+#define CHUNK_CNT 0x30
+/* SDMA Control */
+#define SDMA_CTRL 0x40
+#define   WRITE_NAND 0
+#define   READ_NAND BIT(1)
+#define   CONT_NAND BIT(29)
+#define   CONT_SYSM BIT(30) /* Continue System Memory? */
+#define   SDMA_STRT BIT(31)
+/* SDMA Address of Main Data */
+#define SDMA_MAIN_ADDR 0x44
+/* SDMA Address of Spare Data */
+#define SDMA_SPARE_ADDR 0x48
+/* DPE Version Number */
+#define DP_VER 0xD0
+#define   DP_VER_OFFSET 16
+
+/* Status bytes between each chunk of spare data */
+#define STAT_BYTES 4
+#define   NO_ERR 0x00
+#define   MAX_CORR_ERR 0x28
+#define   UNCORR_ERR 0xFE
+#define   ERASED_CHUNK 0xFF
+
+struct mxic_ecc_engine {
+	struct device *dev;
+	void __iomem *regs;
+
+	/* ECC machinery */
+	unsigned int data_step_sz;
+	unsigned int oob_step_sz;
+	unsigned int parity_sz;
+	unsigned int meta_sz;
+	u8 *status;
+	int steps;
+
+	/* Completion boilerplate */
+	int irq;
+	struct completion complete;
+
+	/* DMA boilerplate */
+	struct nand_ecc_req_tweak_ctx req_ctx;
+	u8 *oobwithstat;
+	struct scatterlist sg[2];
+	struct nand_page_io_req *req;
+};
+
+static int mxic_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (section < 0 || section >= eng->steps)
+		return -ERANGE;
+
+	oobregion->offset = (section * eng->oob_step_sz) + eng->meta_sz;
+	oobregion->length = eng->parity_sz;
+
+	return 0;
+}
+
+static int mxic_ecc_ooblayout_free(struct mtd_info *mtd, int section,
+				   struct mtd_oob_region *oobregion)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (section < 0 || section >= eng->steps)
+		return -ERANGE;
+
+	if (!section) {
+		oobregion->offset = 2;
+		oobregion->length = eng->meta_sz - 2;
+	} else {
+		oobregion->offset = section * eng->oob_step_sz;
+		oobregion->length = eng->meta_sz;
+	}
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops mxic_ecc_ooblayout_ops = {
+	.ecc = mxic_ecc_ooblayout_ecc,
+	.free = mxic_ecc_ooblayout_free,
+};
+
+static void mxic_ecc_disable_engine(struct mxic_ecc_engine *eng)
+{
+	u32 reg;
+
+	reg = readl(eng->regs + DP_CONFIG);
+	reg &= ~ECC_EN;
+	writel(reg, eng->regs + DP_CONFIG);
+}
+
+static void mxic_ecc_enable_engine(struct mxic_ecc_engine *eng)
+{
+	u32 reg;
+
+	reg = readl(eng->regs + DP_CONFIG);
+	reg |= ECC_EN;
+	writel(reg, eng->regs + DP_CONFIG);
+}
+
+static void mxic_ecc_disable_int(struct mxic_ecc_engine *eng)
+{
+	writel(0, eng->regs + INTRPT_SIG_EN);
+}
+
+static void mxic_ecc_enable_int(struct mxic_ecc_engine *eng)
+{
+	writel(TRANS_CMPLT, eng->regs + INTRPT_SIG_EN);
+}
+
+static irqreturn_t mxic_ecc_isr(int irq, void *dev_id)
+{
+	struct mxic_ecc_engine *eng = dev_id;
+	u32 sts;
+
+	sts = readl(eng->regs + INTRPT_STS);
+	if (!sts)
+		return IRQ_NONE;
+
+	if (sts & TRANS_CMPLT)
+		complete(&eng->complete);
+
+	writel(sts, eng->regs + INTRPT_STS);
+
+	return IRQ_HANDLED;
+}
+
+static int mxic_ecc_init_ctx(struct nand_device *nand, struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	struct nand_ecc_props *reqs = &nand->ecc.requirements;
+	struct nand_ecc_props *user = &nand->ecc.user_conf;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct mxic_ecc_engine *eng;
+	int step_size = 0, strength = 0, desired_correction = 0, steps, idx;
+	int possible_strength[] = {4, 8, 40, 48};
+	int spare_size[] = {32, 32, 96, 96};
+	u32 spare_reg;
+	int ret;
+
+	eng = devm_kzalloc(dev, sizeof(*eng), GFP_KERNEL);
+	if (!eng)
+		return -ENOMEM;
+
+	nand->ecc.ctx.priv = eng;
+	nand->ecc.engine->priv = eng;
+
+	eng->dev = dev;
+
+	/*
+	 * Both memory regions for the ECC engine itself and the AXI slave
+	 * address are mandatory.
+	 */
+	eng->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(eng->regs)) {
+		dev_err(dev, "Missing memory region\n");
+		return PTR_ERR(eng->regs);
+	}
+
+	mxic_ecc_disable_engine(eng);
+	mxic_ecc_disable_int(eng);
+
+	/* IRQ is optional yet much more efficient */
+	eng->irq = platform_get_irq_byname(pdev, "ecc-engine");
+	if (eng->irq > 0) {
+		ret = devm_request_irq(dev, eng->irq, mxic_ecc_isr, 0,
+				       "mxic-ecc", eng);
+		if (ret)
+			return ret;
+	} else {
+		dev_info(dev, "No ECC engine IRQ (%d), using polling\n",
+			 eng->irq);
+		eng->irq = 0;
+	}
+
+	/* 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;
+	}
+
+	mtd_set_ooblayout(mtd, &mxic_ecc_ooblayout_ops);
+
+	/* Enable all status bits */
+	writel(TRANS_CMPLT | SDMA_MAIN | SDMA_SPARE | ECC_ERR |
+	       TO_SPARE | TO_MAIN, eng->regs + INTRPT_STS_EN);
+
+	/* Configure the correction depending on the NAND device topology */
+	if (user->step_size && user->strength) {
+		step_size = user->step_size;
+		strength = user->strength;
+	} else if (reqs->step_size && reqs->strength) {
+		step_size = reqs->step_size;
+		strength = reqs->strength;
+	}
+
+	if (step_size && strength) {
+		steps = mtd->writesize / step_size;
+		desired_correction = steps * strength;
+	}
+
+	/* Step size is fixed to 1kiB, strength may vary (4 possible values) */
+	conf->step_size = SZ_1K;
+	steps = mtd->writesize / conf->step_size;
+
+	eng->status = devm_kzalloc(dev, steps * sizeof(u8), GFP_KERNEL);
+	if (!eng->status)
+		return -ENOMEM;
+
+	if (desired_correction) {
+		strength = desired_correction / steps;
+
+		for (idx = 0; idx < ARRAY_SIZE(possible_strength); idx++)
+			if (possible_strength[idx] >= strength)
+				break;
+
+		idx = min_t(unsigned int, idx,
+			    ARRAY_SIZE(possible_strength) - 1);
+	} else {
+		/* Missing data, maximize the correction */
+		idx = ARRAY_SIZE(possible_strength) - 1;
+	}
+
+	/* Tune the selected strength until it fits in the OOB area */
+	for (; idx >= 0; idx--) {
+		if (spare_size[idx] * steps <= mtd->oobsize)
+			break;
+	}
+
+	/* This engine cannot be used with this NAND device */
+	if (idx < 0)
+		return -EINVAL;
+
+	/* Configure the engine for the desired strength */
+	writel(ECC_TYP(idx), eng->regs + DP_CONFIG);
+	conf->strength = possible_strength[idx];
+	spare_reg = readl(eng->regs + SPARE_SIZE);
+
+	eng->steps = steps;
+	eng->data_step_sz = mtd->writesize / steps;
+	eng->oob_step_sz = mtd->oobsize / steps;
+	eng->parity_sz = PARITY_SZ(spare_reg);
+	eng->meta_sz = META_SZ(spare_reg);
+
+	/* Ensure buffers will contain enough bytes to store the STAT_BYTES */
+	eng->req_ctx.oob_buffer_size = nanddev_per_page_oobsize(nand) +
+				       (eng->steps * STAT_BYTES);
+	ret = nand_ecc_init_req_tweaking(&eng->req_ctx, nand);
+	if (ret)
+		return ret;
+
+	eng->oobwithstat = kmalloc(mtd->oobsize + (eng->steps * STAT_BYTES),
+				   GFP_KERNEL);
+	if (!eng->oobwithstat) {
+		ret = -ENOMEM;
+		goto cleanup_req_tweak;
+	}
+
+	sg_init_table(eng->sg, 2);
+
+	/* Configuration dump and sanity checks */
+	dev_err(dev, "DPE version number: %d\n",
+		readl(eng->regs + DP_VER) >> DP_VER_OFFSET);
+	dev_err(dev, "Chunk size: %d\n", readl(eng->regs + CHUNK_SIZE));
+	dev_err(dev, "Main size: %d\n", readl(eng->regs + MAIN_SIZE));
+	dev_err(dev, "Spare size: %d\n", SPARE_SZ(spare_reg));
+	dev_err(dev, "Rsv size: %ld\n", RSV_SZ(spare_reg));
+	dev_err(dev, "Parity size: %d\n", eng->parity_sz);
+	dev_err(dev, "Meta size: %d\n", eng->meta_sz);
+
+	if (eng->meta_sz + eng->parity_sz + RSV_SZ(spare_reg) != SPARE_SZ(spare_reg)) {
+		dev_err(dev, "Wrong OOB configuration: %d + %d + %ld != %d\n",
+			eng->meta_sz, eng->parity_sz, RSV_SZ(spare_reg),
+			SPARE_SZ(spare_reg));
+		ret = -EINVAL;
+		goto free_oobwithstat;
+	}
+
+	if (eng->oob_step_sz != SPARE_SZ(spare_reg)) {
+		dev_err(dev, "Wrong OOB configuration: %d != %d\n",
+			eng->oob_step_sz, SPARE_SZ(spare_reg));
+		ret = -EINVAL;
+		goto free_oobwithstat;
+	}
+
+	return 0;
+
+free_oobwithstat:
+	kfree(eng->oobwithstat);
+cleanup_req_tweak:
+	nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+
+	return ret;
+}
+
+static int mxic_ecc_init_ctx_external(struct nand_device *nand)
+{
+	struct device *dev = nand->ecc.engine->dev;
+	struct mxic_ecc_engine *eng;
+	int ret;
+
+	dev_info(dev, "Macronix ECC engine in external mode\n");
+
+	ret = mxic_ecc_init_ctx(nand, dev);
+	if (ret)
+		return ret;
+
+	eng = nand->ecc.ctx.priv;
+
+	/* Trigger each step manually */
+	writel(1, eng->regs + CHUNK_CNT);
+	writel(BURST_TYP_INCREASING | ECC_PACKED | MEM2MEM,
+	       eng->regs + HC_CONFIG);
+
+	return 0;
+}
+
+static void mxic_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (eng) {
+		nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+		kfree(eng->oobwithstat);
+	}
+}
+
+static int mxic_ecc_data_xfer_wait_for_completion(struct mxic_ecc_engine *eng)
+{
+	u32 val;
+	int ret;
+
+	if (eng->irq) {
+		init_completion(&eng->complete);
+		mxic_ecc_enable_int(eng);
+		ret = wait_for_completion_timeout(&eng->complete,
+						  msecs_to_jiffies(1000));
+		mxic_ecc_disable_int(eng);
+	} else {
+		ret = readl_poll_timeout(eng->regs + INTRPT_STS, val,
+					 val & TRANS_CMPLT, 10, USEC_PER_SEC);
+		writel(val, eng->regs + INTRPT_STS);
+	}
+
+	if (ret) {
+		dev_err(eng->dev, "Timeout on data xfer completion (sts 0x%08x)\n", val);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int mxic_ecc_process_data(struct mxic_ecc_engine *eng)
+{
+	/* Retrieve the direction */
+	unsigned int dir = (eng->req->type == NAND_PAGE_READ) ?
+			   READ_NAND : WRITE_NAND;
+
+	/* Trigger processing */
+	writel(SDMA_STRT | dir, eng->regs + SDMA_CTRL);
+
+	/* Wait for completion */
+	return mxic_ecc_data_xfer_wait_for_completion(eng);
+}
+
+static void mxic_ecc_extract_status_bytes(struct mxic_ecc_engine *eng, u8 *buf)
+{
+	int next_stat_pos;
+	int step;
+
+	/* Extract the ECC status */
+	for (step = 0; step < eng->steps; step++) {
+		next_stat_pos = eng->oob_step_sz +
+				((STAT_BYTES + eng->oob_step_sz) * step);
+
+		eng->status[step] = buf[next_stat_pos];
+	}
+}
+
+static void mxic_ecc_reconstruct_oobbuf(struct mxic_ecc_engine *eng,
+					u8 *dst, const u8 *src)
+{
+	int step;
+
+	/* Reconstruct the OOB buffer linearly (without the ECC status bytes) */
+	for (step = 0; step < eng->steps; step++)
+		memcpy(dst + (step * eng->oob_step_sz),
+		       src + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->oob_step_sz);
+}
+
+static void mxic_ecc_add_room_in_oobbuf(struct mxic_ecc_engine *eng,
+					u8 *dst, const u8 *src)
+{
+	int step;
+
+	/* Add some space in the OOB buffer for the status bytes */
+	for (step = 0; step < eng->steps; step++)
+		memcpy(dst + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       src + (step * eng->oob_step_sz),
+		       eng->oob_step_sz);
+}
+
+static int mxic_ecc_count_biterrs(struct mxic_ecc_engine *eng, struct mtd_info *mtd)
+{
+	struct device *dev = eng->dev;
+	unsigned int max_bf = 0;
+	bool failure = false;
+	int step;
+
+	for (step = 0; step < eng->steps; step++) {
+		u8 stat = eng->status[step];
+
+		if (stat == NO_ERR) {
+			dev_dbg(dev, "ECC step %d: no error\n", step);
+		} else if (stat == ERASED_CHUNK) {
+			dev_dbg(dev, "ECC step %d: erased\n", step);
+		} else if (stat == UNCORR_ERR || stat > MAX_CORR_ERR) {
+			dev_dbg(dev, "ECC step %d: uncorrectable\n", step);
+			mtd->ecc_stats.failed++;
+			failure = true;
+		} else {
+			dev_dbg(dev, "ECC step %d: %d bits corrected\n",
+				step, stat);
+			max_bf = max_t(unsigned int, max_bf, stat);
+			mtd->ecc_stats.corrected += stat;
+		}
+	}
+
+	return failure ? -EBADMSG : max_bf;
+}
+
+/* External ECC engine helpers */
+static int mxic_ecc_prepare_io_req_external(struct nand_device *nand,
+					    struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int offset, nents, step, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	nand_ecc_tweak_req(&eng->req_ctx, req);
+	eng->req = req;
+
+	if (req->type == NAND_PAGE_READ)
+		return 0;
+
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.out);
+
+	sg_set_buf(&eng->sg[0], req->databuf.out, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	mxic_ecc_enable_engine(eng);
+
+	for (step = 0; step < eng->steps; step++) {
+		writel(sg_dma_address(&eng->sg[0]) + (step * eng->data_step_sz),
+		       eng->regs + SDMA_MAIN_ADDR);
+		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->regs + SDMA_SPARE_ADDR);
+		ret = mxic_ecc_process_data(eng);
+		if (ret)
+			break;
+	}
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	/* Retrieve the calculated ECC bytes */
+	for (step = 0; step < eng->steps; step++) {
+		offset = eng->meta_sz + (step * eng->oob_step_sz);
+		mtd_ooblayout_get_eccbytes(mtd,
+					   (u8 *)eng->req->oobbuf.out + offset,
+					   eng->oobwithstat + (step * STAT_BYTES),
+					   step * eng->parity_sz,
+					   eng->parity_sz);
+	}
+
+	return ret;
+}
+
+static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
+					   struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int nents, step, ret;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	if (req->type == NAND_PAGE_WRITE) {
+		nand_ecc_restore_req(&eng->req_ctx, req);
+		return 0;
+	}
+
+	/* Copy the OOB buffer and add room for the ECC engine status bytes */
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.in);
+
+	sg_set_buf(&eng->sg[0], req->databuf.in, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	mxic_ecc_enable_engine(eng);
+
+	for (step = 0; step < eng->steps; step++) {
+		writel(sg_dma_address(&eng->sg[0]) + (step * eng->data_step_sz),
+		       eng->regs + SDMA_MAIN_ADDR);
+		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
+		       eng->regs + SDMA_SPARE_ADDR);
+		ret = mxic_ecc_process_data(eng);
+		if (ret)
+			break;
+	}
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	/* Extract the status bytes and reconstruct the buffer */
+	mxic_ecc_extract_status_bytes(eng, eng->oobwithstat);
+	mxic_ecc_reconstruct_oobbuf(eng, eng->req->oobbuf.in, eng->oobwithstat);
+
+	nand_ecc_restore_req(&eng->req_ctx, req);
+
+	return mxic_ecc_count_biterrs(eng, mtd);
+}
+
+static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
+	.init_ctx = mxic_ecc_init_ctx_external,
+	.cleanup_ctx = mxic_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_ecc_prepare_io_req_external,
+	.finish_io_req = mxic_ecc_finish_io_req_external,
+};
+
+static int mxic_ecc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nand_ecc_engine *ecceng;
+
+	ecceng = devm_kzalloc(dev, sizeof(*ecceng), GFP_KERNEL);
+	if (!ecceng)
+		return -ENOMEM;
+
+	ecceng->dev = dev;
+	ecceng->ops = &mxic_ecc_engine_external_ops;
+	nand_ecc_register_on_host_hw_engine(ecceng);
+
+	return 0;
+}
+
+static int mxic_ecc_remove(struct platform_device *pdev)
+{
+	struct nand_ecc_engine *ecceng;
+
+	ecceng = nand_ecc_match_on_host_hw_engine(&pdev->dev);
+	if (ecceng)
+		nand_ecc_unregister_on_host_hw_engine(ecceng);
+
+	return 0;
+}
+
+static const struct of_device_id mxic_ecc_of_ids[] = {
+	{
+		.compatible = "mxicy,nand-ecc-engine-rev3",
+	},
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mxic_ecc_of_ids);
+
+static struct platform_driver mxic_ecc_driver = {
+	.driver	= {
+		.name = "mxic-nand-ecc-engine",
+		.of_match_table = mxic_ecc_of_ids,
+	},
+	.probe = mxic_ecc_probe,
+	.remove	= mxic_ecc_remove,
+};
+module_platform_driver(mxic_ecc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Miquel Raynal <miquel.raynal at bootlin.com>");
+MODULE_DESCRIPTION("Macronix NAND hardware ECC controller");
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:04 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:04 +0200
Subject: [PATCH 13/18] mtd: nand: mxic-ecc: Support SPI pipelined mode
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-14-miquel.raynal@bootlin.com>

Introduce the support for another possible configuration: the ECC
engine may work as DMA master (pipelined) and move itself the data
to/from the NAND chip into the buffer, applying the necessary
corrections/computations on the fly.

This driver offers an ECC engine implementation that must be
instatiated from a SPI controller driver.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/mtd/nand/ecc-mxic.c       | 148 +++++++++++++++++++++++++++++-
 include/linux/mtd/nand-ecc-mxic.h |  36 ++++++++
 2 files changed, 181 insertions(+), 3 deletions(-)
 create mode 100644 include/linux/mtd/nand-ecc-mxic.h

diff --git a/drivers/mtd/nand/ecc-mxic.c b/drivers/mtd/nand/ecc-mxic.c
index d9b251ab9201..555ba7f19027 100644
--- a/drivers/mtd/nand/ecc-mxic.c
+++ b/drivers/mtd/nand/ecc-mxic.c
@@ -39,7 +39,9 @@
 #define INTRPT_SIG_EN 0x0C
 /* Host Controller Configuration */
 #define HC_CONFIG 0x10
+#define   DEV2MEM 0 /* TRANS_TYP_DMA in the spec */
 #define   MEM2MEM BIT(4) /* TRANS_TYP_IO in the spec */
+#define   MAPPING BIT(5) /* TRANS_TYP_MAPPING in the spec */
 #define   ECC_PACKED 0 /* LAYOUT_TYP_INTEGRATED in the spec */
 #define   ECC_INTERLEAVED BIT(2) /* LAYOUT_TYP_DISTRIBUTED in the spec */
 #define   BURST_TYP_FIXED 0
@@ -101,6 +103,7 @@ struct mxic_ecc_engine {
 	u8 *oobwithstat;
 	struct scatterlist sg[2];
 	struct nand_page_io_req *req;
+	unsigned int pageoffs;
 };
 
 static int mxic_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
@@ -188,6 +191,31 @@ static irqreturn_t mxic_ecc_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static struct device *mxic_ecc_get_engine_dev(struct device *dev)
+{
+	struct platform_device *eccpdev;
+	struct device_node *np;
+
+	/*
+	 * If the device node contains this property, it means the device does
+	 * not represent the actual ECC engine.
+	 */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (!np)
+		return dev;
+
+	eccpdev = of_find_device_by_node(np);
+	if (!eccpdev) {
+		of_node_put(np);
+		return NULL;
+	}
+
+	platform_device_put(eccpdev);
+	of_node_put(np);
+
+	return &eccpdev->dev;
+}
+
 static int mxic_ecc_init_ctx(struct nand_device *nand, struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -379,6 +407,41 @@ static int mxic_ecc_init_ctx_external(struct nand_device *nand)
 	return 0;
 }
 
+static int mxic_ecc_init_ctx_pipelined(struct nand_device *nand)
+{
+	struct mxic_ecc_engine *eng;
+	struct device *dev;
+	int ret;
+
+	/*
+	 * In the case of a pipelined engine, the device registering the ECC
+	 * engine is not the actual ECC engine device but the host controller.
+	 */
+	dev = mxic_ecc_get_engine_dev(nand->ecc.engine->dev);
+	if (!dev)
+		return -EINVAL;
+
+	dev_info(dev, "Macronix ECC engine in pipelined/mapping mode\n");
+
+	ret = mxic_ecc_init_ctx(nand, dev);
+	if (ret)
+		return ret;
+
+	eng = nand->ecc.ctx.priv;
+
+	/* All steps should be handled in one go directly by the internal DMA */
+	writel(eng->steps, eng->regs + CHUNK_CNT);
+
+	/*
+	 * Interleaved ECC scheme cannot be used otherwise factory bad block
+	 * markers would be lost. A packed layout is mandatory.
+	 */
+	writel(BURST_TYP_INCREASING | ECC_PACKED | MAPPING,
+	       eng->regs + HC_CONFIG);
+
+	return 0;
+}
+
 static void mxic_ecc_cleanup_ctx(struct nand_device *nand)
 {
 	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
@@ -414,18 +477,22 @@ static int mxic_ecc_data_xfer_wait_for_completion(struct mxic_ecc_engine *eng)
 	return 0;
 }
 
-static int mxic_ecc_process_data(struct mxic_ecc_engine *eng)
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
 {
 	/* Retrieve the direction */
 	unsigned int dir = (eng->req->type == NAND_PAGE_READ) ?
 			   READ_NAND : WRITE_NAND;
 
+	if (dirmap)
+		writel(dirmap, eng->regs + HC_SLV_ADDR);
+
 	/* Trigger processing */
 	writel(SDMA_STRT | dir, eng->regs + SDMA_CTRL);
 
 	/* Wait for completion */
 	return mxic_ecc_data_xfer_wait_for_completion(eng);
 }
+EXPORT_SYMBOL_GPL(mxic_ecc_process_data);
 
 static void mxic_ecc_extract_status_bytes(struct mxic_ecc_engine *eng, u8 *buf)
 {
@@ -528,7 +595,7 @@ static int mxic_ecc_prepare_io_req_external(struct nand_device *nand,
 		       eng->regs + SDMA_MAIN_ADDR);
 		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
 		       eng->regs + SDMA_SPARE_ADDR);
-		ret = mxic_ecc_process_data(eng);
+		ret = mxic_ecc_process_data(eng, 0);
 		if (ret)
 			break;
 	}
@@ -582,7 +649,7 @@ static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
 		       eng->regs + SDMA_MAIN_ADDR);
 		writel(sg_dma_address(&eng->sg[1]) + (step * (eng->oob_step_sz + STAT_BYTES)),
 		       eng->regs + SDMA_SPARE_ADDR);
-		ret = mxic_ecc_process_data(eng);
+		ret = mxic_ecc_process_data(eng, 0);
 		if (ret)
 			break;
 	}
@@ -600,6 +667,64 @@ static int mxic_ecc_finish_io_req_external(struct nand_device *nand,
 	return mxic_ecc_count_biterrs(eng, mtd);
 }
 
+/* Pipelined ECC engine helpers */
+static int mxic_ecc_prepare_io_req_pipelined(struct nand_device *nand,
+					     struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	int nents;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	nand_ecc_tweak_req(&eng->req_ctx, req);
+	eng->req = req;
+
+	/* Copy the OOB buffer and add room for the ECC engine status bytes */
+	mxic_ecc_add_room_in_oobbuf(eng, eng->oobwithstat, eng->req->oobbuf.in);
+
+	sg_set_buf(&eng->sg[0], req->databuf.in, req->datalen);
+	sg_set_buf(&eng->sg[1], eng->oobwithstat,
+		   req->ooblen + (eng->steps * STAT_BYTES));
+
+	nents = dma_map_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+	if (!nents)
+		return -EINVAL;
+
+	writel(sg_dma_address(&eng->sg[0]), eng->regs + SDMA_MAIN_ADDR);
+	writel(sg_dma_address(&eng->sg[1]), eng->regs + SDMA_SPARE_ADDR);
+
+	mxic_ecc_enable_engine(eng);
+
+	return 0;
+}
+
+static int mxic_ecc_finish_io_req_pipelined(struct nand_device *nand,
+					    struct nand_page_io_req *req)
+{
+	struct mxic_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	int ret = 0;
+
+	if (req->mode == MTD_OPS_RAW)
+		return 0;
+
+	mxic_ecc_disable_engine(eng);
+
+	dma_unmap_sg(eng->dev, eng->sg, 2, DMA_BIDIRECTIONAL);
+
+	if (req->type == NAND_PAGE_READ) {
+		mxic_ecc_extract_status_bytes(eng, eng->oobwithstat);
+		mxic_ecc_reconstruct_oobbuf(eng, eng->req->oobbuf.in,
+					    eng->oobwithstat);
+		ret = mxic_ecc_count_biterrs(eng, mtd);
+	}
+
+	nand_ecc_restore_req(&eng->req_ctx, req);
+
+	return ret;
+}
+
 static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
 	.init_ctx = mxic_ecc_init_ctx_external,
 	.cleanup_ctx = mxic_ecc_cleanup_ctx,
@@ -607,6 +732,23 @@ static struct nand_ecc_engine_ops mxic_ecc_engine_external_ops = {
 	.finish_io_req = mxic_ecc_finish_io_req_external,
 };
 
+static struct nand_ecc_engine_ops mxic_ecc_engine_pipelined_ops = {
+	.init_ctx = mxic_ecc_init_ctx_pipelined,
+	.cleanup_ctx = mxic_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_ecc_prepare_io_req_pipelined,
+	.finish_io_req = mxic_ecc_finish_io_req_pipelined,
+};
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
+{
+	return &mxic_ecc_engine_pipelined_ops;
+}
+EXPORT_SYMBOL_GPL(mxic_ecc_get_pipelined_ops);
+
+/*
+ * Only the external ECC engine is exported as the pipelined is SoC specific, so
+ * it is registered directly by the drivers that wrap it.
+ */
 static int mxic_ecc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
diff --git a/include/linux/mtd/nand-ecc-mxic.h b/include/linux/mtd/nand-ecc-mxic.h
new file mode 100644
index 000000000000..d48b7fe05644
--- /dev/null
+++ b/include/linux/mtd/nand-ecc-mxic.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright ? 2019 Macronix
+ * Author: Miqu?l Raynal <miquel.raynal at bootlin.com>
+ *
+ * Header for the Macronix external ECC engine.
+ */
+
+#ifndef __MTD_NAND_ECC_MXIC_H__
+#define __MTD_NAND_ECC_MXIC_H__
+
+#include <linux/device.h>
+
+struct mxic_ecc_engine;
+
+#if IS_ENABLED(CONFIG_MTD_NAND_ECC_MXIC)
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void);
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap);
+
+#else /* !CONFIG_MTD_NAND_ECC_MXIC */
+
+struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
+{
+	return NULL;
+}
+
+static inline
+int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
+{
+	return -ENOTSUPP;
+}
+
+#endif /* CONFIG_MTD_NAND_ECC_MXIC */
+
+#endif /* __MTD_NAND_ECC_MXIC_H__ */
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:05 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:05 +0200
Subject: [PATCH 14/18] spi: mxic: Fix the transmit path
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-15-miquel.raynal@bootlin.com>

By working with external hardware ECC engines, we figured out that
Under certain circumstances, it is needed for the SPI controller to
check INT_TX_EMPTY and INT_RX_NOT_EMPTY in both receive and transmit
path (not only in the receive path). The delay penalty being
negligible, move this code in the common path.

Fixes: b942d80b0a39 ("spi: Add MXIC controller driver")
Cc: stable at vger.kernel.org
Suggested-by: Mason Yang <masonccyang at mxic.com.tw>
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
Reviewed-by: Zhengxun Li <zhengxunli at mxic.com.tw>
---
 drivers/spi/spi-mxic.c | 28 ++++++++++++----------------
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 45889947afed..03fce4493aa7 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -304,25 +304,21 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 
 		writel(data, mxic->regs + TXD(nbytes % 4));
 
+		ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+					 sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
+		if (ret)
+			return ret;
+
+		ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+					 sts & INT_RX_NOT_EMPTY, 0,
+					 USEC_PER_SEC);
+		if (ret)
+			return ret;
+
+		data = readl(mxic->regs + RXD);
 		if (rxbuf) {
-			ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
-						 sts & INT_TX_EMPTY, 0,
-						 USEC_PER_SEC);
-			if (ret)
-				return ret;
-
-			ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
-						 sts & INT_RX_NOT_EMPTY, 0,
-						 USEC_PER_SEC);
-			if (ret)
-				return ret;
-
-			data = readl(mxic->regs + RXD);
 			data >>= (8 * (4 - nbytes));
 			memcpy(rxbuf + pos, &data, nbytes);
-			WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
-		} else {
-			readl(mxic->regs + RXD);
 		}
 		WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
 
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:06 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:06 +0200
Subject: [PATCH 15/18] spi: mxic: Create a helper to configure the controller
 before an operation
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-16-miquel.raynal@bootlin.com>

Create the mxic_spi_set_hc_cfg() helper to configure the HC_CFG
register. This helper will soon be used by the dirmap implementation and
having this code factorized out earlier will clarify this addition.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 31 +++++++++++++++++++------------
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 03fce4493aa7..068543c40ce7 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -280,6 +280,22 @@ static void mxic_spi_hw_init(struct mxic_spi *mxic)
 	       mxic->regs + HC_CFG);
 }
 
+static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
+{
+	int nio = 1;
+
+	if (spi->mode & (SPI_TX_OCTAL | SPI_RX_OCTAL))
+		nio = 8;
+	else if (spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
+		nio = 4;
+	else if (spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
+		nio = 2;
+
+	return flags | HC_CFG_NIO(nio) |
+	       HC_CFG_TYPE(spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
+	       HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1);
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 			      void *rxbuf, unsigned int len)
 {
@@ -357,7 +373,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
 	struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
-	int nio = 1, i, ret;
+	int i, ret;
 	u32 ss_ctrl;
 	u8 addr[8], cmd[2];
 
@@ -365,18 +381,9 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 	if (ret)
 		return ret;
 
-	if (mem->spi->mode & (SPI_TX_OCTAL | SPI_RX_OCTAL))
-		nio = 8;
-	else if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
-		nio = 4;
-	else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
-		nio = 2;
-
-	writel(HC_CFG_NIO(nio) |
-	       HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
-	       HC_CFG_SLV_ACT(mem->spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1) |
-	       HC_CFG_MAN_CS_EN,
+	writel(mxic_spi_prep_hc_cfg(mem->spi, HC_CFG_MAN_CS_EN),
 	       mxic->regs + HC_CFG);
+
 	writel(HC_EN_BIT, mxic->regs + HC_EN);
 
 	ss_ctrl = OP_CMD_BYTES(op->cmd.nbytes) |
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:07 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:07 +0200
Subject: [PATCH 16/18] spi: mxic: Create a helper to ease the start of an
 operation
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-17-miquel.raynal@bootlin.com>

Create the mxic_spi_mem_prep_op_cfg() helper to provide the content to
write to the register controlling the next IO command. This helper will
soon be used by the dirmap implementation and having this code
factorized out earlier will clarify this addition.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 53 +++++++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 24 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 068543c40ce7..3c4e64cbe812 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -296,6 +296,33 @@ static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
 	       HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1);
 }
 
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+{
+	u32 cfg = OP_CMD_BYTES(op->cmd.nbytes) |
+		  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
+		  (op->cmd.dtr ? OP_CMD_DDR : 0);
+
+	if (op->addr.nbytes)
+		cfg |= OP_ADDR_BYTES(op->addr.nbytes) |
+		       OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) |
+		       (op->addr.dtr ? OP_ADDR_DDR : 0);
+
+	if (op->dummy.nbytes)
+		cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
+
+	if (op->data.nbytes) {
+		cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) |
+		       (op->data.dtr ? OP_DATA_DDR : 0);
+		if (op->data.dir == SPI_MEM_DATA_IN) {
+			cfg |= OP_READ;
+			if (op->data.dtr)
+				cfg |= OP_DQS_EN;
+		}
+	}
+
+	return cfg;
+}
+
 static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 			      void *rxbuf, unsigned int len)
 {
@@ -374,7 +401,6 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 {
 	struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
 	int i, ret;
-	u32 ss_ctrl;
 	u8 addr[8], cmd[2];
 
 	ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
@@ -386,29 +412,8 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 
 	writel(HC_EN_BIT, mxic->regs + HC_EN);
 
-	ss_ctrl = OP_CMD_BYTES(op->cmd.nbytes) |
-		  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
-		  (op->cmd.dtr ? OP_CMD_DDR : 0);
-
-	if (op->addr.nbytes)
-		ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) |
-			   OP_ADDR_BUSW(fls(op->addr.buswidth) - 1) |
-			   (op->addr.dtr ? OP_ADDR_DDR : 0);
-
-	if (op->dummy.nbytes)
-		ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes);
-
-	if (op->data.nbytes) {
-		ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) |
-			   (op->data.dtr ? OP_DATA_DDR : 0);
-		if (op->data.dir == SPI_MEM_DATA_IN) {
-			ss_ctrl |= OP_READ;
-			if (op->data.dtr)
-				ss_ctrl |= OP_DQS_EN;
-		}
-	}
-
-	writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select));
+	writel(mxic_spi_mem_prep_op_cfg(op),
+	       mxic->regs + SS_CTRL(mem->spi->chip_select));
 
 	writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
 	       mxic->regs + HC_CFG);
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:08 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:08 +0200
Subject: [PATCH 17/18] spi: mxic: Add support for direct mapping
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-18-miquel.raynal@bootlin.com>

Implement the ->dirmap_create() and ->dirmap_read/write() hooks to
provide a fast path for read and write accesses.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
Tested-by: Zhengxun Li <zhengxunli at mxic.com.tw>
Reviewed-by: Zhengxun Li <zhengxunli at mxic.com.tw>
---
 drivers/spi/spi-mxic.c | 112 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 109 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index 3c4e64cbe812..ae697173eaee 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -172,6 +172,11 @@ struct mxic_spi {
 	struct clk *send_dly_clk;
 	void __iomem *regs;
 	u32 cur_speed_hz;
+	struct {
+		void __iomem *map;
+		dma_addr_t dma;
+		size_t size;
+	} linear;
 };
 
 static int mxic_spi_clk_enable(struct mxic_spi *mxic)
@@ -296,7 +301,8 @@ static u32 mxic_spi_prep_hc_cfg(struct spi_device *spi, u32 flags)
 	       HC_CFG_SLV_ACT(spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1);
 }
 
-static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
+static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op,
+				    unsigned int data_len)
 {
 	u32 cfg = OP_CMD_BYTES(op->cmd.nbytes) |
 		  OP_CMD_BUSW(fls(op->cmd.buswidth) - 1) |
@@ -310,7 +316,8 @@ static u32 mxic_spi_mem_prep_op_cfg(const struct spi_mem_op *op)
 	if (op->dummy.nbytes)
 		cfg |= OP_DUMMY_CYC(op->dummy.nbytes);
 
-	if (op->data.nbytes) {
+	/* Direct mapping data.nbytes field is not populated */
+	if (data_len) {
 		cfg |= OP_DATA_BUSW(fls(op->data.buswidth) - 1) |
 		       (op->data.dtr ? OP_DATA_DDR : 0);
 		if (op->data.dir == SPI_MEM_DATA_IN) {
@@ -371,6 +378,77 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 	return 0;
 }
 
+static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
+					u64 offs, size_t len, void *buf)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+	int ret;
+	u32 sts;
+
+	if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
+		return -EINVAL;
+
+	writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
+
+	writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
+	       mxic->regs + LRD_CFG);
+	writel(desc->info.offset + offs, mxic->regs + LRD_ADDR);
+	len = min_t(size_t, len, mxic->linear.size);
+	writel(len, mxic->regs + LRD_RANGE);
+	writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
+	       LMODE_SLV_ACT(desc->mem->spi->chip_select) |
+	       LMODE_EN,
+	       mxic->regs + LRD_CTRL);
+
+	memcpy_fromio(buf, mxic->linear.map, len);
+
+	writel(INT_LRD_DIS, mxic->regs + INT_STS);
+	writel(0, mxic->regs + LRD_CTRL);
+
+	ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+				 sts & INT_LRD_DIS, 0, USEC_PER_SEC);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
+static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
+					 u64 offs, size_t len,
+					 const void *buf)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+	u32 sts;
+	int ret;
+
+	if (WARN_ON(offs + desc->info.offset + len > U32_MAX))
+		return -EINVAL;
+
+	writel(mxic_spi_prep_hc_cfg(desc->mem->spi, 0), mxic->regs + HC_CFG);
+
+	writel(mxic_spi_mem_prep_op_cfg(&desc->info.op_tmpl, len),
+	       mxic->regs + LWR_CFG);
+	writel(desc->info.offset + offs, mxic->regs + LWR_ADDR);
+	len = min_t(size_t, len, mxic->linear.size);
+	writel(len, mxic->regs + LWR_RANGE);
+	writel(LMODE_CMD0(desc->info.op_tmpl.cmd.opcode) |
+	       LMODE_SLV_ACT(desc->mem->spi->chip_select) |
+	       LMODE_EN,
+	       mxic->regs + LWR_CTRL);
+
+	memcpy_toio(mxic->linear.map, buf, len);
+
+	writel(INT_LWR_DIS, mxic->regs + INT_STS);
+	writel(0, mxic->regs + LWR_CTRL);
+
+	ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
+				 sts & INT_LWR_DIS, 0, USEC_PER_SEC);
+	if (ret)
+		return ret;
+
+	return len;
+}
+
 static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 				     const struct spi_mem_op *op)
 {
@@ -396,6 +474,22 @@ static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
 		return spi_mem_dtr_supports_op(mem, op);
 }
 
+static int mxic_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
+{
+	struct mxic_spi *mxic = spi_master_get_devdata(desc->mem->spi->master);
+
+	if (!mxic->linear.map)
+		return -ENOTSUPP;
+
+	if (desc->info.offset + desc->info.length > U32_MAX)
+		return -ENOTSUPP;
+
+	if (!mxic_spi_mem_supports_op(desc->mem, &desc->info.op_tmpl))
+		return -ENOTSUPP;
+
+	return 0;
+}
+
 static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 				const struct spi_mem_op *op)
 {
@@ -412,7 +506,7 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 
 	writel(HC_EN_BIT, mxic->regs + HC_EN);
 
-	writel(mxic_spi_mem_prep_op_cfg(op),
+	writel(mxic_spi_mem_prep_op_cfg(op, op->data.nbytes),
 	       mxic->regs + SS_CTRL(mem->spi->chip_select));
 
 	writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
@@ -454,6 +548,9 @@ static int mxic_spi_mem_exec_op(struct spi_mem *mem,
 static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
 	.supports_op = mxic_spi_mem_supports_op,
 	.exec_op = mxic_spi_mem_exec_op,
+	.dirmap_create = mxic_spi_mem_dirmap_create,
+	.dirmap_read = mxic_spi_mem_dirmap_read,
+	.dirmap_write = mxic_spi_mem_dirmap_write,
 };
 
 static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
@@ -583,6 +680,15 @@ static int mxic_spi_probe(struct platform_device *pdev)
 	if (IS_ERR(mxic->regs))
 		return PTR_ERR(mxic->regs);
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
+	mxic->linear.map = devm_ioremap_resource(&pdev->dev, res);
+	if (!IS_ERR(mxic->linear.map)) {
+		mxic->linear.dma = res->start;
+		mxic->linear.size = resource_size(res);
+	} else {
+		mxic->linear.map = NULL;
+	}
+
 	pm_runtime_enable(&pdev->dev);
 	master->auto_runtime_pm = true;
 
-- 
2.27.0



From miquel.raynal at bootlin.com  Wed Oct 20 07:28:09 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Wed, 20 Oct 2021 16:28:09 +0200
Subject: [PATCH 18/18] spi: mxic: Add support for pipelined ECC operations
In-Reply-To: <20211020142809.349347-1-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
Message-ID: <20211020142809.349347-19-miquel.raynal@bootlin.com>

Some SPI-NAND chips do not have a proper on-die ECC engine providing
error correction/detection. This is particularly an issue on embedded
devices with limited resources because all the computations must
happen in software, unless an external hardware engine is provided.

These external engines are new and can be of two categories: external
or pipelined. Macronix is providing both, the former being already
supported. The second, however, is very SoC implementation dependent
and must be instantiated by the SPI host controller directly.

An entire subsystem has been contributed to support these engines which
makes the insertion into another subsystem such as SPI quite
straightforward without the need for a lot of specific functions.

Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
 drivers/spi/spi-mxic.c | 114 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 112 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
index ae697173eaee..21cdf0beed2c 100644
--- a/drivers/spi/spi-mxic.c
+++ b/drivers/spi/spi-mxic.c
@@ -12,6 +12,8 @@
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand-ecc-mxic.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
@@ -167,6 +169,7 @@
 #define HW_TEST(x)		(0xe0 + ((x) * 4))
 
 struct mxic_spi {
+	struct device *dev;
 	struct clk *ps_clk;
 	struct clk *send_clk;
 	struct clk *send_dly_clk;
@@ -177,6 +180,10 @@ struct mxic_spi {
 		dma_addr_t dma;
 		size_t size;
 	} linear;
+	struct {
+		struct nand_ecc_engine *engine;
+		bool enabled;
+	} ecc;
 };
 
 static int mxic_spi_clk_enable(struct mxic_spi *mxic)
@@ -378,6 +385,13 @@ static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
 	return 0;
 }
 
+static struct mxic_ecc_engine *mxic_spi_to_ecc_engine(struct mxic_spi *mxic)
+{
+	struct nand_ecc_engine *ecc_engine = mxic->ecc.engine;
+
+	return ecc_engine->priv;
+}
+
 static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
 					u64 offs, size_t len, void *buf)
 {
@@ -400,7 +414,14 @@ static ssize_t mxic_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
 	       LMODE_EN,
 	       mxic->regs + LRD_CTRL);
 
-	memcpy_fromio(buf, mxic->linear.map, len);
+	if (mxic->ecc.enabled) {
+		ret = mxic_ecc_process_data(mxic_spi_to_ecc_engine(mxic),
+					    mxic->linear.dma + offs);
+		if (ret)
+			return ret;
+	} else {
+		memcpy_fromio(buf, mxic->linear.map, len);
+	}
 
 	writel(INT_LRD_DIS, mxic->regs + INT_STS);
 	writel(0, mxic->regs + LRD_CTRL);
@@ -436,7 +457,14 @@ static ssize_t mxic_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
 	       LMODE_EN,
 	       mxic->regs + LWR_CTRL);
 
-	memcpy_toio(mxic->linear.map, buf, len);
+	if (mxic->ecc.enabled) {
+		ret = mxic_ecc_process_data(mxic_spi_to_ecc_engine(mxic),
+					    mxic->linear.dma + offs);
+		if (ret)
+			return ret;
+	} else {
+		memcpy_toio(mxic->linear.map, buf, len);
+	}
 
 	writel(INT_LWR_DIS, mxic->regs + INT_STS);
 	writel(0, mxic->regs + LWR_CTRL);
@@ -615,6 +643,80 @@ static int mxic_spi_transfer_one(struct spi_master *master,
 	return 0;
 }
 
+/* ECC wrapper */
+static int mxic_spi_mem_ecc_init_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+
+	return ops->init_ctx(nand);
+}
+
+static void mxic_spi_mem_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+
+	ops->cleanup_ctx(nand);
+}
+
+static struct mxic_spi *mxic_nand_to_spi(struct nand_device *nand)
+{
+	struct device *dev = nand->ecc.engine->dev;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mxic_spi *mxic = spi_master_get_devdata(master);
+
+	return mxic;
+}
+
+static int mxic_spi_mem_ecc_prepare_io_req(struct nand_device *nand,
+					   struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+	struct mxic_spi *mxic = mxic_nand_to_spi(nand);
+
+	mxic->ecc.enabled = (req->mode != MTD_OPS_RAW);
+
+	return ops->prepare_io_req(nand, req);
+}
+
+static int mxic_spi_mem_ecc_finish_io_req(struct nand_device *nand,
+					  struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mxic_ecc_get_pipelined_ops();
+	struct mxic_spi *mxic = mxic_nand_to_spi(nand);
+
+	mxic->ecc.enabled = false;
+
+	return ops->finish_io_req(nand, req);
+}
+
+static struct nand_ecc_engine_ops mxic_spi_mem_ecc_engine_pipelined_ops = {
+	.init_ctx = mxic_spi_mem_ecc_init_ctx,
+	.cleanup_ctx = mxic_spi_mem_ecc_cleanup_ctx,
+	.prepare_io_req = mxic_spi_mem_ecc_prepare_io_req,
+	.finish_io_req = mxic_spi_mem_ecc_finish_io_req,
+};
+
+static int mxic_spi_mem_ecc_probe(struct platform_device *pdev,
+				  struct mxic_spi *mxic)
+{
+	struct nand_ecc_engine *ecceng;
+
+	if (!mxic_ecc_get_pipelined_ops())
+		return -EOPNOTSUPP;
+
+	ecceng = devm_kzalloc(&pdev->dev, sizeof(*ecceng), GFP_KERNEL);
+	if (!ecceng)
+		return -ENOMEM;
+
+	ecceng->dev = &pdev->dev;
+	ecceng->ops = &mxic_spi_mem_ecc_engine_pipelined_ops;
+
+	nand_ecc_register_on_host_hw_engine(ecceng);
+	mxic->ecc.engine = ecceng;
+
+	return 0;
+}
+
 static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev)
 {
 	struct spi_master *master = dev_get_drvdata(dev);
@@ -660,6 +762,7 @@ static int mxic_spi_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, master);
 
 	mxic = spi_master_get_devdata(master);
+	mxic->dev = &pdev->dev;
 
 	master->dev.of_node = pdev->dev.of_node;
 
@@ -705,6 +808,10 @@ static int mxic_spi_probe(struct platform_device *pdev)
 
 	mxic_spi_hw_init(mxic);
 
+	ret = mxic_spi_mem_ecc_probe(pdev, mxic);
+	if (ret)
+		dev_warn(&pdev->dev, "SPI-mem ECC engine not available\n");
+
 	ret = spi_register_master(master);
 	if (ret) {
 		dev_err(&pdev->dev, "spi_register_master failed\n");
@@ -717,8 +824,11 @@ static int mxic_spi_probe(struct platform_device *pdev)
 static int mxic_spi_remove(struct platform_device *pdev)
 {
 	struct spi_master *master = platform_get_drvdata(pdev);
+	struct mxic_spi *mxic = spi_master_get_devdata(master);
+	struct nand_ecc_engine *ecc_engine = mxic->ecc.engine;
 
 	pm_runtime_disable(&pdev->dev);
+	nand_ecc_unregister_on_host_hw_engine(ecc_engine);
 	spi_unregister_master(master);
 
 	return 0;
-- 
2.27.0



From lkp at intel.com  Wed Oct 20 12:39:02 2021
From: lkp at intel.com (kernel test robot)
Date: Thu, 21 Oct 2021 03:39:02 +0800
Subject: [PATCH 18/18] spi: mxic: Add support for pipelined ECC operations
In-Reply-To: <20211020142809.349347-19-miquel.raynal@bootlin.com>
References: <20211020142809.349347-19-miquel.raynal@bootlin.com>
Message-ID: <202110210336.V0zAiGGM-lkp@intel.com>

Hi Miquel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on mtd/nand/next mtd/mtd/next mtd/mtd/fixes v5.15-rc6 next-20211020]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Miquel-Raynal/External-ECC-engines-Macronix-support/20211020-223036
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: riscv-randconfig-r004-20211019 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 9660563950aaed54020bfdf0be07e7096a9553e4)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/9b602c348c84bbe0698c891b14e29cf25ef74b6a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Miquel-Raynal/External-ECC-engines-Macronix-support/20211020-223036
        git checkout 9b602c348c84bbe0698c891b14e29cf25ef74b6a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/spi/spi-mxic.c:16:
>> include/linux/mtd/nand-ecc-mxic.h:23:29: warning: no previous prototype for function 'mxic_ecc_get_pipelined_ops' [-Wmissing-prototypes]
   struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
                               ^
   include/linux/mtd/nand-ecc-mxic.h:23:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
   ^
   static 
   1 warning generated.


vim +/mxic_ecc_get_pipelined_ops +23 include/linux/mtd/nand-ecc-mxic.h

ccf53b4df2cab6 Miquel Raynal 2021-10-20  22  
ccf53b4df2cab6 Miquel Raynal 2021-10-20 @23  struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
ccf53b4df2cab6 Miquel Raynal 2021-10-20  24  {
ccf53b4df2cab6 Miquel Raynal 2021-10-20  25  	return NULL;
ccf53b4df2cab6 Miquel Raynal 2021-10-20  26  }
ccf53b4df2cab6 Miquel Raynal 2021-10-20  27  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 45283 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211021/44f36871/attachment-0001.gz>

From robh at kernel.org  Wed Oct 20 14:14:47 2021
From: robh at kernel.org (Rob Herring)
Date: Wed, 20 Oct 2021 16:14:47 -0500
Subject: [PATCH 03/18] dt-bindings: mtd: nand-chip: Create a NAND chip
 description
In-Reply-To: <20211020142809.349347-4-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-4-miquel.raynal@bootlin.com>
Message-ID: <1634764487.024191.2962583.nullmailer@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:54 +0200, Miquel Raynal wrote:
> Move the NAND chip description out of the NAND controller file. Indeed,
> a subsequent part of the properties supported by a raw NAND chip are
> also supported by SPI-NAND chips. So let's create a generic NAND chip
> description which will be pulled by nand-controller.yaml and later by
> spi-nand.yaml as well.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../devicetree/bindings/mtd/nand-chip.yaml    | 71 +++++++++++++++++++
>  .../bindings/mtd/nand-controller.yaml         | 53 ++------------
>  2 files changed, 75 insertions(+), 49 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mtd/nand-chip.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.example.dt.yaml: nand-controller at f0442800: nand at 1: '#address-cells', '#size-cells', 'compatible', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.example.dt.yaml: nand-controller at f0442800: nand at 1: '#address-cells', '#size-cells', 'compatible', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.example.dt.yaml: nand-controller at 10000200: nand at 0: '#address-cells', '#size-cells', 'compatible', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/brcm,brcmnand.example.dt.yaml: nand-controller at 10000200: nand at 0: '#address-cells', '#size-cells', 'compatible', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/ingenic,nand.example.dt.yaml: nand-controller at 1: nand at 1: 'nand-ecc-mode', 'nand-on-flash-bbt', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/ingenic,nand.example.dt.yaml: nand-controller at 1: nand at 1: 'nand-ecc-mode', 'nand-on-flash-bbt', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.example.dt.yaml: nand-controller at ff4b0000: nand at 0: 'label', 'nand-bus-width', 'nand-ecc-mode', 'nand-is-boot-medium', 'rockchip,boot-blks', 'rockchip,boot-ecc-strength' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.example.dt.yaml: nand-controller at ff4b0000: nand at 0: 'label', 'nand-bus-width', 'nand-ecc-mode', 'nand-is-boot-medium', 'rockchip,boot-blks', 'rockchip,boot-ecc-strength' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.example.dt.yaml: nand-controller at 58002000: nand at 0: '#address-cells', '#size-cells', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.example.dt.yaml: nand-controller at 58002000: nand at 0: '#address-cells', '#size-cells', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/intel,lgm-nand.example.dt.yaml: nand-controller at e0f00000: nand at 0: 'nand-ecc-mode' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/intel,lgm-nand.example.dt.yaml: nand-controller at e0f00000: nand at 0: 'nand-ecc-mode' does not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/intel,lgm-nand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.example.dt.yaml: nand-controller at 1ac00000: nand at 0: 'nand-bus-width', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.example.dt.yaml: nand-controller at 1ac00000: nand at 0: 'nand-bus-width', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.example.dt.yaml: nand-controller at 79b0000: nand at 0: 'nand-bus-width', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.example.dt.yaml: nand-controller at 79b0000: nand at 0: 'nand-bus-width', 'partitions' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.example.dt.yaml: nand-controller at 4,0: nand at 0: '#address-cells', '#size-cells', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.example.dt.yaml: nand-controller at 4,0: nand at 0: '#address-cells', '#size-cells', 'nand-on-flash-bbt' do not match any of the regexes: 'pinctrl-[0-9]+'
	From schema: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mtd/nand-controller.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1543921

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.



From robh at kernel.org  Wed Oct 20 14:14:47 2021
From: robh at kernel.org (Rob Herring)
Date: Wed, 20 Oct 2021 16:14:47 -0500
Subject: [PATCH 04/18] dt-bindings: mtd: spi-nand: Convert spi-nand
 description file to yaml
In-Reply-To: <20211020142809.349347-5-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-5-miquel.raynal@bootlin.com>
Message-ID: <1634764487.038982.2962586.nullmailer@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:55 +0200, Miquel Raynal wrote:
> Let's get rid of spi-nand.txt by converting it to yaml schema. While at
> converting this file, let's actually pull all the generic properties
> from nand-chip.yaml which might apply to a SPI-NAND chip.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../devicetree/bindings/mtd/spi-nand.txt      |  5 ----
>  .../devicetree/bindings/mtd/spi-nand.yaml     | 27 +++++++++++++++++++
>  2 files changed, 27 insertions(+), 5 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
>  create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
xargs: dt-doc-validate: exited with status 255; aborting
make[1]: *** Deleting file 'Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml'
Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
make[1]: *** [scripts/Makefile.lib:385: Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml] Error 255
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1441: dt_binding_check] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1543922

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.



From martin.petersen at oracle.com  Wed Oct 20 20:42:44 2021
From: martin.petersen at oracle.com (Martin K. Petersen)
Date: Wed, 20 Oct 2021 23:42:44 -0400
Subject: [PATCH 0/9] block: reviewed add_disk() error handling set
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <163478764105.7011.9400354892813636458.b4-ty@oracle.com>

On Fri, 15 Oct 2021 16:30:19 -0700, Luis Chamberlain wrote:

> Jens,
> 
> I had last split up patches into 7 groups, but at this point now
> most changes are merged except a few more drivers. Instead of creating
> a new patch set for each of the 7 groups I'm creating 3 new groups of
> patches now:
> 
> [...]

Applied to 5.16/scsi-queue, thanks!

[1/9] scsi/sd: add error handling support for add_disk()
      https://git.kernel.org/mkp/scsi/c/2a7a891f4c40
[2/9] scsi/sr: add error handling support for add_disk()
      https://git.kernel.org/mkp/scsi/c/e9d658c2175b

-- 
Martin K. Petersen	Oracle Linux Engineering


From lkp at intel.com  Wed Oct 20 22:22:05 2021
From: lkp at intel.com (kernel test robot)
Date: Thu, 21 Oct 2021 13:22:05 +0800
Subject: [PATCH 13/18] mtd: nand: mxic-ecc: Support SPI pipelined mode
In-Reply-To: <20211020142809.349347-14-miquel.raynal@bootlin.com>
References: <20211020142809.349347-14-miquel.raynal@bootlin.com>
Message-ID: <202110211322.GeQkngml-lkp@intel.com>

Hi Miquel,

I love your patch! Perhaps something to improve:

[auto build test WARNING on broonie-spi/for-next]
[also build test WARNING on mtd/nand/next mtd/mtd/next mtd/mtd/fixes v5.15-rc6 next-20211020]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Miquel-Raynal/External-ECC-engines-Macronix-support/20211020-223036
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
config: hexagon-randconfig-r014-20211021 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 3cea2505fd8d99a9ba0cb625aecfe28a47c4e3f8)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ccf53b4df2cab6209b1c56f22e1a1955f59b8ea0
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Miquel-Raynal/External-ECC-engines-Macronix-support/20211020-223036
        git checkout ccf53b4df2cab6209b1c56f22e1a1955f59b8ea0
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All warnings (new ones prefixed by >>):

>> drivers/mtd/nand/ecc-mxic.c:480:5: warning: no previous prototype for function 'mxic_ecc_process_data' [-Wmissing-prototypes]
   int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
       ^
   drivers/mtd/nand/ecc-mxic.c:480:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
   ^
   static 
>> drivers/mtd/nand/ecc-mxic.c:742:29: warning: no previous prototype for function 'mxic_ecc_get_pipelined_ops' [-Wmissing-prototypes]
   struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
                               ^
   drivers/mtd/nand/ecc-mxic.c:742:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   struct nand_ecc_engine_ops *mxic_ecc_get_pipelined_ops(void)
   ^
   static 
   2 warnings generated.


vim +/mxic_ecc_process_data +480 drivers/mtd/nand/ecc-mxic.c

   479	
 > 480	int mxic_ecc_process_data(struct mxic_ecc_engine *eng, dma_addr_t dirmap)
   481	{
   482		/* Retrieve the direction */
   483		unsigned int dir = (eng->req->type == NAND_PAGE_READ) ?
   484				   READ_NAND : WRITE_NAND;
   485	
   486		if (dirmap)
   487			writel(dirmap, eng->regs + HC_SLV_ADDR);
   488	
   489		/* Trigger processing */
   490		writel(SDMA_STRT | dir, eng->regs + SDMA_CTRL);
   491	
   492		/* Wait for completion */
   493		return mxic_ecc_data_xfer_wait_for_completion(eng);
   494	}
   495	EXPORT_SYMBOL_GPL(mxic_ecc_process_data);
   496	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 29024 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211021/00dec7b6/attachment-0001.gz>

From caihuoqing at baidu.com  Thu Oct 21 01:43:43 2021
From: caihuoqing at baidu.com (Cai Huoqing)
Date: Thu, 21 Oct 2021 16:43:43 +0800
Subject: [PATCH] ubifs: Make use of the helper macro kthread_run()
Message-ID: <20211021084344.2501-1-caihuoqing@baidu.com>

Repalce kthread_create/wake_up_process() with kthread_run()
to simplify the code.

Signed-off-by: Cai Huoqing <caihuoqing at baidu.com>
---
 fs/ubifs/super.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f0fb25727d96..0e7f206c43cf 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1367,7 +1367,7 @@ static int mount_ubifs(struct ubifs_info *c)
 	sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
 	if (!c->ro_mount) {
 		/* Create background thread */
-		c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
+		c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name);
 		if (IS_ERR(c->bgt)) {
 			err = PTR_ERR(c->bgt);
 			c->bgt = NULL;
@@ -1375,7 +1375,6 @@ static int mount_ubifs(struct ubifs_info *c)
 				  c->bgt_name, err);
 			goto out_wbufs;
 		}
-		wake_up_process(c->bgt);
 	}
 
 	err = ubifs_read_master(c);
@@ -1780,7 +1779,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 		goto out;
 
 	/* Create background thread */
-	c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
+	c->bgt = kthread_run(ubifs_bg_thread, c, "%s", c->bgt_name);
 	if (IS_ERR(c->bgt)) {
 		err = PTR_ERR(c->bgt);
 		c->bgt = NULL;
@@ -1788,7 +1787,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 			  c->bgt_name, err);
 		goto out;
 	}
-	wake_up_process(c->bgt);
 
 	c->orph_buf = vmalloc(c->leb_size);
 	if (!c->orph_buf) {
-- 
2.25.1



From Tudor.Ambarus at microchip.com  Thu Oct 21 01:44:34 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Thu, 21 Oct 2021 08:44:34 +0000
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
 <20211019172623.hi5c4i274bv3lnqw@ti.com>
 <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>
Message-ID: <208ed4a3-fd89-9efb-6dd6-6bddc5c1d818@microchip.com>

On 10/20/21 12:55 PM, Tudor.Ambarus at microchip.com wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 10/19/21 8:26 PM, Pratyush Yadav wrote:
>>>> While we are on this topic, I find this a bit "ugly". Having to set
>>>> late_init() for setting these flags for each flash is not exactly very
>>>> clean or readable. I don't know how the future will look like, but if
>>>> each flash/family needs its own late_init() to set some flags, it won't
>>>> be very readable. We seem to be trading one type of complexity for
>>>> another. I dunno which is the lesser evil though...
>>> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
>>> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
>>> the late_init() function to see what's there. As you saw, late_init() can be
>>> used for tweaking flash's parameters, settings and methods, not just NOR flags,
>>> so I would expect that this hook to be present among flashes that don't define
>>> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
>>> the hook will be there anyway.
>>>
>>> This patch opens the door on how we could handle the flash_info flags. All flash_info
>>> flags that can be determined when parsing SFDP can be removed and use for flashes that
>>> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
>>> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
>>> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
>>> 1/ flashes with SFDP will set the flags as:
>>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> 2/ flashes without SFDP:
>>> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
>>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> spi_nor_info_init_params()
>>> 3/ flashes that collide, one with SFDP and the other without:
>>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>>> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
>>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>> To me it looks like you can separate these flags into three classes:
>>
>>   1. Whether to parse SFDP or not.
>>   2. Flags that can't be discovered via SFDP.
>>   3. Flags that can be discovered by SFDP ideally but can't be
>>      discovered for this particular flash because either SFDP is missing
>>      or the table for this flag is missing.
> 
> These are the flash_info flags, indeed. Apart of these there are the SNOR_F flags
> which are set either statically (one sets a flash_info flag equivalent when
> declaring the flash), or dynamically when parsing SFDP. Check
> SPI_NOR_4B_OPCODES and SNOR_F_4B_OPCODES for example.
> 
>>
>> With your series, flags from 1 and 2 are populated via .flags in
>> flash_info and the ones from 3 are populated via late_init().
> 
> My proposal was to get rid of the flash_info flags from the 3rd category that you
> described, and set the SNOR_F equivalents in a late_init() hook. This way we also
> control when the SNOR_F equivalents are set, late in the init call. But this can
> be achieved with your proposal as well, let's see.
> 
>>
>> Why can't we have 3 different fields for these 3 different flags? In
>> flash_info, we can set .parse_sfdp to true/false to indicate SFDP
>> support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable
>> flags. And we can set .fixup_flags = A | B | C (can probably pick a
>> better name) for the flags that your series sets through late_init().
>>
>> This way, you have a clear separation between the three and they are all
>> clearly visible in the flash entry itself.
> 
> The downside that I see with this is that we extend the flash_info struct with new
> fields and the spi-nor.o's size will increase whether the fields are used or not,
> as we have lots of flash_info entries. This reminds me that probably I should have
> put the late_init() hook inside const struct spi_nor_fixups. Anyway, we can avoid
> increasing the size with some flash_info flags masks. We use the same flash_info flags
> entry, but we introduce some masks, to separate the type of flags. Something like:
> SPI_NOR_PARSE_SFDP |
>         NON_SFDP_FLAGS(SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_SWP_IS_VOLATILE)
> these are for category 1 and 2 in your description
> 
> or
> SPI_NOR_SKIP_SFDP | SFDP_FLAGS(SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
> for categories 1 and 3 in your description
> 
> but you can end up with flags like:
> SPI_NOR_SKIP_SFDP | SFDP_FLAGS() | NON_SFDP_FLAGS()
> 
> 
>>
>> The only case where this might run into trouble is when a SFDP flash has
>> a collision with a non-SFDP flash and they both need different
>> fixup_flags. But I supposed that is a problem even if you use
> 
> we can probably solve this by putting the minimum supported flags by both
> and fill the rest in fixup hooks after we determine which flash is which.
> 
>> late_init() so it certainly doesn't make anything worse.
> 
> yes, this is a different topic.
> 
>>
>> I have not given this extensive thought, but it seems to make sense to
>> me, and I feel that it would make the flow easier to follow. Thoughts?
> 
> Both approaches are fine. Your method keeps all flags in one place but duplicates
> the setting of flags, you'll have "if flash_info flag, set SNOR_F flag".
> Mine gets rid of the SFDP flash_info flags and directly sets SNOR_F equivalents
> with the detriment of introducing fixup hooks at flash declaration. Can we involve
> Michael and Vignesh to get their preference so that we come to an agreement and move
> forward?
> 

I'll go with the flags mask idea.

Cheers,
ta

From p.yadav at ti.com  Thu Oct 21 02:30:12 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 21 Oct 2021 15:00:12 +0530
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <208ed4a3-fd89-9efb-6dd6-6bddc5c1d818@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
 <20211019172623.hi5c4i274bv3lnqw@ti.com>
 <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>
 <208ed4a3-fd89-9efb-6dd6-6bddc5c1d818@microchip.com>
Message-ID: <20211021093010.fjqriexdvsjgihkr@ti.com>

On 21/10/21 08:44AM, Tudor.Ambarus at microchip.com wrote:
> On 10/20/21 12:55 PM, Tudor.Ambarus at microchip.com wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > On 10/19/21 8:26 PM, Pratyush Yadav wrote:
> >>>> While we are on this topic, I find this a bit "ugly". Having to set
> >>>> late_init() for setting these flags for each flash is not exactly very
> >>>> clean or readable. I don't know how the future will look like, but if
> >>>> each flash/family needs its own late_init() to set some flags, it won't
> >>>> be very readable. We seem to be trading one type of complexity for
> >>>> another. I dunno which is the lesser evil though...
> >>> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
> >>> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
> >>> the late_init() function to see what's there. As you saw, late_init() can be
> >>> used for tweaking flash's parameters, settings and methods, not just NOR flags,
> >>> so I would expect that this hook to be present among flashes that don't define
> >>> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
> >>> the hook will be there anyway.
> >>>
> >>> This patch opens the door on how we could handle the flash_info flags. All flash_info
> >>> flags that can be determined when parsing SFDP can be removed and use for flashes that
> >>> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
> >>> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
> >>> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
> >>> 1/ flashes with SFDP will set the flags as:
> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> >>> 2/ flashes without SFDP:
> >>> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
> >>> spi_nor_info_init_params()
> >>> 3/ flashes that collide, one with SFDP and the other without:
> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
> >>> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
> >> To me it looks like you can separate these flags into three classes:
> >>
> >>   1. Whether to parse SFDP or not.
> >>   2. Flags that can't be discovered via SFDP.
> >>   3. Flags that can be discovered by SFDP ideally but can't be
> >>      discovered for this particular flash because either SFDP is missing
> >>      or the table for this flag is missing.
> > 
> > These are the flash_info flags, indeed. Apart of these there are the SNOR_F flags
> > which are set either statically (one sets a flash_info flag equivalent when
> > declaring the flash), or dynamically when parsing SFDP. Check
> > SPI_NOR_4B_OPCODES and SNOR_F_4B_OPCODES for example.
> > 
> >>
> >> With your series, flags from 1 and 2 are populated via .flags in
> >> flash_info and the ones from 3 are populated via late_init().
> > 
> > My proposal was to get rid of the flash_info flags from the 3rd category that you
> > described, and set the SNOR_F equivalents in a late_init() hook. This way we also
> > control when the SNOR_F equivalents are set, late in the init call. But this can
> > be achieved with your proposal as well, let's see.
> > 
> >>
> >> Why can't we have 3 different fields for these 3 different flags? In
> >> flash_info, we can set .parse_sfdp to true/false to indicate SFDP
> >> support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable
> >> flags. And we can set .fixup_flags = A | B | C (can probably pick a
> >> better name) for the flags that your series sets through late_init().
> >>
> >> This way, you have a clear separation between the three and they are all
> >> clearly visible in the flash entry itself.
> > 
> > The downside that I see with this is that we extend the flash_info struct with new
> > fields and the spi-nor.o's size will increase whether the fields are used or not,
> > as we have lots of flash_info entries. This reminds me that probably I should have
> > put the late_init() hook inside const struct spi_nor_fixups. Anyway, we can avoid
> > increasing the size with some flash_info flags masks. We use the same flash_info flags
> > entry, but we introduce some masks, to separate the type of flags. Something like:
> > SPI_NOR_PARSE_SFDP |
> >         NON_SFDP_FLAGS(SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_SWP_IS_VOLATILE)
> > these are for category 1 and 2 in your description
> > 
> > or
> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS(SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
> > for categories 1 and 3 in your description
> > 
> > but you can end up with flags like:
> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS() | NON_SFDP_FLAGS()
> > 
> > 
> >>
> >> The only case where this might run into trouble is when a SFDP flash has
> >> a collision with a non-SFDP flash and they both need different
> >> fixup_flags. But I supposed that is a problem even if you use
> > 
> > we can probably solve this by putting the minimum supported flags by both
> > and fill the rest in fixup hooks after we determine which flash is which.
> > 
> >> late_init() so it certainly doesn't make anything worse.
> > 
> > yes, this is a different topic.
> > 
> >>
> >> I have not given this extensive thought, but it seems to make sense to
> >> me, and I feel that it would make the flow easier to follow. Thoughts?
> > 
> > Both approaches are fine. Your method keeps all flags in one place but duplicates
> > the setting of flags, you'll have "if flash_info flag, set SNOR_F flag".
> > Mine gets rid of the SFDP flash_info flags and directly sets SNOR_F equivalents
> > with the detriment of introducing fixup hooks at flash declaration. Can we involve
> > Michael and Vignesh to get their preference so that we come to an agreement and move
> > forward?
> > 
> 
> I'll go with the flags mask idea.

Fine by me. I am worried about running out of flag bits but we should be 
able to bump up the flags field to 64 bits without much trouble when 
that happens.

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From lee.jones at linaro.org  Thu Oct 21 03:56:53 2021
From: lee.jones at linaro.org (Lee Jones)
Date: Thu, 21 Oct 2021 11:56:53 +0100
Subject: [PATCH v2 1/3] mtd: spi-nor: intel-spi: Disable write protection
 only if asked
In-Reply-To: <20211007112132.30934-2-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
 <20211007112132.30934-2-mika.westerberg@linux.intel.com>
Message-ID: <YXFHdXE91+PjSDv2@google.com>

On Thu, 07 Oct 2021, Mika Westerberg wrote:

> Currently the driver tries to disable the BIOS write protection
> automatically even if this is not what the user wants. For this reason
> modify the driver so that by default it does not touch the write
> protection. Only if specifically asked by the user (setting writeable=1
> command line parameter) the driver tries to disable the BIOS write
> protection.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> ---
>  drivers/mfd/lpc_ich.c                         | 59 +++++++++++++++++--
>  .../mtd/spi-nor/controllers/intel-spi-pci.c   | 29 +++++----
>  drivers/mtd/spi-nor/controllers/intel-spi.c   | 41 ++++++-------
>  include/linux/platform_data/x86/intel-spi.h   |  6 +-
>  4 files changed, 96 insertions(+), 39 deletions(-)

For the MFD parts:

 Acked-by: Lee Jones <lee.jones at linaro.org>

Whoever ends up taking this needs to send out a pull-request to an
immutable branch please.

-- 
Lee Jones [???]
Senior Technical Lead - Developer Services
Linaro.org ? Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog


From lee.jones at linaro.org  Thu Oct 21 03:57:14 2021
From: lee.jones at linaro.org (Lee Jones)
Date: Thu, 21 Oct 2021 11:57:14 +0100
Subject: [PATCH v2 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211007112132.30934-3-mika.westerberg@linux.intel.com>
References: <20211007112132.30934-1-mika.westerberg@linux.intel.com>
 <20211007112132.30934-3-mika.westerberg@linux.intel.com>
Message-ID: <YXFHimJ75Bpg5sSP@google.com>

On Thu, 07 Oct 2021, Mika Westerberg wrote:

> The preferred way to implement SPI-NOR controller drivers is through SPI
> subsubsystem utilizing the SPI MEM core functions. This converts the
> Intel SPI flash controller driver over the SPI MEM by moving the driver
> from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> SPI MEM functions. The driver name will be changed from intel-spi to
> spi-intel to match the convention used in the SPI subsystem.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> ---
>  drivers/mtd/spi-nor/controllers/Kconfig       |  36 ---
>  drivers/mtd/spi-nor/controllers/Makefile      |   3 -
>  drivers/mtd/spi-nor/controllers/intel-spi.h   |  21 --
>  drivers/spi/Kconfig                           |  39 +++
>  drivers/spi/Makefile                          |   3 +
>  .../intel-spi-pci.c => spi/spi-intel-pci.c}   |  20 +-
>  .../spi-intel-platform.c}                     |  21 +-
>  .../intel-spi.c => spi/spi-intel.c}           | 304 +++++++++++-------
>  drivers/spi/spi-intel.h                       |  19 ++
>  include/linux/mfd/lpc_ich.h                   |   2 +-
>  .../x86/{intel-spi.h => spi-intel.h}          |   6 +-
>  11 files changed, 254 insertions(+), 220 deletions(-)
>  delete mode 100644 drivers/mtd/spi-nor/controllers/intel-spi.h
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-pci.c => spi/spi-intel-pci.c} (86%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi-platform.c => spi/spi-intel-platform.c} (65%)
>  rename drivers/{mtd/spi-nor/controllers/intel-spi.c => spi/spi-intel.c} (80%)
>  create mode 100644 drivers/spi/spi-intel.h
>  rename include/linux/platform_data/x86/{intel-spi.h => spi-intel.h} (89%)

For the MFD parts:                                                
                                                                  
 Acked-by: Lee Jones <lee.jones at linaro.org>                       
                                                                  
Whoever ends up taking this needs to send out a pull-request to an
immutable branch please.                                          

-- 
Lee Jones [???]
Senior Technical Lead - Developer Services
Linaro.org ? Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog


From arnd at arndb.de  Thu Oct 21 05:20:40 2021
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 21 Oct 2021 14:20:40 +0200
Subject: BUG: KASAN: use-after-free in blk_mq_sched_tags_teardown
In-Reply-To: <CA+G9fYvv6YsRM2Qf7AGMo3nwqkuAt_D1i+6H_ApHk3kmScyDyg@mail.gmail.com>
References: <CA+G9fYvv6YsRM2Qf7AGMo3nwqkuAt_D1i+6H_ApHk3kmScyDyg@mail.gmail.com>
Message-ID: <CAK8P3a21U0jzMOUWp1rhrNrD3szxxrwo59SBYG89xpYJGXteRA@mail.gmail.com>

On Thu, Oct 21, 2021 at 2:01 PM Naresh Kamboju
<naresh.kamboju at linaro.org> wrote:
>
> Following KASAN BUG noticed on linux next 20211021 while booting qemu-arm64
> with allmodconfig.

> [   77.730367][    T5] Freed by task 1:
> [   77.732009][    T5]  kasan_save_stack+0x30/0x80
> [   77.734083][    T5]  kasan_set_track+0x30/0x80
> [   77.736085][    T5]  kasan_set_free_info+0x34/0x80
> [   77.738261][    T5]  ____kasan_slab_free+0xfc/0x1c0
> [   77.740433][    T5]  __kasan_slab_free+0x3c/0x80
> [   77.742518][    T5]  slab_free_freelist_hook+0x1d4/0x2c0
> [   77.744892][    T5]  kfree+0x160/0x300
> [   77.746618][    T5]  blktrans_dev_release+0x64/0x100
> [   77.748821][    T5]  del_mtd_blktrans_dev+0x1c0/0x240
> [   77.751079][    T5]  mtdblock_remove_dev+0x28/0x80
> [   77.753246][    T5]  blktrans_notify_remove+0xa4/0x140
> [   77.755507][    T5]  del_mtd_device+0x84/0x1c0
> [   77.757541][    T5]  mtd_device_unregister+0x90/0xc0
> [   77.759764][    T5]  physmap_flash_remove+0x58/0x180
> [   77.762012][    T5]  platform_remove+0x48/0xc0
> [   77.764032][    T5]  __device_release_driver+0x1dc/0x340
> [   77.766393][    T5]  driver_detach+0x138/0x200
> [   77.768396][    T5]  bus_remove_driver+0x100/0x180
> [   77.770554][    T5]  driver_unregister+0x64/0xc0
> [   77.772633][    T5]  platform_driver_unregister+0x28/0x80
> [   77.775042][    T5]  physmap_init+0xc4/0xfc
> [   77.776994][    T5]  do_one_initcall+0xb0/0x2c0
> [   77.779028][    T5]  do_initcalls+0x17c/0x244
> [   77.781023][    T5]  kernel_init_freeable+0x2d4/0x378
> [   77.783269][    T5]  kernel_init+0x34/0x180
> [   77.785196][    T5]  ret_from_fork+0x10/0x20
> [   77.787135][    T5]
> ...
> full boot log link,
> https://pastebin.com/xL5MYSD6

I think this is related to an earlier bug that Anders reported a while ago,
see [1]. I had looked at it originally, and found that this probably a
device that gets probed from CONFIG_MTD_PHYSMAP_COMPAT
and then freed again immediately after we find the device does not
exist, starting with commit dcb3e137ce9b ("[MTD] physmap: make
physmap compat explicit").

It's not really the fault of CONFIG_MTD_PHYSMAP_COMPAT
describing a nonexisting device, but instead it's something in the
cleanup path.

        Arnd

[1] https://lore.kernel.org/linux-mtd/CADYN=9Kjw_3cDGAvh9=+nNwdYof1kUPKG-SUOP5FsQhZ+gz62Q at mail.gmail.com/


From hch at lst.de  Thu Oct 21 05:44:36 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:36 +0200
Subject: simplify bdi unregistation
Message-ID: <20211021124441.668816-1-hch@lst.de>

Hi Andrew,

this series simplifies the BDI code to get tid of the magic
auto-unregister feature that hid a recent block layer refcounting
bug.

Diffstat:
 drivers/mtd/mtdcore.c |    1 +
 fs/super.c            |    3 +++
 include/linux/fs.h    |    1 +
 mm/backing-dev.c      |   17 +++++++----------
 4 files changed, 12 insertions(+), 10 deletions(-)


From hch at lst.de  Thu Oct 21 05:44:37 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:37 +0200
Subject: [PATCH 1/5] mm: export bdi_unregister
In-Reply-To: <20211021124441.668816-1-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
Message-ID: <20211021124441.668816-2-hch@lst.de>

To wind down the magic auto-unregister semantics we'll need to push this
into modular code.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 mm/backing-dev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 4a9d4e27d0d9b..8a46a0a4b72fa 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -958,6 +958,7 @@ void bdi_unregister(struct backing_dev_info *bdi)
 		bdi->owner = NULL;
 	}
 }
+EXPORT_SYMBOL(bdi_unregister);
 
 static void release_bdi(struct kref *ref)
 {
-- 
2.30.2



From hch at lst.de  Thu Oct 21 05:44:38 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:38 +0200
Subject: [PATCH 2/5] mtd: call bdi_unregister explicitly
In-Reply-To: <20211021124441.668816-1-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
Message-ID: <20211021124441.668816-3-hch@lst.de>

Call bdi_unregister explicitly instead of relying on the automatic
unregistration.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 drivers/mtd/mtdcore.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c8fd7f758938b..c904e23c82379 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -2409,6 +2409,7 @@ static void __exit cleanup_mtd(void)
 	if (proc_mtd)
 		remove_proc_entry("mtd", NULL);
 	class_unregister(&mtd_class);
+	bdi_unregister(mtd_bdi);
 	bdi_put(mtd_bdi);
 	idr_destroy(&mtd_idr);
 }
-- 
2.30.2



From hch at lst.de  Thu Oct 21 05:44:39 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:39 +0200
Subject: [PATCH 3/5] fs: explicitly unregister per-superblock BDIs
In-Reply-To: <20211021124441.668816-1-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
Message-ID: <20211021124441.668816-4-hch@lst.de>

Add a new SB_I_ flag to mark superblocks that have an ephemeral bdi
associated with them, an unregister it when the superblock is shut down.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 fs/super.c         | 3 +++
 include/linux/fs.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/fs/super.c b/fs/super.c
index bcef3a6f4c4b5..3bfc0f8fbd5bc 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -476,6 +476,8 @@ void generic_shutdown_super(struct super_block *sb)
 	spin_unlock(&sb_lock);
 	up_write(&sb->s_umount);
 	if (sb->s_bdi != &noop_backing_dev_info) {
+		if (sb->s_iflags & SB_I_PERSB_BDI)
+			bdi_unregister(sb->s_bdi);
 		bdi_put(sb->s_bdi);
 		sb->s_bdi = &noop_backing_dev_info;
 	}
@@ -1562,6 +1564,7 @@ int super_setup_bdi_name(struct super_block *sb, char *fmt, ...)
 	}
 	WARN_ON(sb->s_bdi != &noop_backing_dev_info);
 	sb->s_bdi = bdi;
+	sb->s_iflags |= SB_I_PERSB_BDI;
 
 	return 0;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index e7a633353fd20..226de651f52e6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1443,6 +1443,7 @@ extern int send_sigurg(struct fown_struct *fown);
 #define SB_I_UNTRUSTED_MOUNTER		0x00000040
 
 #define SB_I_SKIP_SYNC	0x00000100	/* Skip superblock at global sync */
+#define SB_I_PERSB_BDI	0x00000200	/* has a per-sb bdi */
 
 /* Possible states of 'frozen' field */
 enum {
-- 
2.30.2



From hch at lst.de  Thu Oct 21 05:44:40 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:40 +0200
Subject: [PATCH 4/5] mm: don't automatically unregister bdis
In-Reply-To: <20211021124441.668816-1-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
Message-ID: <20211021124441.668816-5-hch@lst.de>

All BDI users now unregister explicitly.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 mm/backing-dev.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 8a46a0a4b72fa..768e9ae489f66 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -965,8 +965,7 @@ static void release_bdi(struct kref *ref)
 	struct backing_dev_info *bdi =
 			container_of(ref, struct backing_dev_info, refcnt);
 
-	if (test_bit(WB_registered, &bdi->wb.state))
-		bdi_unregister(bdi);
+	WARN_ON_ONCE(test_bit(WB_registered, &bdi->wb.state));
 	WARN_ON_ONCE(bdi->dev);
 	wb_exit(&bdi->wb);
 	kfree(bdi);
-- 
2.30.2



From hch at lst.de  Thu Oct 21 05:44:41 2021
From: hch at lst.de (Christoph Hellwig)
Date: Thu, 21 Oct 2021 14:44:41 +0200
Subject: [PATCH 5/5] mm: simplify bdi refcounting
In-Reply-To: <20211021124441.668816-1-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
Message-ID: <20211021124441.668816-6-hch@lst.de>

Move grabbing and releasing the bdi refcount out of the common
wb_init/wb_exit helpers into code that is only used for the non-default
memcg driven bdi_writeback structures.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 mm/backing-dev.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 768e9ae489f66..5ccb250898083 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -291,8 +291,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
 
 	memset(wb, 0, sizeof(*wb));
 
-	if (wb != &bdi->wb)
-		bdi_get(bdi);
 	wb->bdi = bdi;
 	wb->last_old_flush = jiffies;
 	INIT_LIST_HEAD(&wb->b_dirty);
@@ -316,7 +314,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
 
 	err = fprop_local_init_percpu(&wb->completions, gfp);
 	if (err)
-		goto out_put_bdi;
+		return err;
 
 	for (i = 0; i < NR_WB_STAT_ITEMS; i++) {
 		err = percpu_counter_init(&wb->stat[i], 0, gfp);
@@ -330,9 +328,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
 	while (i--)
 		percpu_counter_destroy(&wb->stat[i]);
 	fprop_local_destroy_percpu(&wb->completions);
-out_put_bdi:
-	if (wb != &bdi->wb)
-		bdi_put(bdi);
 	return err;
 }
 
@@ -373,8 +368,6 @@ static void wb_exit(struct bdi_writeback *wb)
 		percpu_counter_destroy(&wb->stat[i]);
 
 	fprop_local_destroy_percpu(&wb->completions);
-	if (wb != &wb->bdi->wb)
-		bdi_put(wb->bdi);
 }
 
 #ifdef CONFIG_CGROUP_WRITEBACK
@@ -397,6 +390,7 @@ static void cgwb_release_workfn(struct work_struct *work)
 	struct bdi_writeback *wb = container_of(work, struct bdi_writeback,
 						release_work);
 	struct blkcg *blkcg = css_to_blkcg(wb->blkcg_css);
+	struct backing_dev_info *bdi = wb->bdi;
 
 	mutex_lock(&wb->bdi->cgwb_release_mutex);
 	wb_shutdown(wb);
@@ -416,6 +410,7 @@ static void cgwb_release_workfn(struct work_struct *work)
 
 	percpu_ref_exit(&wb->refcnt);
 	wb_exit(wb);
+	bdi_put(bdi);
 	WARN_ON_ONCE(!list_empty(&wb->b_attached));
 	kfree_rcu(wb, rcu);
 }
@@ -497,6 +492,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
 	INIT_LIST_HEAD(&wb->b_attached);
 	INIT_WORK(&wb->release_work, cgwb_release_workfn);
 	set_bit(WB_registered, &wb->state);
+	bdi_get(bdi);
 
 	/*
 	 * The root wb determines the registered state of the whole bdi and
@@ -528,6 +524,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
 	goto out_put;
 
 err_fprop_exit:
+	bdi_put(bdi);
 	fprop_local_destroy_percpu(&wb->memcg_completions);
 err_ref_exit:
 	percpu_ref_exit(&wb->refcnt);
-- 
2.30.2



From john.garry at huawei.com  Thu Oct 21 06:20:47 2021
From: john.garry at huawei.com (John Garry)
Date: Thu, 21 Oct 2021 14:20:47 +0100
Subject: BUG: KASAN: use-after-free in blk_mq_sched_tags_teardown
In-Reply-To: <CAK8P3a21U0jzMOUWp1rhrNrD3szxxrwo59SBYG89xpYJGXteRA@mail.gmail.com>
References: <CA+G9fYvv6YsRM2Qf7AGMo3nwqkuAt_D1i+6H_ApHk3kmScyDyg@mail.gmail.com>
 <CAK8P3a21U0jzMOUWp1rhrNrD3szxxrwo59SBYG89xpYJGXteRA@mail.gmail.com>
Message-ID: <aae28ac1-aa3f-3602-8732-9b3a87e9cdf0@huawei.com>

On 21/10/2021 13:20, Arnd Bergmann wrote:
> On Thu, Oct 21, 2021 at 2:01 PM Naresh Kamboju
> <naresh.kamboju at linaro.org> wrote:
>>
>> Following KASAN BUG noticed on linux next 20211021 while booting qemu-arm64
>> with allmodconfig.
> 
>> [   77.730367][    T5] Freed by task 1:
>> [   77.732009][    T5]  kasan_save_stack+0x30/0x80
>> [   77.734083][    T5]  kasan_set_track+0x30/0x80
>> [   77.736085][    T5]  kasan_set_free_info+0x34/0x80
>> [   77.738261][    T5]  ____kasan_slab_free+0xfc/0x1c0
>> [   77.740433][    T5]  __kasan_slab_free+0x3c/0x80
>> [   77.742518][    T5]  slab_free_freelist_hook+0x1d4/0x2c0
>> [   77.744892][    T5]  kfree+0x160/0x300
>> [   77.746618][    T5]  blktrans_dev_release+0x64/0x100
>> [   77.748821][    T5]  del_mtd_blktrans_dev+0x1c0/0x240
>> [   77.751079][    T5]  mtdblock_remove_dev+0x28/0x80
>> [   77.753246][    T5]  blktrans_notify_remove+0xa4/0x140
>> [   77.755507][    T5]  del_mtd_device+0x84/0x1c0
>> [   77.757541][    T5]  mtd_device_unregister+0x90/0xc0
>> [   77.759764][    T5]  physmap_flash_remove+0x58/0x180
>> [   77.762012][    T5]  platform_remove+0x48/0xc0
>> [   77.764032][    T5]  __device_release_driver+0x1dc/0x340
>> [   77.766393][    T5]  driver_detach+0x138/0x200
>> [   77.768396][    T5]  bus_remove_driver+0x100/0x180
>> [   77.770554][    T5]  driver_unregister+0x64/0xc0
>> [   77.772633][    T5]  platform_driver_unregister+0x28/0x80
>> [   77.775042][    T5]  physmap_init+0xc4/0xfc
>> [   77.776994][    T5]  do_one_initcall+0xb0/0x2c0
>> [   77.779028][    T5]  do_initcalls+0x17c/0x244
>> [   77.781023][    T5]  kernel_init_freeable+0x2d4/0x378
>> [   77.783269][    T5]  kernel_init+0x34/0x180
>> [   77.785196][    T5]  ret_from_fork+0x10/0x20
>> [   77.787135][    T5]
>> ...
>> full boot log link,
>> https://pastebin.com/xL5MYSD6
> 
> I think this is related to an earlier bug that Anders reported a while ago,
> see [1]. I had looked at it originally, and found that this probably a
> device that gets probed from CONFIG_MTD_PHYSMAP_COMPAT
> and then freed again immediately after we find the device does not
> exist, starting with commit dcb3e137ce9b ("[MTD] physmap: make
> physmap compat explicit").
> 
> It's not really the fault of CONFIG_MTD_PHYSMAP_COMPAT
> describing a nonexisting device, but instead it's something in the
> cleanup path.
> 

Maybe there is more than one issue, but the fix I mentioned in my 
earlier reply resolves a UAF which can I trigger on my system:

[  674.333618] FAT-fs (sda1): unable to read boot sector to mark fs as dirty
[  674.422877] 
==================================================================
[  674.430097] BUG: KASAN: use-after-free in 
blk_mq_sched_tags_teardown+0xb4/0x12c
[  674.437412] Read of size 4 at addr ffff001053f40100 by task umount/557
[  674.443934]
[  674.445418] CPU: 6 PID: 557 Comm: umount Not tainted 
5.15.0-rc3-00045-g000f88ac8830 #420
[  674.453502] Hardware name: Huawei Taishan 2280 /D05, BIOS Hisilicon 
D05 IT21 Nemo 2.0 RC0 04/18/2018
[  674.462626] Call trace:
[  674.465063]  dump_backtrace+0x0/0x2b4
[  674.468724]  show_stack+0x1c/0x30
[  674.472036]  dump_stack_lvl+0x68/0x84
[  674.475695]  print_address_description.constprop.0+0x74/0x2b8
[  674.481438]  kasan_report+0x1e4/0x24c
[  674.485096]  __asan_load4+0x98/0xd0
[  674.488579]  blk_mq_sched_tags_teardown+0xb4/0x12c
[  674.493366]  blk_mq_exit_sched+0x110/0x140
[  674.497459]  __elevator_exit+0x38/0x60
[  674.501203]  blk_release_queue+0x10c/0x1cc
[  674.505295]  kobject_put+0xac/0x180
[  674.508780]  blk_put_queue+0x18/0x24
[  674.512350]  disk_release+0x64/0x90
[  674.515836]  device_release+0x98/0x110
[  674.519581]  kobject_put+0xac/0x180
[  674.523065]  put_device+0x18/0x30
[  674.526374]  put_disk+0x30/0x44
[  674.529511]  part_release+0x28/0x4c
[  674.532993]  device_release+0x98/0x110
[  674.536737]  kobject_put+0xac/0x180
[  674.540221]  put_device+0x18/0x30
[  674.543531]  blkdev_put+0xe4/0x340
[  674.546930]  kill_block_super+0x60/0xa0
[  674.550762]  deactivate_locked_super+0x78/0x104
[  674.555289]  deactivate_super+0x90/0xac
[  674.559121]  cleanup_mnt+0x164/0x214
[  674.562691]  __cleanup_mnt+0x18/0x24
[  674.566260]  task_work_run+0xb8/0x1cc
[  674.569918]  do_notify_resume+0x11a8/0x1abc
[  674.574098]  el0_svc+0x6c/0x7c
[  674.577148]  el0t_64_sync_handler+0x1a8/0x1b0
[  674.581500]  el0t_64_sync+0x1a0/0x1a4
[  674.585157]
[  674.586639] The buggy address belongs to the page:
[  674.591420] page:(____ptrval____) refcount:0 mapcount:-128 
mapping:0000000000000000 index:0x0 pfn:0x1053f40
[  674.601154] flags: 0xbfffc0000000000(node=0|zone=2|lastcpupid=0xffff)
[  674.607594] raw: 0bfffc0000000000 fffffc00415ff008 ffff0017fbffebb0 
0000000000000000
[  674.615331] raw: 0000000000000000 0000000000000006 00000000ffffff7f 
0000000000000000
[  674.623065] page dumped because: kasan: bad access detected
[  674.628628]
[  674.630109] Memory state around the buggy address:
[  674.634891]  ffff001053f40000: ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff
[  674.642105]  ffff001053f40080: ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff
[  674.649319] >ffff001053f40100: ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff
[  674.656531]                    ^
[  674.659751]  ffff001053f40180: ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff
[  674.666964]  ffff001053f40200: ff ff ff ff ff ff ff ff ff ff ff ff ff 
ff ff ff
[  674.674177] 
==================================================================
[  674.681389] Disabling lock debugging due to kernel taint
root@(none)$
root@(none)$

Note that my baseline includes recent block changes which would be on 
next 20211021

Thanks,
John

>          Arnd
> 
> [1] https://lore.kernel.org/linux-mtd/CADYN=9Kjw_3cDGAvh9=+nNwdYof1kUPKG-SUOP5FsQhZ+gz62Q at mail.gmail.com/
> .
> 



From miquel.raynal at bootlin.com  Thu Oct 21 07:09:32 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Thu, 21 Oct 2021 16:09:32 +0200
Subject: [PATCH 04/18] dt-bindings: mtd: spi-nand: Convert spi-nand
 description file to yaml
In-Reply-To: <1634764487.038982.2962586.nullmailer@robh.at.kernel.org>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-5-miquel.raynal@bootlin.com>
 <1634764487.038982.2962586.nullmailer@robh.at.kernel.org>
Message-ID: <20211021160932.4169f66f@xps13>

Hi Rob,

robh at kernel.org wrote on Wed, 20 Oct 2021 16:14:47 -0500:

> On Wed, 20 Oct 2021 16:27:55 +0200, Miquel Raynal wrote:
> > Let's get rid of spi-nand.txt by converting it to yaml schema. While at
> > converting this file, let's actually pull all the generic properties
> > from nand-chip.yaml which might apply to a SPI-NAND chip.
> > 
> > Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> > ---
> >  .../devicetree/bindings/mtd/spi-nand.txt      |  5 ----
> >  .../devicetree/bindings/mtd/spi-nand.yaml     | 27 +++++++++++++++++++
> >  2 files changed, 27 insertions(+), 5 deletions(-)
> >  delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
> >  create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml
> >   
> 
> My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> on your patch (DT_CHECKER_FLAGS is new in v5.13):
> 
> yamllint warnings/errors:
> 
> dtschema/dtc warnings/errors:
> Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
> xargs: dt-doc-validate: exited with status 255; aborting
> make[1]: *** Deleting file 'Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml'
> Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
> make[1]: *** [scripts/Makefile.lib:385: Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml] Error 255
> make[1]: *** Waiting for unfinished jobs....
> make: *** [Makefile:1441: dt_binding_check] Error 2

I am not able to reproduce this error and in general I don't understand
it. There is no relationship between this change and
snps,dw-apb-ssi.yaml. Also the fact that nand-chip-yaml do not exist,
it was just created in the patch before so I wonder how much I should
trust this error.

Also, maybe I am not using the tools properly, but it is very hard to
send correct bindings at the first try. Running make dt_binding_check
takes ages, any change in one yaml file will recheck the entire data
base and filtering out on a single yaml file is generally too
restrictive and still prints unrelated errors of syntax on other files.
I don't know how much of this is actually expected and/or if someone is
working on it.

Thanks,
Miqu?l


From axboe at kernel.dk  Thu Oct 21 08:01:06 2021
From: axboe at kernel.dk (Jens Axboe)
Date: Thu, 21 Oct 2021 09:01:06 -0600
Subject: (subset) [PATCH 0/9] block: reviewed add_disk() error handling set
In-Reply-To: <20211015233028.2167651-1-mcgrof@kernel.org>
References: <20211015233028.2167651-1-mcgrof@kernel.org>
Message-ID: <163482846658.50565.12530170761457767964.b4-ty@kernel.dk>

On Fri, 15 Oct 2021 16:30:19 -0700, Luis Chamberlain wrote:
> Jens,
> 
> I had last split up patches into 7 groups, but at this point now
> most changes are merged except a few more drivers. Instead of creating
> a new patch set for each of the 7 groups I'm creating 3 new groups of
> patches now:
> 
> [...]

Applied, thanks!

[3/9] dm: add add_disk() error handling
      commit: e7089f65dd51afeda5eb760506b5950d95f9ec29
[4/9] bcache: add error handling support for add_disk()
      commit: 2961c3bbcaec0ed7fb7b9a465b3796f37f2294e5
[5/9] xen-blkfront: add error handling support for add_disk()
      commit: 293a7c528803321479593d42d0898bb5a9769db1
[6/9] m68k/emu/nfblock: add error handling support for add_disk()
      commit: 21fd880d3da7564bab68979417cab7408e4f9642
[7/9] um/drivers/ubd_kern: add error handling support for add_disk()
      commit: 66638f163a2b5c5b462ca38525129b14a20117eb
[8/9] rnbd: add error handling support for add_disk()
      commit: 2e9e31bea01997450397d64da43b6675e0adb9e3
[9/9] mtd: add add_disk() error handling
      commit: 83b863f4a3f0de4ece7802d9121fed0c3e64145f

Best regards,
-- 
Jens Axboe




From havasiefr at gmail.com  Thu Oct 21 08:33:15 2021
From: havasiefr at gmail.com (Kristof Havasi)
Date: Thu, 21 Oct 2021 17:33:15 +0200
Subject: UBIFS panic during brown-out
In-Reply-To: <CADBnMvhCmNQsYRVAveuf=Ri820bLyLdcrA71Nywh0mVL+X8Fng@mail.gmail.com>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
 <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
 <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>
 <1040411488.65265.1634045778705.JavaMail.zimbra@nod.at>
 <CADBnMvidNZEiJfSTLe-rj+V0N=EtW8jTrYXzc2KRJKNS-zkCjg@mail.gmail.com>
 <CADBnMvhCmNQsYRVAveuf=Ri820bLyLdcrA71Nywh0mVL+X8Fng@mail.gmail.com>
Message-ID: <CADBnMviZDXD4p6U4fPDsMFsY1OJYEcjkNGTXDRbbM0mKDVpaAQ@mail.gmail.com>

Dear Richard,

I noticed that I forgot to Cc linux-mtd from the previous emails.

Latest update: we could reproduce the bug with a v5.10 port.
The same EPERM error is hit.

Happy to hear any hints on how I can support in fixing this issue.

Best Regards,
Krist?f


On Tue, 19 Oct 2021 at 18:09, Kristof Havasi <havasiefr at gmail.com> wrote:
>
> Dear Richard,
>
> a quick update on the topic:
>
> I disabled UBIFS-Authentication (but left UBIFS-Encryption), and our
> stress-test has been running successfully without the mount-issue
> (+1150 power-cuts)
> for 3+ days.
>
> If I understand correctly, the hit EPERM error originates from finding
> an auth-snode,
> where the hmac over the previous data nodes doesn't match the calculated one.
> (A possible tampering case, I guess).
>
> If you could give some pointers where to maybe inject more analysis
> printk-s which
> would help further, I would happily re-do the test. (Wasn't yet
> successful to create
> a minimal program to reproduce the issue.)
>
> Is e.g. n_nodes of any interest here?
> Or something on the writer's side which would help further? I am not
> familiar with
> the ubifs source code, but if you point me to the place where the
> caches are written
> to the flash and the authentication node is inserted, I could add some
> debugging there.
>
> > > >> 5.4 is not fresh. Can you use a more recent kernel?
> Would a port to v5.10.y be fresh enough?
>
> Best regards,
> Krist?f
>
> On Thu, 14 Oct 2021 at 13:08, Kristof Havasi <havasiefr at gmail.com> wrote:
> >
> > Dear Richard,
> >
> > On Tue, 12 Oct 2021 at 15:36, Richard Weinberger <richard at nod.at> wrote:
> > >
> > > Krist?f,
> > >
> > > ----- Urspr?ngliche Mail -----
> > > > Von: "Kristof Havasi" <havasiefr at gmail.com>
> > > >> So, are you really talking about brown-out? If so, better talk to you hardware
> > > >> guys.
> > > >
> > > > Sorry, s/brown-out/power-cut/.
> > >
> > > :-)
> > >
> > > >>
> > > >> > Does the Auth+Encryption combo increase the chances for corrupting the FS
> > > >> > during brown-out, due to the extra operations?
> > > >>
> > > >> Assuming you actually meant power-cut.
> > > >> Both features are rather new, so there can be still bugs.
> > > >
> > > > If the logs do not reveal any pointers, we could re-test with disabled enc/auth.
> > > >
> > > >>
> > > >> > Would you suggest turning on any of the chk_* knobs in the debugfs?
> > > >> > I am not sure that they are helpful, or will just modify the behaviour of the
> > > >> > timings of the system too much.
> > > >>
> > > >> Let's start with logs first.
> > > >>
> > > >> > Would it be a last resort in case the brown-out is detected to switch the FS
> > > >> > into ro mode? Is there any API/ABI apart from the debugfs's ro_error knob to
> > > >> > switch the FS into read-only mode and so trying to prevent file-system
> > > >> > corruption?
> > > >>
> > > >> Not really. You need to make sure that the current NAND command is finished
> > > >> and no new one will be scheduled. Depending on your hardware design this can
> > > >> be a challenge.
> > > >
> > > > So would a "successful `sync` and ro mode switch" be a safe bet, if
> > > > during the two
> > > > actions no new data is written to the FS?
> > >
> > > Kind of. Actually UBIFS should handle this just fine.
> > > Before we consider workarounds, let's give the problem more thought.
> >
> > I can see that in all pre-crash cases the recovery is successful:
> >
> > ubi0: scanning is finished
> > ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> > ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> > ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> > ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> > ubi0: good PEBs: 4063, bad PEBs: 32, corrupted PEBs: 0
> > ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> > ubi0: max/mean erase counter: 3/1, WL threshold: 4096, image sequence
> > number: 1244242931
> > ubi0: available PEBs: 0, total reserved PEBs: 4063, PEBs reserved for
> > bad PEB handling: 48
> > ubi0: background thread "ubi_bgt0d" started, PID 622
> > UBIFS (ubi0:4): Mounting in authenticated mode
> > UBIFS (ubi0:4): recovery needed
> > UBIFS (ubi0:4): recovery deferred
> > UBIFS (ubi0:4): UBIFS: mounted UBI device 0, volume 4, name "rootfs", R/O mode
> > UBIFS (ubi0:4): LEB size: 253952 bytes (248 KiB), min./max. I/O unit
> > sizes: 4096 bytes/4096 bytes
> > UBIFS (ubi0:4): FS size: 1004888064 bytes (958 MiB, 3957 LEBs),
> > journal size 9404416 bytes (8 MiB, 38 LEBs)
> > UBIFS (ubi0:4): reserved for root: 0 bytes (0 KiB)
> > UBIFS (ubi0:4): media format: w5/r0 (latest is w5/r0), UUID
> > 33BCA4FE-C691-4F5D-ACD1-D2B9D6D6B201, small LPT model
> > VFS: Mounted root (ubifs filesystem) readonly on device 0:13.
> > fscrypt: AES-256-CTS-CBC using implementation "cts(atmel-cbc-aes)"
> > devtmpfs: mounted
> > Freeing unused kernel memory: 1024K
> > Run /sbin/init as init process
> > fscrypt: AES-256-XTS using implementation "xts(atmel-ecb-aes)"
> > UBIFS (ubi0:4): completing deferred recovery
> > UBIFS (ubi0:4): background thread "ubifs_bgt0_4" started, PID 632
> > UBIFS (ubi0:4): deferred recovery completed
> >
> > >
> > > >>
> > > >> > Any pointers are welcomed!
> > > >> >
> > > >> > We are on Kernel v5.4.150
> > > >> > We use _both_ UBIFS Authentication and Encryption.
> > > >> > The board is a SAMA5D3 powered embedded device with 1GB NAND flash,
> > > >> > which is not even nearly full (10% used).
> > > >> >
> > > >> > Kernel panic after the last brown-out:
> > > >> > ubi0: scanning is finished
> > > >> > ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> > > >> > ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> > > >> > ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> > > >> > ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> > > >> > ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
> > > >> > ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> > > >> > ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
> > > >> > sequence number: 921361235
> > > >> >>ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for bad PEB
> > > >> >>handling: 67
> > > >> > ubi0: background thread "ubi_bgt0d" started, PID 617
> > > >> > UBIFS (ubi0:4): Mounting in authenticated mode
> > > >> > UBIFS (ubi0:4): recovery needed
> > > >> >>VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
> > > >>
> > > >> There is a lot of context missing. Can you please share the full logs?
> > > >> Usually UBIFS prints in detail what went wrong.
> > > >
> > > > I couldn't see any UBIFS logs over the serial (but the kernel log
> > > > level was also only 1)
> > > > and the application log was also redirected there...
> > > > But here is the full log from the application logs through the power-cut and the
> > > > boot-up
> > > >
> > > > [Sat Oct 09 14:15:00 2021] pwr outage WARN: Power outage detected ...
> > > > [Sat Oct 09 14:15:00 2021] pwr outage INFO: Low Power mode activated
> > > > [Sat Oct 09 14:15:00 2021] event manager TRACE: Database
> > > > /data/logsystem.db opened successfully
> > > > [Sat Oct 09 14:15:00 2021] event manager TRACE: SQLite prepare :
> > > > SELECT * FROM log_sys WHERE  event_flag=2 OR event_flag=1 ORDER BY
> > > > timestamp ASC LIMIT 1;
> > > > [Sat Oct 09 14:15:00 2021] fnn logger TRACE: Database
> > > > /data/logcustomer.db opened successfully
> > > > [snip] some 10s of lines of application log related to SQL operations
> > > > [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : SELECT
> > > > MAX(repetition_counter), MAX(record_number), MAX(parent_record_number)
> > > > FROM log_customer WHERE  timestamp > ?1 AND event_id = ?2 AND
> > > > event_sub_id = ?3 AND user_identity = ?4 AND subject_identity = ?5 AND
> > > > message_extensions = ?6 AND peer_identity = ?7;
> > > > [Sat Oct 09 14:15:00 2021] fnn logger TRACE: Stepping:
> > > > SELECT MAX(repetition_counter), MAX(record_number),
> > > > MAX(parent_record_number) FROM log_customer WHERE  timestamp >
> > > > 1633695300 AND event_id = 19005 AND event_sub_id = 1 AND user_identity
> > > > = '' AND subject_identity = '01005e3180a0.eefr2000003006.sm' AND
> > > > message_extensions = '' AND peer_identity = '';
> > > > [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQL-Step executed successfully
> > > > [Sat Oct 09 14:15:00 2021] fnn logger TRACE: SQLite prepare : UPDATE
> > > > log_customer SET [snip] WHERE record_number = ?21 AND
> > > > repetition_counter = ?22;
> > > > [Sat Oct 09 14:15:01 2021] fnn logger TRACE: Stepping:
> > > > UPDATE log_customer SET repetition_counter = 372, parent_record_number
> > > > = 3031, seconds_index = 246, timestamp = 1633781700, level = 2,
> > > > version = 1, length = 0, device_typ?RomBOOT
> > > > RomBOOT
> > > >
> > > > AT91Bootstrap for SMGW 3.8.12-00020-g0f08dbf (Wed Apr 14 18:46:12 CEST 2021)
> > > >
> > > > NAND: ONFI flash detected
> > > > NAND: Manufacturer ID: 0x2c Chip ID: 0xd3
> > > > NAND: Page Bytes: 4096, Spare Bytes: 224
> > > > NAND: ECC Correctability Bits: 8, ECC Sector Bytes: 512
> > > > NAND: Disable On-Die ECC
> > > > NAND: Initialize PMECC params, cap: 8, sector: 512
> > > > NAND: Initialize UBI...
> > > > UBI: Loading volume-table 0 at PEB 202 with copy flag!
> > > > NAND: Loading UBI volume kernel kernel-spare to @0x22000000
> > > > (0xffffffff bytes length)...
> > > > UBI: Length of Vol-2 updated to 3128 KB
> > > > NAND: Loading UBI volume dtb dtb-spare to @0x21000000 (0xffffffff
> > > > bytes length)...
> > > > UBI: Length of Vol-0 updated to 33 KB
> > > >
> > > > Booting zImage ......
> > > >
> > > > Using device tree in place at 0x210001f4
> > > > DT: Injected MAC addresses
> > > > DT: Populated virtual-eprom
> > > >
> > > > Starting linux kernel ..., machid: 0xffffffff
> > > >
> > > > Booting Linux on physical CPU 0x0
> > > > Linux version 5.4.109-00033-ga88943c1e68
> > > > (root at runner-tzue45hw-project-205-concurrent-0) (gcc version 6.5.0
> > > > (Linaro GCC 6.5-2018.12)) #1 Wed Apr 14 18:46:17 CEST 2021
> > > > CPU: ARMv7 Processor [410fc051] revision 1 (ARMv7), cr=10c53c7d
> > > > CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
> > > > OF: fdt: Machine model: SMGW
> > > > Memory policy: Data cache writeback
> > > > CPU: All CPU(s) started in SVC mode.
> > > > Built 1 zonelists, mobility grouping on.  Total pages: 32511
> > > > Kernel command line: rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs
> > > > rootflags=auth_hash_name=sha256,auth_key=ubifsauth:0000aaaaffff0000
> > > > Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, linear)
> > > > Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, linear)
> > > > mem auto-init: stack:off, heap alloc:on, heap free:on
> > > > mem auto-init: clearing system memory may take some time...
> > > > Memory: 121196K/131068K available (5120K kernel code, 197K rwdata,
> > > > 956K rodata, 1024K init, 153K bss, 9872K reserved, 0K cma-reserved)
> > > > NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
> > > > random: get_random_bytes called from start_kernel+0x2ec/0x41c with crng_init=0
> > > > master clk is overclocked
> > > > clocksource: pit: mask: 0xfffffff max_cycles: 0xfffffff, max_idle_ns:
> > > > 14479245754 ns
> > > > Console: colour dummy device 80x30
> > > > printk: console [tty0] enabled
> > > > sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every
> > > > 21474836475000000ns
> > > > Calibrating delay loop... 351.43 BogoMIPS (lpj=1757184)
> > > > pid_max: default: 32768 minimum: 301
> > > > Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> > > > Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
> > > > CPU: Testing write buffer coherency: ok
> > > > Setting up static identity map for 0x20100000 - 0x2010003c
> > > > devtmpfs: initialized
> > > > VFP support v0.3: implementor 41 architecture 2 part 30 variant 5 rev 1
> > > > clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff,
> > > > max_idle_ns: 19112604462750000 ns
> > > > futex hash table entries: 256 (order: -1, 3072 bytes, linear)
> > > > pinctrl core: initialized pinctrl subsystem
> > > > NET: Registered protocol family 16
> > > > DMA: preallocated 256 KiB pool for atomic coherent allocations
> > > > cpuidle: using governor ladder
> > > > gpio-at91 fffff200.gpio: at address (ptrval)
> > > > gpio-at91 fffff400.gpio: at address (ptrval)
> > > > gpio-at91 fffff600.gpio: at address (ptrval)
> > > > gpio-at91 fffff800.gpio: at address (ptrval)
> > > > gpio-at91 fffffa00.gpio: at address (ptrval)
> > > > pinctrl-at91 ahb:apb:pinctrl at fffff200: initialized AT91 pinctrl driver
> > > > atmel_tcb f0010000.timer: IRQ index 1 not found
> > > > atmel_tcb f0010000.timer: IRQ index 2 not found
> > > > atmel_tcb f8014000.timer: IRQ index 1 not found
> > > > atmel_tcb f8014000.timer: IRQ index 2 not found
> > > > at_hdmac ffffe600.dma-controller: Atmel AHB DMA Controller ( cpy set
> > > > slave ), 8 channels
> > > > at_hdmac ffffe800.dma-controller: Atmel AHB DMA Controller ( cpy set
> > > > slave ), 8 channels
> > > > AT91: Detected SoC family: sama5d3
> > > > AT91: Detected SoC: sama5d35, revision 2
> > > > usbcore: registered new interface driver usbfs
> > > > usbcore: registered new interface driver hub
> > > > usbcore: registered new device driver usb
> > > > at91_i2c f0014000.i2c: using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
> > > > at91_i2c f0014000.i2c: AT91 i2c bus driver (hw version: 0x402).
> > > > at91_i2c f0018000.i2c: can't get DMA channel, continue without DMA support
> > > > at91_i2c f0018000.i2c: AT91 i2c bus driver (hw version: 0x402).
> > > > clocksource: Switched to clocksource pit
> > > > NET: Registered protocol family 2
> > > > tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 4096 bytes, linear)
> > > > TCP established hash table entries: 1024 (order: 0, 4096 bytes, linear)
> > > > TCP bind hash table entries: 1024 (order: 0, 4096 bytes, linear)
> > > > TCP: Hash tables configured (established 1024 bind 1024)
> > > > UDP hash table entries: 256 (order: 0, 4096 bytes, linear)
> > > > UDP-Lite hash table entries: 256 (order: 0, 4096 bytes, linear)
> > > > NET: Registered protocol family 1
> > > > Initialise system trusted keyrings
> > > > workingset: timestamp_bits=30 max_order=15 bucket_order=0
> > > > NET: Registered protocol family 38
> > > > Key type asymmetric registered
> > > > Asymmetric key parser 'x509' registered
> > > > atmel_usart_serial.0.auto: ttyS1 at MMIO 0xf001c000 (irq = 21,
> > > > base_baud = 4125000) is a ATMEL_SERIAL
> > > > atmel_usart_serial.1.auto: ttyS2 at MMIO 0xf0020000 (irq = 22,
> > > > base_baud = 8250000) is a ATMEL_SERIAL
> > > > atmel_usart_serial.2.auto: ttyS3 at MMIO 0xf8020000 (irq = 24,
> > > > base_baud = 4125000) is a ATMEL_SERIAL
> > > > atmel_usart_serial.3.auto: ttyS0 at MMIO 0xffffee00 (irq = 32,
> > > > base_baud = 8250000) is a ATMEL_SERIAL
> > > > printk: console [ttyS0] enabled
> > > > atmel_spi f8008000.spi: DMA TX channel not available, SPI unable to use DMA
> > > > atmel_spi f8008000.spi: Atmel SPI Controller using PIO only
> > > > ksz8863 at 0 enforce active low on chipselect handle
> > > > atmel_spi f8008000.spi: Atmel SPI Controller version 0x213 at
> > > > 0xf8008000 (irq 23)
> > > > libphy: Fixed MDIO Bus: probed
> > > > macb f0028000.ethernet: invalid hw address, using random
> > > > random: fast init done
> > > > libphy: MACB_mii_bus: probed
> > > > Generic PHY fixed-0:00: attached PHY driver [Generic PHY]
> > > > (mii_bus:phy_addr=fixed-0:00, irq=POLL)
> > > > macb f0028000.ethernet eth0: Cadence GEM rev 0x00020119 at 0xf0028000
> > > > irq 40 (12:71:da:58:0b:2d)
> > > > libphy: MACB_mii_bus: probed
> > > > Micrel KSZ8081 or KSZ8091 f802c000.ethernet-ffffffff:00: attached PHY
> > > > driver [Micrel KSZ8081 or KSZ8091]
> > > > (mii_bus:phy_addr=f802c000.ethernet-ffffffff:00, irq=45)
> > > > macb f802c000.ethernet eth1: Cadence MACB rev 0x0001010c at 0xf802c000
> > > > irq 41 (d8:c4:97:1c:9a:d7)
> > > > usbcore: registered new interface driver cdc_ether
> > > > usbcore: registered new interface driver cdc_ncm
> > > > usbcore: registered new interface driver cdc_mbim
> > > > ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> > > > ehci-platform: EHCI generic platform driver
> > > > ehci-atmel: EHCI Atmel driver
> > > > atmel-ehci 700000.ehci: EHCI Host Controller
> > > > atmel-ehci 700000.ehci: new USB bus registered, assigned bus number 1
> > > > atmel-ehci 700000.ehci: irq 43, io mem 0x00700000
> > > > atmel-ehci 700000.ehci: USB 2.0 started, EHCI 1.00
> > > > usb usb1: New USB device found, idVendor=1d6b, idProduct=0002, bcdDevice= 5.04
> > > > usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> > > > usb usb1: Product: EHCI Host Controller
> > > > usb usb1: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ehci_hcd
> > > > usb usb1: SerialNumber: 700000.ehci
> > > > hub 1-0:1.0: USB hub found
> > > > hub 1-0:1.0: 3 ports detected
> > > > ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> > > > ohci-platform: OHCI generic platform driver
> > > > ohci-atmel: OHCI Atmel driver
> > > > at91_ohci 600000.ohci: USB Host Controller
> > > > at91_ohci 600000.ohci: new USB bus registered, assigned bus number 2
> > > > at91_ohci 600000.ohci: irq 43, io mem 0x00600000
> > > > usb usb2: New USB device found, idVendor=1d6b, idProduct=0001, bcdDevice= 5.04
> > > > usb usb2: New USB device strings: Mfr=3, Product=2, SerialNumber=1
> > > > usb usb2: Product: USB Host Controller
> > > > usb usb2: Manufacturer: Linux 5.4.109-00033-ga88943c1e68 ohci_hcd
> > > > usb usb2: SerialNumber: at91
> > > > hub 2-0:1.0: USB hub found
> > > > hub 2-0:1.0: 3 ports detected
> > > > usbcore: registered new interface driver cdc_acm
> > > > cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
> > > > usbcore: registered new interface driver cdc_wdm
> > > > usbcore: registered new interface driver usbserial_generic
> > > > usbserial: USB Serial support registered for generic
> > > > usbcore: registered new interface driver option
> > > > usbserial: USB Serial support registered for GSM modem (1-port)
> > > > usbcore: registered new interface driver usb_serial_simple
> > > > usbserial: USB Serial support registered for carelink
> > > > usbserial: USB Serial support registered for zio
> > > > usbserial: USB Serial support registered for funsoft
> > > > usbserial: USB Serial support registered for flashloader
> > > > usbserial: USB Serial support registered for google
> > > > usbserial: USB Serial support registered for libtransistor
> > > > usbserial: USB Serial support registered for vivopay
> > > > usbserial: USB Serial support registered for moto_modem
> > > > usbserial: USB Serial support registered for motorola_tetra
> > > > usbserial: USB Serial support registered for novatel_gps
> > > > usbserial: USB Serial support registered for hp4x
> > > > usbserial: USB Serial support registered for suunto
> > > > usbserial: USB Serial support registered for siemens_mpi
> > > > rtc-rv8803 1-0032: registered as rtc0
> > > > i2c /dev entries driver
> > > > at91-reset fffffe00.rstc: Starting after wakeup
> > > > at91sam9_wdt: enabled (heartbeat=15 sec, nowayout=1)
> > > > atmel_aes f8038000.aes: version: 0x135
> > > > atmel_aes f8038000.aes: Atmel AES - Using dma1chan0, dma1chan1 for DMA transfers
> > > > atmel_sha f8034000.sha: version: 0x410
> > > > atmel_sha f8034000.sha: using dma1chan2 for DMA transfers
> > > > atmel_sha f8034000.sha: Atmel SHA1/SHA256/SHA224/SHA384/SHA512
> > > > atmel_tdes f803c000.tdes: version: 0x701
> > > > atmel_tdes f803c000.tdes: using dma1chan3, dma1chan4 for DMA transfers
> > > > atmel_tdes f803c000.tdes: Atmel DES/TDES
> > > > usbcore: registered new interface driver usbhid
> > > > usbhid: USB HID core driver
> > > > nand: device found, Manufacturer ID: 0x2c, Chip ID: 0xd3
> > > > nand: Micron MT29F8G08ABACAWP
> > > > nand: 1024 MiB, SLC, erase size: 256 KiB, page size: 4096, OOB size: 224
> > > > Bad block table found at page 262080, version 0x01
> > > > Bad block table found at page 262016, version 0x01
> > > > nand_read_bbt: bad block at 0x000000dc0000
> > > > nand_read_bbt: bad block at 0x00000e280000
> > > > nand_read_bbt: bad block at 0x000024f40000
> > > > nand_read_bbt: bad block at 0x000026ec0000
> > > > nand_read_bbt: bad block at 0x000027ec0000
> > > > nand_read_bbt: bad block at 0x00002f140000
> > > > nand_read_bbt: bad block at 0x000030ec0000
> > > > nand_read_bbt: bad block at 0x000033b40000
> > > > nand_read_bbt: bad block at 0x000038840000
> > > > 2 fixed-partitions partitions found on MTD device atmel_nand
> > > > Creating 2 MTD partitions on "atmel_nand":
> > > > 0x000000000000-0x000000040000 : "at91bootstrap"
> > > > 0x000000040000-0x000040000000 : "ubivols"
> > > > NET: Registered protocol family 10
> > > > Segment Routing with IPv6
> > > > sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
> > > > NET: Registered protocol family 17
> > > > 8021q: 802.1Q VLAN Support v1.8
> > > > Loading compiled-in X.509 certificates
> > > > Loaded X.509 cert 'EFR: efr.de: a54308f075327fb6c3a6fb687fdabc10ce4c51c6'
> > > > Key type ._fscrypt registered
> > > > Key type .fscrypt registered
> > > > ksz8795-switch spi0.0: active low/falling IRQ
> > > > libphy: dsa slave smi: probed
> > > > ksz8795-switch spi0.0 han (uninitialized): PHY [dsa-0.0:00] driver
> > > > [Micrel KSZ886X Switch]
> > > > ksz8795-switch spi0.0 cls (uninitialized): PHY [dsa-0.0:01] driver
> > > > [Micrel KSZ886X Switch]
> > > > ksz8795-switch spi0.0: Using legacy PHYLIB callbacks. Please migrate to PHYLINK!
> > > > DSA: tree 0 setup
> > > > ubi0: attaching mtd1
> > > > usb 2-3: new full-speed USB device number 2 using at91_ohci
> > > > usb 2-3: New USB device found, idVendor=08e6, idProduct=3437, bcdDevice= 2.01
> > > > usb 2-3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
> > > > usb 2-3: Product: USB SmartCard Reader
> > > > usb 2-3: Manufacturer: Gemalto
> > > > random: crng init done
> > > > ubi0: scanning is finished
> > > > ubi0: attached mtd1 (name "ubivols", size 1023 MiB)
> > > > ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
> > > > ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
> > > > ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
> > > > ubi0: good PEBs: 4082, bad PEBs: 13, corrupted PEBs: 0
> > > > ubi0: user volume: 5, internal volumes: 1, max. volumes count: 128
> > > > ubi0: max/mean erase counter: 118/11, WL threshold: 4096, image
> > > > sequence number: 921361235
> > > > ubi0: available PEBs: 0, total reserved PEBs: 4082, PEBs reserved for
> > > > bad PEB handling: 67
> > > > ubi0: background thread "ubi_bgt0d" started, PID 617
> > > > rtc-rv8803 1-0032: setting system clock to 2021-10-09T12:16:01 UTC (1633781761)
> > > > UBIFS (ubi0:4): Mounting in authenticated mode
> > > > UBIFS (ubi0:4): recovery needed
> > > > VFS: Cannot open root device "ubi0:rootfs" or ubi0:rootfs: error -1
> > >
> > > Hmm. -1 is -EPERM.
> > > So some authentification check fails.
> > >
> > > Can you find out which -EPERM in fs/ubifs this is?
> > > E.g. by adding a printk() before the return.
> > > Maybe this gives us a clue.
> >
> > I wasn't able to reproduce the crash in a stripped down format, but re-started
> > the full-blown test with the printk()-s before the EPREM-s.
> > It failed again this morning and here is the result:
> >
> > The one yielding is from authenticate_sleb() from fs/ubifs/replay.c,
> > when ubifs_check_hmac() fails:
> >
> > err = ubifs_check_hmac(c, auth->hmac,
> > if (err) {
> >         err = -EPERM;
> >              goto out;
> > }
> >
> > >
> > > > Please append a correct "root=" boot option; here are the available partitions:
> > > > Kernel panic - not syncing: VFS: Unable to mount root fs on ubi0:rootfs
> > > > CPU: 0 PID: 1 Comm: swapper Not tainted 5.4.109-00033-ga88943c1e68 #1
> > > > Hardware name: Atmel SAMA5
> > > > [<c010babc>] (unwind_backtrace) from [<c010a8d0>] (show_stack+0x10/0x14)
> > > > [<c010a8d0>] (show_stack) from [<c0569970>] (panic+0xfc/0x2e8)
> > > > [<c0569970>] (panic) from [<c0801598>] (mount_block_root+0x268/0x2a4)
> > > > [<c0801598>] (mount_block_root) from [<c0801674>] (prepare_namespace+0x9c/0x184)
> > > > [<c0801674>] (prepare_namespace) from [<c056b774>] (kernel_init+0x8/0x108)
> > > > [<c056b774>] (kernel_init) from [<c01010e8>] (ret_from_fork+0x14/0x2c)
> > > > Exception stack(0xc7829fb0 to 0xc7829ff8)
> > > > 9fa0:                                     00000000 00000000 00000000 00000000
> > > > 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
> > > > 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000
> > > > ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on
> > > > ubi0:rootfs ]---
> > > > RomBOOT
> > > > RomBOOT
> > > >
> > > >>
> > > >> 5.4 is not fresh. Can you use a more recent kernel?
> > > >
> > > > We are tracking the latest patches on 5.4, but will try whether a
> > > > rebase to 5.10 is straight-forward or not.
> > > > Or at least port the minimal changes which are needed to re-create the crash.
> > > >
> > > > But first, I will try to reproduce the crash with a stripped down
> > > > program, because with the current tests,
> > > > it can take anywhere between 20-500 iterations of power-cuts with the
> > > > full business logic to trigger the crash.
> > > > (5m ON 30s OFF)
> > >
> > > Thanks,
> > > //richard
> >
> > Best Regards,
> > Krist?f


From richard at nod.at  Thu Oct 21 10:44:26 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 21 Oct 2021 19:44:26 +0200 (CEST)
Subject: UBIFS panic during brown-out
In-Reply-To: <CADBnMviZDXD4p6U4fPDsMFsY1OJYEcjkNGTXDRbbM0mKDVpaAQ@mail.gmail.com>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
 <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
 <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>
 <1040411488.65265.1634045778705.JavaMail.zimbra@nod.at>
 <CADBnMvidNZEiJfSTLe-rj+V0N=EtW8jTrYXzc2KRJKNS-zkCjg@mail.gmail.com>
 <CADBnMvhCmNQsYRVAveuf=Ri820bLyLdcrA71Nywh0mVL+X8Fng@mail.gmail.com>
 <CADBnMviZDXD4p6U4fPDsMFsY1OJYEcjkNGTXDRbbM0mKDVpaAQ@mail.gmail.com>
Message-ID: <1035601262.21954.1634838266590.JavaMail.zimbra@nod.at>

Kristof,

----- Urspr?ngliche Mail -----
> Von: "Kristof Havasi" <havasiefr at gmail.com>
> An: "richard" <richard at nod.at>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>
> Gesendet: Donnerstag, 21. Oktober 2021 17:33:15
> Betreff: Re: UBIFS panic during brown-out

> Dear Richard,
> 
> I noticed that I forgot to Cc linux-mtd from the previous emails.
> 
> Latest update: we could reproduce the bug with a v5.10 port.
> The same EPERM error is hit.
> 
> Happy to hear any hints on how I can support in fixing this issue.

so I fear you found a bug in the UBIFS auth code.
Is it possible to share the filesystem and they keymaterial with me?

Thanks,
//richard


From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:16 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:16 +0800
Subject: [RFC,v3 0/5] Add driver for Mediatek SPI Nand and HW ECC controller 
Message-ID: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>

Add a driver for Mediatek SPI Nand and HW ECC controller

The Mediatek SPI Nand controller can support multiple SPI protocols,
which can support other SPI device in theory. And the SPI Nand controlelr
can cowork with the HW ECC engine for high performance at the pipelined
ecc case.

The RFC patch v3 realize the HW ECC engine in pipelined case.

The RFC patch v1 and v2 only try to get nand info and ecc status
in spi driver. However, this can be resolved by pipelined ECC design.
Only take mt7622 board for dts node example.

Xiangsheng Hou (5):
  mtd: ecc: move mediatek HW ECC driver
  mtd: ecc: realize Mediatek HW ECC driver
  spi: add Mediatek SPI Nand controller driver
  arm64: dts: add snfi node for spi nand
  mtd: spinand: skip set/get oob data bytes when interleaved case

 arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts  |   18 +
 arch/arm64/boot/dts/mediatek/mt7622.dtsi      |   13 +
 drivers/mtd/nand/Kconfig                      |    9 +
 drivers/mtd/nand/Makefile                     |    1 +
 drivers/mtd/nand/core.c                       |   10 +-
 drivers/mtd/nand/ecc.c                        |   88 ++
 drivers/mtd/nand/{raw => }/mtk_ecc.c          |  490 ++++++-
 drivers/mtd/nand/raw/Kconfig                  |    1 +
 drivers/mtd/nand/raw/Makefile                 |    2 +-
 drivers/mtd/nand/raw/mtk_nand.c               |    2 +-
 drivers/mtd/nand/spi/core.c                   |    6 +-
 drivers/spi/Kconfig                           |   11 +
 drivers/spi/Makefile                          |    1 +
 drivers/spi/spi-mtk-snfi.c                    | 1234 +++++++++++++++++
 .../nand/raw => include/linux/mtd}/mtk_ecc.h  |   38 +
 include/linux/mtd/nand.h                      |   11 +
 16 files changed, 1927 insertions(+), 8 deletions(-)
 rename drivers/mtd/nand/{raw => }/mtk_ecc.c (52%)
 create mode 100644 drivers/spi/spi-mtk-snfi.c
 rename {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h (64%)

-- 
2.25.1



From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:19 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:19 +0800
Subject: [RFC,v3 3/5] spi: add Mediatek SPI Nand controller driver
In-Reply-To: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
References: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211022024021.14665-4-xiangsheng.hou@mediatek.com>

This version the SPI driver cowork with MTK pipelined
HW ECC engine.

Signed-off-by: Xiangsheng Hou <xiangsheng.hou at mediatek.com>
---
 drivers/spi/Kconfig        |   11 +
 drivers/spi/Makefile       |    1 +
 drivers/spi/spi-mtk-snfi.c | 1234 ++++++++++++++++++++++++++++++++++++
 3 files changed, 1246 insertions(+)
 create mode 100644 drivers/spi/spi-mtk-snfi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 83e352b0c8f9..6768cd510f77 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -514,6 +514,17 @@ config SPI_MT65XX
 	  say Y or M here.If you are not sure, say N.
 	  SPI drivers for Mediatek MT65XX and MT81XX series ARM SoCs.
 
+config SPI_MTK_SNFI
+	tristate "MediaTek SPI NAND interface"
+	depends on MTD
+	select MTD_SPI_NAND
+	select MTD_NAND_ECC_MTK
+	help
+	  This selects the SPI NAND FLASH interface(SNFI),
+	  which could be found on MediaTek Soc.
+	  Say Y or M here.If you are not sure, say N.
+	  Note Parallel Nand and SPI NAND is alternative on MediaTek SoCs.
+
 config SPI_MT7621
 	tristate "MediaTek MT7621 SPI Controller"
 	depends on RALINK || COMPILE_TEST
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 699db95c8441..0435624905d9 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mpc512x-psc.o
 obj-$(CONFIG_SPI_MPC52xx_PSC)		+= spi-mpc52xx-psc.o
 obj-$(CONFIG_SPI_MPC52xx)		+= spi-mpc52xx.o
 obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o
+obj-$(CONFIG_SPI_MTK_SNFI)              += spi-mtk-snfi.o
 obj-$(CONFIG_SPI_MT7621)		+= spi-mt7621.o
 obj-$(CONFIG_SPI_MTK_NOR)		+= spi-mtk-nor.o
 obj-$(CONFIG_SPI_MXIC)			+= spi-mxic.o
diff --git a/drivers/spi/spi-mtk-snfi.c b/drivers/spi/spi-mtk-snfi.c
new file mode 100644
index 000000000000..f4955e64acdc
--- /dev/null
+++ b/drivers/spi/spi-mtk-snfi.c
@@ -0,0 +1,1234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for MediaTek SPI memory interface
+ *
+ * Copyright (C) 2021 MediaTek Inc.
+ * Authors:	Xiangsheng Hou	<xiangsheng.hou at mediatek.com>
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/mtk_ecc.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi-mem.h>
+
+/* Registers used by the driver */
+#define NFI_CNFG		0x00
+#define		CNFG_DMA			BIT(0)
+#define		CNFG_READ_EN		BIT(1)
+#define		CNFG_DMA_BURST_EN	BIT(2)
+#define		CNFG_HW_ECC_EN		BIT(8)
+#define		CNFG_AUTO_FMT_EN	BIT(9)
+#define		CNFG_OP_CUST		GENMASK(14, 13)
+#define NFI_PAGEFMT		(0x04)
+#define		PAGEFMT_SPARE_MASK	GENMASK(21, 16)
+#define		PAGEFMT_SPARE_SHIFT		(16)
+#define		PAGEFMT_FDM_ECC_SHIFT	(12)
+#define		PAGEFMT_FDM_SHIFT	(8)
+#define		PAGEFMT_FDM_MASK	GENMASK(11, 8)
+#define		PAGEFMT_SEC_SEL_512	BIT(2)
+#define		PAGEFMT_512_2K		(0)
+#define		PAGEFMT_2K_4K		(1)
+#define		PAGEFMT_4K_8K		(2)
+#define		PAGEFMT_8K_16K		(3)
+#define		PAGEFMT_PAGE_MASK	GENMASK(1, 0)
+#define NFI_CON			0x08
+#define		CON_FIFO_FLUSH		BIT(0)
+#define		CON_NFI_RST			BIT(1)
+#define		CON_BRD				BIT(8)
+#define		CON_BWR				BIT(9)
+#define		CON_SEC_SHIFT		12
+#define		CON_SEC_MASK		GENMASK(16, 12)
+#define NFI_INTR_EN		0x10
+#define		INTR_CUS_PROG_EN	BIT(7)
+#define		INTR_CUS_READ_EN	BIT(8)
+#define		INTR_IRQ_EN			BIT(31)
+#define NFI_INTR_STA	0x14
+#define NFI_CMD			0x20
+#define		CMD_DUMMY			0x0
+#define NFI_STRDATA		0x40
+#define		STAR_EN				BIT(0)
+#define NFI_STA			0x60
+#define		NFI_FSM_MASK		GENMASK(19, 16)
+#define		STA_EMP_PAGE		BIT(12)
+#define NFI_ADDRCNTR	0x70
+#define		CNTR_MASK			GENMASK(16, 12)
+#define		ADDRCNTR_SEC_SHIFT	12
+#define		ADDRCNTR_SEC(val) \
+		(((val) & CNTR_MASK) >> ADDRCNTR_SEC_SHIFT)
+#define NFI_STRADDR		0x80
+#define NFI_BYTELEN		0x84
+#define NFI_FDML(x)		(0xA0 + (x) * sizeof(u32) * 2)
+#define NFI_FDMM(x)		(0xA4 + (x) * sizeof(u32) * 2)
+#define NFI_MASTERSTA	0x224
+#define		AHB_BUS_BUSY		BIT(1)
+#define		BUS_BUSY			BIT(0)
+#define SNFI_MAC_OUTL	0x504
+#define SNFI_MAC_INL	0x508
+#define SNFI_RD_CTL2	0x510
+#define		RD_CMD_MASK			0x00ff
+#define		RD_DUMMY_SHIFT		8
+#define SNFI_RD_CTL3			0x514
+#define		RD_ADDR_MASK		0xffff
+#define SNFI_MISC_CTL	0x538
+#define		RD_MODE_MASK		GENMASK(18, 16)
+#define		LATCH_LAT_MASK		GENMASK(9, 8)
+#define		LATCH_LAT_SHIFT		8
+#define		RD_MODE_X2			BIT(16)
+#define		RD_MODE_X4			BIT(17)
+#define		RD_MODE_DQUAL		BIT(18)
+#define		RD_CUSTOM_EN		BIT(6)
+#define		WR_CUSTOM_EN		BIT(7)
+#define		WR_X4_EN			BIT(20)
+#define		SW_RST				BIT(28)
+#define SNFI_MISC_CTL2	0x53c
+#define		WR_LEN_SHIFT		16
+#define SNFI_PG_CTL1	0x524
+#define		WR_LOAD_CMD_MASK	GENMASK(15, 8)
+#define		WR_LOAD_CMD_SHIFT	8
+#define SNFI_PG_CTL2	0x528
+#define		WR_LOAD_ADDR_MASK	GENMASK(15, 0)
+#define SNFI_MAC_CTL	0x500
+#define		MAC_WIP				BIT(0)
+#define		MAC_WIP_READY		BIT(1)
+#define		MAC_TRIG			BIT(2)
+#define		MAC_EN				BIT(3)
+#define		MAC_SIO_SEL			BIT(4)
+#define SNFI_DLY_CTL3	0x548
+#define		SAM_DLY_MASK		GENMASK(5, 0)
+#define SNFI_STA_CTL1	0x550
+#define		CUS_PROG_DONE		BIT(28)
+#define		CUS_READ_DONE		BIT(27)
+#define		SPI_STATE			GENMASK(3, 0)
+#define SNFI_CNFG		0x55c
+#define		SNFI_MODE_EN		BIT(0)
+#define SNFI_GPRAM_DATA	0x800
+#define		SNFI_GPRAM_MAX_LEN	160
+
+#define MTK_SNFI_TIMEOUT			500000
+#define MTK_SNFI_RESET_TIMEOUT		1000000
+#define MTK_SNFI_AUTOSUSPEND_DELAY	1000
+#define KB(x)						((x) * 1024UL)
+
+#define MTK_NFI_MIN_SPARE			(16)
+
+/* supported spare size of each IP */
+static const u8 spare_size_mt7986[] = {
+	16, 26, 27, 28, 32, 36, 40, 44, 48, 49, 50, 51, 52, 62, 61, 63, 64, 67,
+	74
+};
+
+struct mtk_snfi_caps {
+	const u8 *spare_size;
+	u8 num_spare_size;
+	u8 pageformat_spare_shift;
+	u32 max_sector_size;
+};
+
+struct mtk_snfi {
+	struct clk *nfi_clk;
+	struct clk *snfi_clk;
+	struct clk *hclk;
+	struct device *dev;
+	struct completion done;
+
+	const struct mtk_snfi_caps *caps;
+
+	struct {
+		u32 page_size;
+		u32 spare_per_sector;
+		u32 spare_idx;
+		struct nand_ecc_engine *engine;
+		bool enabled;
+		u32 sectors;
+	} ecc;
+
+	u32 fdm_size;
+	u32 fdm_ecc_size;
+
+	u32 sample_delay;
+	u32 read_latency;
+
+	void *tx_buf;
+	dma_addr_t dma_addr;
+	void __iomem *regs;
+};
+
+static void mtk_snfi_mac_enable(struct mtk_snfi *snfi)
+{
+	u32 val;
+
+	val = readl(snfi->regs + SNFI_MAC_CTL);
+	val &= ~MAC_SIO_SEL;
+	val |= MAC_EN;
+
+	writel(val, snfi->regs + SNFI_MAC_CTL);
+}
+
+static int mtk_snfi_mac_trigger(struct mtk_snfi *snfi)
+{
+	u32 val;
+	int ret = 0;
+
+	val = readl(snfi->regs + SNFI_MAC_CTL);
+	val |= MAC_TRIG;
+	writel(val, snfi->regs + SNFI_MAC_CTL);
+
+	ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, val,
+					val & MAC_WIP_READY, 0,
+					MTK_SNFI_TIMEOUT);
+	if (ret < 0) {
+		dev_err(snfi->dev, "wait for wip ready timeout\n");
+		return -EIO;
+	}
+
+	ret = readl_poll_timeout_atomic(snfi->regs + SNFI_MAC_CTL, val,
+					!(val & MAC_WIP), 0,
+					MTK_SNFI_TIMEOUT);
+	if (ret < 0) {
+		dev_err(snfi->dev, "wait for flash update finish timeout\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void mtk_snfi_mac_disable(struct mtk_snfi *snfi)
+{
+	u32 val;
+
+	val = readl(snfi->regs + SNFI_MAC_CTL);
+	val &= ~(MAC_TRIG | MAC_EN);
+	writel(val, snfi->regs + SNFI_MAC_CTL);
+}
+
+static int mtk_snfi_mac_op(struct mtk_snfi *snfi)
+{
+	int ret = 0;
+
+	mtk_snfi_mac_enable(snfi);
+	ret = mtk_snfi_mac_trigger(snfi);
+	mtk_snfi_mac_disable(snfi);
+
+	return ret;
+}
+
+static inline void mtk_snfi_read_fdm(struct mtk_snfi *snfi,
+			const struct spi_mem_op *op)
+{
+	u32 vall, valm;
+	u8 *oobptr = op->data.buf.in;
+	int i, j;
+
+	oobptr += snfi->ecc.page_size;
+	for (i = 0; i < snfi->ecc.sectors; i++) {
+		vall = readl(snfi->regs + NFI_FDML(i));
+		valm = readl(snfi->regs + NFI_FDMM(i));
+
+		for (j = 0; j < snfi->fdm_size; j++)
+			oobptr[j] = (j >= 4 ? valm : vall) >> ((j % 4) * 8);
+
+		oobptr += snfi->fdm_size;
+	}
+}
+
+static inline void mtk_snfi_write_fdm(struct mtk_snfi *snfi,
+			const struct spi_mem_op *op)
+{
+	const u8 *oobptr = op->data.buf.out;
+	u32 vall, valm;
+	int i, j;
+
+	oobptr += snfi->ecc.page_size;
+	for (i = 0; i < snfi->ecc.sectors; i++) {
+		vall = 0;
+		valm = 0;
+		for (j = 0; j < 8; j++) {
+			if (j < 4)
+				vall |= (j < snfi->fdm_size ? oobptr[j] : 0xff)
+						<< (j * 8);
+			else
+				valm |= (j < snfi->fdm_size ? oobptr[j] : 0xff)
+						<< ((j - 4) * 8);
+		}
+		writel(vall, snfi->regs + NFI_FDML(i));
+		writel(valm, snfi->regs + NFI_FDMM(i));
+
+		oobptr += snfi->fdm_size;
+	}
+}
+
+static irqreturn_t mtk_snfi_irq(int irq, void *id)
+{
+	struct mtk_snfi *snfi = id;
+	u32 sta, ien;
+
+	sta = readl(snfi->regs + NFI_INTR_STA);
+	ien = readl(snfi->regs + NFI_INTR_EN);
+
+	if (!(sta & ien))
+		return IRQ_NONE;
+
+	writel(0, snfi->regs + NFI_INTR_EN);
+	complete(&snfi->done);
+
+	return IRQ_HANDLED;
+}
+
+static int mtk_snfi_enable_clk(struct device *dev, struct mtk_snfi *snfi)
+{
+	int ret;
+
+	ret = clk_prepare_enable(snfi->nfi_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable nfi clk\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(snfi->snfi_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable snfi clk\n");
+		clk_disable_unprepare(snfi->nfi_clk);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(snfi->hclk);
+	if (ret) {
+		dev_err(dev, "failed to enable hclk\n");
+		clk_disable_unprepare(snfi->nfi_clk);
+		clk_disable_unprepare(snfi->snfi_clk);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mtk_snfi_disable_clk(struct mtk_snfi *snfi)
+{
+	clk_disable_unprepare(snfi->nfi_clk);
+	clk_disable_unprepare(snfi->snfi_clk);
+	clk_disable_unprepare(snfi->hclk);
+}
+
+static int mtk_snfi_reset(struct mtk_snfi *snfi)
+{
+	u32 val;
+	int ret;
+
+	val = readl(snfi->regs + SNFI_MISC_CTL) | SW_RST;
+	writel(val, snfi->regs + SNFI_MISC_CTL);
+
+	ret = readw_poll_timeout(snfi->regs + SNFI_STA_CTL1, val,
+				 !(val & SPI_STATE), 0,
+				 MTK_SNFI_RESET_TIMEOUT);
+	if (ret) {
+		dev_warn(snfi->dev, "spi state not idle 0x%x\n", val);
+		return ret;
+	}
+
+	val = readl(snfi->regs + SNFI_MISC_CTL);
+	val &= ~SW_RST;
+	writel(val, snfi->regs + SNFI_MISC_CTL);
+
+	writew(CON_FIFO_FLUSH | CON_NFI_RST, snfi->regs + NFI_CON);
+	ret = readw_poll_timeout(snfi->regs + NFI_STA, val,
+				 !(val & NFI_FSM_MASK), 0,
+				 MTK_SNFI_RESET_TIMEOUT);
+	if (ret) {
+		dev_warn(snfi->dev, "nfi fsm not idle 0x%x\n", val);
+		return ret;
+	}
+
+	val = readl(snfi->regs + NFI_STRDATA);
+	val &= ~STAR_EN;
+	writew(val, snfi->regs + NFI_STRDATA);
+
+	return 0;
+}
+
+static int mtk_snfi_init(struct mtk_snfi *snfi)
+{
+	int ret;
+	u32 val;
+
+	ret = mtk_snfi_reset(snfi);
+	if (ret)
+		return ret;
+
+	writel(SNFI_MODE_EN, snfi->regs + SNFI_CNFG);
+
+	if (snfi->sample_delay) {
+		val = readl(snfi->regs + SNFI_DLY_CTL3);
+		val &= ~SAM_DLY_MASK;
+		val |= snfi->sample_delay;
+		writel(val, snfi->regs + SNFI_DLY_CTL3);
+	}
+
+	if (snfi->read_latency) {
+		val = readl(snfi->regs + SNFI_MISC_CTL);
+		val &= ~LATCH_LAT_MASK;
+		val |= (snfi->read_latency << LATCH_LAT_SHIFT);
+		writel(val, snfi->regs + SNFI_MISC_CTL);
+	}
+
+	return 0;
+}
+
+static void mtk_snfi_prepare_for_tx(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op)
+{
+	u32 val;
+
+	val = readl(snfi->regs + SNFI_PG_CTL1);
+	val &= ~WR_LOAD_CMD_MASK;
+	val |= op->cmd.opcode << WR_LOAD_CMD_SHIFT;
+	writel(val, snfi->regs + SNFI_PG_CTL1);
+
+	writel(op->addr.val & WR_LOAD_ADDR_MASK,
+		   snfi->regs + SNFI_PG_CTL2);
+
+	val = readl(snfi->regs + SNFI_MISC_CTL);
+	val |= WR_CUSTOM_EN;
+	if (op->data.buswidth == 4)
+		val |= WR_X4_EN;
+	writel(val, snfi->regs + SNFI_MISC_CTL);
+
+	val = snfi->ecc.page_size +
+		  snfi->ecc.sectors * snfi->ecc.spare_per_sector;
+
+	writel(val << WR_LEN_SHIFT,
+		snfi->regs + SNFI_MISC_CTL2);
+	writel(INTR_CUS_PROG_EN | INTR_IRQ_EN,
+		snfi->regs + NFI_INTR_EN);
+}
+
+static void mtk_snfi_prepare_for_rx(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op)
+{
+	u32 val, dummy_cycle;
+
+	dummy_cycle = (op->dummy.nbytes << 3) >>
+				  (ffs(op->dummy.buswidth) - 1);
+	val = (op->cmd.opcode & RD_CMD_MASK) |
+		  (dummy_cycle << RD_DUMMY_SHIFT);
+	writel(val, snfi->regs + SNFI_RD_CTL2);
+
+	writel(op->addr.val & RD_ADDR_MASK,
+		   snfi->regs + SNFI_RD_CTL3);
+
+	val = readl(snfi->regs + SNFI_MISC_CTL);
+	val |= RD_CUSTOM_EN;
+	val &= ~RD_MODE_MASK;
+	if (op->data.buswidth == 4)
+		val |= RD_MODE_X4 | RD_MODE_DQUAL;
+	else if (op->data.buswidth == 2)
+		val |= RD_MODE_X2 | RD_MODE_DQUAL;
+
+	writel(val, snfi->regs + SNFI_MISC_CTL);
+
+	val = snfi->ecc.page_size +
+		  snfi->ecc.sectors * snfi->ecc.spare_per_sector;
+	writel(val, snfi->regs + SNFI_MISC_CTL2);
+
+	writel(INTR_CUS_READ_EN | INTR_IRQ_EN,
+		   snfi->regs + NFI_INTR_EN);
+}
+
+static int mtk_snfi_prepare(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op, bool rx)
+{
+	int ret;
+	dma_addr_t addr;
+	u32 val;
+
+	addr = dma_map_single(snfi->dev,
+				op->data.buf.in, op->data.nbytes,
+				rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+	ret = dma_mapping_error(snfi->dev, addr);
+	if (ret) {
+		dev_err(snfi->dev, "dma mapping error\n");
+		return -EINVAL;
+	}
+
+	snfi->dma_addr = addr;
+	writel(lower_32_bits(addr), snfi->regs + NFI_STRADDR);
+
+	if (snfi->ecc.enabled && !rx)
+		mtk_snfi_write_fdm(snfi, op);
+
+	val = readw(snfi->regs + NFI_CNFG);
+	val |= CNFG_DMA | CNFG_DMA_BURST_EN | CNFG_OP_CUST;
+	val |= rx ? CNFG_READ_EN : 0;
+
+	if (snfi->ecc.enabled)
+		val |= CNFG_HW_ECC_EN | CNFG_AUTO_FMT_EN;
+
+	writew(val, snfi->regs + NFI_CNFG);
+
+	writel(snfi->ecc.sectors << CON_SEC_SHIFT, snfi->regs + NFI_CON);
+
+	init_completion(&snfi->done);
+
+	/* trigger state machine to custom op mode */
+	writel(CMD_DUMMY, snfi->regs + NFI_CMD);
+
+	if (rx)
+		mtk_snfi_prepare_for_rx(snfi, op);
+	else
+		mtk_snfi_prepare_for_tx(snfi, op);
+
+	return 0;
+}
+
+static void mtk_snfi_trigger(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op, bool rx)
+{
+	u32 val;
+
+	val = readl(snfi->regs + NFI_CON);
+	val |= rx ? CON_BRD : CON_BWR;
+	writew(val, snfi->regs + NFI_CON);
+
+	writew(STAR_EN, snfi->regs + NFI_STRDATA);
+}
+
+static int mtk_snfi_wait_done(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op, bool rx)
+{
+	u32 val;
+	int ret;
+
+	ret = wait_for_completion_timeout(&snfi->done, msecs_to_jiffies(500));
+	if (!ret) {
+		dev_err(snfi->dev, "wait for %d completion done timeout\n", rx);
+		return -ETIMEDOUT;
+	}
+
+	if (rx) {
+		ret = readl_poll_timeout_atomic(snfi->regs + NFI_BYTELEN, val,
+				ADDRCNTR_SEC(val) >= snfi->ecc.sectors, 0,
+					MTK_SNFI_TIMEOUT);
+		if (ret < 0) {
+			dev_err(snfi->dev, "wait for read sector count timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		ret = readl_poll_timeout_atomic(snfi->regs + NFI_MASTERSTA, val,
+					!(val & (AHB_BUS_BUSY | BUS_BUSY)),
+					0, MTK_SNFI_TIMEOUT);
+		if (ret) {
+			dev_err(snfi->dev, "wait for bus busy timeout\n");
+			return -ETIMEDOUT;
+		}
+
+	} else {
+		ret = readl_poll_timeout_atomic(snfi->regs + NFI_ADDRCNTR, val,
+					ADDRCNTR_SEC(val) >= snfi->ecc.sectors,
+					0, MTK_SNFI_TIMEOUT);
+		if (ret) {
+			dev_err(snfi->dev, "wait for program sector count timeout\n");
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+static void mtk_snfi_complete(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op, bool rx)
+{
+	u32 val;
+
+	dma_unmap_single(snfi->dev,
+					 snfi->dma_addr, op->data.nbytes,
+					 rx ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
+
+	if (snfi->ecc.enabled && rx)
+		mtk_snfi_read_fdm(snfi, op);
+
+	val = readl(snfi->regs + SNFI_MISC_CTL);
+	val &= rx ? ~RD_CUSTOM_EN : ~WR_CUSTOM_EN;
+	writel(val, snfi->regs + SNFI_MISC_CTL);
+
+	val = readl(snfi->regs + SNFI_STA_CTL1);
+	val |= rx ? CUS_READ_DONE : CUS_PROG_DONE;
+	writew(val, snfi->regs + SNFI_STA_CTL1);
+	val &= rx ? ~CUS_READ_DONE : ~CUS_PROG_DONE;
+	writew(val, snfi->regs + SNFI_STA_CTL1);
+
+	/* Disable interrupt */
+	val = readl(snfi->regs + NFI_INTR_EN);
+	val &= rx ? ~INTR_CUS_READ_EN : ~INTR_CUS_PROG_EN;
+	writew(val, snfi->regs + NFI_INTR_EN);
+
+	writew(0, snfi->regs + NFI_CNFG);
+	writew(0, snfi->regs + NFI_CON);
+}
+
+static int mtk_snfi_transfer_dma(struct mtk_snfi *snfi,
+			   const struct spi_mem_op *op, bool rx)
+{
+	int ret;
+
+	ret = mtk_snfi_prepare(snfi, op, rx);
+	if (ret)
+		return ret;
+
+	mtk_snfi_trigger(snfi, op, rx);
+
+	ret = mtk_snfi_wait_done(snfi, op, rx);
+
+	mtk_snfi_complete(snfi, op, rx);
+
+	return ret;
+}
+
+static int mtk_snfi_transfer_mac(struct mtk_snfi *snfi,
+			    const u8 *txbuf, u8 *rxbuf,
+			    const u32 txlen, const u32 rxlen)
+{
+	u32 i, j, val, tmp;
+	u8 *p_tmp = (u8 *)(&tmp);
+	u32 addr_offset = 0;
+	int ret = 0;
+
+	/* Move tx data to gpram in snfi mac mode */
+	for (i = 0; i < txlen; ) {
+		for (j = 0, tmp = 0; i < txlen && j < 4; i++, j++)
+			p_tmp[j] = txbuf[i];
+
+		writel(tmp, snfi->regs + SNFI_GPRAM_DATA + addr_offset);
+		addr_offset += 4;
+	}
+
+	writel(txlen, snfi->regs + SNFI_MAC_OUTL);
+	writel(rxlen, snfi->regs + SNFI_MAC_INL);
+
+	ret = mtk_snfi_mac_op(snfi);
+	if (ret) {
+		dev_warn(snfi->dev, "snfi mac operation fail\n");
+		return ret;
+	}
+
+	/* Get tx data from gpram in snfi mac mode */
+	if (rxlen)
+		for (i = 0, addr_offset = rounddown(txlen, 4); i < rxlen; ) {
+			val = readl(snfi->regs +
+					    SNFI_GPRAM_DATA + addr_offset);
+			for (j = 0; i < rxlen && j < 4; i++, j++, rxbuf++) {
+				if (i == 0)
+					j = txlen % 4;
+				*rxbuf = (val >> (j * 8)) & 0xff;
+			}
+			addr_offset += 4;
+		}
+
+	return ret;
+}
+
+static int mtk_snfi_exec_op(struct spi_mem *mem,
+			    const struct spi_mem_op *op)
+{
+	struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
+	u8 *buf, *txbuf = snfi->tx_buf, *rxbuf = NULL;
+	u32 txlen = 0, rxlen = 0;
+	int i, ret = 0;
+	bool rx;
+
+	rx = op->data.dir == SPI_MEM_DATA_IN;
+
+	ret = mtk_snfi_reset(snfi);
+	if (ret) {
+		dev_warn(snfi->dev, "reset snfi fail\n");
+		return ret;
+	}
+
+	/*
+	 * If tx/rx data buswidth is not 0/1, use snfi DMA mode.
+	 * Otherwise, use snfi mac mode.
+	 */
+	if ((op->data.buswidth != 1) && (op->data.buswidth != 0)) {
+		ret = mtk_snfi_transfer_dma(snfi, op, rx);
+		if (ret)
+			dev_warn(snfi->dev, "snfi dma transfer %d fail %d\n",
+					 rx, ret);
+		return ret;
+	}
+
+	txbuf[txlen++] = op->cmd.opcode;
+
+	if (op->addr.nbytes)
+		for (i = 0; i < op->addr.nbytes; i++)
+			txbuf[txlen++] = op->addr.val >>
+					(8 * (op->addr.nbytes - i - 1));
+
+	txlen += op->dummy.nbytes;
+
+	if (op->data.dir == SPI_MEM_DATA_OUT) {
+		buf = (u8 *)op->data.buf.out;
+		for (i = 0; i < op->data.nbytes; i++)
+			txbuf[txlen++] = buf[i];
+	}
+
+	if (op->data.dir == SPI_MEM_DATA_IN) {
+		rxbuf = (u8 *)op->data.buf.in;
+		rxlen = op->data.nbytes;
+	}
+
+	ret = mtk_snfi_transfer_mac(snfi, txbuf, rxbuf, txlen, rxlen);
+	if (ret)
+		dev_warn(snfi->dev, "snfi mac transfer %d fail %d\n",
+				 op->data.dir, ret);
+
+	return ret;
+}
+
+static int mtk_snfi_check_buswidth(u8 width)
+{
+	switch (width) {
+	case 1:
+	case 2:
+	case 4:
+		return 0;
+
+	default:
+		break;
+	}
+
+	return -ENOTSUPP;
+}
+
+static bool mtk_snfi_supports_op(struct spi_mem *mem,
+				 const struct spi_mem_op *op)
+{
+	struct mtk_snfi *snfi = spi_controller_get_devdata(mem->spi->master);
+	int ret = 0;
+
+	if (!spi_mem_default_supports_op(mem, op))
+		return false;
+
+	if (op->cmd.buswidth != 1)
+		return false;
+
+	/*
+	 * For one operation will use snfi mac mode when data
+	 * buswidth is 0/1. However, the HW ECC engine can not
+	 * be used in mac mode.
+	 */
+	if (snfi->ecc.enabled && op->data.buswidth == 1 &&
+			op->data.nbytes >= SNFI_GPRAM_MAX_LEN)
+		return false;
+
+	switch (op->data.dir) {
+	/* For spi mem data in, can support 1/2/4 buswidth */
+	case SPI_MEM_DATA_IN:
+		if (op->addr.nbytes)
+			ret |= mtk_snfi_check_buswidth(op->addr.buswidth);
+
+		if (op->dummy.nbytes)
+			ret |= mtk_snfi_check_buswidth(op->dummy.buswidth);
+
+		if (op->data.nbytes)
+			ret |= mtk_snfi_check_buswidth(op->data.buswidth);
+
+		if (ret)
+			return false;
+
+		break;
+	case SPI_MEM_DATA_OUT:
+		/*
+		 * For spi mem data out, can support 0/1 buswidth
+		 * for addr/dummy and 1/4 buswidth for data.
+		 */
+		if ((op->addr.buswidth != 0) && (op->addr.buswidth != 1))
+			return false;
+
+		if ((op->dummy.buswidth != 0) && (op->dummy.buswidth != 1))
+			return false;
+
+		if ((op->data.buswidth != 1) && (op->data.buswidth != 4))
+			return false;
+
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+static int mtk_snfi_adjust_op_size(struct spi_mem *mem,
+				   struct spi_mem_op *op)
+{
+	u32 len, max_len;
+
+	/*
+	 * The op size only support SNFI_GPRAM_MAX_LEN which will
+	 * use the snfi mac mode when data buswidth is 0/1.
+	 * Otherwise, the snfi can max support 16KB.
+	 */
+	if ((op->data.buswidth == 1) || (op->data.buswidth == 0))
+		max_len = SNFI_GPRAM_MAX_LEN;
+	else
+		max_len = KB(16);
+
+	len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
+	if (len > max_len)
+		return -ENOTSUPP;
+
+	if ((len + op->data.nbytes) > max_len)
+		op->data.nbytes = max_len - len;
+
+	return 0;
+}
+
+static const struct mtk_snfi_caps mtk_snfi_caps_mt7986 = {
+	.spare_size = spare_size_mt7986,
+	.num_spare_size = 19,
+	.pageformat_spare_shift = 16,
+	.max_sector_size = 1024,
+};
+
+static const struct spi_controller_mem_ops mtk_snfi_ops = {
+	.adjust_op_size = mtk_snfi_adjust_op_size,
+	.supports_op = mtk_snfi_supports_op,
+	.exec_op = mtk_snfi_exec_op,
+};
+
+static const struct of_device_id mtk_snfi_id_table[] = {
+	{ .compatible = "mediatek,mt7986-snfi",
+	  .data = &mtk_snfi_caps_mt7986,
+	},
+	{  /* sentinel */ }
+};
+
+/* ECC wrapper */
+static struct mtk_snfi *mtk_nand_to_spi(struct nand_device *nand)
+{
+	struct device *dev = nand->ecc.engine->dev;
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mtk_snfi *snfi = spi_master_get_devdata(master);
+
+	return snfi;
+}
+
+static int mtk_snfi_set_spare_per_sector(struct nand_device *nand,
+				struct mtk_snfi *snfi, u32 *sps, u32 *idx)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	const u8 *spare = snfi->caps->spare_size;
+	u32 i, closest_spare = 0;
+
+	eng->nsteps = nand->memorg.pagesize / conf->step_size;
+	*sps = nand->memorg.oobsize / eng->nsteps;
+
+	if (conf->step_size == 1024)
+		*sps >>= 1;
+
+	if ((*sps < snfi->fdm_size) || (*sps < MTK_NFI_MIN_SPARE))
+		return -EINVAL;
+
+	for (i = 0; i < snfi->caps->num_spare_size; i++) {
+		if (*sps >= spare[i] && spare[i] >= spare[closest_spare]) {
+			closest_spare = i;
+			if (*sps == spare[i])
+				break;
+		}
+	}
+
+	*sps = spare[closest_spare];
+	*idx = closest_spare;
+
+	if (conf->step_size == 1024)
+		*sps <<= 1;
+
+	return 0;
+}
+
+static int mtk_snfi_ecc_init(struct nand_device *nand)
+{
+	struct nand_ecc_props *reqs = &nand->ecc.requirements;
+	struct nand_ecc_props *user = &nand->ecc.user_conf;
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	struct mtk_snfi *snfi = mtk_nand_to_spi(nand);
+	struct mtk_ecc_engine *eng;
+	u32 spare, idx;
+	int ret;
+
+	eng = kzalloc(sizeof(*eng), GFP_KERNEL);
+	if (!eng)
+		return -ENOMEM;
+
+	nand->ecc.ctx.priv = eng;
+	nand->ecc.engine->priv = eng;
+
+	/* Configure the correction depending on the NAND device topology */
+	if (user->step_size && user->strength) {
+		conf->step_size = user->step_size;
+		conf->strength = user->strength;
+	} else if (reqs->step_size && reqs->strength) {
+		conf->step_size = reqs->step_size;
+		conf->strength = reqs->strength;
+	}
+
+	/*
+	 * align eccstrength and eccsize.
+	 * The MTK HW ECC engine only support 512 and 1024 eccsize.
+	 */
+	if (conf->step_size < 1024) {
+		if (nand->memorg.pagesize > 512 &&
+			    snfi->caps->max_sector_size > 512) {
+			conf->step_size = 1024;
+			conf->strength <<= 1;
+		} else {
+			conf->step_size = 512;
+		}
+	} else {
+		conf->step_size = 1024;
+	}
+
+	ret = mtk_snfi_set_spare_per_sector(nand, snfi, &spare, &idx);
+
+	/* These will be used by the snfi driver */
+	snfi->ecc.page_size = nand->memorg.pagesize;
+	snfi->ecc.spare_per_sector = spare;
+	snfi->ecc.spare_idx = idx;
+	snfi->ecc.sectors = nand->memorg.pagesize / conf->step_size;
+
+	/* These will be used by HW ECC engine */
+	eng->oob_per_sector = spare;
+	eng->nsteps = snfi->ecc.sectors;
+
+	return ret;
+}
+
+static int mtk_snfi_ecc_init_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mtk_ecc_get_pipelined_ops();
+	int ret;
+
+	ret = mtk_snfi_ecc_init(nand);
+	if (ret) {
+		pr_info("mtk snfi ecc init fail!\n");
+		return ret;
+	}
+
+	return ops->init_ctx(nand);
+}
+
+static void mtk_snfi_ecc_cleanup_ctx(struct nand_device *nand)
+{
+	struct nand_ecc_engine_ops *ops = mtk_ecc_get_pipelined_ops();
+
+	ops->cleanup_ctx(nand);
+}
+
+static int mtk_snfi_prepare_for_ecc(struct nand_device *nand,
+					struct mtk_snfi *snfi)
+{
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	u32 val;
+
+	switch (nand->memorg.pagesize) {
+	case 512:
+		val = PAGEFMT_512_2K | PAGEFMT_SEC_SEL_512;
+		break;
+	case KB(2):
+		if (conf->step_size == 512)
+			val = PAGEFMT_2K_4K | PAGEFMT_SEC_SEL_512;
+		else
+			val = PAGEFMT_512_2K;
+		break;
+	case KB(4):
+		if (conf->step_size == 512)
+			val = PAGEFMT_4K_8K | PAGEFMT_SEC_SEL_512;
+		else
+			val = PAGEFMT_2K_4K;
+		break;
+	case KB(8):
+		if (conf->step_size == 512)
+			val = PAGEFMT_8K_16K | PAGEFMT_SEC_SEL_512;
+		else
+			val = PAGEFMT_4K_8K;
+		break;
+	case KB(16):
+		val = PAGEFMT_8K_16K;
+		break;
+	default:
+		dev_err(snfi->dev, "invalid page len: %d\n",
+				nand->memorg.pagesize);
+		return -EINVAL;
+	}
+
+	snfi->fdm_size = eng->fdm_size;
+	snfi->fdm_ecc_size = eng->fdm_ecc_size;
+
+	val |= snfi->ecc.spare_idx << PAGEFMT_SPARE_SHIFT;
+	val |= snfi->fdm_size << PAGEFMT_FDM_SHIFT;
+	val |= snfi->fdm_ecc_size << PAGEFMT_FDM_ECC_SHIFT;
+	writel(val, snfi->regs + NFI_PAGEFMT);
+
+	return 0;
+}
+
+static int mtk_snfi_ecc_prepare_io_req(struct nand_device *nand,
+						struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mtk_ecc_get_pipelined_ops();
+	struct mtk_snfi *snfi = mtk_nand_to_spi(nand);
+	int ret;
+
+	snfi->ecc.enabled = (req->mode != MTD_OPS_RAW);
+	ret = mtk_snfi_prepare_for_ecc(nand, snfi);
+	if (ret)
+		return ret;
+
+	return ops->prepare_io_req(nand, req);
+}
+
+static int mtk_snfi_ecc_finish_io_req(struct nand_device *nand,
+						struct nand_page_io_req *req)
+{
+	struct nand_ecc_engine_ops *ops = mtk_ecc_get_pipelined_ops();
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtk_snfi *snfi = mtk_nand_to_spi(nand);
+
+	if (snfi->ecc.enabled) {
+		eng->read_empty =
+			readl(snfi->regs + NFI_STA) & STA_EMP_PAGE;
+		snfi->ecc.enabled = false;
+	}
+
+	return ops->finish_io_req(nand, req);
+}
+
+static struct nand_ecc_engine_ops mtk_snfi_ecc_engine_pipelined_ops = {
+	.init_ctx = mtk_snfi_ecc_init_ctx,
+	.cleanup_ctx = mtk_snfi_ecc_cleanup_ctx,
+	.prepare_io_req = mtk_snfi_ecc_prepare_io_req,
+	.finish_io_req = mtk_snfi_ecc_finish_io_req,
+};
+
+static int mtk_snfi_ecc_probe(struct platform_device *pdev,
+				struct mtk_snfi *snfi)
+{
+	struct nand_ecc_engine *ecceng;
+
+	if (!mtk_ecc_get_pipelined_ops())
+		return -EOPNOTSUPP;
+
+	ecceng = devm_kzalloc(&pdev->dev, sizeof(*ecceng), GFP_KERNEL);
+	if (!ecceng)
+		return -ENOMEM;
+
+	ecceng->dev = &pdev->dev;
+	ecceng->ops = &mtk_snfi_ecc_engine_pipelined_ops;
+
+	nand_ecc_register_on_host_hw_engine(ecceng);
+	snfi->ecc.engine = ecceng;
+
+	return 0;
+}
+
+static int mtk_snfi_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct spi_controller *ctlr;
+	struct mtk_snfi *snfi;
+	struct resource *res;
+	int ret, irq;
+	u32 val = 0;
+
+	ctlr = spi_alloc_master(&pdev->dev, sizeof(*snfi));
+	if (!ctlr)
+		return -ENOMEM;
+
+	snfi = spi_controller_get_devdata(ctlr);
+	snfi->dev = &pdev->dev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	snfi->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(snfi->regs)) {
+		ret = PTR_ERR(snfi->regs);
+		goto err_put_master;
+	}
+
+	ret = of_property_read_u32(np, "sample-delay", &val);
+	if (!ret)
+		snfi->sample_delay = val;
+
+	ret = of_property_read_u32(np, "read-latency", &val);
+	if (!ret)
+		snfi->read_latency = val;
+
+	snfi->nfi_clk = devm_clk_get(&pdev->dev, "nfi_clk");
+	if (IS_ERR(snfi->nfi_clk)) {
+		dev_err(&pdev->dev, "not found nfi clk\n");
+		ret = PTR_ERR(snfi->nfi_clk);
+		goto err_put_master;
+	}
+
+	snfi->snfi_clk = devm_clk_get(&pdev->dev, "snfi_clk");
+	if (IS_ERR(snfi->snfi_clk)) {
+		dev_err(&pdev->dev, "not found snfi clk\n");
+		ret = PTR_ERR(snfi->snfi_clk);
+		goto err_put_master;
+	}
+
+	snfi->hclk = devm_clk_get(&pdev->dev, "hclk");
+	if (IS_ERR(snfi->hclk)) {
+		dev_err(&pdev->dev, "not found hclk\n");
+		ret = PTR_ERR(snfi->hclk);
+		goto err_put_master;
+	}
+
+	ret = mtk_snfi_enable_clk(&pdev->dev, snfi);
+	if (ret)
+		goto err_put_master;
+
+	snfi->caps = of_device_get_match_data(&pdev->dev);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "not found snfi irq resource\n");
+		ret = -EINVAL;
+		goto clk_disable;
+	}
+
+	ret = devm_request_irq(&pdev->dev, irq, mtk_snfi_irq,
+					0, "mtk-snfi", snfi);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request snfi irq\n");
+		goto clk_disable;
+	}
+
+	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to set dma mask\n");
+		goto clk_disable;
+	}
+
+	snfi->tx_buf = kzalloc(SNFI_GPRAM_MAX_LEN, GFP_KERNEL);
+	if (!snfi->tx_buf) {
+		ret = -ENOMEM;
+		goto clk_disable;
+	}
+
+	ctlr->dev.of_node = np;
+	ctlr->mem_ops = &mtk_snfi_ops;
+	ctlr->mode_bits = SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
+	ctlr->auto_runtime_pm = true;
+
+	dev_set_drvdata(&pdev->dev, ctlr);
+
+	ret = mtk_snfi_init(snfi);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to init snfi\n");
+		goto free_buf;
+	}
+
+	ret = mtk_snfi_ecc_probe(pdev, snfi);
+	if (ret) {
+		dev_warn(&pdev->dev, "SPI-mem ECC engine not available\n");
+		goto free_buf;
+	}
+
+	pm_runtime_enable(&pdev->dev);
+
+	ret = devm_spi_register_master(&pdev->dev, ctlr);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register spi master\n");
+		goto disable_pm_runtime;
+	}
+
+	return 0;
+
+disable_pm_runtime:
+	pm_runtime_disable(&pdev->dev);
+
+free_buf:
+	kfree(snfi->tx_buf);
+
+clk_disable:
+	mtk_snfi_disable_clk(snfi);
+
+err_put_master:
+	spi_master_put(ctlr);
+
+	return ret;
+}
+
+static int mtk_snfi_remove(struct platform_device *pdev)
+{
+	struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev);
+	struct mtk_snfi *snfi = spi_controller_get_devdata(ctlr);
+
+	pm_runtime_disable(&pdev->dev);
+	kfree(snfi->tx_buf);
+	spi_master_put(ctlr);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mtk_snfi_runtime_suspend(struct device *dev)
+{
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+	struct mtk_snfi *snfi = spi_controller_get_devdata(ctlr);
+
+	mtk_snfi_disable_clk(snfi);
+
+	return 0;
+}
+
+static int mtk_snfi_runtime_resume(struct device *dev)
+{
+	struct spi_controller *ctlr = dev_get_drvdata(dev);
+	struct mtk_snfi *snfi = spi_controller_get_devdata(ctlr);
+	int ret;
+
+	ret = mtk_snfi_enable_clk(dev, snfi);
+	if (ret)
+		return ret;
+
+	ret = mtk_snfi_init(snfi);
+	if (ret)
+		dev_err(dev, "failed to init snfi\n");
+
+	return ret;
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops mtk_snfi_pm_ops = {
+	SET_RUNTIME_PM_OPS(mtk_snfi_runtime_suspend,
+			   mtk_snfi_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+			   pm_runtime_force_resume)
+};
+
+static struct platform_driver mtk_snfi_driver = {
+	.driver = {
+		.name	= "mtk-snfi",
+		.of_match_table = mtk_snfi_id_table,
+		.pm = &mtk_snfi_pm_ops,
+	},
+	.probe		= mtk_snfi_probe,
+	.remove		= mtk_snfi_remove,
+};
+
+module_platform_driver(mtk_snfi_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Xiangsheng Hou <xiangsheng.hou at mediatek.com>");
+MODULE_DESCRIPTION("Mediatek SPI memory controller driver");
-- 
2.25.1



From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:21 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:21 +0800
Subject: [RFC,
 v3 5/5] mtd: spinand: skip set/get oob data bytes when interleaved
 case
In-Reply-To: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
References: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211022024021.14665-6-xiangsheng.hou@mediatek.com>

For syndrome layout, ECC/free byte in oob layout and main
data are interleaved. For this case, it is better to set/get
oob data bytes in ECC engine.

For MTK ECC engine, although it can auto place data as sector +
oob free + oob ecc for one page in pipelined. However, the bad
mark will be not fit with nand spec. Therefore, there have bad
mark swap operation in ecc engine.

But, the swap opeation(between bbm 0xff with 1byte main data) will
lead to more one byte than oobavailable. Set oob databytes after
bad mark swap will lead to lost one oob free byte.

Therefore, just try to modify the spi nand framework for review.
And this may be common for the interleaved case.

Signed-off-by: Xiangsheng Hou <xiangsheng.hou at mediatek.com>
---
 drivers/mtd/nand/spi/core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 2c8685f1f2fa..32a4707982c5 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -401,7 +401,8 @@ static int spinand_read_from_cache_op(struct spinand_device *spinand,
 		       req->datalen);
 
 	if (req->ooblen) {
-		if (req->mode == MTD_OPS_AUTO_OOB)
+		if (req->mode == MTD_OPS_AUTO_OOB &&
+			nand->ecc.user_conf.placement != NAND_ECC_PLACEMENT_INTERLEAVED)
 			mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
 						    spinand->oobbuf,
 						    req->ooboffs,
@@ -442,7 +443,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 		       req->datalen);
 
 	if (req->ooblen) {
-		if (req->mode == MTD_OPS_AUTO_OOB)
+		if (req->mode == MTD_OPS_AUTO_OOB &&
+			nand->ecc.user_conf.placement != NAND_ECC_PLACEMENT_INTERLEAVED)
 			mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
 						    spinand->oobbuf,
 						    req->ooboffs,
-- 
2.25.1



From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:17 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:17 +0800
Subject: [RFC,v3 1/5] mtd: ecc: move mediatek HW ECC driver
In-Reply-To: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
References: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211022024021.14665-2-xiangsheng.hou@mediatek.com>

Move Mediatek HW ECC source driver to mtd nand folder and the header
file to include linux mtd folder.
The HW ECC driver can be used by Mediatek raw nand and spi nand
controller.

Signed-off-by: Xiangsheng Hou <xiangsheng.hou at mediatek.com>
---
 drivers/mtd/nand/Kconfig                              | 9 +++++++++
 drivers/mtd/nand/Makefile                             | 1 +
 drivers/mtd/nand/{raw => }/mtk_ecc.c                  | 2 +-
 drivers/mtd/nand/raw/Kconfig                          | 1 +
 drivers/mtd/nand/raw/Makefile                         | 2 +-
 drivers/mtd/nand/raw/mtk_nand.c                       | 2 +-
 {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h | 0
 7 files changed, 14 insertions(+), 3 deletions(-)
 rename drivers/mtd/nand/{raw => }/mtk_ecc.c (99%)
 rename {drivers/mtd/nand/raw => include/linux/mtd}/mtk_ecc.h (100%)

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index b40455234cbd..e657823329d2 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -46,6 +46,15 @@ config MTD_NAND_ECC_SW_BCH
 	  ECC codes. They are used with NAND devices requiring more than 1 bit
 	  of error correction.
 
+config MTD_NAND_ECC_MTK
+	bool "Mediatek hardware ECC engine"
+	select MTD_NAND_ECC
+	help
+	  This enables support for Mediatek hardware ECC engine which
+	  used for error correction. This correction strength depends
+	  on different project. The ECC engine can be used with Mediatek
+	  raw nand and spi nand controller driver.
+
 endmenu
 
 endmenu
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 1c0b46960eb1..66d1741fe7ff 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -10,3 +10,4 @@ obj-y	+= spi/
 nandcore-$(CONFIG_MTD_NAND_ECC) += ecc.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_HAMMING) += ecc-sw-hamming.o
 nandcore-$(CONFIG_MTD_NAND_ECC_SW_BCH) += ecc-sw-bch.o
+nandcore-$(CONFIG_MTD_NAND_ECC_MTK) += mtk_ecc.o
diff --git a/drivers/mtd/nand/raw/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
similarity index 99%
rename from drivers/mtd/nand/raw/mtk_ecc.c
rename to drivers/mtd/nand/mtk_ecc.c
index c437d97debb8..ce0f8b491e5d 100644
--- a/drivers/mtd/nand/raw/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -16,7 +16,7 @@
 #include <linux/of_platform.h>
 #include <linux/mutex.h>
 
-#include "mtk_ecc.h"
+#include <linux/mtd/mtk_ecc.h>
 
 #define ECC_IDLE_MASK		BIT(0)
 #define ECC_IRQ_EN		BIT(0)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 67b7cb67c030..c90bc166034b 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -362,6 +362,7 @@ config MTD_NAND_MTK
 	tristate "MTK NAND controller"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
 	depends on HAS_IOMEM
+	select MTD_NAND_ECC_MTK
 	help
 	  Enables support for NAND controller on MTK SoCs.
 	  This controller is found on mt27xx, mt81xx, mt65xx SoCs.
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile
index 2f97958c3a33..49d3946c166b 100644
--- a/drivers/mtd/nand/raw/Makefile
+++ b/drivers/mtd/nand/raw/Makefile
@@ -48,7 +48,7 @@ obj-$(CONFIG_MTD_NAND_SUNXI)		+= sunxi_nand.o
 obj-$(CONFIG_MTD_NAND_HISI504)	        += hisi504_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)		+= brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)		+= qcom_nandc.o
-obj-$(CONFIG_MTD_NAND_MTK)		+= mtk_ecc.o mtk_nand.o
+obj-$(CONFIG_MTD_NAND_MTK)		+= mtk_nand.o
 obj-$(CONFIG_MTD_NAND_MXIC)		+= mxic_nand.o
 obj-$(CONFIG_MTD_NAND_TEGRA)		+= tegra_nand.o
 obj-$(CONFIG_MTD_NAND_STM32_FMC2)	+= stm32_fmc2_nand.o
diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c
index 5c5c92132287..7d8a6b35c102 100644
--- a/drivers/mtd/nand/raw/mtk_nand.c
+++ b/drivers/mtd/nand/raw/mtk_nand.c
@@ -17,7 +17,7 @@
 #include <linux/iopoll.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include "mtk_ecc.h"
+#include <linux/mtd/mtk_ecc.h>
 
 /* NAND controller register definition */
 #define NFI_CNFG		(0x00)
diff --git a/drivers/mtd/nand/raw/mtk_ecc.h b/include/linux/mtd/mtk_ecc.h
similarity index 100%
rename from drivers/mtd/nand/raw/mtk_ecc.h
rename to include/linux/mtd/mtk_ecc.h
-- 
2.25.1



From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:20 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:20 +0800
Subject: [RFC,v3 4/5] arm64: dts: add snfi node for spi nand
In-Reply-To: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
References: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211022024021.14665-5-xiangsheng.hou@mediatek.com>

Signed-off-by: Xiangsheng Hou <xiangsheng.hou at mediatek.com>
---
 arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts | 18 ++++++++++++++++++
 arch/arm64/boot/dts/mediatek/mt7622.dtsi     | 13 +++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index f2dc850010f1..f4ba86c451fc 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -223,6 +223,24 @@ &nandc {
 	status = "disabled";
 };
 
+&snfi {
+	pinctrl-names = "default";
+	/* pin shared with spic */
+	pinctrl-0 = <&snfi_pins>;
+	nand-ecc-engine = <&bch>;
+	status = "disabled";
+
+	spi_nand at 0 {
+		compatible = "spi-nand";
+		reg = <0>;
+		spi-max-frequency = <104000000>;
+		spi-tx-bus-width = <4>;
+		spi-rx-bus-width = <4>;
+		nand-ecc-engine = <&snfi>;
+		nand-ecc-placement = "interleaved";
+	};
+};
+
 &nor_flash {
 	pinctrl-names = "default";
 	pinctrl-0 = <&spi_nor_pins>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
index 890a942ec608..0525e4de5ec0 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -545,6 +545,19 @@ nandc: nfi at 1100d000 {
 		status = "disabled";
 	};
 
+	snfi: spi at 1100d000 {
+		compatible = "mediatek,mt7622-snfi";
+		reg = <0 0x1100D000 0 0x1000>;
+		interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_LOW>;
+		clocks = <&infracfg_ao CK_INFRA_NFI1_CK>,
+			 <&infracfg_ao CK_INFRA_SPINFI1_CK>,
+			 <&infracfg_ao CK_INFRA_NFI_HCK_CK>;
+		clock-names = "nfi_clk", "snfi_clk", "hclk";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		status = "disabled";
+	};
+
 	bch: ecc at 1100e000 {
 		compatible = "mediatek,mt7622-ecc";
 		reg = <0 0x1100e000 0 0x1000>;
-- 
2.25.1



From xiangsheng.hou at mediatek.com  Thu Oct 21 19:40:18 2021
From: xiangsheng.hou at mediatek.com (Xiangsheng Hou)
Date: Fri, 22 Oct 2021 10:40:18 +0800
Subject: [RFC,v3 2/5] mtd: ecc: realize Mediatek HW ECC driver
In-Reply-To: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
References: <20211022024021.14665-1-xiangsheng.hou@mediatek.com>
Message-ID: <20211022024021.14665-3-xiangsheng.hou@mediatek.com>

The v3 driver realize Mediatek HW ECC engine with pipelined
case.

Signed-off-by: Xiangsheng Hou <xiangsheng.hou at mediatek.com>
---
 drivers/mtd/nand/core.c     |  10 +-
 drivers/mtd/nand/ecc.c      |  88 +++++++
 drivers/mtd/nand/mtk_ecc.c  | 488 ++++++++++++++++++++++++++++++++++++
 include/linux/mtd/mtk_ecc.h |  38 +++
 include/linux/mtd/nand.h    |  11 +
 5 files changed, 632 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c
index 5e13a03d2b32..b228b4d13b7a 100644
--- a/drivers/mtd/nand/core.c
+++ b/drivers/mtd/nand/core.c
@@ -232,7 +232,9 @@ static int nanddev_get_ecc_engine(struct nand_device *nand)
 		nand->ecc.engine = nand_ecc_get_on_die_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand->ecc.engine = nand_ecc_get_on_host_hw_engine(nand);
+		if (PTR_ERR(nand->ecc.engine) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
 		break;
 	default:
 		pr_err("Missing ECC engine type\n");
@@ -252,7 +254,7 @@ static int nanddev_put_ecc_engine(struct nand_device *nand)
 {
 	switch (nand->ecc.ctx.conf.engine_type) {
 	case NAND_ECC_ENGINE_TYPE_ON_HOST:
-		pr_err("On-host hardware ECC engines not supported yet\n");
+		nand_ecc_put_on_host_hw_engine(nand);
 		break;
 	case NAND_ECC_ENGINE_TYPE_NONE:
 	case NAND_ECC_ENGINE_TYPE_SOFT:
@@ -297,7 +299,9 @@ int nanddev_ecc_engine_init(struct nand_device *nand)
 	/* Look for the ECC engine to use */
 	ret = nanddev_get_ecc_engine(nand);
 	if (ret) {
-		pr_err("No ECC engine found\n");
+		if (ret != -EPROBE_DEFER)
+			pr_err("No ECC engine found\n");
+
 		return ret;
 	}
 
diff --git a/drivers/mtd/nand/ecc.c b/drivers/mtd/nand/ecc.c
index 6c43dfda01d4..55d6946da9c3 100644
--- a/drivers/mtd/nand/ecc.c
+++ b/drivers/mtd/nand/ecc.c
@@ -96,7 +96,12 @@
 #include <linux/module.h>
 #include <linux/mtd/nand.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
 
+static LIST_HEAD(on_host_hw_engines);
+static DEFINE_MUTEX(on_host_hw_engines_mutex);
 /**
  * nand_ecc_init_ctx - Init the ECC engine context
  * @nand: the NAND device
@@ -611,6 +616,89 @@ struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand)
 }
 EXPORT_SYMBOL(nand_ecc_get_on_die_hw_engine);
 
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	struct nand_ecc_engine *item;
+
+	if (!engine)
+		return -ENOTSUPP;
+
+	/* Prevent multiple registerations of one engine */
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item == engine)
+			return 0;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_add_tail(&engine->node, &on_host_hw_engines);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_register_on_host_hw_engine);
+
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine)
+{
+	if (!engine)
+		return -ENOTSUPP;
+
+	mutex_lock(&on_host_hw_engines_mutex);
+	list_del(&engine->node);
+	mutex_unlock(&on_host_hw_engines_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_ecc_unregister_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev)
+{
+	struct nand_ecc_engine *item;
+
+	list_for_each_entry(item, &on_host_hw_engines, node)
+		if (item->dev == dev)
+			return item;
+
+	return NULL;
+}
+EXPORT_SYMBOL(nand_ecc_match_on_host_hw_engine);
+
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand)
+{
+	struct nand_ecc_engine *engine = NULL;
+	struct device *dev = &nand->mtd.dev;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	if (list_empty(&on_host_hw_engines))
+		return NULL;
+
+	/* Check for an explicit nand-ecc-engine property */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (np) {
+		pdev = of_find_device_by_node(np);
+		if (!pdev)
+			return ERR_PTR(-EPROBE_DEFER);
+
+		engine = nand_ecc_match_on_host_hw_engine(&pdev->dev);
+		platform_device_put(pdev);
+		of_node_put(np);
+
+		if (!engine)
+			return ERR_PTR(-EPROBE_DEFER);
+	}
+
+	if (engine)
+		get_device(engine->dev);
+
+	return engine;
+}
+EXPORT_SYMBOL(nand_ecc_get_on_host_hw_engine);
+
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand)
+{
+	put_device(nand->ecc.engine->dev);
+}
+EXPORT_SYMBOL(nand_ecc_put_on_host_hw_engine);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Miquel Raynal <miquel.raynal at bootlin.com>");
 MODULE_DESCRIPTION("Generic ECC engine");
diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c
index ce0f8b491e5d..e0c971d6a443 100644
--- a/drivers/mtd/nand/mtk_ecc.c
+++ b/drivers/mtd/nand/mtk_ecc.c
@@ -16,6 +16,7 @@
 #include <linux/of_platform.h>
 #include <linux/mutex.h>
 
+#include <linux/mtd/nand.h>
 #include <linux/mtd/mtk_ecc.h>
 
 #define ECC_IDLE_MASK		BIT(0)
@@ -41,6 +42,9 @@
 #define ECC_IDLE_REG(op)	((op) == ECC_ENCODE ? ECC_ENCIDLE : ECC_DECIDLE)
 #define ECC_CTL_REG(op)		((op) == ECC_ENCODE ? ECC_ENCCON : ECC_DECCON)
 
+#define ECC_FDM_MAX_SIZE 8
+#define ECC_FDM_MIN_SIZE 1
+
 struct mtk_ecc_caps {
 	u32 err_mask;
 	const u8 *ecc_strength;
@@ -79,6 +83,10 @@ static const u8 ecc_strength_mt7622[] = {
 	4, 6, 8, 10, 12, 14, 16
 };
 
+static const u8 ecc_strength_mt7986[] = {
+	4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24
+};
+
 enum mtk_ecc_regs {
 	ECC_ENCPAR00,
 	ECC_ENCIRQ_EN,
@@ -115,6 +123,15 @@ static int mt7622_ecc_regs[] = {
 	[ECC_DECIRQ_STA] =      0x144,
 };
 
+static int mt7986_ecc_regs[] = {
+	[ECC_ENCPAR00] =        0x300,
+	[ECC_ENCIRQ_EN] =       0x80,
+	[ECC_ENCIRQ_STA] =      0x84,
+	[ECC_DECDONE] =         0x124,
+	[ECC_DECIRQ_EN] =       0x200,
+	[ECC_DECIRQ_STA] =      0x204,
+};
+
 static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
 				     enum mtk_ecc_operation op)
 {
@@ -447,6 +464,464 @@ unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc)
 }
 EXPORT_SYMBOL(mtk_ecc_get_parity_bits);
 
+static inline int data_off(struct nand_device *nand, int i)
+{
+	int eccsize = nand->ecc.ctx.conf.step_size;
+
+	return i * eccsize;
+}
+
+static inline int fdm_off(struct nand_device *nand, int i)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	int poi;
+
+	if (i < eng->bad_mark.sec)
+		poi = (i + 1) * eng->fdm_size;
+	else if (i == eng->bad_mark.sec)
+		poi = 0;
+	else
+		poi = i * eng->fdm_size;
+
+	return poi;
+}
+
+static inline int mtk_ecc_data_len(struct nand_device *nand)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	int eccsize = nand->ecc.ctx.conf.step_size;
+	int eccbytes = eng->oob_ecc;
+
+	return eccsize + eng->fdm_size + eccbytes;
+}
+
+static inline u8 *mtk_ecc_sec_ptr(struct nand_device *nand,  int i)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	return eng->page_buf + i * mtk_ecc_data_len(nand);
+}
+
+static inline u8 *mtk_ecc_fdm_ptr(struct nand_device *nand, int i)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	int eccsize = nand->ecc.ctx.conf.step_size;
+
+	return eng->page_buf + i * mtk_ecc_data_len(nand) + eccsize;
+}
+
+static void mtk_ecc_no_bad_mark_swap(struct nand_device *a, u8 *b,
+							u8 *c)
+{
+	/* nop */
+}
+
+static void mtk_ecc_bad_mark_swap(struct nand_device *nand, u8 *databuf,
+							u8 *oobbuf)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	int step_size = nand->ecc.ctx.conf.step_size;
+	u32 bad_pos = eng->bad_mark.pos;
+
+	bad_pos += eng->bad_mark.sec * step_size;
+
+	swap(oobbuf[0], databuf[bad_pos]);
+}
+
+static void mtk_ecc_set_bad_mark_ctl(struct mtk_ecc_bad_mark_ctl *bm_ctl,
+				     struct mtd_info *mtd)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+
+	if (mtd->writesize == 512) {
+		bm_ctl->bm_swap = mtk_ecc_no_bad_mark_swap;
+	} else {
+		bm_ctl->bm_swap = mtk_ecc_bad_mark_swap;
+		bm_ctl->sec = mtd->writesize / mtk_ecc_data_len(nand);
+		bm_ctl->pos = mtd->writesize % mtk_ecc_data_len(nand);
+	}
+}
+
+static int mtk_ecc_ooblayout_free(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *oob_region)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	u32 eccsteps, bbm_bytes = 0;
+
+	eccsteps = mtd->writesize / conf->step_size;
+
+	if (section >= eccsteps)
+		return -ERANGE;
+
+	/* reserve 1 byte for bad mark only for section 0 */
+	if (section == 0)
+		bbm_bytes = 1;
+
+	oob_region->length = eng->fdm_size - bbm_bytes;
+	oob_region->offset = section * eng->fdm_size + bbm_bytes;
+
+	return 0;
+}
+
+static int mtk_ecc_ooblayout_ecc(struct mtd_info *mtd, int section,
+				 struct mtd_oob_region *oob_region)
+{
+	struct nand_device *nand = mtd_to_nanddev(mtd);
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (section)
+		return -ERANGE;
+
+	oob_region->offset = eng->fdm_size * eng->nsteps;
+	oob_region->length = mtd->oobsize - oob_region->offset;
+
+	return 0;
+}
+
+static const struct mtd_ooblayout_ops mtk_ecc_ooblayout_ops = {
+	.free = mtk_ecc_ooblayout_free,
+	.ecc = mtk_ecc_ooblayout_ecc,
+};
+
+const struct mtd_ooblayout_ops *mtk_ecc_get_ooblayout(void)
+{
+	return &mtk_ecc_ooblayout_ops;
+}
+
+static struct device *mtk_ecc_get_engine_dev(struct device *dev)
+{
+	struct platform_device *eccpdev;
+	struct device_node *np;
+
+	/*
+	 * The device node is only the host controller,
+	 * not the actual ECC engine when pipelined case.
+	 */
+	np = of_parse_phandle(dev->of_node, "nand-ecc-engine", 0);
+	if (!np)
+		return NULL;
+
+	eccpdev = of_find_device_by_node(np);
+	if (!eccpdev) {
+		of_node_put(np);
+		return NULL;
+	}
+
+	platform_device_put(eccpdev);
+	of_node_put(np);
+
+	return &eccpdev->dev;
+}
+
+/*
+ * mtk_ecc_data_format() - Covert data between ecc format and data/oob buf
+ *
+ * Mediatek HW ECC engine organize data/oob free/oob ecc by sector,
+ * the data format for one page as bellow:
+ * ||          sector 0         ||          sector 1         || ...
+ * || data |   fdm    | oob ecc || data ||   fdm   | oob ecc || ...
+ *
+ * Terefore, it`s necessary to covert data when read/write in MTD_OPS_RAW.
+ * These data include bad mark, sector data, fdm data and oob ecc.
+ */
+static void mtk_ecc_data_format(struct nand_device *nand,
+			u8 *databuf, u8 *oobbuf, bool write)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	int step_size = nand->ecc.ctx.conf.step_size;
+	int i;
+
+	if (write) {
+		for (i = 0; i < eng->nsteps; i++) {
+			if (i == eng->bad_mark.sec)
+				eng->bad_mark.bm_swap(nand,
+						databuf, oobbuf);
+			memcpy(mtk_ecc_sec_ptr(nand, i),
+				   databuf + data_off(nand, i), step_size);
+
+			memcpy(mtk_ecc_fdm_ptr(nand, i),
+				   oobbuf + fdm_off(nand, i),
+				   eng->fdm_size);
+
+			memcpy(mtk_ecc_fdm_ptr(nand, i) + eng->fdm_size,
+				   oobbuf + eng->fdm_size * eng->nsteps +
+				   i * eng->oob_ecc,
+				   eng->oob_ecc);
+
+			/* swap back when write */
+			if (i == eng->bad_mark.sec)
+				eng->bad_mark.bm_swap(nand,
+						databuf, oobbuf);
+		}
+	} else {
+		for (i = 0; i < eng->nsteps; i++) {
+			memcpy(databuf + data_off(nand, i),
+				   mtk_ecc_sec_ptr(nand, i), step_size);
+
+			memcpy(oobbuf + fdm_off(nand, i),
+				   mtk_ecc_sec_ptr(nand, i) + step_size,
+				   eng->fdm_size);
+
+			memcpy(oobbuf + eng->fdm_size * eng->nsteps +
+				   i * eng->oob_ecc,
+				   mtk_ecc_sec_ptr(nand, i) + step_size
+				   + eng->fdm_size,
+				   eng->oob_ecc);
+
+			if (i == eng->bad_mark.sec)
+				eng->bad_mark.bm_swap(nand,
+						databuf, oobbuf);
+		}
+	}
+}
+
+static void mtk_ecc_fdm_shift(struct nand_device *nand,
+				u8 *dst_buf, u8 *src_buf)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	u8 *poi;
+	int i;
+
+	for (i = 0; i < eng->nsteps; i++) {
+		if (i < eng->bad_mark.sec)
+			poi = src_buf + (i + 1) * eng->fdm_size;
+		else if (i == eng->bad_mark.sec)
+			poi = src_buf;
+		else
+			poi = src_buf + i * eng->fdm_size;
+
+		memcpy(dst_buf + i * eng->fdm_size, poi, eng->fdm_size);
+	}
+}
+
+int mtk_ecc_prepare_io_req_pipelined(struct nand_device *nand,
+					  struct nand_page_io_req *req)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	u8 *buf = eng->page_buf;
+
+	nand_ecc_tweak_req(&eng->req_ctx, req);
+
+	if (req->mode == MTD_OPS_RAW) {
+		if (req->type == NAND_PAGE_WRITE) {
+			/* change data/oob buf to MTK HW ECC data format */
+			mtk_ecc_data_format(nand, req->databuf.in,
+					req->oobbuf.in, true);
+			req->databuf.out = buf;
+			req->oobbuf.out = buf + nand->memorg.pagesize;
+		}
+	} else {
+		eng->ecc_cfg.op = ECC_DECODE;
+		if (req->type == NAND_PAGE_WRITE) {
+			memset(eng->oob_buf, 0xff, nand->memorg.oobsize);
+			mtd_ooblayout_set_databytes(mtd, req->oobbuf.out,
+							eng->oob_buf,
+							req->ooboffs,
+							mtd->oobavail);
+			eng->bad_mark.bm_swap(nand,
+						req->databuf.in, eng->oob_buf);
+			mtk_ecc_fdm_shift(nand, req->oobbuf.in,
+						eng->oob_buf);
+
+			eng->ecc_cfg.op = ECC_ENCODE;
+		}
+
+		eng->ecc_cfg.mode = ECC_NFI_MODE;
+		eng->ecc_cfg.sectors = eng->nsteps;
+		return mtk_ecc_enable(eng->ecc, &eng->ecc_cfg);
+	}
+
+	return 0;
+}
+
+int mtk_ecc_finish_io_req_pipelined(struct nand_device *nand,
+					  struct nand_page_io_req *req)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct mtk_ecc_stats stats;
+	u8 *buf = eng->page_buf;
+	int ret;
+
+	if (req->type == NAND_PAGE_WRITE) {
+		if (req->mode != MTD_OPS_RAW) {
+			mtk_ecc_disable(eng->ecc);
+			mtk_ecc_fdm_shift(nand, eng->oob_buf,
+					req->oobbuf.in);
+			eng->bad_mark.bm_swap(nand,
+					req->databuf.in, eng->oob_buf);
+		}
+		nand_ecc_restore_req(&eng->req_ctx, req);
+
+		return 0;
+	}
+
+	if (req->mode == MTD_OPS_RAW) {
+		memcpy(buf, req->databuf.in,
+			   nand->memorg.pagesize);
+		memcpy(buf + nand->memorg.pagesize,
+			   req->oobbuf.in, nand->memorg.oobsize);
+
+		/* change MTK HW ECC data format to data/oob buf */
+		mtk_ecc_data_format(nand, req->databuf.in,
+				req->oobbuf.in, false);
+		nand_ecc_restore_req(&eng->req_ctx, req);
+
+		return 0;
+	}
+
+	ret = mtk_ecc_wait_done(eng->ecc, ECC_DECODE);
+	if (ret)
+		return -ETIMEDOUT;
+
+	if (eng->read_empty) {
+		memset(req->databuf.in, 0xff, nand->memorg.pagesize);
+		memset(req->oobbuf.in, 0xff, nand->memorg.oobsize);
+
+		ret = 0;
+	} else {
+		mtk_ecc_get_stats(eng->ecc, &stats, eng->nsteps);
+		mtd->ecc_stats.corrected += stats.corrected;
+		mtd->ecc_stats.failed += stats.failed;
+
+		/*
+		 * Return -EBADMSG when exit uncorrect ecc error.
+		 * Otherwise, return the bitflips.
+		 */
+		if (stats.failed)
+			ret = -EBADMSG;
+		else
+			ret = stats.bitflips;
+
+		mtk_ecc_fdm_shift(nand, eng->oob_buf, req->oobbuf.in);
+		eng->bad_mark.bm_swap(nand,
+					req->databuf.in, eng->oob_buf);
+		mtd_ooblayout_get_databytes(mtd, req->oobbuf.in,
+			eng->oob_buf,
+			0, mtd->oobavail);
+	}
+
+	mtk_ecc_disable(eng->ecc);
+	nand_ecc_restore_req(&eng->req_ctx, req);
+
+	return ret;
+}
+
+int mtk_ecc_init_ctx_pipelined(struct nand_device *nand)
+{
+	struct nand_ecc_props *conf = &nand->ecc.ctx.conf;
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+	struct mtd_info *mtd = nanddev_to_mtd(nand);
+	struct device *dev;
+	int free, ret;
+
+	/*
+	 * In the case of a pipelined engine, the device registering the ECC
+	 * engine is not the actual ECC engine device but the host controller.
+	 */
+	dev = mtk_ecc_get_engine_dev(nand->ecc.engine->dev);
+	if (!dev) {
+		ret = -EINVAL;
+		goto free_engine;
+	}
+
+	eng->ecc = dev_get_drvdata(dev);
+
+	/* calculate oob free bytes except ecc parity data */
+	free = (conf->strength * mtk_ecc_get_parity_bits(eng->ecc)
+		+ 7) >> 3;
+	free = eng->oob_per_sector - free;
+
+	/*
+	 * enhance ecc strength if oob left is bigger than max FDM size
+	 * or reduce ecc strength if oob size is not enough for ecc
+	 * parity data.
+	 */
+	if (free > ECC_FDM_MAX_SIZE)
+		eng->oob_ecc = eng->oob_per_sector - ECC_FDM_MAX_SIZE;
+	else if (free < 0)
+		eng->oob_ecc = eng->oob_per_sector - ECC_FDM_MIN_SIZE;
+
+	/* calculate and adjust ecc strenth based on oob ecc bytes */
+	conf->strength = (eng->oob_ecc << 3) /
+				 mtk_ecc_get_parity_bits(eng->ecc);
+	mtk_ecc_adjust_strength(eng->ecc, &conf->strength);
+
+	eng->oob_ecc = DIV_ROUND_UP(conf->strength *
+				 mtk_ecc_get_parity_bits(eng->ecc), 8);
+
+	eng->fdm_size = eng->oob_per_sector - eng->oob_ecc;
+	if (eng->fdm_size > ECC_FDM_MAX_SIZE)
+		eng->fdm_size = ECC_FDM_MAX_SIZE;
+
+	eng->fdm_ecc_size = ECC_FDM_MIN_SIZE;
+
+	eng->oob_ecc = eng->oob_per_sector - eng->fdm_size;
+
+	if (!mtd->ooblayout)
+		mtd_set_ooblayout(mtd, mtk_ecc_get_ooblayout());
+
+	ret = nand_ecc_init_req_tweaking(&eng->req_ctx, nand);
+	if (ret)
+		goto free_engine;
+
+	eng->oob_buf = kzalloc(mtd->oobsize, GFP_KERNEL);
+	eng->page_buf =
+		kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
+	if (!eng->oob_buf || !eng->page_buf) {
+		ret = -ENOMEM;
+		goto free_bufs;
+	}
+
+	mtk_ecc_set_bad_mark_ctl(&eng->bad_mark, mtd);
+	eng->ecc_cfg.strength = conf->strength;
+	eng->ecc_cfg.len = conf->step_size + eng->fdm_ecc_size;
+
+	return 0;
+
+free_bufs:
+	nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+	kfree(eng->oob_buf);
+	kfree(eng->page_buf);
+free_engine:
+	kfree(eng);
+
+	return ret;
+}
+
+void mtk_ecc_cleanup_ctx_pipelined(struct nand_device *nand)
+{
+	struct mtk_ecc_engine *eng = nand->ecc.ctx.priv;
+
+	if (eng) {
+		nand_ecc_cleanup_req_tweaking(&eng->req_ctx);
+		kfree(eng->ecc);
+		kfree(eng->oob_buf);
+		kfree(eng->page_buf);
+		kfree(eng);
+	}
+}
+
+/*
+ * The on-host mtk HW ECC engine work at pipelined situation,
+ * will be registered by the drivers that wrap it.
+ */
+static struct nand_ecc_engine_ops mtk_ecc_engine_pipelined_ops = {
+	.init_ctx = mtk_ecc_init_ctx_pipelined,
+	.cleanup_ctx = mtk_ecc_cleanup_ctx_pipelined,
+	.prepare_io_req = mtk_ecc_prepare_io_req_pipelined,
+	.finish_io_req = mtk_ecc_finish_io_req_pipelined,
+};
+
+struct nand_ecc_engine_ops *mtk_ecc_get_pipelined_ops(void)
+{
+	return &mtk_ecc_engine_pipelined_ops;
+}
+EXPORT_SYMBOL(mtk_ecc_get_pipelined_ops);
+
 static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = {
 	.err_mask = 0x3f,
 	.ecc_strength = ecc_strength_mt2701,
@@ -477,6 +952,16 @@ static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = {
 	.pg_irq_sel = 0,
 };
 
+static const struct mtk_ecc_caps mtk_ecc_caps_mt7986 = {
+	.err_mask = 0x1f,
+	.ecc_strength = ecc_strength_mt7986,
+	.ecc_regs = mt7986_ecc_regs,
+	.num_ecc_strength = 11,
+	.ecc_mode_shift = 5,
+	.parity_bits = 14,
+	.pg_irq_sel = 1,
+};
+
 static const struct of_device_id mtk_ecc_dt_match[] = {
 	{
 		.compatible = "mediatek,mt2701-ecc",
@@ -487,6 +972,9 @@ static const struct of_device_id mtk_ecc_dt_match[] = {
 	}, {
 		.compatible = "mediatek,mt7622-ecc",
 		.data = &mtk_ecc_caps_mt7622,
+	}, {
+		.compatible = "mediatek,mt7986-ecc",
+		.data = &mtk_ecc_caps_mt7986,
 	},
 	{},
 };
diff --git a/include/linux/mtd/mtk_ecc.h b/include/linux/mtd/mtk_ecc.h
index 0e48c36e6ca0..a286183d16c4 100644
--- a/include/linux/mtd/mtk_ecc.h
+++ b/include/linux/mtd/mtk_ecc.h
@@ -33,6 +33,31 @@ struct mtk_ecc_config {
 	u32 len;
 };
 
+struct mtk_ecc_bad_mark_ctl {
+	void (*bm_swap)(struct nand_device *, u8 *databuf, u8* oobbuf);
+	u32 sec;
+	u32 pos;
+};
+
+struct mtk_ecc_engine {
+	struct nand_ecc_req_tweak_ctx req_ctx;
+
+	u32 oob_per_sector;
+	u32 oob_ecc;
+	u32 fdm_size;
+	u32 fdm_ecc_size;
+
+	bool read_empty;
+	u32 nsteps;
+
+	u8 *page_buf;
+	u8 *oob_buf;
+
+	struct mtk_ecc *ecc;
+	struct mtk_ecc_config ecc_cfg;
+	struct mtk_ecc_bad_mark_ctl bad_mark;
+};
+
 int mtk_ecc_encode(struct mtk_ecc *, struct mtk_ecc_config *, u8 *, u32);
 void mtk_ecc_get_stats(struct mtk_ecc *, struct mtk_ecc_stats *, int);
 int mtk_ecc_wait_done(struct mtk_ecc *, enum mtk_ecc_operation);
@@ -44,4 +69,17 @@ unsigned int mtk_ecc_get_parity_bits(struct mtk_ecc *ecc);
 struct mtk_ecc *of_mtk_ecc_get(struct device_node *);
 void mtk_ecc_release(struct mtk_ecc *);
 
+#if IS_ENABLED(CONFIG_MTD_NAND_ECC_MTK)
+
+struct nand_ecc_engine_ops *mtk_ecc_get_pipelined_ops(void);
+
+#else /* !CONFIG_MTD_NAND_ECC_MTK */
+
+struct nand_ecc_engine_ops *mtk_ecc_get_pipelined_ops(void)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_MTD_NAND_ECC_MTK */
+
 #endif
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 32fc7edf65b3..5ffd3e359515 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -265,10 +265,16 @@ struct nand_ecc_engine_ops {
 
 /**
  * struct nand_ecc_engine - ECC engine abstraction for NAND devices
+ * @dev: Host device
+ * @node: Private field for registration time
  * @ops: ECC engine operations
+ * @priv: Private data
  */
 struct nand_ecc_engine {
+	struct device *dev;
+	struct list_head node;
 	struct nand_ecc_engine_ops *ops;
+	void *priv;
 };
 
 void of_get_nand_ecc_user_config(struct nand_device *nand);
@@ -279,8 +285,13 @@ 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);
 bool nand_ecc_is_strong_enough(struct nand_device *nand);
+int nand_ecc_register_on_host_hw_engine(struct nand_ecc_engine *engine);
+int nand_ecc_unregister_on_host_hw_engine(struct nand_ecc_engine *engine);
 struct nand_ecc_engine *nand_ecc_get_sw_engine(struct nand_device *nand);
 struct nand_ecc_engine *nand_ecc_get_on_die_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_get_on_host_hw_engine(struct nand_device *nand);
+struct nand_ecc_engine *nand_ecc_match_on_host_hw_engine(struct device *dev);
+void nand_ecc_put_on_host_hw_engine(struct nand_device *nand);
 
 #if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_HAMMING)
 struct nand_ecc_engine *nand_ecc_sw_hamming_get_engine(void);
-- 
2.25.1



From geoff at infradead.org  Thu Oct 21 20:10:49 2021
From: geoff at infradead.org (Geoff Levand)
Date: Thu, 21 Oct 2021 20:10:49 -0700
Subject: [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <YW2duaTqf3qUbTIm@bombadil.infradead.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <a31970d6-8631-9d9d-a36f-8f4fcebfb1e6@infradead.org>
 <YW2duaTqf3qUbTIm@bombadil.infradead.org>
Message-ID: <24bc86d0-9d8d-8c8a-7f74-a87f9089342b@infradead.org>

Hi Luis,

On 10/18/21 9:15 AM, Luis Chamberlain wrote:
> On Sun, Oct 17, 2021 at 08:26:33AM -0700, Geoff Levand wrote:
>> Hi Luis,
>>
>> On 10/15/21 4:52 PM, Luis Chamberlain wrote:
>>> This patch set consists of al the straggler drivers for which we have
>>> have no patch reviews done for yet. I'd like to ask for folks to please
>>> consider chiming in, specially if you're the maintainer for the driver.
>>> Additionally if you can specify if you'll take the patch in yourself or
>>> if you want Jens to take it, that'd be great too.
>>
>> Do you have a git repo with the patch set applied that I can use to test with?
> 
> Sure, although the second to last patch is in a state of flux given
> the ataflop driver currently is broken and so we're seeing how to fix
> that first:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git/log/?h=20211011-for-axboe-add-disk-error-handling

That branch has so many changes applied on top of the base v5.15-rc4
that the patches I need to apply to test on PS3 with don't apply.

Do you have something closer to say v5.15-rc5?  Preferred would be
just your add_disk() error handling patches plus what they depend
on.

Thanks.

-Geoff


From richard at nod.at  Fri Oct 22 00:50:29 2021
From: richard at nod.at (Richard Weinberger)
Date: Fri, 22 Oct 2021 09:50:29 +0200 (CEST)
Subject: [PATCH] mtd/block2mtd: don't poke into block layer internals
In-Reply-To: <20211019055309.GA20805@lst.de>
References: <20211014145206.1488967-1-hch@lst.de>
 <20211014145206.1488967-2-hch@lst.de>
 <1862961222.73085.1634239699925.JavaMail.zimbra@nod.at>
 <20211019055309.GA20805@lst.de>
Message-ID: <977960225.24313.1634889029764.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "hch" <hch at lst.de>
> An: "richard" <richard at nod.at>
> CC: "hch" <hch at lst.de>, "joern" <joern at lazybastard.org>, "Miquel Raynal" <miquel.raynal at bootlin.com>, "Vignesh
> Raghavendra" <vigneshr at ti.com>, "linux-mtd" <linux-mtd at lists.infradead.org>
> Gesendet: Dienstag, 19. Oktober 2021 07:53:09
> Betreff: Re: [PATCH] mtd/block2mtd: don't poke into block layer internals

> On Thu, Oct 14, 2021 at 09:28:19PM +0200, Richard Weinberger wrote:
>> > instead.  Note that this contains a small behavior change in that erase
>> > now unconditionally writes all Fs instead of first scanning for them.
>> 
>> Unless you have a strong opinoin I'd like to keep the scanning.
>> The original use case of block2mtd is using Compact Flash (ATA)
>> as MTD. Some of this devices are super stupid and I fear the 0xFF scanning
>> is here to avoid programming 0xFF bytes into the NAND.
>> Just to be on the safe side...
> 
> I played with keeping the scanning, but it really is a mess.  Shouldn't
> the higher layers (ubi, jffs2, etc) know what has already been erased?

Well, the higher layers are allowed to unconditionally re-erase a block.
I had a short discussion with Miquel, since it is not entirely clear what
the purpose of the read-before-write logic in the erase handler is, let's
keep on the safe side and keep it.

Either it is a performance optimization because erase was super slow on
compact flash cards at the time when Joern created block2mtd.
Or they have been super stupid^Wsimple and writing 0xFF bytes to an erased
region (via mtd_erase) was problematic.
 
> Btw, Joerns address bounces.  Does anyone know if he still wants to
> maintain block2mtd and has a new address or if he should be removed from
> the maintainers list?

I sent a patch to remove him from the maintainers file.
If Joern returns I'll happily revert the patch.

Thanks,
//richard


From Tudor.Ambarus at microchip.com  Fri Oct 22 01:00:00 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 08:00:00 +0000
Subject: [PATCH v2 20/35] mtd: spi-nor: core: Use container_of to get the
 pointer to struct spi_nor
In-Reply-To: <21e6d006-228e-7834-7a4e-afbfc65fec72@rasmusvillemoes.dk>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-21-tudor.ambarus@microchip.com>
 <21e6d006-228e-7834-7a4e-afbfc65fec72@rasmusvillemoes.dk>
Message-ID: <4295413c-e6ba-db8c-eda6-8b61293b1ec6@microchip.com>

On 7/27/21 10:08 AM, Rasmus Villemoes wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 27/07/2021 06.52, Tudor Ambarus wrote:
>> Get the pointer to the containing struct spi_nor by using container_of.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>> ---
>>  drivers/mtd/spi-nor/core.c | 1 -
>>  drivers/mtd/spi-nor/core.h | 2 +-
>>  2 files changed, 1 insertion(+), 2 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 9885d434ea83..5c8cffb5e6f2 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -3175,7 +3175,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>>
>>       if (!mtd->name)
>>               mtd->name = dev_name(dev);
>> -     mtd->priv = nor;
>>       mtd->type = MTD_NORFLASH;
>>       mtd->writesize = nor->params->writesize;
>>       mtd->flags = MTD_CAP_NORFLASH;
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index 987797a789c8..8fddc685d2d3 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -557,7 +557,7 @@ void spi_nor_otp_init(struct spi_nor *nor);
>>
>>  static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
>>  {
> 
> Somewhat unrelated, but while you're here, why not get rid of that
> __maybe_unused and make this an ordinary "static inline"?
> 

Will do. Thanks.


From jack at suse.cz  Fri Oct 22 01:41:49 2021
From: jack at suse.cz (Jan Kara)
Date: Fri, 22 Oct 2021 10:41:49 +0200
Subject: [PATCH 1/5] mm: export bdi_unregister
In-Reply-To: <20211021124441.668816-2-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-2-hch@lst.de>
Message-ID: <20211022084149.GB1026@quack2.suse.cz>

On Thu 21-10-21 14:44:37, Christoph Hellwig wrote:
> To wind down the magic auto-unregister semantics we'll need to push this
> into modular code.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

> ---
>  mm/backing-dev.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/mm/backing-dev.c b/mm/backing-dev.c
> index 4a9d4e27d0d9b..8a46a0a4b72fa 100644
> --- a/mm/backing-dev.c
> +++ b/mm/backing-dev.c
> @@ -958,6 +958,7 @@ void bdi_unregister(struct backing_dev_info *bdi)
>  		bdi->owner = NULL;
>  	}
>  }
> +EXPORT_SYMBOL(bdi_unregister);
>  
>  static void release_bdi(struct kref *ref)
>  {
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Fri Oct 22 01:43:25 2021
From: jack at suse.cz (Jan Kara)
Date: Fri, 22 Oct 2021 10:43:25 +0200
Subject: [PATCH 2/5] mtd: call bdi_unregister explicitly
In-Reply-To: <20211021124441.668816-3-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-3-hch@lst.de>
Message-ID: <20211022084325.GC1026@quack2.suse.cz>

On Thu 21-10-21 14:44:38, Christoph Hellwig wrote:
> Call bdi_unregister explicitly instead of relying on the automatic
> unregistration.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

> ---
>  drivers/mtd/mtdcore.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c8fd7f758938b..c904e23c82379 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -2409,6 +2409,7 @@ static void __exit cleanup_mtd(void)
>  	if (proc_mtd)
>  		remove_proc_entry("mtd", NULL);
>  	class_unregister(&mtd_class);
> +	bdi_unregister(mtd_bdi);
>  	bdi_put(mtd_bdi);
>  	idr_destroy(&mtd_idr);
>  }
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From S.Riedmueller at phytec.de  Fri Oct 22 01:45:52 2021
From: S.Riedmueller at phytec.de (=?utf-8?B?U3RlZmFuIFJpZWRtw7xsbGVy?=)
Date: Fri, 22 Oct 2021 08:45:52 +0000
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211013050148.2w373kpbfaeuxbwm@umbrella>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
 <20211013050148.2w373kpbfaeuxbwm@umbrella>
Message-ID: <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>

Hi Han,

sorry it took me some time to get back to you.

On Wed, 2021-10-13 at 00:01 -0500, Han Xu wrote:
> On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> > According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> > when doing a gpmi_io clk rate change. So gate the clocks off before
> > the rate change in nfc_apply_timings and ungate them again after the
> > change.
> > 
> > Otherwise this rate change can lead to an unresponsive GPMI core which
> > results in DMA timeouts and failed driver probe:
> > 
> > [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> > ...
> > [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> > ...
> > [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
> > [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > ...
> > 
> > Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> > ---
> > Hi,
> > 
> > I'm not sure about the error handling here, if it is actually neccessary.
> > So some feedback would be nice here.
> > 
> > Thanks,
> > Stefan
> > ---
> >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
> >  1 file changed, 19 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > index a1f7000f033e..326c8a895f1f 100644
> > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct
> > gpmi_nand_data *this,
> >  			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD :
> > 0);
> >  }
> >  
> > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> >  {
> >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> >  	struct resources *r = &this->resources;
> >  	void __iomem *gpmi_regs = r->gpmi_regs;
> >  	unsigned int dll_wait_time_us;
> > +	int ret;
> > +
> > +	if (GPMI_IS_MX6Q(this)) {
> 
> Not only for 6Q but for GPMI_IS_MX6

Can you confirm that i.MX 6SX and i.MX 7 are affected by the ERR007117 erratum
as well? Because the i.MX 6UL/ULL are included by the GPMI_IS_MX6Q already.

Or do we need another macro for i.MX 6UL/ULL as Christian has suggested
earlier?

Thanks,
Stefan

> 
> > +		ret = __gpmi_enable_clk(this, false);
> > +		if (ret)
> > +			return ret;
> > +	}
> >  
> >  	clk_set_rate(r->clock[0], hw->clk_rate);
> >  
> > +	if (GPMI_IS_MX6Q(this)) {
> > +		ret = __gpmi_enable_clk(this, true);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> >  
> > @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct
> > gpmi_nand_data *this)
> >  
> >  	/* Wait for the DLL to settle. */
> >  	udelay(dll_wait_time_us);
> > +
> > +	return 0;
> >  }
> >  
> >  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
> >  	 */
> >  	if (this->hw.must_apply_timings) {
> >  		this->hw.must_apply_timings = false;
> > -		gpmi_nfc_apply_timings(this);
> > +		ret = gpmi_nfc_apply_timings(this);
> > +		if (ret)
> > +			return ret;
> >  	}
> >  
> >  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
> > -- 
> > 2.25.1
> > 

From jack at suse.cz  Fri Oct 22 01:48:41 2021
From: jack at suse.cz (Jan Kara)
Date: Fri, 22 Oct 2021 10:48:41 +0200
Subject: [PATCH 3/5] fs: explicitly unregister per-superblock BDIs
In-Reply-To: <20211021124441.668816-4-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-4-hch@lst.de>
Message-ID: <20211022084841.GD1026@quack2.suse.cz>

On Thu 21-10-21 14:44:39, Christoph Hellwig wrote:
> Add a new SB_I_ flag to mark superblocks that have an ephemeral bdi
> associated with them, an unregister it when the superblock is shut down.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

> ---
>  fs/super.c         | 3 +++
>  include/linux/fs.h | 1 +
>  2 files changed, 4 insertions(+)
> 
> diff --git a/fs/super.c b/fs/super.c
> index bcef3a6f4c4b5..3bfc0f8fbd5bc 100644
> --- a/fs/super.c
> +++ b/fs/super.c
> @@ -476,6 +476,8 @@ void generic_shutdown_super(struct super_block *sb)
>  	spin_unlock(&sb_lock);
>  	up_write(&sb->s_umount);
>  	if (sb->s_bdi != &noop_backing_dev_info) {
> +		if (sb->s_iflags & SB_I_PERSB_BDI)
> +			bdi_unregister(sb->s_bdi);
>  		bdi_put(sb->s_bdi);
>  		sb->s_bdi = &noop_backing_dev_info;
>  	}
> @@ -1562,6 +1564,7 @@ int super_setup_bdi_name(struct super_block *sb, char *fmt, ...)
>  	}
>  	WARN_ON(sb->s_bdi != &noop_backing_dev_info);
>  	sb->s_bdi = bdi;
> +	sb->s_iflags |= SB_I_PERSB_BDI;
>  
>  	return 0;
>  }
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index e7a633353fd20..226de651f52e6 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1443,6 +1443,7 @@ extern int send_sigurg(struct fown_struct *fown);
>  #define SB_I_UNTRUSTED_MOUNTER		0x00000040
>  
>  #define SB_I_SKIP_SYNC	0x00000100	/* Skip superblock at global sync */
> +#define SB_I_PERSB_BDI	0x00000200	/* has a per-sb bdi */
>  
>  /* Possible states of 'frozen' field */
>  enum {
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Fri Oct 22 01:51:07 2021
From: jack at suse.cz (Jan Kara)
Date: Fri, 22 Oct 2021 10:51:07 +0200
Subject: [PATCH 4/5] mm: don't automatically unregister bdis
In-Reply-To: <20211021124441.668816-5-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-5-hch@lst.de>
Message-ID: <20211022085107.GE1026@quack2.suse.cz>

On Thu 21-10-21 14:44:40, Christoph Hellwig wrote:
> All BDI users now unregister explicitly.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza

> ---
>  mm/backing-dev.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/mm/backing-dev.c b/mm/backing-dev.c
> index 8a46a0a4b72fa..768e9ae489f66 100644
> --- a/mm/backing-dev.c
> +++ b/mm/backing-dev.c
> @@ -965,8 +965,7 @@ static void release_bdi(struct kref *ref)
>  	struct backing_dev_info *bdi =
>  			container_of(ref, struct backing_dev_info, refcnt);
>  
> -	if (test_bit(WB_registered, &bdi->wb.state))
> -		bdi_unregister(bdi);
> +	WARN_ON_ONCE(test_bit(WB_registered, &bdi->wb.state));
>  	WARN_ON_ONCE(bdi->dev);
>  	wb_exit(&bdi->wb);
>  	kfree(bdi);
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From jack at suse.cz  Fri Oct 22 02:02:03 2021
From: jack at suse.cz (Jan Kara)
Date: Fri, 22 Oct 2021 11:02:03 +0200
Subject: [PATCH 5/5] mm: simplify bdi refcounting
In-Reply-To: <20211021124441.668816-6-hch@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-6-hch@lst.de>
Message-ID: <20211022090203.GF1026@quack2.suse.cz>

On Thu 21-10-21 14:44:41, Christoph Hellwig wrote:
> Move grabbing and releasing the bdi refcount out of the common
> wb_init/wb_exit helpers into code that is only used for the non-default
> memcg driven bdi_writeback structures.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Can we perhaps add a comment to struct bdi_writeback definition (or maybe
wb_init()?) mentioning that it holds a reference to 'bdi' if it is
bdi_writeback struct for a cgroup? I don't see it mentioned anywhere and
now that you've changed the code, it isn't that obvious from the code
either... Otherwise the patch looks good so feel free to add:

Reviewed-by: Jan Kara <jack at suse.cz>

								Honza


> ---
>  mm/backing-dev.c | 13 +++++--------
>  1 file changed, 5 insertions(+), 8 deletions(-)
> 
> diff --git a/mm/backing-dev.c b/mm/backing-dev.c
> index 768e9ae489f66..5ccb250898083 100644
> --- a/mm/backing-dev.c
> +++ b/mm/backing-dev.c
> @@ -291,8 +291,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
>  
>  	memset(wb, 0, sizeof(*wb));
>  
> -	if (wb != &bdi->wb)
> -		bdi_get(bdi);
>  	wb->bdi = bdi;
>  	wb->last_old_flush = jiffies;
>  	INIT_LIST_HEAD(&wb->b_dirty);
> @@ -316,7 +314,7 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
>  
>  	err = fprop_local_init_percpu(&wb->completions, gfp);
>  	if (err)
> -		goto out_put_bdi;
> +		return err;
>  
>  	for (i = 0; i < NR_WB_STAT_ITEMS; i++) {
>  		err = percpu_counter_init(&wb->stat[i], 0, gfp);
> @@ -330,9 +328,6 @@ static int wb_init(struct bdi_writeback *wb, struct backing_dev_info *bdi,
>  	while (i--)
>  		percpu_counter_destroy(&wb->stat[i]);
>  	fprop_local_destroy_percpu(&wb->completions);
> -out_put_bdi:
> -	if (wb != &bdi->wb)
> -		bdi_put(bdi);
>  	return err;
>  }
>  
> @@ -373,8 +368,6 @@ static void wb_exit(struct bdi_writeback *wb)
>  		percpu_counter_destroy(&wb->stat[i]);
>  
>  	fprop_local_destroy_percpu(&wb->completions);
> -	if (wb != &wb->bdi->wb)
> -		bdi_put(wb->bdi);
>  }
>  
>  #ifdef CONFIG_CGROUP_WRITEBACK
> @@ -397,6 +390,7 @@ static void cgwb_release_workfn(struct work_struct *work)
>  	struct bdi_writeback *wb = container_of(work, struct bdi_writeback,
>  						release_work);
>  	struct blkcg *blkcg = css_to_blkcg(wb->blkcg_css);
> +	struct backing_dev_info *bdi = wb->bdi;
>  
>  	mutex_lock(&wb->bdi->cgwb_release_mutex);
>  	wb_shutdown(wb);
> @@ -416,6 +410,7 @@ static void cgwb_release_workfn(struct work_struct *work)
>  
>  	percpu_ref_exit(&wb->refcnt);
>  	wb_exit(wb);
> +	bdi_put(bdi);
>  	WARN_ON_ONCE(!list_empty(&wb->b_attached));
>  	kfree_rcu(wb, rcu);
>  }
> @@ -497,6 +492,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
>  	INIT_LIST_HEAD(&wb->b_attached);
>  	INIT_WORK(&wb->release_work, cgwb_release_workfn);
>  	set_bit(WB_registered, &wb->state);
> +	bdi_get(bdi);
>  
>  	/*
>  	 * The root wb determines the registered state of the whole bdi and
> @@ -528,6 +524,7 @@ static int cgwb_create(struct backing_dev_info *bdi,
>  	goto out_put;
>  
>  err_fprop_exit:
> +	bdi_put(bdi);
>  	fprop_local_destroy_percpu(&wb->memcg_completions);
>  err_ref_exit:
>  	percpu_ref_exit(&wb->refcnt);
> -- 
> 2.30.2
> 
-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From michael at walle.cc  Fri Oct 22 04:21:11 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 13:21:11 +0200
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <20210817102429.kmhuef5hxumllxjj@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
Message-ID: <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>

Am 2021-08-17 12:24, schrieb Pratyush Yadav:
> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>> Used to initialize the NOR flags for settings that are not defined
>> in the JESD216 SFDP standard, thus can not be retrieved when parsing
>> SFDP. No functional change.
> 
> I am worried if the order in which these flags are set can cause some
> subtle bugs.
> 
> I can see one instance of it with SNOR_F_HAS_LOCK.
> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there are
> no locking ops specified, it sets the default locking ops. This works
> fine before this patch because the flag is set before the function is
> called. But now, the flag will be set _after_ the function is called,
> and so you will never be able to set the default flags.

Maybe we should just forbid to look at the SNOR_F_ flags in these
functions. Instead the information could also be deduced by looking at
the SPI_NOR_ flags.

-michael


From michael at walle.cc  Fri Oct 22 04:37:58 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 13:37:58 +0200
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <20211021093010.fjqriexdvsjgihkr@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
 <20211019172623.hi5c4i274bv3lnqw@ti.com>
 <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>
 <208ed4a3-fd89-9efb-6dd6-6bddc5c1d818@microchip.com>
 <20211021093010.fjqriexdvsjgihkr@ti.com>
Message-ID: <cdee860e7208267eacae884899fc6d36@walle.cc>

Am 2021-10-21 11:30, schrieb Pratyush Yadav:
> On 21/10/21 08:44AM, Tudor.Ambarus at microchip.com wrote:
>> On 10/20/21 12:55 PM, Tudor.Ambarus at microchip.com wrote:
>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>> >
>> > On 10/19/21 8:26 PM, Pratyush Yadav wrote:
>> >>>> While we are on this topic, I find this a bit "ugly". Having to set
>> >>>> late_init() for setting these flags for each flash is not exactly very
>> >>>> clean or readable. I don't know how the future will look like, but if
>> >>>> each flash/family needs its own late_init() to set some flags, it won't
>> >>>> be very readable. We seem to be trading one type of complexity for
>> >>>> another. I dunno which is the lesser evil though...
>> >>> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
>> >>> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
>> >>> the late_init() function to see what's there. As you saw, late_init() can be
>> >>> used for tweaking flash's parameters, settings and methods, not just NOR flags,
>> >>> so I would expect that this hook to be present among flashes that don't define
>> >>> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
>> >>> the hook will be there anyway.
>> >>>
>> >>> This patch opens the door on how we could handle the flash_info flags. All flash_info
>> >>> flags that can be determined when parsing SFDP can be removed and use for flashes that
>> >>> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
>> >>> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
>> >>> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
>> >>> 1/ flashes with SFDP will set the flags as:
>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> >>> 2/ flashes without SFDP:
>> >>> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> >>> spi_nor_info_init_params()
>> >>> 3/ flashes that collide, one with SFDP and the other without:
>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>> >>> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>> >> To me it looks like you can separate these flags into three classes:
>> >>
>> >>   1. Whether to parse SFDP or not.
>> >>   2. Flags that can't be discovered via SFDP.
>> >>   3. Flags that can be discovered by SFDP ideally but can't be
>> >>      discovered for this particular flash because either SFDP is missing
>> >>      or the table for this flag is missing.
>> >
>> > These are the flash_info flags, indeed. Apart of these there are the SNOR_F flags
>> > which are set either statically (one sets a flash_info flag equivalent when
>> > declaring the flash), or dynamically when parsing SFDP. Check
>> > SPI_NOR_4B_OPCODES and SNOR_F_4B_OPCODES for example.
>> >
>> >>
>> >> With your series, flags from 1 and 2 are populated via .flags in
>> >> flash_info and the ones from 3 are populated via late_init().
>> >
>> > My proposal was to get rid of the flash_info flags from the 3rd category that you
>> > described, and set the SNOR_F equivalents in a late_init() hook. This way we also
>> > control when the SNOR_F equivalents are set, late in the init call. But this can
>> > be achieved with your proposal as well, let's see.
>> >
>> >>
>> >> Why can't we have 3 different fields for these 3 different flags? In
>> >> flash_info, we can set .parse_sfdp to true/false to indicate SFDP
>> >> support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable
>> >> flags. And we can set .fixup_flags = A | B | C (can probably pick a
>> >> better name) for the flags that your series sets through late_init().
>> >>
>> >> This way, you have a clear separation between the three and they are all
>> >> clearly visible in the flash entry itself.
>> >
>> > The downside that I see with this is that we extend the flash_info struct with new
>> > fields and the spi-nor.o's size will increase whether the fields are used or not,
>> > as we have lots of flash_info entries. This reminds me that probably I should have
>> > put the late_init() hook inside const struct spi_nor_fixups. Anyway, we can avoid
>> > increasing the size with some flash_info flags masks. We use the same flash_info flags
>> > entry, but we introduce some masks, to separate the type of flags. Something like:
>> > SPI_NOR_PARSE_SFDP |
>> >         NON_SFDP_FLAGS(SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_SWP_IS_VOLATILE)
>> > these are for category 1 and 2 in your description
>> >
>> > or
>> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS(SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
>> > for categories 1 and 3 in your description
>> >
>> > but you can end up with flags like:
>> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS() | NON_SFDP_FLAGS()
>> >
>> >
>> >>
>> >> The only case where this might run into trouble is when a SFDP flash has
>> >> a collision with a non-SFDP flash and they both need different
>> >> fixup_flags. But I supposed that is a problem even if you use
>> >
>> > we can probably solve this by putting the minimum supported flags by both
>> > and fill the rest in fixup hooks after we determine which flash is which.
>> >
>> >> late_init() so it certainly doesn't make anything worse.
>> >
>> > yes, this is a different topic.
>> >
>> >>
>> >> I have not given this extensive thought, but it seems to make sense to
>> >> me, and I feel that it would make the flow easier to follow. Thoughts?
>> >
>> > Both approaches are fine. Your method keeps all flags in one place but duplicates
>> > the setting of flags, you'll have "if flash_info flag, set SNOR_F flag".
>> > Mine gets rid of the SFDP flash_info flags and directly sets SNOR_F equivalents
>> > with the detriment of introducing fixup hooks at flash declaration. Can we involve
>> > Michael and Vignesh to get their preference so that we come to an agreement and move
>> > forward?
>> >
>> 
>> I'll go with the flags mask idea.
> 
> Fine by me. I am worried about running out of flag bits but we should 
> be
> able to bump up the flags field to 64 bits without much trouble when
> that happens.

I'm sorry, I'm late to this. But I'd prefer the flags, simply because 
the
"set flags with a function" doesn't scale very well; you can't ORing
functions together. So we'll eventually have many functions for 
different
combinations of the flags.

Is running out of bits really a problem? Even if we need more than 32 
bits,
we can just use set_bit() with an array of ulongs.

-michael


From michael at walle.cc  Fri Oct 22 04:53:28 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 13:53:28 +0200
Subject: [PATCH v2 21/35] mtd: spi-nor: Introduce spi_nor_set_mtd_info()
In-Reply-To: <20210727045222.905056-22-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-22-tudor.ambarus@microchip.com>
Message-ID: <d68a7324a38c42ffb3add4d7c7bf0906@walle.cc>

Am 2021-07-27 06:52, schrieb Tudor Ambarus:
> Used to init all the mtd_info fields. Move the mtd_info init
> the last thing in the spi_nor_scan(), so that we avoid superfluous
> initialization of the mtd_info fields in case of errors.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---
>  drivers/mtd/spi-nor/core.c | 55 +++++++++++++++++++++-----------------
>  1 file changed, 31 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 5c8cffb5e6f2..26acfc9901db 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -3124,6 +3124,36 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  	return info;
>  }
> 
> +static void spi_nor_set_mtd_info(struct spi_nor *nor)
> +{
> +	struct mtd_info *mtd = &nor->mtd;
> +	struct device *dev = nor->dev;
> +
> +	spi_nor_register_locking_ops(nor);
This ..

> +
> +	/* Configure OTP parameters and ops */
> +	spi_nor_otp_init(nor);

.. this looks odd here now.

The first could be renamed to express that it only registers
mtd ops.

spi_nor_otp_init() does more - strictly speaking. That is,
it does also check that the otp region length is a power of 2.

At least it should also be renamed. But then I wonder, if in the
future there is more to do in spi_nor_otp_init(), where do we put
that then?

So mhh. I don't know. spi_nor_otp_init() is a more fitting name,
but calling it in spi_nor_set_mtd_info() is odd.

-michael


From michael at walle.cc  Fri Oct 22 04:57:06 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 13:57:06 +0200
Subject: [PATCH v2 22/35] mtd: spi-nor: core: Use common naming scheme for
 setting mtd_info fields
In-Reply-To: <20210727045222.905056-23-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-23-tudor.ambarus@microchip.com>
Message-ID: <4c0ac0a3efa3075e77260185767c8554@walle.cc>

Am 2021-07-27 06:52, schrieb Tudor Ambarus:
> The functions names are self explanatory, get rid of the comment
> for the OTP function.

Mhh. I see, this partly addresses my comments to the previous patch.
Maybe it would have been better to have this squashed into one
commit :p

But my main concern remains: what if we need more that just
the mtd callbacks assigments. Basically we loose the otp_init()
call.

-michael


From michael at walle.cc  Fri Oct 22 05:01:35 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 14:01:35 +0200
Subject: [PATCH v2 23/35] mtd: spi-nor: Get rid of nor->page_size
In-Reply-To: <20210727045222.905056-24-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-24-tudor.ambarus@microchip.com>
Message-ID: <585e8c1efafd4220f3b3e09c2396417a@walle.cc>

Am 2021-07-27 06:52, schrieb Tudor Ambarus:
> nor->page_size duplicated what nor->params->page_size indicates
> for no good reason. page_size is a flash parameter of fixed value
> and it is better suited to be found in nor->params->page_size.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>

..

>  		/* Flash in Power of 2 mode */
> -		nor->page_size = (nor->page_size == 264) ? 256 : 512;
> -		nor->mtd.writebufsize = nor->page_size;
> -		nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
> -		nor->mtd.erasesize = 8 * nor->page_size;
> +		page_size = (nor->params->page_size == 264) ? 256 : 512;

weird stuff.

Reviewed-by: Michael Walle <michael at walle.cc>


From michael at walle.cc  Fri Oct 22 05:07:13 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 14:07:13 +0200
Subject: [PATCH v2 24/35] mtd: spi-nor: core: Fix spi_nor_flash_parameter
 otp description
In-Reply-To: <20210727045222.905056-25-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-25-tudor.ambarus@microchip.com>
Message-ID: <31cf795a9c93ee3dc5fb23f15d32ca41@walle.cc>

Am 2021-07-27 06:52, schrieb Tudor Ambarus:
> Update the description of the otp member of the
> struct spi_nor_flash_parameter.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---
>  drivers/mtd/spi-nor/core.h | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 7fb0cfabe85a..501d9212ba9b 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -250,7 +250,7 @@ struct spi_nor_otp {
>   *                      higher index in the array, the higher 
> priority.
>   * @erase_map:		the erase map parsed from the SFDP Sector Map 
> Parameter
>   *                      Table.
> - * @otp_info:		describes the OTP regions.

whoops.

Reviewed-by: Michael Walle <michael at walle.cc>

> + * @otp:		SPI NOR OTP info.
>   * @octal_dtr_enable:	enables SPI NOR octal DTR mode.
>   * @quad_enable:	enables SPI NOR quad mode.
>   * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
> @@ -262,7 +262,6 @@ struct spi_nor_otp {
>   *                      e.g. different opcodes, specific address 
> calculation,
>   *                      page size, etc.
>   * @locking_ops:	SPI NOR locking methods.
> - * @otp:		SPI NOR OTP methods.
>   */
>  struct spi_nor_flash_parameter {
>  	u64				size;


From p.yadav at ti.com  Fri Oct 22 05:10:12 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 22 Oct 2021 17:40:12 +0530
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
Message-ID: <20211022121010.mzul7qsxi6s4ru2w@ti.com>

On 22/10/21 01:21PM, Michael Walle wrote:
> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
> > On 27/07/21 07:52AM, Tudor Ambarus wrote:
> > > Used to initialize the NOR flags for settings that are not defined
> > > in the JESD216 SFDP standard, thus can not be retrieved when parsing
> > > SFDP. No functional change.
> > 
> > I am worried if the order in which these flags are set can cause some
> > subtle bugs.
> > 
> > I can see one instance of it with SNOR_F_HAS_LOCK.
> > spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there are
> > no locking ops specified, it sets the default locking ops. This works
> > fine before this patch because the flag is set before the function is
> > called. But now, the flag will be set _after_ the function is called,
> > and so you will never be able to set the default flags.
> 
> Maybe we should just forbid to look at the SNOR_F_ flags in these
> functions. Instead the information could also be deduced by looking at
> the SPI_NOR_ flags.

TBH I never quite understood why we have two sets of flags in the first 
place, when the SNOR_F* flags pretty much mirror what SPI_NOR* flags 
mean. Dunno...

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From michael at walle.cc  Fri Oct 22 05:12:46 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 14:12:46 +0200
Subject: [PATCH v2 25/35] mtd: spi-nor: core: Move
 spi_nor_set_addr_width() in spi_nor_setup()
In-Reply-To: <20210727045222.905056-26-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-26-tudor.ambarus@microchip.com>
Message-ID: <4375732149fe8c96a85ee119395e7400@walle.cc>

Am 2021-07-27 06:52, schrieb Tudor Ambarus:
> spi_nor_setup() configures the SPI NOR memory. Setting the addr width
> is too a configuration, hence we can move the spi_nor_set_addr_width()
> in spi_nor_setup().
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>

..

>  static int spi_nor_setup(struct spi_nor *nor,
>  			 const struct spi_nor_hwcaps *hwcaps)
>  {
> +	int ret;
> +
>  	if (!nor->params->setup)
> -		return 0;
> +		return spi_nor_set_addr_width(nor);
> 
> -	return nor->params->setup(nor, hwcaps);
> +	ret = nor->params->setup(nor, hwcaps);
> +	if (ret)
> +		return ret;
> +
> +	return spi_nor_set_addr_width(nor);
>  }

Why not

static int spi_nor_setup(struct spi_nor *nor,
			 const struct spi_nor_hwcaps *hwcaps)
{
	int ret;

	if (nor->params->setup) {
		ret = nor->params->setup(nor, hwcaps);
		if (ret)
			return ret;
	}

	return spi_nor_set_addr_width(nor)
}

-michael


From Tudor.Ambarus at microchip.com  Fri Oct 22 05:36:58 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 12:36:58 +0000
Subject: [PATCH v2 25/35] mtd: spi-nor: core: Move
 spi_nor_set_addr_width() in spi_nor_setup()
In-Reply-To: <4375732149fe8c96a85ee119395e7400@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-26-tudor.ambarus@microchip.com>
 <4375732149fe8c96a85ee119395e7400@walle.cc>
Message-ID: <d48f232c-de8c-257f-bc21-be2354dd6106@microchip.com>

On 10/22/21 3:12 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>> spi_nor_setup() configures the SPI NOR memory. Setting the addr width
>> is too a configuration, hence we can move the spi_nor_set_addr_width()
>> in spi_nor_setup().
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> 
> ..
> 
>> ?static int spi_nor_setup(struct spi_nor *nor,
>> ?????????????????????? const struct spi_nor_hwcaps *hwcaps)
>> ?{
>> +???? int ret;
>> +
>> ????? if (!nor->params->setup)
>> -???????????? return 0;
>> +???????????? return spi_nor_set_addr_width(nor);
>>
>> -???? return nor->params->setup(nor, hwcaps);
>> +???? ret = nor->params->setup(nor, hwcaps);
>> +???? if (ret)
>> +???????????? return ret;
>> +
>> +???? return spi_nor_set_addr_width(nor);
>> ?}
> 
> Why not
> 
> static int spi_nor_setup(struct spi_nor *nor,
> ??????????????????????? const struct spi_nor_hwcaps *hwcaps)
> {
> ?????? int ret;
> 
> ?????? if (nor->params->setup) {
> ?????????????? ret = nor->params->setup(nor, hwcaps);
> ?????????????? if (ret)
> ?????????????????????? return ret;
> ?????? }
> 
> ?????? return spi_nor_set_addr_width(nor)
> }
> 
> -michael

right, I'm reworking the series right now, that's how I updated it too.

From michael at walle.cc  Fri Oct 22 05:41:17 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 14:41:17 +0200
Subject: [PATCH v2 26/35] mtd: spi-nor: core: Introduce
 spi_nor_init_default_params()
In-Reply-To: <42dd1311-7e75-a57c-c62c-d0d452608cdf@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-27-tudor.ambarus@microchip.com>
 <20210824173018.n6fw6t6mg4bwah37@ti.com>
 <42dd1311-7e75-a57c-c62c-d0d452608cdf@microchip.com>
Message-ID: <2919e1cfdf2b52780fbab6a196642d9d@walle.cc>

Am 2021-10-04 06:17, schrieb Tudor.Ambarus at microchip.com:
> On 8/24/21 8:30 PM, Pratyush Yadav wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>> Called for all flashes, regardless if they define SFDP tables or not.
>>> 
>>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>>> ---
>>>  drivers/mtd/spi-nor/core.c | 92 
>>> +++++++++++++++++++++-----------------
>>>  1 file changed, 52 insertions(+), 40 deletions(-)
>>> 
>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> index b3a01d7d6f0b..9193317f897d 100644
>>> --- a/drivers/mtd/spi-nor/core.c
>>> +++ b/drivers/mtd/spi-nor/core.c
>>> @@ -2543,6 +2543,56 @@ static int spi_nor_setup(struct spi_nor *nor,
>>>       return spi_nor_set_addr_width(nor);
>>>  }
>>> 
>>> +/**
>>> + * spi_nor_init_default_params() - Default initialization of flash 
>>> parameters
>>> + * and settings. Done for all flashes, regardless is they define 
>>> SFDP tables
>>> + * or not.
>>> + * @nor:     pointer to a 'struct spi_nor'.
>>> + */
>>> +static void spi_nor_init_default_params(struct spi_nor *nor)
>>> +{
>>> +     struct spi_nor_flash_parameter *params = nor->params;
>>> +     const struct flash_info *info = nor->info;
>>> +     struct device_node *np = spi_nor_get_flash_node(nor);
>>> +
>>> +     params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>>> +     params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>>> +     params->setup = spi_nor_default_setup;
>>> +     params->otp.org = &info->otp_org;
>>> +
>>> +     /* Default to 16-bit Write Status (01h) Command */
>>> +     nor->flags |= SNOR_F_HAS_16BIT_SR;
>>> +
>>> +     /* Set SPI NOR sizes. */
>>> +     params->writesize = 1;
>>> +     params->size = (u64)info->sector_size * info->n_sectors;
>>> +     params->page_size = info->page_size;
>> 
>> I think these two lines should go in spi_nor_info_init_params() since
>> you are using the nor info to initialize these parameters. Otherwise,
>> what even is the difference between these two functions?
> 
> I think a better name for spi_nor_info_init_params() is
> spi_nor_nonsfdp_info_init_params(). This method will eventually be 
> called
> just for non SFDP flashes. Check conversation in 18/35.
> 
> And maybe I should rename spi_nor_nonsfdp_flags_init to
> spi_nor_nonsfdp_info_init_snor_f.

Urgh. I really dislike that suffix. Somehow the flags prefix
creeps into the function name. If that function is expected
to only set the SNOR_F_ flags then there should be a comment.

>> 
>>> +
>>> +     if (!(info->flags & SPI_NOR_NO_FR)) {
>>> +             /* Default to Fast Read for DT and non-DT platform 
>>> devices. */
>>> +             params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>>> +
>>> +             /* Mask out Fast Read if not requested at DT 
>>> instantiation. */
>>> +             if (np && !of_property_read_bool(np, "m25p,fast-read"))
>>> +                     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>>> +     }

Hm, this looks really weird.

why not:

/* default to fast read */
params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;

/* unless the flash doesn't support it */
if (info->flags & SPI_NOR_NO_FR)
     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;

/* or the device tree doesn't explicitly request it */
if (np && !of_property_read_bool(np, "m25p,fast-read"))
     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;

I know the old code was the same, but it might go into another
patch. The SPI_NOR_NO_FR suggests that fast read was always the
default. Otherwise, it would have been SPI_NOR_HAS_FAST_READ.

>>> +
>>> +     /* (Fast) Read settings. */
>>> +     params->hwcaps.mask |= SNOR_HWCAPS_READ;
>>> +     spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>>> +                               0, 0, SPINOR_OP_READ,
>>> +                               SNOR_PROTO_1_1_1);
>>> +
>>> +     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>>> +             
>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>>> +                                       0, 8, SPINOR_OP_READ_FAST,
>>> +                                       SNOR_PROTO_1_1_1);
>>> +     /* Page Program settings. */
>>> +     params->hwcaps.mask |= SNOR_HWCAPS_PP;
>>> +     spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>>> +                             SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>>> +}
>>> +
>>>  /**
>>>   * spi_nor_manufacturer_init_params() - Initialize the flash's 
>>> parameters and
>>>   * settings based on MFR register and ->default_init() hook.
>>> @@ -2609,43 +2659,8 @@ static void spi_nor_info_init_params(struct 
>>> spi_nor *nor)
>>>       struct spi_nor_flash_parameter *params = nor->params;
>>>       struct spi_nor_erase_map *map = &params->erase_map;
>>>       const struct flash_info *info = nor->info;
>>> -     struct device_node *np = spi_nor_get_flash_node(nor);
>>>       u8 i, erase_mask;
>>> 
>>> -     /* Initialize default flash parameters and settings. */
>>> -     params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>>> -     params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>>> -     params->setup = spi_nor_default_setup;
>>> -     params->otp.org = &info->otp_org;
>>> -
>>> -     /* Default to 16-bit Write Status (01h) Command */
>>> -     nor->flags |= SNOR_F_HAS_16BIT_SR;
>>> -
>>> -     /* Set SPI NOR sizes. */
>>> -     params->writesize = 1;
>>> -     params->size = (u64)info->sector_size * info->n_sectors;
>>> -     params->page_size = info->page_size;
>>> -
>>> -     if (!(info->flags & SPI_NOR_NO_FR)) {
>>> -             /* Default to Fast Read for DT and non-DT platform 
>>> devices. */
>>> -             params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>>> -
>>> -             /* Mask out Fast Read if not requested at DT 
>>> instantiation. */
>>> -             if (np && !of_property_read_bool(np, "m25p,fast-read"))
>>> -                     params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>>> -     }
>>> -
>>> -     /* (Fast) Read settings. */
>>> -     params->hwcaps.mask |= SNOR_HWCAPS_READ;
>>> -     spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>>> -                               0, 0, SPINOR_OP_READ,
>>> -                               SNOR_PROTO_1_1_1);
>>> -
>>> -     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>>> -             
>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>>> -                                       0, 8, SPINOR_OP_READ_FAST,
>>> -                                       SNOR_PROTO_1_1_1);
>>> -
>>>       if (info->flags & SPI_NOR_DUAL_READ) {
>>>               params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
>>>               
>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],
>>> @@ -2674,11 +2689,6 @@ static void spi_nor_info_init_params(struct 
>>> spi_nor *nor)
>>>                                         SNOR_PROTO_8_8_8_DTR);
>>>       }
>>> 
>>> -     /* Page Program settings. */
>>> -     params->hwcaps.mask |= SNOR_HWCAPS_PP;
>>> -     spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>>> -                             SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>>> -
>>>       if (info->flags & SPI_NOR_OCTAL_DTR_PP) {
>>>               params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
>>>               /*
>>> @@ -2823,6 +2833,8 @@ static int spi_nor_init_params(struct spi_nor 
>>> *nor)
>>>       if (!nor->params)
>>>               return -ENOMEM;
>>> 
>>> +     spi_nor_init_default_params(nor);
>>> +
>>>       spi_nor_info_init_params(nor);
>>> 
>>>       spi_nor_manufacturer_init_params(nor);
>> 
>> I am neutral towards this patch. I don't think it improves much, but 
>> at
>> the same time it doesn't make anything worse either.
> 
> I think it helps readability. It splits spi_nor_init_params() into
> smaller logical chunks,
> based on the type of initialization. We should usually avoid long
> methods where we can split
> them in logical chunks, it makes the code pleasant to read.

I'm fine with that. Just want to say, that then we have to think
about what goes where and where we draw the line.

-michael


From Tudor.Ambarus at microchip.com  Fri Oct 22 05:42:18 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 12:42:18 +0000
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <20211022121010.mzul7qsxi6s4ru2w@ti.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
 <20211022121010.mzul7qsxi6s4ru2w@ti.com>
Message-ID: <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>

On 10/22/21 3:10 PM, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 22/10/21 01:21PM, Michael Walle wrote:
>> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>> Used to initialize the NOR flags for settings that are not defined
>>>> in the JESD216 SFDP standard, thus can not be retrieved when parsing
>>>> SFDP. No functional change.
>>>
>>> I am worried if the order in which these flags are set can cause some
>>> subtle bugs.
>>>
>>> I can see one instance of it with SNOR_F_HAS_LOCK.
>>> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there are
>>> no locking ops specified, it sets the default locking ops. This works
>>> fine before this patch because the flag is set before the function is
>>> called. But now, the flag will be set _after_ the function is called,
>>> and so you will never be able to set the default flags.
>>
>> Maybe we should just forbid to look at the SNOR_F_ flags in these
>> functions. Instead the information could also be deduced by looking at
>> the SPI_NOR_ flags.

not true.

> 
> TBH I never quite understood why we have two sets of flags in the first
> place, when the SNOR_F* flags pretty much mirror what SPI_NOR* flags
> mean. Dunno...
> 
struct spi_nor { 
cut
        const struct flash_info *info;  
cut
}

const, which is the way it should be. Every flag that is discovered at SFDP
time will fill the SNOR_F correspondent, and only SNOR_F will be used across
the core driver.


From Tudor.Ambarus at microchip.com  Fri Oct 22 05:43:36 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 12:43:36 +0000
Subject: [PATCH v2 18/35] mtd: spi-nor: Get rid of SPI_NOR_4B_OPCODES flag
In-Reply-To: <cdee860e7208267eacae884899fc6d36@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-19-tudor.ambarus@microchip.com>
 <20210817121626.5vcwuluheqfqrqc3@ti.com>
 <d7d7b602-0c42-dc14-71f5-9b89303a0941@microchip.com>
 <20211019172623.hi5c4i274bv3lnqw@ti.com>
 <e3e5c59e-08c0-07c7-e77a-5edfc3502388@microchip.com>
 <208ed4a3-fd89-9efb-6dd6-6bddc5c1d818@microchip.com>
 <20211021093010.fjqriexdvsjgihkr@ti.com>
 <cdee860e7208267eacae884899fc6d36@walle.cc>
Message-ID: <6989d2e0-8397-f512-2019-79e4f0895c13@microchip.com>

On 10/22/21 2:37 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-10-21 11:30, schrieb Pratyush Yadav:
>> On 21/10/21 08:44AM, Tudor.Ambarus at microchip.com wrote:
>>> On 10/20/21 12:55 PM, Tudor.Ambarus at microchip.com wrote:
>>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>> >
>>> > On 10/19/21 8:26 PM, Pratyush Yadav wrote:
>>> >>>> While we are on this topic, I find this a bit "ugly". Having to set
>>> >>>> late_init() for setting these flags for each flash is not exactly very
>>> >>>> clean or readable. I don't know how the future will look like, but if
>>> >>>> each flash/family needs its own late_init() to set some flags, it won't
>>> >>>> be very readable. We seem to be trading one type of complexity for
>>> >>>> another. I dunno which is the lesser evil though...
>>> >>> Your point is valid. This patch removes SPI_NOR_4B_OPCODES and sets
>>> >>> SNOR_F_4B_OPCODES in a late_init() hook, forcing the reader to go through
>>> >>> the late_init() function to see what's there. As you saw, late_init() can be
>>> >>> used for tweaking flash's parameters, settings and methods, not just NOR flags,
>>> >>> so I would expect that this hook to be present among flashes that don't define
>>> >>> the SFDP tables or for flashes that have parameters that are not SFDP discoverable,
>>> >>> the hook will be there anyway.
>>> >>>
>>> >>> This patch opens the door on how we could handle the flash_info flags. All flash_info
>>> >>> flags that can be determined when parsing SFDP can be removed and use for flashes that
>>> >>> skip SFDP, SNOR_F equivalents in late_init() methods. spi_nor_info_init_params()
>>> >>> should NOT be called for SFDP capable flashes anyway, because in case of SFDP flashes,
>>> >>> all the settings done in spi_nor_info_init_params() are overwritten when parsing SFDP.
>>> >>> 1/ flashes with SFDP will set the flags as:
>>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> >>> 2/ flashes without SFDP:
>>> >>> SPI_NOR_SKIP_SFDP | non-sfdp-discoverable-flags
>>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> >>> spi_nor_info_init_params()
>>> >>> 3/ flashes that collide, one with SFDP and the other without:
>>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>>> >>> 4/ individual flash, no collisions, a flavor supports SFDP, the other not:
>>> >>> SPI_NOR_PARSE_SFDP | non-sfdp-discoverable-flags
>>> >>> and a late_init() for SNOR_F equivalents of flash_info flags from
>>> >>> spi_nor_info_init_params(), that will be used for the flash without SFDP.
>>> >> To me it looks like you can separate these flags into three classes:
>>> >>
>>> >>?? 1. Whether to parse SFDP or not.
>>> >>?? 2. Flags that can't be discovered via SFDP.
>>> >>?? 3. Flags that can be discovered by SFDP ideally but can't be
>>> >>????? discovered for this particular flash because either SFDP is missing
>>> >>????? or the table for this flag is missing.
>>> >
>>> > These are the flash_info flags, indeed. Apart of these there are the SNOR_F flags
>>> > which are set either statically (one sets a flash_info flag equivalent when
>>> > declaring the flash), or dynamically when parsing SFDP. Check
>>> > SPI_NOR_4B_OPCODES and SNOR_F_4B_OPCODES for example.
>>> >
>>> >>
>>> >> With your series, flags from 1 and 2 are populated via .flags in
>>> >> flash_info and the ones from 3 are populated via late_init().
>>> >
>>> > My proposal was to get rid of the flash_info flags from the 3rd category that you
>>> > described, and set the SNOR_F equivalents in a late_init() hook. This way we also
>>> > control when the SNOR_F equivalents are set, late in the init call. But this can
>>> > be achieved with your proposal as well, let's see.
>>> >
>>> >>
>>> >> Why can't we have 3 different fields for these 3 different flags? In
>>> >> flash_info, we can set .parse_sfdp to true/false to indicate SFDP
>>> >> support. We can set .nonsfdp_flags = X | Y | Z for non-sfdp-discoverable
>>> >> flags. And we can set .fixup_flags = A | B | C (can probably pick a
>>> >> better name) for the flags that your series sets through late_init().
>>> >>
>>> >> This way, you have a clear separation between the three and they are all
>>> >> clearly visible in the flash entry itself.
>>> >
>>> > The downside that I see with this is that we extend the flash_info struct with new
>>> > fields and the spi-nor.o's size will increase whether the fields are used or not,
>>> > as we have lots of flash_info entries. This reminds me that probably I should have
>>> > put the late_init() hook inside const struct spi_nor_fixups. Anyway, we can avoid
>>> > increasing the size with some flash_info flags masks. We use the same flash_info flags
>>> > entry, but we introduce some masks, to separate the type of flags. Something like:
>>> > SPI_NOR_PARSE_SFDP |
>>> >???????? NON_SFDP_FLAGS(SPI_NOR_TB_SR_BIT6 | SPI_NOR_4BIT_BP | SPI_NOR_SWP_IS_VOLATILE)
>>> > these are for category 1 and 2 in your description
>>> >
>>> > or
>>> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS(SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP)
>>> > for categories 1 and 3 in your description
>>> >
>>> > but you can end up with flags like:
>>> > SPI_NOR_SKIP_SFDP | SFDP_FLAGS() | NON_SFDP_FLAGS()
>>> >
>>> >
>>> >>
>>> >> The only case where this might run into trouble is when a SFDP flash has
>>> >> a collision with a non-SFDP flash and they both need different
>>> >> fixup_flags. But I supposed that is a problem even if you use
>>> >
>>> > we can probably solve this by putting the minimum supported flags by both
>>> > and fill the rest in fixup hooks after we determine which flash is which.
>>> >
>>> >> late_init() so it certainly doesn't make anything worse.
>>> >
>>> > yes, this is a different topic.
>>> >
>>> >>
>>> >> I have not given this extensive thought, but it seems to make sense to
>>> >> me, and I feel that it would make the flow easier to follow. Thoughts?
>>> >
>>> > Both approaches are fine. Your method keeps all flags in one place but duplicates
>>> > the setting of flags, you'll have "if flash_info flag, set SNOR_F flag".
>>> > Mine gets rid of the SFDP flash_info flags and directly sets SNOR_F equivalents
>>> > with the detriment of introducing fixup hooks at flash declaration. Can we involve
>>> > Michael and Vignesh to get their preference so that we come to an agreement and move
>>> > forward?
>>> >
>>>
>>> I'll go with the flags mask idea.
>>
>> Fine by me. I am worried about running out of flag bits but we should
>> be
>> able to bump up the flags field to 64 bits without much trouble when
>> that happens.
> 
> I'm sorry, I'm late to this. But I'd prefer the flags, simply because
> the
> "set flags with a function" doesn't scale very well; you can't ORing
> functions together. So we'll eventually have many functions for
> different
> combinations of the flags.
> 
> Is running out of bits really a problem? Even if we need more than 32
> bits,
> we can just use set_bit() with an array of ulongs.

right. Anyway, we should aim to have less and less flags. I'll try to get rid
of few.

Cheers,
ta


From Tudor.Ambarus at microchip.com  Fri Oct 22 05:51:04 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 12:51:04 +0000
Subject: [PATCH v2 22/35] mtd: spi-nor: core: Use common naming scheme for
 setting mtd_info fields
In-Reply-To: <4c0ac0a3efa3075e77260185767c8554@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-23-tudor.ambarus@microchip.com>
 <4c0ac0a3efa3075e77260185767c8554@walle.cc>
Message-ID: <7d264652-abcb-b317-7745-36995deff003@microchip.com>

On 10/22/21 2:57 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>> The functions names are self explanatory, get rid of the comment
>> for the OTP function.
> 
> Mhh. I see, this partly addresses my comments to the previous patch.
> Maybe it would have been better to have this squashed into one
> commit :p

one thing per patch

> 
> But my main concern remains: what if we need more that just
> the mtd callbacks assigments. Basically we loose the otp_init()
> call.

        if (WARN_ON(!is_power_of_2(spi_nor_otp_region_len(nor))))               
                return;

is there just to avoid setting the mtd function pointers when OTP
region length is not power of 2. This is not an init, just a check,
so for the moment I see it ok to have it in spi_nor_set_mtd_otp_ops().

If some OTP init is required we'll introduce it.

From Tudor.Ambarus at microchip.com  Fri Oct 22 05:55:26 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 12:55:26 +0000
Subject: [PATCH v2 26/35] mtd: spi-nor: core: Introduce
 spi_nor_init_default_params()
In-Reply-To: <2919e1cfdf2b52780fbab6a196642d9d@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-27-tudor.ambarus@microchip.com>
 <20210824173018.n6fw6t6mg4bwah37@ti.com>
 <42dd1311-7e75-a57c-c62c-d0d452608cdf@microchip.com>
 <2919e1cfdf2b52780fbab6a196642d9d@walle.cc>
Message-ID: <f1630106-2e62-30d5-0613-abac800f6f2b@microchip.com>

On 10/22/21 3:41 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-10-04 06:17, schrieb Tudor.Ambarus at microchip.com:
>> On 8/24/21 8:30 PM, Pratyush Yadav wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know
>>> the content is safe
>>>
>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>> Called for all flashes, regardless if they define SFDP tables or not.
>>>>
>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
>>>> ---
>>>> ?drivers/mtd/spi-nor/core.c | 92
>>>> +++++++++++++++++++++-----------------
>>>> ?1 file changed, 52 insertions(+), 40 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>> index b3a01d7d6f0b..9193317f897d 100644
>>>> --- a/drivers/mtd/spi-nor/core.c
>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>> @@ -2543,6 +2543,56 @@ static int spi_nor_setup(struct spi_nor *nor,
>>>> ????? return spi_nor_set_addr_width(nor);
>>>> ?}
>>>>
>>>> +/**
>>>> + * spi_nor_init_default_params() - Default initialization of flash
>>>> parameters
>>>> + * and settings. Done for all flashes, regardless is they define
>>>> SFDP tables
>>>> + * or not.
>>>> + * @nor:???? pointer to a 'struct spi_nor'.
>>>> + */
>>>> +static void spi_nor_init_default_params(struct spi_nor *nor)
>>>> +{
>>>> +???? struct spi_nor_flash_parameter *params = nor->params;
>>>> +???? const struct flash_info *info = nor->info;
>>>> +???? struct device_node *np = spi_nor_get_flash_node(nor);
>>>> +
>>>> +???? params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>>>> +???? params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>>>> +???? params->setup = spi_nor_default_setup;
>>>> +???? params->otp.org = &info->otp_org;
>>>> +
>>>> +???? /* Default to 16-bit Write Status (01h) Command */
>>>> +???? nor->flags |= SNOR_F_HAS_16BIT_SR;
>>>> +
>>>> +???? /* Set SPI NOR sizes. */
>>>> +???? params->writesize = 1;
>>>> +???? params->size = (u64)info->sector_size * info->n_sectors;
>>>> +???? params->page_size = info->page_size;
>>>
>>> I think these two lines should go in spi_nor_info_init_params() since
>>> you are using the nor info to initialize these parameters. Otherwise,
>>> what even is the difference between these two functions?
>>
>> I think a better name for spi_nor_info_init_params() is
>> spi_nor_nonsfdp_info_init_params(). This method will eventually be
>> called
>> just for non SFDP flashes. Check conversation in 18/35.
>>
>> And maybe I should rename spi_nor_nonsfdp_flags_init to
>> spi_nor_nonsfdp_info_init_snor_f.
> 
> Urgh. I really dislike that suffix. Somehow the flags prefix

:) I'll think of something better then.

> creeps into the function name. If that function is expected
> to only set the SNOR_F_ flags then there should be a comment.
> 
>>>
>>>> +
>>>> +???? if (!(info->flags & SPI_NOR_NO_FR)) {
>>>> +???????????? /* Default to Fast Read for DT and non-DT platform
>>>> devices. */
>>>> +???????????? params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>>>> +
>>>> +???????????? /* Mask out Fast Read if not requested at DT
>>>> instantiation. */
>>>> +???????????? if (np && !of_property_read_bool(np, "m25p,fast-read"))
>>>> +???????????????????? params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>>>> +???? }
> 
> Hm, this looks really weird.
> 
> why not:
> 
> /* default to fast read */
> params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
> 
> /* unless the flash doesn't support it */
> if (info->flags & SPI_NOR_NO_FR)
> ??? params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> 
> /* or the device tree doesn't explicitly request it */
> if (np && !of_property_read_bool(np, "m25p,fast-read"))
> ??? params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> 
> I know the old code was the same, but it might go into another
> patch. The SPI_NOR_NO_FR suggests that fast read was always the

right, dedicated patch. I'll check it.

> default. Otherwise, it would have been SPI_NOR_HAS_FAST_READ.

> 
>>>> +
>>>> +???? /* (Fast) Read settings. */
>>>> +???? params->hwcaps.mask |= SNOR_HWCAPS_READ;
>>>> +???? spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>>>> +?????????????????????????????? 0, 0, SPINOR_OP_READ,
>>>> +?????????????????????????????? SNOR_PROTO_1_1_1);
>>>> +
>>>> +???? if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>>>> +
>>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>>>> +?????????????????????????????????????? 0, 8, SPINOR_OP_READ_FAST,
>>>> +?????????????????????????????????????? SNOR_PROTO_1_1_1);
>>>> +???? /* Page Program settings. */
>>>> +???? params->hwcaps.mask |= SNOR_HWCAPS_PP;
>>>> +???? spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>>>> +???????????????????????????? SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>>>> +}
>>>> +
>>>> ?/**
>>>> ? * spi_nor_manufacturer_init_params() - Initialize the flash's
>>>> parameters and
>>>> ? * settings based on MFR register and ->default_init() hook.
>>>> @@ -2609,43 +2659,8 @@ static void spi_nor_info_init_params(struct
>>>> spi_nor *nor)
>>>> ????? struct spi_nor_flash_parameter *params = nor->params;
>>>> ????? struct spi_nor_erase_map *map = &params->erase_map;
>>>> ????? const struct flash_info *info = nor->info;
>>>> -???? struct device_node *np = spi_nor_get_flash_node(nor);
>>>> ????? u8 i, erase_mask;
>>>>
>>>> -???? /* Initialize default flash parameters and settings. */
>>>> -???? params->quad_enable = spi_nor_sr2_bit1_quad_enable;
>>>> -???? params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
>>>> -???? params->setup = spi_nor_default_setup;
>>>> -???? params->otp.org = &info->otp_org;
>>>> -
>>>> -???? /* Default to 16-bit Write Status (01h) Command */
>>>> -???? nor->flags |= SNOR_F_HAS_16BIT_SR;
>>>> -
>>>> -???? /* Set SPI NOR sizes. */
>>>> -???? params->writesize = 1;
>>>> -???? params->size = (u64)info->sector_size * info->n_sectors;
>>>> -???? params->page_size = info->page_size;
>>>> -
>>>> -???? if (!(info->flags & SPI_NOR_NO_FR)) {
>>>> -???????????? /* Default to Fast Read for DT and non-DT platform
>>>> devices. */
>>>> -???????????? params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>>>> -
>>>> -???????????? /* Mask out Fast Read if not requested at DT
>>>> instantiation. */
>>>> -???????????? if (np && !of_property_read_bool(np, "m25p,fast-read"))
>>>> -???????????????????? params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>>>> -???? }
>>>> -
>>>> -???? /* (Fast) Read settings. */
>>>> -???? params->hwcaps.mask |= SNOR_HWCAPS_READ;
>>>> -???? spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
>>>> -?????????????????????????????? 0, 0, SPINOR_OP_READ,
>>>> -?????????????????????????????? SNOR_PROTO_1_1_1);
>>>> -
>>>> -???? if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>>>> -
>>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
>>>> -?????????????????????????????????????? 0, 8, SPINOR_OP_READ_FAST,
>>>> -?????????????????????????????????????? SNOR_PROTO_1_1_1);
>>>> -
>>>> ????? if (info->flags & SPI_NOR_DUAL_READ) {
>>>> ????????????? params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
>>>>
>>>> spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],
>>>> @@ -2674,11 +2689,6 @@ static void spi_nor_info_init_params(struct
>>>> spi_nor *nor)
>>>> ??????????????????????????????????????? SNOR_PROTO_8_8_8_DTR);
>>>> ????? }
>>>>
>>>> -???? /* Page Program settings. */
>>>> -???? params->hwcaps.mask |= SNOR_HWCAPS_PP;
>>>> -???? spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
>>>> -???????????????????????????? SPINOR_OP_PP, SNOR_PROTO_1_1_1);
>>>> -
>>>> ????? if (info->flags & SPI_NOR_OCTAL_DTR_PP) {
>>>> ????????????? params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
>>>> ????????????? /*
>>>> @@ -2823,6 +2833,8 @@ static int spi_nor_init_params(struct spi_nor
>>>> *nor)
>>>> ????? if (!nor->params)
>>>> ????????????? return -ENOMEM;
>>>>
>>>> +???? spi_nor_init_default_params(nor);
>>>> +
>>>> ????? spi_nor_info_init_params(nor);
>>>>
>>>> ????? spi_nor_manufacturer_init_params(nor);
>>>
>>> I am neutral towards this patch. I don't think it improves much, but
>>> at
>>> the same time it doesn't make anything worse either.
>>
>> I think it helps readability. It splits spi_nor_init_params() into
>> smaller logical chunks,
>> based on the type of initialization. We should usually avoid long
>> methods where we can split
>> them in logical chunks, it makes the code pleasant to read.
> 
> I'm fine with that. Just want to say, that then we have to think
> about what goes where and where we draw the line.
> 

Okay, I'll propose some guidance in the commit message.

From michael at walle.cc  Fri Oct 22 05:59:19 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 14:59:19 +0200
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
 <20211022121010.mzul7qsxi6s4ru2w@ti.com>
 <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>
Message-ID: <5a1497c9b2f07b2e6b91deb8ef17646f@walle.cc>

Am 2021-10-22 14:42, schrieb Tudor.Ambarus at microchip.com:
> On 10/22/21 3:10 PM, Pratyush Yadav wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> On 22/10/21 01:21PM, Michael Walle wrote:
>>> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
>>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>>> Used to initialize the NOR flags for settings that are not defined
>>>>> in the JESD216 SFDP standard, thus can not be retrieved when 
>>>>> parsing
>>>>> SFDP. No functional change.
>>>> 
>>>> I am worried if the order in which these flags are set can cause 
>>>> some
>>>> subtle bugs.
>>>> 
>>>> I can see one instance of it with SNOR_F_HAS_LOCK.
>>>> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there 
>>>> are
>>>> no locking ops specified, it sets the default locking ops. This 
>>>> works
>>>> fine before this patch because the flag is set before the function 
>>>> is
>>>> called. But now, the flag will be set _after_ the function is 
>>>> called,
>>>> and so you will never be able to set the default flags.
>>> 
>>> Maybe we should just forbid to look at the SNOR_F_ flags in these
>>> functions. Instead the information could also be deduced by looking 
>>> at
>>> the SPI_NOR_ flags.
> 
> not true.

I guess you mean that some init flash init functions might set it, too.
Right? IMHO this goes into the spaghetti code direction again.
spi_nor_late_init_params() must not look at the SNOR_F_ flags. There
are too much inter-function dependencies and it is really hard to
follow the call chain.

The locking ops should also go into the (static) flash init which only
depends on the SPI_NOR_ flags. If SNOR_F_HAS_LOCK will be added at
in an init function, then this code should also take care of setting
the correct locking ops. Maybe both can be set together with a helper.

-michael


From michael at walle.cc  Fri Oct 22 06:08:46 2021
From: michael at walle.cc (Michael Walle)
Date: Fri, 22 Oct 2021 15:08:46 +0200
Subject: [PATCH v2 22/35] mtd: spi-nor: core: Use common naming scheme for
 setting mtd_info fields
In-Reply-To: <7d264652-abcb-b317-7745-36995deff003@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-23-tudor.ambarus@microchip.com>
 <4c0ac0a3efa3075e77260185767c8554@walle.cc>
 <7d264652-abcb-b317-7745-36995deff003@microchip.com>
Message-ID: <9c08f234068d328dd229893e836cda60@walle.cc>

Am 2021-10-22 14:51, schrieb Tudor.Ambarus at microchip.com:
> On 10/22/21 2:57 PM, Michael Walle wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>>> The functions names are self explanatory, get rid of the comment
>>> for the OTP function.
>> 
>> Mhh. I see, this partly addresses my comments to the previous patch.
>> Maybe it would have been better to have this squashed into one
>> commit :p
> 
> one thing per patch

well it is really just one thing, you're moving the function. but then
the function name doesn't make sense anymore. So the patch on its own
is wrong or at least it makes things worse. Also, I'm reviewing that
just to see this function was renamed (correctly) in the next patch.

>> But my main concern remains: what if we need more that just
>> the mtd callbacks assigments. Basically we loose the otp_init()
>> call.
> 
>         if (WARN_ON(!is_power_of_2(spi_nor_otp_region_len(nor))))
>                 return;
> 
> is there just to avoid setting the mtd function pointers when OTP
> region length is not power of 2. This is not an init, just a check,
> so for the moment I see it ok to have it in spi_nor_set_mtd_otp_ops().

It is a sanity check which actually has nothing to do with the mtd ops
registration. Just to see if there was a mistake in the otp info flags.

Of course, if that is not the case, we don't set the ops. But that 
doesn't
mean it is part of the mtd op assigment.

I said stricly speaking, I'm ok with having that in the (now renamed)
"otp set mtd ops" function.

-michael


From Tudor.Ambarus at microchip.com  Fri Oct 22 06:25:56 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 13:25:56 +0000
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <5a1497c9b2f07b2e6b91deb8ef17646f@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
 <20211022121010.mzul7qsxi6s4ru2w@ti.com>
 <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>
 <5a1497c9b2f07b2e6b91deb8ef17646f@walle.cc>
Message-ID: <9bf93cbf-fc57-54ae-2439-45e4d75dc0b7@microchip.com>

On 10/22/21 3:59 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-10-22 14:42, schrieb Tudor.Ambarus at microchip.com:
>> On 10/22/21 3:10 PM, Pratyush Yadav wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know
>>> the content is safe
>>>
>>> On 22/10/21 01:21PM, Michael Walle wrote:
>>>> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
>>>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>>>> Used to initialize the NOR flags for settings that are not defined
>>>>>> in the JESD216 SFDP standard, thus can not be retrieved when
>>>>>> parsing
>>>>>> SFDP. No functional change.
>>>>>
>>>>> I am worried if the order in which these flags are set can cause
>>>>> some
>>>>> subtle bugs.
>>>>>
>>>>> I can see one instance of it with SNOR_F_HAS_LOCK.
>>>>> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there
>>>>> are
>>>>> no locking ops specified, it sets the default locking ops. This
>>>>> works
>>>>> fine before this patch because the flag is set before the function
>>>>> is
>>>>> called. But now, the flag will be set _after_ the function is
>>>>> called,
>>>>> and so you will never be able to set the default flags.
>>>>
>>>> Maybe we should just forbid to look at the SNOR_F_ flags in these
>>>> functions. Instead the information could also be deduced by looking
>>>> at
>>>> the SPI_NOR_ flags.
>>
>> not true.
> 
> I guess you mean that some init flash init functions might set it, too.
> Right? IMHO this goes into the spaghetti code direction again.
> spi_nor_late_init_params() must not look at the SNOR_F_ flags. There
> are too much inter-function dependencies and it is really hard to
> follow the call chain.

I don't think I understand what you are referring to. The flash_info flags
are used just to set their SNOR_F correspondents. Take SNOR_F_4B_OPCODES for
example. A flash that can't discover 4b opcodes support when parsing SFDP,
will set the SPI_NOR_4B_OPCODES flash_info flag. Flashes that can discover it,
will ignore/not set the SPI_NOR_4B_OPCODES flag, and let the SFDP do its thing:
the SFDP code will set the SNOR_F_4B_OPCODES flag. The only flags that are used
across the SPI NOR core are the nor->flags (SNOR_F).
> 
> The locking ops should also go into the (static) flash init which only
> depends on the SPI_NOR_ flags. If SNOR_F_HAS_LOCK will be added at

we don't have to specify the locking methods, we have generic ones. A single
flag is enough.

> in an init function, then this code should also take care of setting

what init function? We're just setting some flags.

> the correct locking ops. Maybe both can be set together with a helper.

From Tudor.Ambarus at microchip.com  Fri Oct 22 06:34:02 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 22 Oct 2021 13:34:02 +0000
Subject: [PATCH v2 22/35] mtd: spi-nor: core: Use common naming scheme for
 setting mtd_info fields
In-Reply-To: <9c08f234068d328dd229893e836cda60@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-23-tudor.ambarus@microchip.com>
 <4c0ac0a3efa3075e77260185767c8554@walle.cc>
 <7d264652-abcb-b317-7745-36995deff003@microchip.com>
 <9c08f234068d328dd229893e836cda60@walle.cc>
Message-ID: <cb4ffd6f-1f68-1f29-c648-c464d5c8eef6@microchip.com>

On 10/22/21 4:08 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-10-22 14:51, schrieb Tudor.Ambarus at microchip.com:
>> On 10/22/21 2:57 PM, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know
>>> the content is safe
>>>
>>> Am 2021-07-27 06:52, schrieb Tudor Ambarus:
>>>> The functions names are self explanatory, get rid of the comment
>>>> for the OTP function.
>>>
>>> Mhh. I see, this partly addresses my comments to the previous patch.
>>> Maybe it would have been better to have this squashed into one
>>> commit :p
>>
>> one thing per patch
> 
> well it is really just one thing, you're moving the function. but then
> the function name doesn't make sense anymore. So the patch on its own
> is wrong or at least it makes things worse. Also, I'm reviewing that
> just to see this function was renamed (correctly) in the next patch.

I'll squash it then.

> 
>>> But my main concern remains: what if we need more that just
>>> the mtd callbacks assigments. Basically we loose the otp_init()
>>> call.
>>
>> ??????? if (WARN_ON(!is_power_of_2(spi_nor_otp_region_len(nor))))
>> ??????????????? return;
>>
>> is there just to avoid setting the mtd function pointers when OTP
>> region length is not power of 2. This is not an init, just a check,
>> so for the moment I see it ok to have it in spi_nor_set_mtd_otp_ops().
> 
> It is a sanity check which actually has nothing to do with the mtd ops
> registration. Just to see if there was a mistake in the otp info flags.
> 
> Of course, if that is not the case, we don't set the ops. But that
> doesn't
> mean it is part of the mtd op assigment.
> 
> I said stricly speaking, I'm ok with having that in the (now renamed)
> "otp set mtd ops" function.

ok, I'll keep it. If condition is true, you don't set the mtd ops. I find it
part of the mtd op assignment.


From han.xu at nxp.com  Fri Oct 22 07:35:14 2021
From: han.xu at nxp.com (han.xu at nxp.com)
Date: Fri, 22 Oct 2021 09:35:14 -0500
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
 <20211013050148.2w373kpbfaeuxbwm@umbrella>
 <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>
Message-ID: <20211022143514.lplk6jaxklq3rxry@umbrella>

On 21/10/22 08:45AM, Stefan Riedm?ller wrote:
> Hi Han,
> 
> sorry it took me some time to get back to you.
> 
> On Wed, 2021-10-13 at 00:01 -0500, Han Xu wrote:
> > On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> > > According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> > > when doing a gpmi_io clk rate change. So gate the clocks off before
> > > the rate change in nfc_apply_timings and ungate them again after the
> > > change.
> > > 
> > > Otherwise this rate change can lead to an unresponsive GPMI core which
> > > results in DMA timeouts and failed driver probe:
> > > 
> > > [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> > > ...
> > > [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> > > ...
> > > [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read: -22
> > > [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > ...
> > > 
> > > Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> > > ---
> > > Hi,
> > > 
> > > I'm not sure about the error handling here, if it is actually neccessary.
> > > So some feedback would be nice here.
> > > 
> > > Thanks,
> > > Stefan
> > > ---
> > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
> > >  1 file changed, 19 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > index a1f7000f033e..326c8a895f1f 100644
> > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct
> > > gpmi_nand_data *this,
> > >  			      (use_half_period ? BM_GPMI_CTRL1_HALF_PERIOD :
> > > 0);
> > >  }
> > >  
> > > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > >  {
> > >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > >  	struct resources *r = &this->resources;
> > >  	void __iomem *gpmi_regs = r->gpmi_regs;
> > >  	unsigned int dll_wait_time_us;
> > > +	int ret;
> > > +
> > > +	if (GPMI_IS_MX6Q(this)) {
> > 
> > Not only for 6Q but for GPMI_IS_MX6
> 
> Can you confirm that i.MX 6SX and i.MX 7 are affected by the ERR007117 erratum
> as well? Because the i.MX 6UL/ULL are included by the GPMI_IS_MX6Q already.

i.MX6SX has the glitch issue for sure, but I can double check if it's due to the
same errata. I will also go check if the errata will affect i.MX7

> 
> Or do we need another macro for i.MX 6UL/ULL as Christian has suggested
> earlier?
> 
> Thanks,
> Stefan
> 
> > 
> > > +		ret = __gpmi_enable_clk(this, false);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > >  
> > >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > >  
> > > +	if (GPMI_IS_MX6Q(this)) {
> > > +		ret = __gpmi_enable_clk(this, true);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > >  
> > > @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct
> > > gpmi_nand_data *this)
> > >  
> > >  	/* Wait for the DLL to settle. */
> > >  	udelay(dll_wait_time_us);
> > > +
> > > +	return 0;
> > >  }
> > >  
> > >  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > > @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
> > >  	 */
> > >  	if (this->hw.must_apply_timings) {
> > >  		this->hw.must_apply_timings = false;
> > > -		gpmi_nfc_apply_timings(this);
> > > +		ret = gpmi_nfc_apply_timings(this);
> > > +		if (ret)
> > > +			return ret;
> > >  	}
> > >  
> > >  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op->ninstrs);
> > > -- 
> > > 2.25.1
> > > 


From robh at kernel.org  Fri Oct 22 15:36:18 2021
From: robh at kernel.org (Rob Herring)
Date: Fri, 22 Oct 2021 17:36:18 -0500
Subject: [PATCH 04/18] dt-bindings: mtd: spi-nand: Convert spi-nand
 description file to yaml
In-Reply-To: <20211021160932.4169f66f@xps13>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-5-miquel.raynal@bootlin.com>
 <1634764487.038982.2962586.nullmailer@robh.at.kernel.org>
 <20211021160932.4169f66f@xps13>
Message-ID: <YXM84oCOAr6pSOw2@robh.at.kernel.org>

On Thu, Oct 21, 2021 at 04:09:32PM +0200, Miquel Raynal wrote:
> Hi Rob,
> 
> robh at kernel.org wrote on Wed, 20 Oct 2021 16:14:47 -0500:
> 
> > On Wed, 20 Oct 2021 16:27:55 +0200, Miquel Raynal wrote:
> > > Let's get rid of spi-nand.txt by converting it to yaml schema. While at
> > > converting this file, let's actually pull all the generic properties
> > > from nand-chip.yaml which might apply to a SPI-NAND chip.
> > > 
> > > Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> > > ---
> > >  .../devicetree/bindings/mtd/spi-nand.txt      |  5 ----
> > >  .../devicetree/bindings/mtd/spi-nand.yaml     | 27 +++++++++++++++++++
> > >  2 files changed, 27 insertions(+), 5 deletions(-)
> > >  delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
> > >  create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml
> > >   
> > 
> > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
> > on your patch (DT_CHECKER_FLAGS is new in v5.13):
> > 
> > yamllint warnings/errors:
> > 
> > dtschema/dtc warnings/errors:
> > Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
> > xargs: dt-doc-validate: exited with status 255; aborting
> > make[1]: *** Deleting file 'Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml'
> > Unknown file referenced: [Errno 2] No such file or directory: '/usr/local/lib/python3.8/dist-packages/dtschema/schemas/mtd/nand-chip.yaml'
> > make[1]: *** [scripts/Makefile.lib:385: Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.example.dt.yaml] Error 255
> > make[1]: *** Waiting for unfinished jobs....
> > make: *** [Makefile:1441: dt_binding_check] Error 2
> 
> I am not able to reproduce this error and in general I don't understand
> it. There is no relationship between this change and
> snps,dw-apb-ssi.yaml. Also the fact that nand-chip-yaml do not exist,
> it was just created in the patch before so I wonder how much I should
> trust this error.

I think you can ignore this. The prior patch should have been applied, 
but looks like it wasn't. My script's patch applying logic is not what 
I'd call robust.

> Also, maybe I am not using the tools properly, but it is very hard to
> send correct bindings at the first try. Running make dt_binding_check
> takes ages, any change in one yaml file will recheck the entire data
> base and filtering out on a single yaml file is generally too
> restrictive and still prints unrelated errors of syntax on other files.

Do you set 'DT_SCHEMA_FILES'? That will check just the schema you set 
it to. You still need to not set it at the end because any schema could 
apply to any example, so we have to check everything.

Also using DT_SCHEMA_FILES should be a bit faster with what's queued for 
5.16.

> I don't know how much of this is actually expected and/or if someone is
> working on it.

Due to python startup times being slow, it turns out to generally be 
faster to not have make track changes and do things incrementally. 
That's why all the schema are checked at once (though sharded with 
xargs). So I'm not really sure there's much we can do. I've certainly 
investigated it.

Rob


From robh at kernel.org  Fri Oct 22 15:47:30 2021
From: robh at kernel.org (Rob Herring)
Date: Fri, 22 Oct 2021 17:47:30 -0500
Subject: [PATCH 03/18] dt-bindings: mtd: nand-chip: Create a NAND chip
 description
In-Reply-To: <20211020142809.349347-4-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-4-miquel.raynal@bootlin.com>
Message-ID: <YXM/giZYKFc0BJHe@robh.at.kernel.org>

On Wed, Oct 20, 2021 at 04:27:54PM +0200, Miquel Raynal wrote:
> Move the NAND chip description out of the NAND controller file. Indeed,
> a subsequent part of the properties supported by a raw NAND chip are
> also supported by SPI-NAND chips. So let's create a generic NAND chip
> description which will be pulled by nand-controller.yaml and later by
> spi-nand.yaml as well.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../devicetree/bindings/mtd/nand-chip.yaml    | 71 +++++++++++++++++++
>  .../bindings/mtd/nand-controller.yaml         | 53 ++------------
>  2 files changed, 75 insertions(+), 49 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mtd/nand-chip.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mtd/nand-chip.yaml b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
> new file mode 100644
> index 000000000000..1f230a3ee27d
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
> @@ -0,0 +1,71 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mtd/nand-chip.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NAND Chip and NAND Controller Generic Binding
> +
> +maintainers:
> +  - Miquel Raynal <miquel.raynal at bootlin.com>
> +
> +description: |
> +  This file covers the generic description of a NAND chip. It implies that the
> +  bus interface should not be taken into account: both raw NAND devices and
> +  SPI-NAND devices are concerned by this description.
> +
> +properties:
> +  reg:
> +    description:
> +      Contains the chip-select IDs.
> +
> +  nand-ecc-engine:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: |
> +      A phandle on the hardware ECC engine if any. There are
> +      basically three possibilities:
> +      1/ The ECC engine is part of the NAND controller, in this
> +      case the phandle should reference the parent node.
> +      2/ The ECC engine is part of the NAND part (on-die), in this
> +      case the phandle should reference the node itself.
> +      3/ The ECC engine is external, in this case the phandle should
> +      reference the specific ECC engine node.
> +
> +  nand-use-soft-ecc-engine:
> +    type: boolean
> +    description: Use a software ECC engine.
> +
> +  nand-no-ecc-engine:
> +    type: boolean
> +    description: Do not use any ECC correction.
> +
> +  nand-ecc-algo:
> +    description:
> +      Desired ECC algorithm.
> +    $ref: /schemas/types.yaml#/definitions/string
> +    enum: [hamming, bch, rs]
> +
> +  nand-ecc-strength:
> +    description:
> +      Maximum number of bits that can be corrected per ECC step.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 1
> +
> +  nand-ecc-step-size:
> +    description:
> +      Number of data bytes covered by a single ECC step.
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    minimum: 1
> +
> +  secure-regions:
> +    $ref: /schemas/types.yaml#/definitions/uint64-matrix
> +    description:
> +      Regions in the NAND chip which are protected using a secure element
> +      like Trustzone. This property contains the start address and size of
> +      the secure regions present.
> +
> +required:
> +  - reg
> +
> +additionalProperties: false

This is the source of the errors reported as this wasn't set before. If 
we're allowing custom properties (not defined here) within nand chip 
nodes, then each schema with custom properties has to reference 
nand-chip.yaml, set 'unevaluatedProperties: false', and then define 
their custom properties. And then this needs to be true. 

Rob


From michael at walle.cc  Sun Oct 24 10:05:01 2021
From: michael at walle.cc (Michael Walle)
Date: Sun, 24 Oct 2021 19:05:01 +0200
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <9bf93cbf-fc57-54ae-2439-45e4d75dc0b7@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
 <20211022121010.mzul7qsxi6s4ru2w@ti.com>
 <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>
 <5a1497c9b2f07b2e6b91deb8ef17646f@walle.cc>
 <9bf93cbf-fc57-54ae-2439-45e4d75dc0b7@microchip.com>
Message-ID: <b06ac5238d85f62ebe588f161e34cf59@walle.cc>

Am 2021-10-22 15:25, schrieb Tudor.Ambarus at microchip.com:
> On 10/22/21 3:59 PM, Michael Walle wrote:
>> EXTERNAL EMAIL: Do not click links or open attachments unless you know 
>> the content is safe
>> 
>> Am 2021-10-22 14:42, schrieb Tudor.Ambarus at microchip.com:
>>> On 10/22/21 3:10 PM, Pratyush Yadav wrote:
>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you 
>>>> know
>>>> the content is safe
>>>> 
>>>> On 22/10/21 01:21PM, Michael Walle wrote:
>>>>> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
>>>>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>>>>> Used to initialize the NOR flags for settings that are not 
>>>>>>> defined
>>>>>>> in the JESD216 SFDP standard, thus can not be retrieved when
>>>>>>> parsing
>>>>>>> SFDP. No functional change.
>>>>>> 
>>>>>> I am worried if the order in which these flags are set can cause
>>>>>> some
>>>>>> subtle bugs.
>>>>>> 
>>>>>> I can see one instance of it with SNOR_F_HAS_LOCK.
>>>>>> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there
>>>>>> are
>>>>>> no locking ops specified, it sets the default locking ops. This
>>>>>> works
>>>>>> fine before this patch because the flag is set before the function
>>>>>> is
>>>>>> called. But now, the flag will be set _after_ the function is
>>>>>> called,
>>>>>> and so you will never be able to set the default flags.
>>>>> 
>>>>> Maybe we should just forbid to look at the SNOR_F_ flags in these
>>>>> functions. Instead the information could also be deduced by looking
>>>>> at
>>>>> the SPI_NOR_ flags.
>>> 
>>> not true.
>> 
>> I guess you mean that some init flash init functions might set it, 
>> too.
>> Right? IMHO this goes into the spaghetti code direction again.
>> spi_nor_late_init_params() must not look at the SNOR_F_ flags. There
>> are too much inter-function dependencies and it is really hard to
>> follow the call chain.
> 
> I don't think I understand what you are referring to. The flash_info 
> flags
> are used just to set their SNOR_F correspondents. Take 
> SNOR_F_4B_OPCODES for
> example. A flash that can't discover 4b opcodes support when parsing 
> SFDP,
> will set the SPI_NOR_4B_OPCODES flash_info flag. Flashes that can 
> discover it,
> will ignore/not set the SPI_NOR_4B_OPCODES flag, and let the SFDP do 
> its thing:
> the SFDP code will set the SNOR_F_4B_OPCODES flag. The only flags that 
> are used
> across the SPI NOR core are the nor->flags (SNOR_F).

Sorry, I wasn't clear enough. I was talking about checking (already set) 
SNOR_F
flags in all these init functions ({flash,manufacturer)->post_sfdp(),
(flash,manufacturer)->late_init, ..). If we didn't allow this, then
we would avoid all these "subtle bugs" which happen because some of 
these
functions depend on another being called first. I.e. all the called
functions within spi_nor_init_params() may only add SNOR_F flags, but 
must
not actually use them. [I see that spi_nor_sfdp_init_params() will
remove SNOR_F_4B_OPCODES. Mhh.]

Btw. I wonder what is the difference between a member being in "struct 
spi_nor"
and being in "struct spi_nor_flash_parameter". Apparently, it should
contain the properties which can be set/changed in the fixups or by
parsing the SFPD. But then there are also the flags which are also
changed in the fixups.

Maybe we should pass the "struct nor" as const and a second parameter
"struct spi_nor_flash_parameter *params" which can be updated by the
called function. This way we can be sure the functions won't change
anything else. I don't suggest to do that right now, just to start
a discussion.

>> The locking ops should also go into the (static) flash init which only
>> depends on the SPI_NOR_ flags. If SNOR_F_HAS_LOCK will be added at
> 
> we don't have to specify the locking methods, we have generic ones. A 
> single
> flag is enough.

Hm, I'm not really sure we need that SNOR_F_HAS_LOCK flag at all.
"if (nor->params->locking_ops)" should be the same. At least the current 
code
which checks the info->flags for SPI_NOR_HAS_LOCK will set the default
locking ops instead of just setting the SNOR_F_HAS_LOCK.

>> in an init function, then this code should also take care of setting
> 
> what init function? We're just setting some flags.

all the functions called in spi_nor_init_params().

>> the correct locking ops. Maybe both can be set together with a helper.

-michael


From michael at walle.cc  Sun Oct 24 10:44:00 2021
From: michael at walle.cc (Michael Walle)
Date: Sun, 24 Oct 2021 19:44:00 +0200
Subject: [PATCH v2 05/35] mtd: spi-nor: Introduce Manufacturer ID
 collisions driver
In-Reply-To: <20210727045222.905056-6-tudor.ambarus@microchip.com>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-6-tudor.ambarus@microchip.com>
Message-ID: <9070118a2a8557a853f4c5e6a3dd4d58@walle.cc>

Am 2021-07-27 06:51, schrieb Tudor Ambarus:
> Some manufacturers completely ignore the manufacturer's identification 
> code
> standard (JEP106) and do not define the manufacturer ID continuation
> scheme. This will result in manufacturer ID collisions.
> 
> An an example, JEP106BA requires Boya that it's manufacturer ID to be
> preceded by 8 continuation codes. Boya's identification code must be:
> 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x68. But Boya ignores 
> the
> continuation scheme and its ID collides with the manufacturer defined 
> in
> bank one: Convex Computer.
> 
> Introduce the manuf-id-collisions driver in order to address ID 
> collisions
> between manufacturers. flash_info entries will be added in a first 
> come,
> first served manner. Differentiation between flashes will be done at
> runtime if possible. Where runtime differentiation is not possible, new
> compatibles will be introduced, but this will be done as a last resort.
> Every new flash addition that define the SFDP tables, should dump its 
> SFDP
> tables in the patch's comment section below the --- line, so that we 
> can
> reference it in case of collisions.

Btw. how will this work in practice? Let's say we have a flash of a
"bad" manufacturer B which is using the manufacturer id of another
"good" manufacturer G. Now flashes of B are added to the kernel.

Some kernel versions later G releases a flash of which uses the exact
same id. How can we now add support for this flash now? If we can
differentiate at runtime, fine. But what if not? Will then
the legitimate owner of the ID will need a new compatible string?

That's the only way I see how this can work.

-michael


From chengzhihao1 at huawei.com  Sun Oct 24 20:41:08 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:08 +0800
Subject: [PATCH 03/11] ubifs: Fix wrong number of inodes locked by ui_mutex in
 ubifs_inode comment
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-4-chengzhihao1@huawei.com>

Since 9ec64962afb1702f75b("ubifs: Implement RENAME_EXCHANGE") and
9e0a1fff8db56eaaebb("ubifs: Implement RENAME_WHITEOUT") are applied,
ubifs_rename locks and changes 4 ubifs inodes, correct the comment
for ui_mutex in ubifs_inode.

Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/ubifs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index c38066ce9ab0..972e41daff01 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -372,7 +372,7 @@ struct ubifs_gced_idx_leb {
  * @ui_mutex exists for two main reasons. At first it prevents inodes from
  * being written back while UBIFS changing them, being in the middle of an VFS
  * operation. This way UBIFS makes sure the inode fields are consistent. For
- * example, in 'ubifs_rename()' we change 3 inodes simultaneously, and
+ * example, in 'ubifs_rename()' we change 4 inodes simultaneously, and
  * write-back must not write any of them before we have finished.
  *
  * The second reason is budgeting - UBIFS has to budget all operations. If an
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:05 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:05 +0800
Subject: [PATCH 00/11] Some bugfixs for ubifs/ubi
Message-ID: <20211025034116.3544321-1-chengzhihao1@huawei.com>


Zhihao Cheng (11):
  ubifs: rename_whiteout: Fix double free for whiteout_ui->data
  ubifs: Fix deadlock in concurrent rename whiteout and inode writeback
  ubifs: Fix wrong number of inodes locked by ui_mutex in ubifs_inode
    comment
  ubifs: Add missing iput if do_tmpfile() failed in rename whiteout
  ubifs: Rename whiteout atomically
  ubifs: Fix 'ui->dirty' race between do_tmpfile() and writeback work
  ubifs: Rectify space amount budget for mkdir/tmpfile operations
  ubifs: setflags: Don't make a budget for 'ui->data_len'
  ubifs: Fix read out-of-bounds in ubifs_wbuf_write_nolock()
  ubi: fastmap: Return error code if memory allocation fails in
    add_aeb()
  ubi: fastmap: Add all fastmap pebs into 'ai->fastmap' when
    fm->used_blocks>=2

 drivers/mtd/ubi/fastmap.c |  69 ++++++-----
 fs/ubifs/dir.c            | 235 +++++++++++++++++++++++---------------
 fs/ubifs/io.c             |  34 +++++-
 fs/ubifs/ioctl.c          |   4 +-
 fs/ubifs/journal.c        |  53 +++++++--
 fs/ubifs/ubifs.h          |   2 +-
 6 files changed, 254 insertions(+), 143 deletions(-)

-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:09 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:09 +0800
Subject: [PATCH 04/11] ubifs: Add missing iput if do_tmpfile() failed in
 rename whiteout
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-5-chengzhihao1@huawei.com>

whiteout inode should be put when do_tmpfile() failed if inode has been
initialized. Otherwise we will get following warning during umount:
  UBIFS error (ubi0:0 pid 1494): ubifs_assert_failed [ubifs]: UBIFS
  assert failed: c->bi.dd_growth == 0, in fs/ubifs/super.c:1930
  VFS: Busy inodes after unmount of ubifs. Self-destruct in 5 seconds.

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 2735ad1affed..6503e6857f6e 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1334,6 +1334,8 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 		err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
 		if (err) {
+			if (whiteout)
+				iput(whiteout);
 			kfree(dev);
 			goto out_release;
 		}
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:06 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:06 +0800
Subject: [PATCH 01/11] ubifs: rename_whiteout: Fix double free for
 whiteout_ui->data
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-2-chengzhihao1@huawei.com>

'whiteout_ui->data' will be freed twice if space budget fail for
rename whiteout operation as following process:

rename_whiteout
  dev = kmalloc
  whiteout_ui->data = dev
  kfree(whiteout_ui->data)  // Free first time
  iput(whiteout)
    ubifs_free_inode
      kfree(ui->data)	    // Double free!

KASAN reports:
==================================================================
BUG: KASAN: double-free or invalid-free in ubifs_free_inode+0x4f/0x70
Call Trace:
  kfree+0x117/0x490
  ubifs_free_inode+0x4f/0x70 [ubifs]
  i_callback+0x30/0x60
  rcu_do_batch+0x366/0xac0
  __do_softirq+0x133/0x57f

Allocated by task 1506:
  kmem_cache_alloc_trace+0x3c2/0x7a0
  do_rename+0x9b7/0x1150 [ubifs]
  ubifs_rename+0x106/0x1f0 [ubifs]
  do_syscall_64+0x35/0x80

Freed by task 1506:
  kfree+0x117/0x490
  do_rename.cold+0x53/0x8a [ubifs]
  ubifs_rename+0x106/0x1f0 [ubifs]
  do_syscall_64+0x35/0x80

The buggy address belongs to the object at ffff88810238bed8 which
belongs to the cache kmalloc-8 of size 8
==================================================================

Let ubifs_free_inode() free 'whiteout_ui->data'. BTW, delete unused
assignment 'whiteout_ui->data_len = 0', process 'ubifs_evict_inode()
-> ubifs_jnl_delete_inode() -> ubifs_jnl_write_inode()' doesn't need it
(because 'inc_nlink(whiteout)' won't be excuted by 'goto out_release',
 and the nlink of whiteout inode is 0).

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 7c61d0ec0159..cfa8881d8cca 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1425,8 +1425,6 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 		err = ubifs_budget_space(c, &wht_req);
 		if (err) {
-			kfree(whiteout_ui->data);
-			whiteout_ui->data_len = 0;
 			iput(whiteout);
 			goto out_release;
 		}
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:16 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:16 +0800
Subject: [PATCH 11/11] ubi: fastmap: Add all fastmap pebs into 'ai->fastmap'
 when fm->used_blocks>=2
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-12-chengzhihao1@huawei.com>

Fastmap pebs(pnum >= UBI_FM_MAX_START) won't be added into 'ai->fastmap'
while attaching ubi device if 'fm->used_blocks' is greater than 2, which
may cause warning from 'ubi_assert(ubi->good_peb_count == found_pebs)':

  UBI assert failed in ubi_wl_init at 1878 (pid 2409)
  Call Trace:
    ubi_wl_init.cold+0xae/0x2af [ubi]
    ubi_attach+0x1b0/0x780 [ubi]
    ubi_init+0x23a/0x3ad [ubi]
    load_module+0x22d2/0x2430

Reproduce:
  ID="0x20,0x33,0x00,0x00" # 16M 16KB PEB, 512 page
  modprobe nandsim id_bytes=$ID
  modprobe ubi mtd="0,0" fm_autoconvert  # Fastmap takes 2 pebs
  rmmod ubi
  modprobe ubi mtd="0,0" fm_autoconvert  # Attach by fastmap

Add all fastmap pebs into list 'ai->fastmap' to make sure they can be
counted into 'found_pebs'.

Fixes: fdf10ed710c0aa ("ubi: Rework Fastmap attach base code")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 drivers/mtd/ubi/fastmap.c | 41 ++++++++++++++-------------------------
 1 file changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 6b5f1ffd961b..88fdf8f5709f 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -828,24 +828,6 @@ static int find_fm_anchor(struct ubi_attach_info *ai)
 	return ret;
 }
 
-static struct ubi_ainf_peb *clone_aeb(struct ubi_attach_info *ai,
-				      struct ubi_ainf_peb *old)
-{
-	struct ubi_ainf_peb *new;
-
-	new = ubi_alloc_aeb(ai, old->pnum, old->ec);
-	if (!new)
-		return NULL;
-
-	new->vol_id = old->vol_id;
-	new->sqnum = old->sqnum;
-	new->lnum = old->lnum;
-	new->scrub = old->scrub;
-	new->copy_flag = old->copy_flag;
-
-	return new;
-}
-
 /**
  * ubi_scan_fastmap - scan the fastmap.
  * @ubi: UBI device object
@@ -875,15 +857,11 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
 	if (fm_anchor < 0)
 		return UBI_NO_FASTMAP;
 
-	/* Copy all (possible) fastmap blocks into our new attach structure. */
+	/* Add fastmap blocks(pnum < UBI_FM_MAX_START) into attach structure. */
 	list_for_each_entry(aeb, &scan_ai->fastmap, u.list) {
-		struct ubi_ainf_peb *new;
-
-		new = clone_aeb(ai, aeb);
-		if (!new)
-			return -ENOMEM;
-
-		list_add(&new->u.list, &ai->fastmap);
+		ret = add_aeb(ai, &ai->fastmap, aeb->pnum, aeb->ec, 0);
+		if (ret)
+			return ret;
 	}
 
 	down_write(&ubi->fm_protect);
@@ -1029,6 +1007,17 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
 				"err: %i)", i, pnum, ret);
 			goto free_hdr;
 		}
+
+		/*
+		 * Add left fastmap blocks (pnum >= UBI_FM_MAX_START) into
+		 * attach structure.
+		 */
+		if (pnum >= UBI_FM_MAX_START) {
+			ret = add_aeb(ai, &ai->fastmap, pnum,
+				      be64_to_cpu(ech->ec), 0);
+			if (ret)
+				goto free_hdr;
+		}
 	}
 
 	kfree(fmsb);
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:07 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:07 +0800
Subject: [PATCH 02/11] ubifs: Fix deadlock in concurrent rename whiteout and
 inode writeback
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-3-chengzhihao1@huawei.com>

Following hung tasks:
[   77.028764] task:kworker/u8:4    state:D stack:    0 pid:  132
[   77.028820] Call Trace:
[   77.029027]  schedule+0x8c/0x1b0
[   77.029067]  mutex_lock+0x50/0x60
[   77.029074]  ubifs_write_inode+0x68/0x1f0 [ubifs]
[   77.029117]  __writeback_single_inode+0x43c/0x570
[   77.029128]  writeback_sb_inodes+0x259/0x740
[   77.029148]  wb_writeback+0x107/0x4d0
[   77.029163]  wb_workfn+0x162/0x7b0

[   92.390442] task:aa              state:D stack:    0 pid: 1506
[   92.390448] Call Trace:
[   92.390458]  schedule+0x8c/0x1b0
[   92.390461]  wb_wait_for_completion+0x82/0xd0
[   92.390469]  __writeback_inodes_sb_nr+0xb2/0x110
[   92.390472]  writeback_inodes_sb_nr+0x14/0x20
[   92.390476]  ubifs_budget_space+0x705/0xdd0 [ubifs]
[   92.390503]  do_rename.cold+0x7f/0x187 [ubifs]
[   92.390549]  ubifs_rename+0x8b/0x180 [ubifs]
[   92.390571]  vfs_rename+0xdb2/0x1170
[   92.390580]  do_renameat2+0x554/0x770

, are caused by concurrent rename whiteout and inode writeback processes:
	rename_whiteout(Thread 1)	        wb_workfn(Thread2)
ubifs_rename
  do_rename
    lock_4_inodes (Hold ui_mutex)
    ubifs_budget_space
      make_free_space
        shrink_liability
	  __writeback_inodes_sb_nr
	    bdi_split_work_to_wbs (Queue new wb work)
					      wb_do_writeback(wb work)
						__writeback_single_inode
					          ubifs_write_inode
					            LOCK(ui_mutex)
							   ?
	      wb_wait_for_completion (Wait wb work) <-- deadlock!

Reproducer (Detail program in [Link]):
  1. SYS_renameat2("/mp/dir/file", "/mp/dir/whiteout", RENAME_WHITEOUT)
  2. Consume out of space before kernel(mdelay) doing budget for whiteout

Fix it by doing whiteout space budget before locking ubifs inodes.
BTW, it also fixes wrong goto tag 'out_release' in whiteout budget
error handling path(It should at least recover dir i_size and unlock
4 ubifs inodes).

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=214733
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index cfa8881d8cca..2735ad1affed 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1324,6 +1324,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	if (flags & RENAME_WHITEOUT) {
 		union ubifs_dev_desc *dev = NULL;
+		struct ubifs_budget_req wht_req;
 
 		dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
 		if (!dev) {
@@ -1345,6 +1346,20 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 		whiteout_ui->data = dev;
 		whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
 		ubifs_assert(c, !whiteout_ui->dirty);
+
+		memset(&wht_req, 0, sizeof(struct ubifs_budget_req));
+		wht_req.dirtied_ino = 1;
+		wht_req.dirtied_ino_d = ALIGN(whiteout_ui->data_len, 8);
+		/*
+		 * To avoid deadlock between space budget (holds ui_mutex and
+		 * waits wb work) and writeback work(waits ui_mutex), do space
+		 * budget before ubifs inodes locked.
+		 */
+		err = ubifs_budget_space(c, &wht_req);
+		if (err) {
+			iput(whiteout);
+			goto out_release;
+		}
 	}
 
 	lock_4_inodes(old_dir, new_dir, new_inode, whiteout);
@@ -1419,16 +1434,6 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 	}
 
 	if (whiteout) {
-		struct ubifs_budget_req wht_req = { .dirtied_ino = 1,
-				.dirtied_ino_d = \
-				ALIGN(ubifs_inode(whiteout)->data_len, 8) };
-
-		err = ubifs_budget_space(c, &wht_req);
-		if (err) {
-			iput(whiteout);
-			goto out_release;
-		}
-
 		inc_nlink(whiteout);
 		mark_inode_dirty(whiteout);
 
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:11 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:11 +0800
Subject: [PATCH 06/11] ubifs: Fix 'ui->dirty' race between do_tmpfile() and
 writeback work
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-7-chengzhihao1@huawei.com>

'ui->dirty' is not protected by 'ui_mutex' in function do_tmpfile() which
may race with ubifs_write_inode[wb_workfn] to access/update 'ui->dirty',
finally dirty space is released twice.

	open(O_TMPFILE)                wb_workfn
do_tmpfile
  ubifs_budget_space(ino_req = { .dirtied_ino = 1})
  d_tmpfile // mark inode(tmpfile) dirty
  ubifs_jnl_update // without holding tmpfile's ui_mutex
    mark_inode_clean(ui)
      if (ui->dirty)
        ubifs_release_dirty_inode_budget(ui)  // release first time
                                   ubifs_write_inode
				     mutex_lock(&ui->ui_mutex)
                                     ubifs_release_dirty_inode_budget(ui)
				     // release second time
				     mutex_unlock(&ui->ui_mutex)
      ui->dirty = 0

Run generic/476 can reproduce following message easily
(See reproducer in [Link]):

  UBIFS error (ubi0:0 pid 2578): ubifs_assert_failed [ubifs]: UBIFS assert
  failed: c->bi.dd_growth >= 0, in fs/ubifs/budget.c:554
  UBIFS warning (ubi0:0 pid 2578): ubifs_ro_mode [ubifs]: switched to
  read-only mode, error -22
  Workqueue: writeback wb_workfn (flush-ubifs_0_0)
  Call Trace:
    ubifs_ro_mode+0x54/0x60 [ubifs]
    ubifs_assert_failed+0x4b/0x80 [ubifs]
    ubifs_release_budget+0x468/0x5a0 [ubifs]
    ubifs_release_dirty_inode_budget+0x53/0x80 [ubifs]
    ubifs_write_inode+0x121/0x1f0 [ubifs]
    ...
    wb_workfn+0x283/0x7b0

Fix it by holding tmpfile ubifs inode lock during ubifs_jnl_update().
Similar problem exists in whiteout renaming, but previous fix("ubifs:
Rename whiteout atomically") has solved the problem.

Fixes: 474b93704f32163 ("ubifs: Implement O_TMPFILE")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=214765
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c | 60 +++++++++++++++++++++++++-------------------------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6344e2bc9338..8a2c42e6b22b 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -399,6 +399,32 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry,
 	return ERR_PTR(err);
 }
 
+/**
+ * lock_2_inodes - a wrapper for locking two UBIFS inodes.
+ * @inode1: first inode
+ * @inode2: second inode
+ *
+ * We do not implement any tricks to guarantee strict lock ordering, because
+ * VFS has already done it for us on the @i_mutex. So this is just a simple
+ * wrapper function.
+ */
+static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
+{
+	mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
+	mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
+}
+
+/**
+ * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
+ * @inode1: first inode
+ * @inode2: second inode
+ */
+static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
+{
+	mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
+	mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
+}
+
 static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 			 struct dentry *dentry, umode_t mode)
 {
@@ -406,7 +432,7 @@ static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 	struct ubifs_info *c = dir->i_sb->s_fs_info;
 	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
 	struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
-	struct ubifs_inode *ui, *dir_ui = ubifs_inode(dir);
+	struct ubifs_inode *ui;
 	int err, instantiated = 0;
 	struct fscrypt_name nm;
 
@@ -454,18 +480,18 @@ static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 	instantiated = 1;
 	mutex_unlock(&ui->ui_mutex);
 
-	mutex_lock(&dir_ui->ui_mutex);
+	lock_2_inodes(dir, inode);
 	err = ubifs_jnl_update(c, dir, &nm, inode, 1, 0);
 	if (err)
 		goto out_cancel;
-	mutex_unlock(&dir_ui->ui_mutex);
+	unlock_2_inodes(dir, inode);
 
 	ubifs_release_budget(c, &req);
 
 	return 0;
 
 out_cancel:
-	mutex_unlock(&dir_ui->ui_mutex);
+	unlock_2_inodes(dir, inode);
 out_inode:
 	make_bad_inode(inode);
 	if (!instantiated)
@@ -692,32 +718,6 @@ static int ubifs_dir_release(struct inode *dir, struct file *file)
 	return 0;
 }
 
-/**
- * lock_2_inodes - a wrapper for locking two UBIFS inodes.
- * @inode1: first inode
- * @inode2: second inode
- *
- * We do not implement any tricks to guarantee strict lock ordering, because
- * VFS has already done it for us on the @i_mutex. So this is just a simple
- * wrapper function.
- */
-static void lock_2_inodes(struct inode *inode1, struct inode *inode2)
-{
-	mutex_lock_nested(&ubifs_inode(inode1)->ui_mutex, WB_MUTEX_1);
-	mutex_lock_nested(&ubifs_inode(inode2)->ui_mutex, WB_MUTEX_2);
-}
-
-/**
- * unlock_2_inodes - a wrapper for unlocking two UBIFS inodes.
- * @inode1: first inode
- * @inode2: second inode
- */
-static void unlock_2_inodes(struct inode *inode1, struct inode *inode2)
-{
-	mutex_unlock(&ubifs_inode(inode2)->ui_mutex);
-	mutex_unlock(&ubifs_inode(inode1)->ui_mutex);
-}
-
 static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
 		      struct dentry *dentry)
 {
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:13 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:13 +0800
Subject: [PATCH 08/11] ubifs: setflags: Don't make a budget for 'ui->data_len'
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-9-chengzhihao1@huawei.com>

'setflags()' affects regular files and directories, only xattr inode,
symlink inode and special inode(pipe/char_dev/block_dev) have none-
zero 'ui->data_len' field.

Remove superfluous space budget for 'dirtied_ino_d', besides add an
assert to verify that 'setflags()' only operates ubifs inode with
zero data_len.

Fixes: 1e51764a3c2ac05a ("UBIFS: add new flash file system")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/ioctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index c6a863487780..ed95e97a3740 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -107,9 +107,9 @@ static int setflags(struct inode *inode, int flags)
 	int err, release;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 	struct ubifs_info *c = inode->i_sb->s_fs_info;
-	struct ubifs_budget_req req = { .dirtied_ino = 1,
-					.dirtied_ino_d = ui->data_len };
+	struct ubifs_budget_req req = { .dirtied_ino = 1 };
 
+	ubifs_assert(c, !ui->data_len);
 	err = ubifs_budget_space(c, &req);
 	if (err)
 		return err;
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:14 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:14 +0800
Subject: [PATCH 09/11] ubifs: Fix read out-of-bounds in
 ubifs_wbuf_write_nolock()
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-10-chengzhihao1@huawei.com>

Function ubifs_wbuf_write_nolock() may access buf out of bounds in
following process:

ubifs_wbuf_write_nolock():
  aligned_len = ALIGN(len, 8);   // Assume len = 4089, aligned_len = 4096
  if (aligned_len <= wbuf->avail) ... // Not satisfy
  if (wbuf->used) {
    ubifs_leb_write()  // Fill some data in avail wbuf
    len -= wbuf->avail;   // len is still not 8-bytes aligned
    aligned_len -= wbuf->avail;
  }
  n = aligned_len >> c->max_write_shift;
  if (n) {
    n <<= c->max_write_shift;
    err = ubifs_leb_write(c, wbuf->lnum, buf + written,
                          wbuf->offs, n);
    // n > len, read out of bounds less than 8(n-len) bytes
  }

, which can be catched by KASAN:
  =========================================================
  BUG: KASAN: slab-out-of-bounds in ecc_sw_hamming_calculate+0x1dc/0x7d0
  Read of size 4 at addr ffff888105594ff8 by task kworker/u8:4/128
  Workqueue: writeback wb_workfn (flush-ubifs_0_0)
  Call Trace:
    kasan_report.cold+0x81/0x165
    nand_write_page_swecc+0xa9/0x160
    ubifs_leb_write+0xf2/0x1b0 [ubifs]
    ubifs_wbuf_write_nolock+0x421/0x12c0 [ubifs]
    write_head+0xdc/0x1c0 [ubifs]
    ubifs_jnl_write_inode+0x627/0x960 [ubifs]
    wb_workfn+0x8af/0xb80

Function ubifs_wbuf_write_nolock() accepts that parameter 'len' is not 8
bytes aligned, the 'len' represents the true length of buf (which is
allocated in 'ubifs_jnl_xxx', eg. ubifs_jnl_write_inode), so
ubifs_wbuf_write_nolock() must handle the length read from 'buf' carefully
to write leb safely.

Fetch a reproducer in [Link].

Fixes: 1e51764a3c2ac0 ("UBIFS: add new flash file system")
Link: https://bugzilla.kernel.org/show_bug.cgi?id=214785
Reported-by: Chengsong Ke <kechengsong at huawei.com>
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/io.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 00b61dba62b7..b019dd6f7fa0 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -833,16 +833,42 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 	 */
 	n = aligned_len >> c->max_write_shift;
 	if (n) {
-		n <<= c->max_write_shift;
+		int m = n - 1;
+
 		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
 		       wbuf->offs);
-		err = ubifs_leb_write(c, wbuf->lnum, buf + written,
-				      wbuf->offs, n);
+
+		if (m) {
+			/* '(n-1)<<c->max_write_shift < len' is always true. */
+			m <<= c->max_write_shift;
+			err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+					      wbuf->offs, m);
+			if (err)
+				goto out;
+			wbuf->offs += m;
+			aligned_len -= m;
+			len -= m;
+			written += m;
+		}
+
+		/*
+		 * The non-written len of buf may be less than 'n' because
+		 * parameter 'len' is not 8 bytes aligned, so here we read
+		 * min(len, n) bytes from buf.
+		 */
+		n = 1 << c->max_write_shift;
+		memcpy(wbuf->buf, buf + written, min(len, n));
+		if (n > len) {
+			ubifs_assert(c, n - len < 8);
+			ubifs_pad(c, wbuf->buf + len, n - len);
+		}
+
+		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, n);
 		if (err)
 			goto out;
 		wbuf->offs += n;
 		aligned_len -= n;
-		len -= n;
+		len -= min(len, n);
 		written += n;
 	}
 
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:10 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:10 +0800
Subject: [PATCH 05/11] ubifs: Rename whiteout atomically
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-6-chengzhihao1@huawei.com>

Currently, rename whiteout has 3 steps:
  1. create tmpfile(which associates old dentry to tmpfile inode) for
     whiteout, and store tmpfile to disk
  2. link whiteout, associate whiteout inode to old dentry agagin and
     store old dentry, old inode, new dentry on disk
  3. writeback dirty whiteout inode to disk

Suddenly power-cut or error occurring(eg. ENOSPC returned by budget,
memory allocation failure) during above steps may cause kinds of problems:
  Problem 1: ENOSPC returned by whiteout space budget (before step 2),
	     old dentry will disappear after rename syscall, whiteout file
	     cannot be found either.

	     ls dir  // we get file, whiteout
	     rename(dir/file, dir/whiteout, REANME_WHITEOUT)
	     ENOSPC = ubifs_budget_space(&wht_req) // return
	     ls dir  // empty (no file, no whiteout)
  Problem 2: Power-cut happens before step 3, whiteout inode with 'nlink=1'
	     is not stored on disk, whiteout dentry(old dentry) is written
	     on disk, whiteout file is lost on next mount (We get "dead
	     directory entry" after executing 'ls -l' on whiteout file).

Now, we use following 3 steps to finish rename whiteout:
  1. create an in-mem inode with 'nlink = 1' as whiteout
  2. ubifs_jnl_rename (Write on disk to finish associating old dentry to
     whiteout inode, associating new dentry with old inode)
  3. iput(whiteout)

Rely writing in-mem inode on disk by ubifs_jnl_rename() to finish rename
whiteout, which avoids middle disk state caused by suddenly power-cut
and error occurring.

Fixes: 9e0a1fff8db56ea ("ubifs: Implement RENAME_WHITEOUT")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c     | 144 +++++++++++++++++++++++++++++----------------
 fs/ubifs/journal.c |  53 ++++++++++++++---
 2 files changed, 137 insertions(+), 60 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 6503e6857f6e..6344e2bc9338 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -349,8 +349,58 @@ static int ubifs_create(struct user_namespace *mnt_userns, struct inode *dir,
 	return err;
 }
 
-static int do_tmpfile(struct inode *dir, struct dentry *dentry,
-		      umode_t mode, struct inode **whiteout)
+static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry,
+				     umode_t mode)
+{
+	int err;
+	struct inode *inode;
+	struct ubifs_inode *ui;
+	struct ubifs_info *c = dir->i_sb->s_fs_info;
+	struct fscrypt_name nm;
+
+	/*
+	 * Create an inode('nlink = 1') for whiteout without updating journal,
+	 * let ubifs_jnl_rename() store it on flash to complete rename whiteout
+	 * atomically.
+	 */
+
+	dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
+		dentry, mode, dir->i_ino);
+
+	err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
+	if (err)
+		return ERR_PTR(err);
+
+	inode = ubifs_new_inode(c, dir, mode);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out_free;
+	}
+	ui = ubifs_inode(inode);
+
+	init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
+	ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
+
+	err = ubifs_init_security(dir, inode, &dentry->d_name);
+	if (err)
+		goto out_inode;
+
+	/* The dir size is updated by do_rename. */
+	insert_inode_hash(inode);
+
+	return inode;
+
+out_inode:
+	make_bad_inode(inode);
+	iput(inode);
+out_free:
+	fscrypt_free_filename(&nm);
+	ubifs_err(c, "cannot create whiteout file, error %d", err);
+	return ERR_PTR(err);
+}
+
+static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
+			 struct dentry *dentry, umode_t mode)
 {
 	struct inode *inode;
 	struct ubifs_info *c = dir->i_sb->s_fs_info;
@@ -392,25 +442,13 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
 	}
 	ui = ubifs_inode(inode);
 
-	if (whiteout) {
-		init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
-		ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
-	}
-
 	err = ubifs_init_security(dir, inode, &dentry->d_name);
 	if (err)
 		goto out_inode;
 
 	mutex_lock(&ui->ui_mutex);
 	insert_inode_hash(inode);
-
-	if (whiteout) {
-		mark_inode_dirty(inode);
-		drop_nlink(inode);
-		*whiteout = inode;
-	} else {
-		d_tmpfile(dentry, inode);
-	}
+	d_tmpfile(dentry, inode);
 	ubifs_assert(c, ui->dirty);
 
 	instantiated = 1;
@@ -441,12 +479,6 @@ static int do_tmpfile(struct inode *dir, struct dentry *dentry,
 	return err;
 }
 
-static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
-			 struct dentry *dentry, umode_t mode)
-{
-	return do_tmpfile(dir, dentry, mode, NULL);
-}
-
 /**
  * vfs_dent_type - get VFS directory entry type.
  * @type: UBIFS directory entry type
@@ -1264,17 +1296,19 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 					.dirtied_ino = 3 };
 	struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
 			.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
+	struct ubifs_budget_req wht_req;
 	struct timespec64 time;
 	unsigned int saved_nlink;
 	struct fscrypt_name old_nm, new_nm;
 
 	/*
-	 * Budget request settings: deletion direntry, new direntry, removing
-	 * the old inode, and changing old and new parent directory inodes.
+	 * Budget request settings:
+	 *   req: deletion direntry, new direntry, removing the old inode,
+	 *   and changing old and new parent directory inodes.
+	 *
+	 *   wht_req: new whiteout inode for RENAME_WHITEOUT.
 	 *
-	 * However, this operation also marks the target inode as dirty and
-	 * does not write it, so we allocate budget for the target inode
-	 * separately.
+	 *   ino_req: marks the target inode as dirty and does not write it.
 	 */
 
 	dbg_gen("dent '%pd' ino %lu in dir ino %lu to dent '%pd' in dir ino %lu flags 0x%x",
@@ -1324,7 +1358,6 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	if (flags & RENAME_WHITEOUT) {
 		union ubifs_dev_desc *dev = NULL;
-		struct ubifs_budget_req wht_req;
 
 		dev = kmalloc(sizeof(union ubifs_dev_desc), GFP_NOFS);
 		if (!dev) {
@@ -1332,26 +1365,27 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 			goto out_release;
 		}
 
-		err = do_tmpfile(old_dir, old_dentry, S_IFCHR | WHITEOUT_MODE, &whiteout);
-		if (err) {
-			if (whiteout)
-				iput(whiteout);
+		/*
+		 * The whiteout inode without dentry is pinned in memory,
+		 * umount won't happen during rename process because we
+		 * got parent dentry.
+		 */
+		whiteout = create_whiteout(old_dir, old_dentry,
+					   S_IFCHR | WHITEOUT_MODE);
+		if (IS_ERR(whiteout)) {
+			err = PTR_ERR(whiteout);
 			kfree(dev);
 			goto out_release;
 		}
 
-		spin_lock(&whiteout->i_lock);
-		whiteout->i_state |= I_LINKABLE;
-		spin_unlock(&whiteout->i_lock);
-
 		whiteout_ui = ubifs_inode(whiteout);
 		whiteout_ui->data = dev;
 		whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0));
 		ubifs_assert(c, !whiteout_ui->dirty);
 
 		memset(&wht_req, 0, sizeof(struct ubifs_budget_req));
-		wht_req.dirtied_ino = 1;
-		wht_req.dirtied_ino_d = ALIGN(whiteout_ui->data_len, 8);
+		wht_req.new_ino = 1;
+		wht_req.new_ino_d = ALIGN(whiteout_ui->data_len, 8);
 		/*
 		 * To avoid deadlock between space budget (holds ui_mutex and
 		 * waits wb work) and writeback work(waits ui_mutex), do space
@@ -1359,6 +1393,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 		 */
 		err = ubifs_budget_space(c, &wht_req);
 		if (err) {
+			/*
+			 * Whiteout inode can not be written on flash by
+			 * ubifs_jnl_write_inode(), because it's neither
+			 * dirty nor zero-nlink.
+			 */
 			iput(whiteout);
 			goto out_release;
 		}
@@ -1433,17 +1472,8 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 		sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
 		if (unlink && IS_SYNC(new_inode))
 			sync = 1;
-	}
-
-	if (whiteout) {
-		inc_nlink(whiteout);
-		mark_inode_dirty(whiteout);
-
-		spin_lock(&whiteout->i_lock);
-		whiteout->i_state &= ~I_LINKABLE;
-		spin_unlock(&whiteout->i_lock);
-
-		iput(whiteout);
+		if (whiteout && IS_SYNC(whiteout))
+			sync = 1;
 	}
 
 	err = ubifs_jnl_rename(c, old_dir, old_inode, &old_nm, new_dir,
@@ -1454,6 +1484,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 	unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
 	ubifs_release_budget(c, &req);
 
+	if (whiteout) {
+		ubifs_release_budget(c, &wht_req);
+		iput(whiteout);
+	}
+
 	mutex_lock(&old_inode_ui->ui_mutex);
 	release = old_inode_ui->dirty;
 	mark_inode_dirty_sync(old_inode);
@@ -1462,11 +1497,16 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 	if (release)
 		ubifs_release_budget(c, &ino_req);
 	if (IS_SYNC(old_inode))
-		err = old_inode->i_sb->s_op->write_inode(old_inode, NULL);
+		/*
+		 * Rename finished here. Although old inode cannot be updated
+		 * on flash, old ctime is not a big problem, don't return err
+		 * code to userspace.
+		 */
+		old_inode->i_sb->s_op->write_inode(old_inode, NULL);
 
 	fscrypt_free_filename(&old_nm);
 	fscrypt_free_filename(&new_nm);
-	return err;
+	return 0;
 
 out_cancel:
 	if (unlink) {
@@ -1487,11 +1527,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
 				inc_nlink(old_dir);
 		}
 	}
+	unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
 	if (whiteout) {
-		drop_nlink(whiteout);
+		ubifs_release_budget(c, &wht_req);
 		iput(whiteout);
 	}
-	unlock_4_inodes(old_dir, new_dir, new_inode, whiteout);
 out_release:
 	ubifs_release_budget(c, &ino_req);
 	ubifs_release_budget(c, &req);
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 8ea680dba61e..a77821f922e2 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -1207,9 +1207,9 @@ int ubifs_jnl_xrename(struct ubifs_info *c, const struct inode *fst_dir,
  * @sync: non-zero if the write-buffer has to be synchronized
  *
  * This function implements the re-name operation which may involve writing up
- * to 4 inodes and 2 directory entries. It marks the written inodes as clean
- * and returns zero on success. In case of failure, a negative error code is
- * returned.
+ * to 4 inodes(new inode, whiteout inode, old and new parent directory inodes)
+ * and 2 directory entries. It marks the written inodes as clean and returns
+ * zero on success. In case of failure, a negative error code is returned.
  */
 int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		     const struct inode *old_inode,
@@ -1222,14 +1222,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 	void *p;
 	union ubifs_key key;
 	struct ubifs_dent_node *dent, *dent2;
-	int err, dlen1, dlen2, ilen, lnum, offs, len, orphan_added = 0;
+	int err, dlen1, dlen2, ilen, wlen, lnum, offs, len, orphan_added = 0;
 	int aligned_dlen1, aligned_dlen2, plen = UBIFS_INO_NODE_SZ;
 	int last_reference = !!(new_inode && new_inode->i_nlink == 0);
 	int move = (old_dir != new_dir);
-	struct ubifs_inode *new_ui;
+	struct ubifs_inode *new_ui, *whiteout_ui;
 	u8 hash_old_dir[UBIFS_HASH_ARR_SZ];
 	u8 hash_new_dir[UBIFS_HASH_ARR_SZ];
 	u8 hash_new_inode[UBIFS_HASH_ARR_SZ];
+	u8 hash_whiteout_inode[UBIFS_HASH_ARR_SZ];
 	u8 hash_dent1[UBIFS_HASH_ARR_SZ];
 	u8 hash_dent2[UBIFS_HASH_ARR_SZ];
 
@@ -1249,9 +1250,20 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 	} else
 		ilen = 0;
 
+	if (whiteout) {
+		whiteout_ui = ubifs_inode(whiteout);
+		ubifs_assert(c, mutex_is_locked(&whiteout_ui->ui_mutex));
+		ubifs_assert(c, whiteout->i_nlink == 1);
+		ubifs_assert(c, !whiteout_ui->dirty);
+		wlen = UBIFS_INO_NODE_SZ;
+		wlen += whiteout_ui->data_len;
+	} else
+		wlen = 0;
+
 	aligned_dlen1 = ALIGN(dlen1, 8);
 	aligned_dlen2 = ALIGN(dlen2, 8);
-	len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) + ALIGN(plen, 8);
+	len = aligned_dlen1 + aligned_dlen2 + ALIGN(ilen, 8) +
+	      ALIGN(wlen, 8) + ALIGN(plen, 8);
 	if (move)
 		len += plen;
 
@@ -1313,6 +1325,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		p += ALIGN(ilen, 8);
 	}
 
+	if (whiteout) {
+		pack_inode(c, p, whiteout, 0);
+		err = ubifs_node_calc_hash(c, p, hash_whiteout_inode);
+		if (err)
+			goto out_release;
+
+		p += ALIGN(wlen, 8);
+	}
+
 	if (!move) {
 		pack_inode(c, p, old_dir, 1);
 		err = ubifs_node_calc_hash(c, p, hash_old_dir);
@@ -1352,6 +1373,9 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		if (new_inode)
 			ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
 						  new_inode->i_ino);
+		if (whiteout)
+			ubifs_wbuf_add_ino_nolock(&c->jheads[BASEHD].wbuf,
+						  whiteout->i_ino);
 	}
 	release_head(c, BASEHD);
 
@@ -1368,8 +1392,6 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		err = ubifs_tnc_add_nm(c, &key, lnum, offs, dlen2, hash_dent2, old_nm);
 		if (err)
 			goto out_ro;
-
-		ubifs_delete_orphan(c, whiteout->i_ino);
 	} else {
 		err = ubifs_add_dirt(c, lnum, dlen2);
 		if (err)
@@ -1390,6 +1412,15 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		offs += ALIGN(ilen, 8);
 	}
 
+	if (whiteout) {
+		ino_key_init(c, &key, whiteout->i_ino);
+		err = ubifs_tnc_add(c, &key, lnum, offs, wlen,
+				    hash_whiteout_inode);
+		if (err)
+			goto out_ro;
+		offs += ALIGN(wlen, 8);
+	}
+
 	ino_key_init(c, &key, old_dir->i_ino);
 	err = ubifs_tnc_add(c, &key, lnum, offs, plen, hash_old_dir);
 	if (err)
@@ -1410,6 +1441,12 @@ int ubifs_jnl_rename(struct ubifs_info *c, const struct inode *old_dir,
 		new_ui->synced_i_size = new_ui->ui_size;
 		spin_unlock(&new_ui->ui_lock);
 	}
+	if (whiteout) {
+		/* No need to mark whiteout inode clean */
+		spin_lock(&whiteout_ui->ui_lock);
+		whiteout_ui->synced_i_size = whiteout_ui->ui_size;
+		spin_unlock(&whiteout_ui->ui_lock);
+	}
 	mark_inode_clean(c, ubifs_inode(old_dir));
 	if (move)
 		mark_inode_clean(c, ubifs_inode(new_dir));
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:12 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:12 +0800
Subject: [PATCH 07/11] ubifs: Rectify space amount budget for mkdir/tmpfile
 operations
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-8-chengzhihao1@huawei.com>

UBIFS should make sure the flash has enough space to store dirty (Data
that is newer than disk) data (in memory), space budget is exactly
designed to do that. If space budget calculates less data than we need,
'make_reservation()' will do more work(return -ENOSPC if no free space
lelf, sometimes we can see "cannot reserve xxx bytes in jhead xxx, error
-28" in ubifs error messages) with ubifs inodes locked, which may effect
other syscalls.

A simple way to decide how much space do we need when make a budget:
See how much space is needed by 'make_reservation()' in ubifs_jnl_xxx()
function according to corresponding operation.

It's better to report ENOSPC in ubifs_budget_space(), as early as we can.

Fixes: 474b93704f32163 ("ubifs: Implement O_TMPFILE")
Fixes: 1e51764a3c2ac05 ("UBIFS: add new flash file system")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 fs/ubifs/dir.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 8a2c42e6b22b..3a0c70362ad6 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -430,15 +430,18 @@ static int ubifs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
 {
 	struct inode *inode;
 	struct ubifs_info *c = dir->i_sb->s_fs_info;
-	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1};
+	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
+					.dirtied_ino = 1};
 	struct ubifs_budget_req ino_req = { .dirtied_ino = 1 };
 	struct ubifs_inode *ui;
 	int err, instantiated = 0;
 	struct fscrypt_name nm;
 
 	/*
-	 * Budget request settings: new dirty inode, new direntry,
-	 * budget for dirtied inode will be released via writeback.
+	 * Budget request settings: new inode, new direntry, changing the
+	 * parent directory inode.
+	 * Allocate budget separately for new dirtied inode, the budget will
+	 * be released via writeback.
 	 */
 
 	dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
@@ -981,7 +984,8 @@ static int ubifs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
 	struct ubifs_inode *dir_ui = ubifs_inode(dir);
 	struct ubifs_info *c = dir->i_sb->s_fs_info;
 	int err, sz_change;
-	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1 };
+	struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1,
+					.dirtied_ino = 1};
 	struct fscrypt_name nm;
 
 	/*
-- 
2.31.1



From chengzhihao1 at huawei.com  Sun Oct 24 20:41:15 2021
From: chengzhihao1 at huawei.com (Zhihao Cheng)
Date: Mon, 25 Oct 2021 11:41:15 +0800
Subject: [PATCH 10/11] ubi: fastmap: Return error code if memory allocation
 fails in add_aeb()
In-Reply-To: <20211025034116.3544321-1-chengzhihao1@huawei.com>
References: <20211025034116.3544321-1-chengzhihao1@huawei.com>
Message-ID: <20211025034116.3544321-11-chengzhihao1@huawei.com>

Abort fastmap scanning and return error code if memory allocation fails
in add_aeb(). Otherwise ubi will get wrong peb statistics information
after scanning.

Fixes: dbb7d2a88d2a7b ("UBI: Add fastmap core")
Signed-off-by: Zhihao Cheng <chengzhihao1 at huawei.com>
---
 drivers/mtd/ubi/fastmap.c | 28 +++++++++++++++++++---------
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 022af59906aa..6b5f1ffd961b 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -468,7 +468,9 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
 			if (err == UBI_IO_FF_BITFLIPS)
 				scrub = 1;
 
-			add_aeb(ai, free, pnum, ec, scrub);
+			ret = add_aeb(ai, free, pnum, ec, scrub);
+			if (ret)
+				goto out;
 			continue;
 		} else if (err == 0 || err == UBI_IO_BITFLIPS) {
 			dbg_bld("Found non empty PEB:%i in pool", pnum);
@@ -638,8 +640,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 0);
+		ret = add_aeb(ai, &ai->free, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 0);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from used list */
@@ -649,8 +653,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 0);
+		ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 0);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from scrub list */
@@ -660,8 +666,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 1);
+		ret = add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 1);
+		if (ret)
+			goto fail;
 	}
 
 	/* read EC values from erase list */
@@ -671,8 +679,10 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
 		if (fm_pos >= fm_size)
 			goto fail_bad;
 
-		add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
-			be32_to_cpu(fmec->ec), 1);
+		ret = add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
+			      be32_to_cpu(fmec->ec), 1);
+		if (ret)
+			goto fail;
 	}
 
 	ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
-- 
2.31.1



From hch at lst.de  Mon Oct 25 00:05:05 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:05 +0200
Subject: move all struct request releated code out of blk-core.c
Message-ID: <20211025070517.1548584-1-hch@lst.de>

Hi Jens,

this series (against the for-5.16/passthrough-flag branch) removes the
remaining struct request related code from blk-core.c and cleans up a
few related bits around that.

Diffstat:
 b/block/Makefile                     |    2 
 b/block/blk-core.c                   |  362 ----------------------
 b/block/blk-mq.c                     |  573 +++++++++++++++++++++++++++++------
 b/block/blk-mq.h                     |    3 
 b/block/blk.h                        |   33 --
 b/drivers/block/paride/pd.c          |    4 
 b/drivers/block/pktcdvd.c            |    2 
 b/drivers/block/virtio_blk.c         |    4 
 b/drivers/md/dm-mpath.c              |    4 
 b/drivers/mmc/core/block.c           |   20 -
 b/drivers/mtd/mtd_blkdevs.c          |   10 
 b/drivers/mtd/ubi/block.c            |    6 
 b/drivers/scsi/scsi_bsg.c            |    2 
 b/drivers/scsi/scsi_error.c          |    2 
 b/drivers/scsi/scsi_ioctl.c          |    4 
 b/drivers/scsi/scsi_lib.c            |   46 ++
 b/drivers/scsi/sg.c                  |    6 
 b/drivers/scsi/sr.c                  |    2 
 b/drivers/scsi/st.c                  |    4 
 b/drivers/scsi/ufs/ufshcd.c          |   20 -
 b/drivers/scsi/ufs/ufshpb.c          |    8 
 b/drivers/target/target_core_pscsi.c |    4 
 b/include/linux/blk-mq.h             |   16 
 block/blk-exec.c                     |  116 -------
 24 files changed, 597 insertions(+), 656 deletions(-)


From hch at lst.de  Mon Oct 25 00:05:06 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:06 +0200
Subject: [PATCH 01/12] block: move blk_rq_err_bytes to scsi
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-2-hch@lst.de>

blk_rq_err_bytes is only used by the scsi midlayer, so move it there.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c        | 41 ----------------------------------------
 drivers/scsi/scsi_lib.c | 42 ++++++++++++++++++++++++++++++++++++++++-
 include/linux/blk-mq.h  |  3 ---
 3 files changed, 41 insertions(+), 45 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 5ffe05b1d17ce..3edc5c5178dd6 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1221,47 +1221,6 @@ blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *
 }
 EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
 
-/**
- * blk_rq_err_bytes - determine number of bytes till the next failure boundary
- * @rq: request to examine
- *
- * Description:
- *     A request could be merge of IOs which require different failure
- *     handling.  This function determines the number of bytes which
- *     can be failed from the beginning of the request without
- *     crossing into area which need to be retried further.
- *
- * Return:
- *     The number of bytes to fail.
- */
-unsigned int blk_rq_err_bytes(const struct request *rq)
-{
-	unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK;
-	unsigned int bytes = 0;
-	struct bio *bio;
-
-	if (!(rq->rq_flags & RQF_MIXED_MERGE))
-		return blk_rq_bytes(rq);
-
-	/*
-	 * Currently the only 'mixing' which can happen is between
-	 * different fastfail types.  We can safely fail portions
-	 * which have all the failfast bits that the first one has -
-	 * the ones which are at least as eager to fail as the first
-	 * one.
-	 */
-	for (bio = rq->bio; bio; bio = bio->bi_next) {
-		if ((bio->bi_opf & ff) != ff)
-			break;
-		bytes += bio->bi_iter.bi_size;
-	}
-
-	/* this could lead to infinite loop */
-	BUG_ON(blk_rq_bytes(rq) && !bytes);
-	return bytes;
-}
-EXPORT_SYMBOL_GPL(blk_rq_err_bytes);
-
 static void update_io_ticks(struct block_device *part, unsigned long now,
 		bool end)
 {
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 9823b65d15368..1f7e68699941f 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -617,6 +617,46 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
 	}
 }
 
+/**
+ * scsi_rq_err_bytes - determine number of bytes till the next failure boundary
+ * @rq: request to examine
+ *
+ * Description:
+ *     A request could be merge of IOs which require different failure
+ *     handling.  This function determines the number of bytes which
+ *     can be failed from the beginning of the request without
+ *     crossing into area which need to be retried further.
+ *
+ * Return:
+ *     The number of bytes to fail.
+ */
+static unsigned int scsi_rq_err_bytes(const struct request *rq)
+{
+	unsigned int ff = rq->cmd_flags & REQ_FAILFAST_MASK;
+	unsigned int bytes = 0;
+	struct bio *bio;
+
+	if (!(rq->rq_flags & RQF_MIXED_MERGE))
+		return blk_rq_bytes(rq);
+
+	/*
+	 * Currently the only 'mixing' which can happen is between
+	 * different fastfail types.  We can safely fail portions
+	 * which have all the failfast bits that the first one has -
+	 * the ones which are at least as eager to fail as the first
+	 * one.
+	 */
+	for (bio = rq->bio; bio; bio = bio->bi_next) {
+		if ((bio->bi_opf & ff) != ff)
+			break;
+		bytes += bio->bi_iter.bi_size;
+	}
+
+	/* this could lead to infinite loop */
+	BUG_ON(blk_rq_bytes(rq) && !bytes);
+	return bytes;
+}
+
 /* Helper for scsi_io_completion() when "reprep" action required. */
 static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
 				      struct request_queue *q)
@@ -794,7 +834,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
 				scsi_print_command(cmd);
 			}
 		}
-		if (!scsi_end_request(req, blk_stat, blk_rq_err_bytes(req)))
+		if (!scsi_end_request(req, blk_stat, scsi_rq_err_bytes(req)))
 			return;
 		fallthrough;
 	case ACTION_REPREP:
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index ebc45cf0450b3..9f9634cd4cfd2 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -949,7 +949,6 @@ struct req_iterator {
  * blk_rq_pos()			: the current sector
  * blk_rq_bytes()		: bytes left in the entire request
  * blk_rq_cur_bytes()		: bytes left in the current segment
- * blk_rq_err_bytes()		: bytes left till the next error boundary
  * blk_rq_sectors()		: sectors left in the entire request
  * blk_rq_cur_sectors()		: sectors left in the current segment
  * blk_rq_stats_sectors()	: sectors of the entire request used for stats
@@ -973,8 +972,6 @@ static inline int blk_rq_cur_bytes(const struct request *rq)
 	return bio_iovec(rq->bio).bv_len;
 }
 
-unsigned int blk_rq_err_bytes(const struct request *rq);
-
 static inline unsigned int blk_rq_sectors(const struct request *rq)
 {
 	return blk_rq_bytes(rq) >> SECTOR_SHIFT;
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:07 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:07 +0200
Subject: [PATCH 02/12] block: remove blk_{get,put}_request
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-3-hch@lst.de>

These are now pointless wrappers around blk_mq_{alloc,free}_request,
so remove them.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c                   | 21 ---------------------
 drivers/block/paride/pd.c          |  4 ++--
 drivers/block/pktcdvd.c            |  2 +-
 drivers/block/virtio_blk.c         |  4 ++--
 drivers/md/dm-mpath.c              |  4 ++--
 drivers/mmc/core/block.c           | 20 ++++++++++----------
 drivers/scsi/scsi_bsg.c            |  2 +-
 drivers/scsi/scsi_error.c          |  2 +-
 drivers/scsi/scsi_ioctl.c          |  4 ++--
 drivers/scsi/scsi_lib.c            |  4 ++--
 drivers/scsi/sg.c                  |  6 +++---
 drivers/scsi/sr.c                  |  2 +-
 drivers/scsi/st.c                  |  4 ++--
 drivers/scsi/ufs/ufshcd.c          | 20 ++++++++++----------
 drivers/scsi/ufs/ufshpb.c          |  8 ++++----
 drivers/target/target_core_pscsi.c |  4 ++--
 include/linux/blk-mq.h             |  3 ---
 17 files changed, 45 insertions(+), 69 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 3edc5c5178dd6..0d267cfb71484 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -597,27 +597,6 @@ bool blk_get_queue(struct request_queue *q)
 }
 EXPORT_SYMBOL(blk_get_queue);
 
-/**
- * blk_get_request - allocate a request
- * @q: request queue to allocate a request for
- * @op: operation (REQ_OP_*) and REQ_* flags, e.g. REQ_SYNC.
- * @flags: BLK_MQ_REQ_* flags, e.g. BLK_MQ_REQ_NOWAIT.
- */
-struct request *blk_get_request(struct request_queue *q, unsigned int op,
-				blk_mq_req_flags_t flags)
-{
-	WARN_ON_ONCE(op & REQ_NOWAIT);
-	WARN_ON_ONCE(flags & ~(BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_PM));
-	return blk_mq_alloc_request(q, op, flags);
-}
-EXPORT_SYMBOL(blk_get_request);
-
-void blk_put_request(struct request *req)
-{
-	blk_mq_free_request(req);
-}
-EXPORT_SYMBOL(blk_put_request);
-
 static void handle_bad_sector(struct bio *bio, sector_t maxsector)
 {
 	char b[BDEVNAME_SIZE];
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 675327df6aff9..9cd0bd509b887 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -775,14 +775,14 @@ static int pd_special_command(struct pd_unit *disk,
 	struct request *rq;
 	struct pd_req *req;
 
-	rq = blk_get_request(disk->gd->queue, REQ_OP_DRV_IN, 0);
+	rq = blk_mq_alloc_request(disk->gd->queue, REQ_OP_DRV_IN, 0);
 	if (IS_ERR(rq))
 		return PTR_ERR(rq);
 	req = blk_mq_rq_to_pdu(rq);
 
 	req->func = func;
 	blk_execute_rq(disk->gd, rq, 0);
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 	return 0;
 }
 
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index cacf64eedad87..40e7a45e3347c 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -726,7 +726,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
 	if (scsi_req(rq)->result)
 		ret = -EIO;
 out:
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 	return ret;
 }
 
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 303caf2d17d0c..f81a768943e15 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -312,7 +312,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
 	struct request *req;
 	int err;
 
-	req = blk_get_request(q, REQ_OP_DRV_IN, 0);
+	req = blk_mq_alloc_request(q, REQ_OP_DRV_IN, 0);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -323,7 +323,7 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
 	blk_execute_rq(vblk->disk, req, false);
 	err = blk_status_to_errno(virtblk_result(blk_mq_rq_to_pdu(req)));
 out:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 	return err;
 }
 
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 694aaca4eea24..510f6c3ab98d4 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -530,7 +530,7 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
 
 	bdev = pgpath->path.dev->bdev;
 	q = bdev_get_queue(bdev);
-	clone = blk_get_request(q, rq->cmd_flags | REQ_NOMERGE,
+	clone = blk_mq_alloc_request(q, rq->cmd_flags | REQ_NOMERGE,
 			BLK_MQ_REQ_NOWAIT);
 	if (IS_ERR(clone)) {
 		/* EBUSY, ENODEV or EWOULDBLOCK: requeue */
@@ -579,7 +579,7 @@ static void multipath_release_clone(struct request *clone,
 						    clone->io_start_time_ns);
 	}
 
-	blk_put_request(clone);
+	blk_mq_free_request(clone);
 }
 
 /*
diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 431af5e8be2f8..74882fa0f86d0 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -258,7 +258,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
 	mq = &md->queue;
 
 	/* Dispatch locking to the block layer */
-	req = blk_get_request(mq->queue, REQ_OP_DRV_OUT, 0);
+	req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_OUT, 0);
 	if (IS_ERR(req)) {
 		count = PTR_ERR(req);
 		goto out_put;
@@ -266,7 +266,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
 	req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP;
 	blk_execute_rq(NULL, req, 0);
 	ret = req_to_mmc_queue_req(req)->drv_op_result;
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 	if (!ret) {
 		pr_info("%s: Locking boot partition ro until next power on\n",
@@ -646,7 +646,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
 	 * Dispatch the ioctl() into the block request queue.
 	 */
 	mq = &md->queue;
-	req = blk_get_request(mq->queue,
+	req = blk_mq_alloc_request(mq->queue,
 		idata->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
@@ -660,7 +660,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md,
 	blk_execute_rq(NULL, req, 0);
 	ioc_err = req_to_mmc_queue_req(req)->drv_op_result;
 	err = mmc_blk_ioctl_copy_to_user(ic_ptr, idata);
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 cmd_done:
 	kfree(idata->buf);
@@ -716,7 +716,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
 	 * Dispatch the ioctl()s into the block request queue.
 	 */
 	mq = &md->queue;
-	req = blk_get_request(mq->queue,
+	req = blk_mq_alloc_request(mq->queue,
 		idata[0]->ic.write_flag ? REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
@@ -733,7 +733,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md,
 	for (i = 0; i < num_of_cmds && !err; i++)
 		err = mmc_blk_ioctl_copy_to_user(&cmds[i], idata[i]);
 
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 cmd_err:
 	for (i = 0; i < num_of_cmds; i++) {
@@ -2730,7 +2730,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
 	int ret;
 
 	/* Ask the block layer about the card status */
-	req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0);
+	req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 	req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS;
@@ -2740,7 +2740,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val)
 		*val = ret;
 		ret = 0;
 	}
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 	return ret;
 }
@@ -2766,7 +2766,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
 		return -ENOMEM;
 
 	/* Ask the block layer for the EXT CSD */
-	req = blk_get_request(mq->queue, REQ_OP_DRV_IN, 0);
+	req = blk_mq_alloc_request(mq->queue, REQ_OP_DRV_IN, 0);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto out_free;
@@ -2775,7 +2775,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp)
 	req_to_mmc_queue_req(req)->drv_op_data = &ext_csd;
 	blk_execute_rq(NULL, req, 0);
 	err = req_to_mmc_queue_req(req)->drv_op_result;
-	blk_put_request(req);
+	blk_mq_free_request(req);
 	if (err) {
 		pr_err("FAILED %d\n", err);
 		goto out_free;
diff --git a/drivers/scsi/scsi_bsg.c b/drivers/scsi/scsi_bsg.c
index 551727a6f6941..081b84bb7985b 100644
--- a/drivers/scsi/scsi_bsg.c
+++ b/drivers/scsi/scsi_bsg.c
@@ -95,7 +95,7 @@ static int scsi_bsg_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
 out_free_cmd:
 	scsi_req_free_cmd(scsi_req(rq));
 out_put_request:
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 	return ret;
 }
 
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 71d027b94be40..36870b41c888d 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1979,7 +1979,7 @@ enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *scmd)
 
 static void eh_lock_door_done(struct request *req, blk_status_t status)
 {
-	blk_put_request(req);
+	blk_mq_free_request(req);
 }
 
 /**
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
index 0078975e3c07c..34412eac4566b 100644
--- a/drivers/scsi/scsi_ioctl.c
+++ b/drivers/scsi/scsi_ioctl.c
@@ -490,7 +490,7 @@ static int sg_io(struct scsi_device *sdev, struct gendisk *disk,
 out_free_cdb:
 	scsi_req_free_cmd(req);
 out_put_request:
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 	return ret;
 }
 
@@ -634,7 +634,7 @@ static int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk,
 	}
 
 error:
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 
 error_free_buffer:
 	kfree(buffer);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1f7e68699941f..514cabc0f31b4 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -260,7 +260,7 @@ int __scsi_execute(struct scsi_device *sdev, const unsigned char *cmd,
 		scsi_normalize_sense(rq->sense, rq->sense_len, sshdr);
 	ret = rq->result;
  out:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 	return ret;
 }
@@ -1140,7 +1140,7 @@ struct request *scsi_alloc_request(struct request_queue *q,
 {
 	struct request *rq;
 
-	rq = blk_get_request(q, op, flags);
+	rq = blk_mq_alloc_request(q, op, flags);
 	if (!IS_ERR(rq))
 		scsi_initialize_rq(rq);
 	return rq;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 85f57ac0b844e..141099ab90921 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -815,7 +815,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
 	if (atomic_read(&sdp->detaching)) {
 		if (srp->bio) {
 			scsi_req_free_cmd(scsi_req(srp->rq));
-			blk_put_request(srp->rq);
+			blk_mq_free_request(srp->rq);
 			srp->rq = NULL;
 		}
 
@@ -1390,7 +1390,7 @@ sg_rq_end_io(struct request *rq, blk_status_t status)
 	 */
 	srp->rq = NULL;
 	scsi_req_free_cmd(scsi_req(rq));
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
 	if (unlikely(srp->orphan)) {
@@ -1830,7 +1830,7 @@ sg_finish_rem_req(Sg_request *srp)
 
 	if (srp->rq) {
 		scsi_req_free_cmd(scsi_req(srp->rq));
-		blk_put_request(srp->rq);
+		blk_mq_free_request(srp->rq);
 	}
 
 	if (srp->res_used)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 7c4d9a9647999..3009b986d1d74 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -1003,7 +1003,7 @@ static int sr_read_cdda_bpc(struct cdrom_device_info *cdi, void __user *ubuf,
 	if (blk_rq_unmap_user(bio))
 		ret = -EFAULT;
 out_put_request:
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 	return ret;
 }
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 1275299f61597..c2d5608f6b1a5 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -530,7 +530,7 @@ static void st_scsi_execute_end(struct request *req, blk_status_t status)
 		complete(SRpnt->waiting);
 
 	blk_rq_unmap_user(tmp);
-	blk_put_request(req);
+	blk_mq_free_request(req);
 }
 
 static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
@@ -557,7 +557,7 @@ static int st_scsi_execute(struct st_request *SRpnt, const unsigned char *cmd,
 		err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen,
 				      GFP_KERNEL);
 		if (err) {
-			blk_put_request(req);
+			blk_mq_free_request(req);
 			return err;
 		}
 	}
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index bf81da2ecf98c..c85f540f6af4e 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2925,7 +2925,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 	 * Even though we use wait_event() which sleeps indefinitely,
 	 * the maximum wait time is bounded by SCSI request timeout.
 	 */
-	req = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+	req = blk_mq_alloc_request(q, REQ_OP_DRV_OUT, 0);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto out_unlock;
@@ -2952,7 +2952,7 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
 				    (struct utp_upiu_req *)lrbp->ucd_rsp_ptr);
 
 out:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 out_unlock:
 	up_read(&hba->clk_scaling_lock);
 	return err;
@@ -6517,9 +6517,9 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 	int task_tag, err;
 
 	/*
-	 * blk_get_request() is used here only to get a free tag.
+	 * blk_mq_alloc_request() is used here only to get a free tag.
 	 */
-	req = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+	req = blk_mq_alloc_request(q, REQ_OP_DRV_OUT, 0);
 	if (IS_ERR(req))
 		return PTR_ERR(req);
 
@@ -6575,7 +6575,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba,
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
 
 	ufshcd_release(hba);
-	blk_put_request(req);
+	blk_mq_free_request(req);
 
 	return err;
 }
@@ -6660,7 +6660,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
 
 	down_read(&hba->clk_scaling_lock);
 
-	req = blk_get_request(q, REQ_OP_DRV_OUT, 0);
+	req = blk_mq_alloc_request(q, REQ_OP_DRV_OUT, 0);
 	if (IS_ERR(req)) {
 		err = PTR_ERR(req);
 		goto out_unlock;
@@ -6741,7 +6741,7 @@ static int ufshcd_issue_devman_upiu_cmd(struct ufs_hba *hba,
 				    (struct utp_upiu_req *)lrbp->ucd_rsp_ptr);
 
 out:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 out_unlock:
 	up_read(&hba->clk_scaling_lock);
 	return err;
@@ -7912,7 +7912,7 @@ static void ufshcd_request_sense_done(struct request *rq, blk_status_t error)
 	if (error != BLK_STS_OK)
 		pr_err("%s: REQUEST SENSE failed (%d)\n", __func__, error);
 	kfree(rq->end_io_data);
-	blk_put_request(rq);
+	blk_mq_free_request(rq);
 }
 
 static int
@@ -7932,7 +7932,7 @@ ufshcd_request_sense_async(struct ufs_hba *hba, struct scsi_device *sdev)
 	if (!buffer)
 		return -ENOMEM;
 
-	req = blk_get_request(sdev->request_queue, REQ_OP_DRV_IN,
+	req = blk_mq_alloc_request(sdev->request_queue, REQ_OP_DRV_IN,
 			      /*flags=*/BLK_MQ_REQ_PM);
 	if (IS_ERR(req)) {
 		ret = PTR_ERR(req);
@@ -7957,7 +7957,7 @@ ufshcd_request_sense_async(struct ufs_hba *hba, struct scsi_device *sdev)
 	return 0;
 
 out_put:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 out_free:
 	kfree(buffer);
 	return ret;
diff --git a/drivers/scsi/ufs/ufshpb.c b/drivers/scsi/ufs/ufshpb.c
index 589af5f6b940a..a2a3080071e9d 100644
--- a/drivers/scsi/ufs/ufshpb.c
+++ b/drivers/scsi/ufs/ufshpb.c
@@ -564,7 +564,7 @@ static int ufshpb_issue_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd,
 	int _read_id;
 	int ret = 0;
 
-	req = blk_get_request(cmd->device->request_queue,
+	req = blk_mq_alloc_request(cmd->device->request_queue,
 			      REQ_OP_DRV_OUT | REQ_SYNC, BLK_MQ_REQ_NOWAIT);
 	if (IS_ERR(req))
 		return -EAGAIN;
@@ -592,7 +592,7 @@ static int ufshpb_issue_pre_req(struct ufshpb_lu *hpb, struct scsi_cmnd *cmd,
 	ufshpb_put_pre_req(hpb, pre_req);
 unlock_out:
 	spin_unlock_irqrestore(&hpb->rgn_state_lock, flags);
-	blk_put_request(req);
+	blk_mq_free_request(req);
 	return ret;
 }
 
@@ -721,7 +721,7 @@ static struct ufshpb_req *ufshpb_get_req(struct ufshpb_lu *hpb,
 		return NULL;
 
 retry:
-	req = blk_get_request(hpb->sdev_ufs_lu->request_queue, dir,
+	req = blk_mq_alloc_request(hpb->sdev_ufs_lu->request_queue, dir,
 			      BLK_MQ_REQ_NOWAIT);
 
 	if (!atomic && (PTR_ERR(req) == -EWOULDBLOCK) && (--retries > 0)) {
@@ -745,7 +745,7 @@ static struct ufshpb_req *ufshpb_get_req(struct ufshpb_lu *hpb,
 
 static void ufshpb_put_req(struct ufshpb_lu *hpb, struct ufshpb_req *rq)
 {
-	blk_put_request(rq->req);
+	blk_mq_free_request(rq->req);
 	kmem_cache_free(hpb->map_req_cache, rq);
 }
 
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index b5705a2bd7618..7fa57fb57bf22 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -1011,7 +1011,7 @@ pscsi_execute_cmd(struct se_cmd *cmd)
 	return 0;
 
 fail_put_request:
-	blk_put_request(req);
+	blk_mq_free_request(req);
 fail:
 	kfree(pt);
 	return ret;
@@ -1066,7 +1066,7 @@ static void pscsi_req_done(struct request *req, blk_status_t status)
 		break;
 	}
 
-	blk_put_request(req);
+	blk_mq_free_request(req);
 	kfree(pt);
 }
 
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 9f9634cd4cfd2..850ecfdebe595 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -892,9 +892,6 @@ static inline bool rq_is_sync(struct request *rq)
 }
 
 void blk_rq_init(struct request_queue *q, struct request *rq);
-void blk_put_request(struct request *rq);
-struct request *blk_get_request(struct request_queue *q, unsigned int op,
-		blk_mq_req_flags_t flags);
 int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 		struct bio_set *bs, gfp_t gfp_mask,
 		int (*bio_ctr)(struct bio *, struct bio *, void *), void *data);
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:08 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:08 +0200
Subject: [PATCH 03/12] block: remove rq_flush_dcache_pages
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-4-hch@lst.de>

This function is trivial, and flush_dcache_page is always defined, so
just open code it in the 2.5 callers.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c          | 19 -------------------
 drivers/mtd/mtd_blkdevs.c | 10 ++++++++--
 drivers/mtd/ubi/block.c   |  6 +++++-
 include/linux/blk-mq.h    | 10 ----------
 4 files changed, 13 insertions(+), 32 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 0d267cfb71484..08c6077365ac9 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1324,25 +1324,6 @@ void blk_steal_bios(struct bio_list *list, struct request *rq)
 }
 EXPORT_SYMBOL_GPL(blk_steal_bios);
 
-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
-/**
- * rq_flush_dcache_pages - Helper function to flush all pages in a request
- * @rq: the request to be flushed
- *
- * Description:
- *     Flush all pages in @rq.
- */
-void rq_flush_dcache_pages(struct request *rq)
-{
-	struct req_iterator iter;
-	struct bio_vec bvec;
-
-	rq_for_each_segment(bvec, rq, iter)
-		flush_dcache_page(bvec.bv_page);
-}
-EXPORT_SYMBOL_GPL(rq_flush_dcache_pages);
-#endif
-
 /**
  * blk_lld_busy - Check if underlying low-level drivers of a device are busy
  * @q : the queue of the device being checked
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index b8ae1ec14e178..356b5bb4db51a 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -46,6 +46,8 @@ static blk_status_t do_blktrans_request(struct mtd_blktrans_ops *tr,
 			       struct mtd_blktrans_dev *dev,
 			       struct request *req)
 {
+	struct req_iterator iter;
+	struct bio_vec bvec;
 	unsigned long block, nsect;
 	char *buf;
 
@@ -76,13 +78,17 @@ static blk_status_t do_blktrans_request(struct mtd_blktrans_ops *tr,
 			}
 		}
 		kunmap(bio_page(req->bio));
-		rq_flush_dcache_pages(req);
+
+		rq_for_each_segment(bvec, req, iter)
+			flush_dcache_page(bvec.bv_page);
 		return BLK_STS_OK;
 	case REQ_OP_WRITE:
 		if (!tr->writesect)
 			return BLK_STS_IOERR;
 
-		rq_flush_dcache_pages(req);
+		rq_for_each_segment(bvec, req, iter)
+			flush_dcache_page(bvec.bv_page);
+
 		buf = kmap(bio_page(req->bio)) + bio_offset(req->bio);
 		for (; nsect > 0; nsect--, block++, buf += tr->blksize) {
 			if (tr->writesect(dev, block, buf)) {
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index e003b4b44ffa2..99e17ee13feb7 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -294,6 +294,8 @@ static void ubiblock_do_work(struct work_struct *work)
 	int ret;
 	struct ubiblock_pdu *pdu = container_of(work, struct ubiblock_pdu, work);
 	struct request *req = blk_mq_rq_from_pdu(pdu);
+	struct req_iterator iter;
+	struct bio_vec bvec;
 
 	blk_mq_start_request(req);
 
@@ -305,7 +307,9 @@ static void ubiblock_do_work(struct work_struct *work)
 	blk_rq_map_sg(req->q, req, pdu->usgl.sg);
 
 	ret = ubiblock_read(pdu);
-	rq_flush_dcache_pages(req);
+
+	rq_for_each_segment(bvec, req, iter)
+		flush_dcache_page(bvec.bv_page);
 
 	blk_mq_end_request(req, errno_to_blk_status(ret));
 }
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index 850ecfdebe595..047ce54fca96c 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -1131,14 +1131,4 @@ static inline bool blk_req_can_dispatch_to_zone(struct request *rq)
 }
 #endif /* CONFIG_BLK_DEV_ZONED */
 
-#ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
-# error	"You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform"
-#endif
-#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
-void rq_flush_dcache_pages(struct request *rq);
-#else
-static inline void rq_flush_dcache_pages(struct request *rq)
-{
-}
-#endif /* ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE */
 #endif /* BLK_MQ_H */
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:09 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:09 +0200
Subject: [PATCH 04/12] block: remove blk-exec.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-5-hch@lst.de>

All this code is tightly coupled to the blk-mq core, so move it
there.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/Makefile   |   2 +-
 block/blk-exec.c | 116 -----------------------------------------------
 block/blk-mq.c   | 107 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 117 deletions(-)
 delete mode 100644 block/blk-exec.c

diff --git a/block/Makefile b/block/Makefile
index 602f7f47b7b6d..9623aff1a346c 100644
--- a/block/Makefile
+++ b/block/Makefile
@@ -5,7 +5,7 @@
 
 obj-y		:= bdev.o fops.o bio.o elevator.o blk-core.o blk-sysfs.o \
 			blk-flush.o blk-settings.o blk-ioc.o blk-map.o \
-			blk-exec.o blk-merge.o blk-timeout.o \
+			blk-merge.o blk-timeout.o \
 			blk-lib.o blk-mq.o blk-mq-tag.o blk-stat.o \
 			blk-mq-sysfs.o blk-mq-cpumap.o blk-mq-sched.o ioctl.o \
 			genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \
diff --git a/block/blk-exec.c b/block/blk-exec.c
deleted file mode 100644
index 1b8b47f6e79bb..0000000000000
--- a/block/blk-exec.c
+++ /dev/null
@@ -1,116 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Functions related to setting various queue properties from drivers
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/bio.h>
-#include <linux/blkdev.h>
-#include <linux/blk-mq.h>
-#include <linux/sched/sysctl.h>
-
-#include "blk.h"
-#include "blk-mq-sched.h"
-
-/**
- * blk_end_sync_rq - executes a completion event on a request
- * @rq: request to complete
- * @error: end I/O status of the request
- */
-static void blk_end_sync_rq(struct request *rq, blk_status_t error)
-{
-	struct completion *waiting = rq->end_io_data;
-
-	rq->end_io_data = (void *)(uintptr_t)error;
-
-	/*
-	 * complete last, if this is a stack request the process (and thus
-	 * the rq pointer) could be invalid right after this complete()
-	 */
-	complete(waiting);
-}
-
-/**
- * blk_execute_rq_nowait - insert a request to I/O scheduler for execution
- * @bd_disk:	matching gendisk
- * @rq:		request to insert
- * @at_head:    insert request at head or tail of queue
- * @done:	I/O completion handler
- *
- * Description:
- *    Insert a fully prepared request at the back of the I/O scheduler queue
- *    for execution.  Don't wait for completion.
- *
- * Note:
- *    This function will invoke @done directly if the queue is dead.
- */
-void blk_execute_rq_nowait(struct gendisk *bd_disk, struct request *rq,
-			   int at_head, rq_end_io_fn *done)
-{
-	WARN_ON(irqs_disabled());
-	WARN_ON(!blk_rq_is_passthrough(rq));
-
-	rq->rq_disk = bd_disk;
-	rq->end_io = done;
-
-	blk_account_io_start(rq);
-
-	/*
-	 * don't check dying flag for MQ because the request won't
-	 * be reused after dying flag is set
-	 */
-	blk_mq_sched_insert_request(rq, at_head, true, false);
-}
-EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
-
-static bool blk_rq_is_poll(struct request *rq)
-{
-	if (!rq->mq_hctx)
-		return false;
-	if (rq->mq_hctx->type != HCTX_TYPE_POLL)
-		return false;
-	if (WARN_ON_ONCE(!rq->bio))
-		return false;
-	return true;
-}
-
-static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
-{
-	do {
-		bio_poll(rq->bio, NULL, 0);
-		cond_resched();
-	} while (!completion_done(wait));
-}
-
-/**
- * blk_execute_rq - insert a request into queue for execution
- * @bd_disk:	matching gendisk
- * @rq:		request to insert
- * @at_head:    insert request at head or tail of queue
- *
- * Description:
- *    Insert a fully prepared request at the back of the I/O scheduler queue
- *    for execution and wait for completion.
- * Return: The blk_status_t result provided to blk_mq_end_request().
- */
-blk_status_t blk_execute_rq(struct gendisk *bd_disk, struct request *rq, int at_head)
-{
-	DECLARE_COMPLETION_ONSTACK(wait);
-	unsigned long hang_check;
-
-	rq->end_io_data = &wait;
-	blk_execute_rq_nowait(bd_disk, rq, at_head, blk_end_sync_rq);
-
-	/* Prevent hang_check timer from firing at us during very long I/O */
-	hang_check = sysctl_hung_task_timeout_secs;
-
-	if (blk_rq_is_poll(rq))
-		blk_rq_poll_completion(rq, &wait);
-	else if (hang_check)
-		while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2)));
-	else
-		wait_for_completion_io(&wait);
-
-	return (blk_status_t)(uintptr_t)rq->end_io_data;
-}
-EXPORT_SYMBOL(blk_execute_rq);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d04ee72ba1255..d8f17b54e2c73 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -28,6 +28,7 @@
 #include <linux/crash_dump.h>
 #include <linux/prefetch.h>
 #include <linux/blk-crypto.h>
+#include <linux/sched/sysctl.h>
 
 #include <trace/events/block.h>
 
@@ -1031,6 +1032,112 @@ void blk_mq_start_request(struct request *rq)
 }
 EXPORT_SYMBOL(blk_mq_start_request);
 
+/**
+ * blk_end_sync_rq - executes a completion event on a request
+ * @rq: request to complete
+ * @error: end I/O status of the request
+ */
+static void blk_end_sync_rq(struct request *rq, blk_status_t error)
+{
+	struct completion *waiting = rq->end_io_data;
+
+	rq->end_io_data = (void *)(uintptr_t)error;
+
+	/*
+	 * complete last, if this is a stack request the process (and thus
+	 * the rq pointer) could be invalid right after this complete()
+	 */
+	complete(waiting);
+}
+
+/**
+ * blk_execute_rq_nowait - insert a request to I/O scheduler for execution
+ * @bd_disk:	matching gendisk
+ * @rq:		request to insert
+ * @at_head:    insert request at head or tail of queue
+ * @done:	I/O completion handler
+ *
+ * Description:
+ *    Insert a fully prepared request at the back of the I/O scheduler queue
+ *    for execution.  Don't wait for completion.
+ *
+ * Note:
+ *    This function will invoke @done directly if the queue is dead.
+ */
+void blk_execute_rq_nowait(struct gendisk *bd_disk, struct request *rq,
+			   int at_head, rq_end_io_fn *done)
+{
+	WARN_ON(irqs_disabled());
+	WARN_ON(!blk_rq_is_passthrough(rq));
+
+	rq->rq_disk = bd_disk;
+	rq->end_io = done;
+
+	blk_account_io_start(rq);
+
+	/*
+	 * don't check dying flag for MQ because the request won't
+	 * be reused after dying flag is set
+	 */
+	blk_mq_sched_insert_request(rq, at_head, true, false);
+}
+EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
+
+static bool blk_rq_is_poll(struct request *rq)
+{
+	if (!rq->mq_hctx)
+		return false;
+	if (rq->mq_hctx->type != HCTX_TYPE_POLL)
+		return false;
+	if (WARN_ON_ONCE(!rq->bio))
+		return false;
+	return true;
+}
+
+static void blk_rq_poll_completion(struct request *rq, struct completion *wait)
+{
+	do {
+		bio_poll(rq->bio, NULL, 0);
+		cond_resched();
+	} while (!completion_done(wait));
+}
+
+/**
+ * blk_execute_rq - insert a request into queue for execution
+ * @bd_disk:	matching gendisk
+ * @rq:		request to insert
+ * @at_head:    insert request at head or tail of queue
+ *
+ * Description:
+ *    Insert a fully prepared request at the back of the I/O scheduler queue
+ *    for execution and wait for completion.
+ * Return: The blk_status_t result provided to blk_mq_end_request().
+ */
+blk_status_t blk_execute_rq(struct gendisk *bd_disk, struct request *rq,
+		int at_head)
+{
+	DECLARE_COMPLETION_ONSTACK(wait);
+	unsigned long hang_check;
+
+	rq->end_io_data = &wait;
+	blk_execute_rq_nowait(bd_disk, rq, at_head, blk_end_sync_rq);
+
+	/* Prevent hang_check timer from firing at us during very long I/O */
+	hang_check = sysctl_hung_task_timeout_secs;
+
+	if (blk_rq_is_poll(rq))
+		blk_rq_poll_completion(rq, &wait);
+	else if (hang_check)
+		while (!wait_for_completion_io_timeout(&wait,
+				hang_check * (HZ/2)))
+			;
+	else
+		wait_for_completion_io(&wait);
+
+	return (blk_status_t)(uintptr_t)rq->end_io_data;
+}
+EXPORT_SYMBOL(blk_execute_rq);
+
 static void __blk_mq_requeue_request(struct request *rq)
 {
 	struct request_queue *q = rq->q;
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:10 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:10 +0200
Subject: [PATCH 05/12] blk-mq: move blk_mq_flush_plug_list
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-6-hch@lst.de>

Move blk_mq_flush_plug_list and blk_mq_plug_issue_direct down in blk-mq.c
to prepare for marking blk_mq_request_issue_directly static without the
need of a forward declaration.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-mq.c | 184 ++++++++++++++++++++++++-------------------------
 1 file changed, 92 insertions(+), 92 deletions(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index d8f17b54e2c73..f46d41a760106 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2277,98 +2277,6 @@ static void blk_mq_commit_rqs(struct blk_mq_hw_ctx *hctx, int *queued,
 	*queued = 0;
 }
 
-static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule)
-{
-	struct blk_mq_hw_ctx *hctx = NULL;
-	struct request *rq;
-	int queued = 0;
-	int errors = 0;
-
-	while ((rq = rq_list_pop(&plug->mq_list))) {
-		bool last = rq_list_empty(plug->mq_list);
-		blk_status_t ret;
-
-		if (hctx != rq->mq_hctx) {
-			if (hctx)
-				blk_mq_commit_rqs(hctx, &queued, from_schedule);
-			hctx = rq->mq_hctx;
-		}
-
-		ret = blk_mq_request_issue_directly(rq, last);
-		switch (ret) {
-		case BLK_STS_OK:
-			queued++;
-			break;
-		case BLK_STS_RESOURCE:
-		case BLK_STS_DEV_RESOURCE:
-			blk_mq_request_bypass_insert(rq, false, last);
-			blk_mq_commit_rqs(hctx, &queued, from_schedule);
-			return;
-		default:
-			blk_mq_end_request(rq, ret);
-			errors++;
-			break;
-		}
-	}
-
-	/*
-	 * If we didn't flush the entire list, we could have told the driver
-	 * there was more coming, but that turned out to be a lie.
-	 */
-	if (errors)
-		blk_mq_commit_rqs(hctx, &queued, from_schedule);
-}
-
-void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
-{
-	struct blk_mq_hw_ctx *this_hctx;
-	struct blk_mq_ctx *this_ctx;
-	unsigned int depth;
-	LIST_HEAD(list);
-
-	if (rq_list_empty(plug->mq_list))
-		return;
-	plug->rq_count = 0;
-
-	if (!plug->multiple_queues && !plug->has_elevator) {
-		blk_mq_plug_issue_direct(plug, from_schedule);
-		if (rq_list_empty(plug->mq_list))
-			return;
-	}
-
-	this_hctx = NULL;
-	this_ctx = NULL;
-	depth = 0;
-	do {
-		struct request *rq;
-
-		rq = rq_list_pop(&plug->mq_list);
-
-		if (!this_hctx) {
-			this_hctx = rq->mq_hctx;
-			this_ctx = rq->mq_ctx;
-		} else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
-			trace_block_unplug(this_hctx->queue, depth,
-						!from_schedule);
-			blk_mq_sched_insert_requests(this_hctx, this_ctx,
-						&list, from_schedule);
-			depth = 0;
-			this_hctx = rq->mq_hctx;
-			this_ctx = rq->mq_ctx;
-
-		}
-
-		list_add(&rq->queuelist, &list);
-		depth++;
-	} while (!rq_list_empty(plug->mq_list));
-
-	if (!list_empty(&list)) {
-		trace_block_unplug(this_hctx->queue, depth, !from_schedule);
-		blk_mq_sched_insert_requests(this_hctx, this_ctx, &list,
-						from_schedule);
-	}
-}
-
 static void blk_mq_bio_to_request(struct request *rq, struct bio *bio,
 		unsigned int nr_segs)
 {
@@ -2508,6 +2416,98 @@ blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
 	return ret;
 }
 
+static void blk_mq_plug_issue_direct(struct blk_plug *plug, bool from_schedule)
+{
+	struct blk_mq_hw_ctx *hctx = NULL;
+	struct request *rq;
+	int queued = 0;
+	int errors = 0;
+
+	while ((rq = rq_list_pop(&plug->mq_list))) {
+		bool last = rq_list_empty(plug->mq_list);
+		blk_status_t ret;
+
+		if (hctx != rq->mq_hctx) {
+			if (hctx)
+				blk_mq_commit_rqs(hctx, &queued, from_schedule);
+			hctx = rq->mq_hctx;
+		}
+
+		ret = blk_mq_request_issue_directly(rq, last);
+		switch (ret) {
+		case BLK_STS_OK:
+			queued++;
+			break;
+		case BLK_STS_RESOURCE:
+		case BLK_STS_DEV_RESOURCE:
+			blk_mq_request_bypass_insert(rq, false, last);
+			blk_mq_commit_rqs(hctx, &queued, from_schedule);
+			return;
+		default:
+			blk_mq_end_request(rq, ret);
+			errors++;
+			break;
+		}
+	}
+
+	/*
+	 * If we didn't flush the entire list, we could have told the driver
+	 * there was more coming, but that turned out to be a lie.
+	 */
+	if (errors)
+		blk_mq_commit_rqs(hctx, &queued, from_schedule);
+}
+
+void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
+{
+	struct blk_mq_hw_ctx *this_hctx;
+	struct blk_mq_ctx *this_ctx;
+	unsigned int depth;
+	LIST_HEAD(list);
+
+	if (rq_list_empty(plug->mq_list))
+		return;
+	plug->rq_count = 0;
+
+	if (!plug->multiple_queues && !plug->has_elevator) {
+		blk_mq_plug_issue_direct(plug, from_schedule);
+		if (rq_list_empty(plug->mq_list))
+			return;
+	}
+
+	this_hctx = NULL;
+	this_ctx = NULL;
+	depth = 0;
+	do {
+		struct request *rq;
+
+		rq = rq_list_pop(&plug->mq_list);
+
+		if (!this_hctx) {
+			this_hctx = rq->mq_hctx;
+			this_ctx = rq->mq_ctx;
+		} else if (this_hctx != rq->mq_hctx || this_ctx != rq->mq_ctx) {
+			trace_block_unplug(this_hctx->queue, depth,
+						!from_schedule);
+			blk_mq_sched_insert_requests(this_hctx, this_ctx,
+						&list, from_schedule);
+			depth = 0;
+			this_hctx = rq->mq_hctx;
+			this_ctx = rq->mq_ctx;
+
+		}
+
+		list_add(&rq->queuelist, &list);
+		depth++;
+	} while (!rq_list_empty(plug->mq_list));
+
+	if (!list_empty(&list)) {
+		trace_block_unplug(this_hctx->queue, depth, !from_schedule);
+		blk_mq_sched_insert_requests(this_hctx, this_ctx, &list,
+						from_schedule);
+	}
+}
+
 void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
 		struct list_head *list)
 {
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:11 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:11 +0200
Subject: [PATCH 06/12] block: move request based cloning helpers to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-7-hch@lst.de>

Keep all the request based code together.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 184 +----------------------------------------------
 block/blk-mq.c   | 175 +++++++++++++++++++++++++++++++++++++++++++-
 block/blk-mq.h   |   3 -
 block/blk.h      |  10 +++
 4 files changed, 185 insertions(+), 187 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 08c6077365ac9..8ae6ba9ec1050 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -618,7 +618,7 @@ static int __init setup_fail_make_request(char *str)
 }
 __setup("fail_make_request=", setup_fail_make_request);
 
-static bool should_fail_request(struct block_device *part, unsigned int bytes)
+bool should_fail_request(struct block_device *part, unsigned int bytes)
 {
 	return part->bd_make_it_fail && should_fail(&fail_make_request, bytes);
 }
@@ -632,15 +632,6 @@ static int __init fail_make_request_debugfs(void)
 }
 
 late_initcall(fail_make_request_debugfs);
-
-#else /* CONFIG_FAIL_MAKE_REQUEST */
-
-static inline bool should_fail_request(struct block_device *part,
-					unsigned int bytes)
-{
-	return false;
-}
-
 #endif /* CONFIG_FAIL_MAKE_REQUEST */
 
 static inline bool bio_check_ro(struct bio *bio)
@@ -1114,92 +1105,6 @@ int iocb_bio_iopoll(struct kiocb *kiocb, struct io_comp_batch *iob,
 }
 EXPORT_SYMBOL_GPL(iocb_bio_iopoll);
 
-/**
- * blk_cloned_rq_check_limits - Helper function to check a cloned request
- *                              for the new queue limits
- * @q:  the queue
- * @rq: the request being checked
- *
- * Description:
- *    @rq may have been made based on weaker limitations of upper-level queues
- *    in request stacking drivers, and it may violate the limitation of @q.
- *    Since the block layer and the underlying device driver trust @rq
- *    after it is inserted to @q, it should be checked against @q before
- *    the insertion using this generic function.
- *
- *    Request stacking drivers like request-based dm may change the queue
- *    limits when retrying requests on other queues. Those requests need
- *    to be checked against the new queue limits again during dispatch.
- */
-static blk_status_t blk_cloned_rq_check_limits(struct request_queue *q,
-				      struct request *rq)
-{
-	unsigned int max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
-
-	if (blk_rq_sectors(rq) > max_sectors) {
-		/*
-		 * SCSI device does not have a good way to return if
-		 * Write Same/Zero is actually supported. If a device rejects
-		 * a non-read/write command (discard, write same,etc.) the
-		 * low-level device driver will set the relevant queue limit to
-		 * 0 to prevent blk-lib from issuing more of the offending
-		 * operations. Commands queued prior to the queue limit being
-		 * reset need to be completed with BLK_STS_NOTSUPP to avoid I/O
-		 * errors being propagated to upper layers.
-		 */
-		if (max_sectors == 0)
-			return BLK_STS_NOTSUPP;
-
-		printk(KERN_ERR "%s: over max size limit. (%u > %u)\n",
-			__func__, blk_rq_sectors(rq), max_sectors);
-		return BLK_STS_IOERR;
-	}
-
-	/*
-	 * The queue settings related to segment counting may differ from the
-	 * original queue.
-	 */
-	rq->nr_phys_segments = blk_recalc_rq_segments(rq);
-	if (rq->nr_phys_segments > queue_max_segments(q)) {
-		printk(KERN_ERR "%s: over max segments limit. (%hu > %hu)\n",
-			__func__, rq->nr_phys_segments, queue_max_segments(q));
-		return BLK_STS_IOERR;
-	}
-
-	return BLK_STS_OK;
-}
-
-/**
- * blk_insert_cloned_request - Helper for stacking drivers to submit a request
- * @q:  the queue to submit the request
- * @rq: the request being queued
- */
-blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *rq)
-{
-	blk_status_t ret;
-
-	ret = blk_cloned_rq_check_limits(q, rq);
-	if (ret != BLK_STS_OK)
-		return ret;
-
-	if (rq->rq_disk &&
-	    should_fail_request(rq->rq_disk->part0, blk_rq_bytes(rq)))
-		return BLK_STS_IOERR;
-
-	if (blk_crypto_insert_cloned_request(rq))
-		return BLK_STS_IOERR;
-
-	blk_account_io_start(rq);
-
-	/*
-	 * Since we have a scheduler attached on the top device,
-	 * bypass a potential scheduler on the bottom device for
-	 * insert.
-	 */
-	return blk_mq_request_issue_directly(rq, true);
-}
-EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
-
 static void update_io_ticks(struct block_device *part, unsigned long now,
 		bool end)
 {
@@ -1352,93 +1257,6 @@ int blk_lld_busy(struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(blk_lld_busy);
 
-/**
- * blk_rq_unprep_clone - Helper function to free all bios in a cloned request
- * @rq: the clone request to be cleaned up
- *
- * Description:
- *     Free all bios in @rq for a cloned request.
- */
-void blk_rq_unprep_clone(struct request *rq)
-{
-	struct bio *bio;
-
-	while ((bio = rq->bio) != NULL) {
-		rq->bio = bio->bi_next;
-
-		bio_put(bio);
-	}
-}
-EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
-
-/**
- * blk_rq_prep_clone - Helper function to setup clone request
- * @rq: the request to be setup
- * @rq_src: original request to be cloned
- * @bs: bio_set that bios for clone are allocated from
- * @gfp_mask: memory allocation mask for bio
- * @bio_ctr: setup function to be called for each clone bio.
- *           Returns %0 for success, non %0 for failure.
- * @data: private data to be passed to @bio_ctr
- *
- * Description:
- *     Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
- *     Also, pages which the original bios are pointing to are not copied
- *     and the cloned bios just point same pages.
- *     So cloned bios must be completed before original bios, which means
- *     the caller must complete @rq before @rq_src.
- */
-int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
-		      struct bio_set *bs, gfp_t gfp_mask,
-		      int (*bio_ctr)(struct bio *, struct bio *, void *),
-		      void *data)
-{
-	struct bio *bio, *bio_src;
-
-	if (!bs)
-		bs = &fs_bio_set;
-
-	__rq_for_each_bio(bio_src, rq_src) {
-		bio = bio_clone_fast(bio_src, gfp_mask, bs);
-		if (!bio)
-			goto free_and_out;
-
-		if (bio_ctr && bio_ctr(bio, bio_src, data))
-			goto free_and_out;
-
-		if (rq->bio) {
-			rq->biotail->bi_next = bio;
-			rq->biotail = bio;
-		} else {
-			rq->bio = rq->biotail = bio;
-		}
-		bio = NULL;
-	}
-
-	/* Copy attributes of the original request to the clone request. */
-	rq->__sector = blk_rq_pos(rq_src);
-	rq->__data_len = blk_rq_bytes(rq_src);
-	if (rq_src->rq_flags & RQF_SPECIAL_PAYLOAD) {
-		rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
-		rq->special_vec = rq_src->special_vec;
-	}
-	rq->nr_phys_segments = rq_src->nr_phys_segments;
-	rq->ioprio = rq_src->ioprio;
-
-	if (rq->bio && blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask) < 0)
-		goto free_and_out;
-
-	return 0;
-
-free_and_out:
-	if (bio)
-		bio_put(bio);
-	blk_rq_unprep_clone(rq);
-
-	return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
-
 int kblockd_schedule_work(struct work_struct *work)
 {
 	return queue_work(kblockd_workqueue, work);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index f46d41a760106..923231023fe84 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2403,7 +2403,7 @@ static void blk_mq_try_issue_directly(struct blk_mq_hw_ctx *hctx,
 	hctx_unlock(hctx, srcu_idx);
 }
 
-blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
+static blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last)
 {
 	blk_status_t ret;
 	int srcu_idx;
@@ -2720,6 +2720,179 @@ void blk_mq_submit_bio(struct bio *bio)
 	blk_queue_exit(q);
 }
 
+/**
+ * blk_cloned_rq_check_limits - Helper function to check a cloned request
+ *                              for the new queue limits
+ * @q:  the queue
+ * @rq: the request being checked
+ *
+ * Description:
+ *    @rq may have been made based on weaker limitations of upper-level queues
+ *    in request stacking drivers, and it may violate the limitation of @q.
+ *    Since the block layer and the underlying device driver trust @rq
+ *    after it is inserted to @q, it should be checked against @q before
+ *    the insertion using this generic function.
+ *
+ *    Request stacking drivers like request-based dm may change the queue
+ *    limits when retrying requests on other queues. Those requests need
+ *    to be checked against the new queue limits again during dispatch.
+ */
+static blk_status_t blk_cloned_rq_check_limits(struct request_queue *q,
+				      struct request *rq)
+{
+	unsigned int max_sectors = blk_queue_get_max_sectors(q, req_op(rq));
+
+	if (blk_rq_sectors(rq) > max_sectors) {
+		/*
+		 * SCSI device does not have a good way to return if
+		 * Write Same/Zero is actually supported. If a device rejects
+		 * a non-read/write command (discard, write same,etc.) the
+		 * low-level device driver will set the relevant queue limit to
+		 * 0 to prevent blk-lib from issuing more of the offending
+		 * operations. Commands queued prior to the queue limit being
+		 * reset need to be completed with BLK_STS_NOTSUPP to avoid I/O
+		 * errors being propagated to upper layers.
+		 */
+		if (max_sectors == 0)
+			return BLK_STS_NOTSUPP;
+
+		printk(KERN_ERR "%s: over max size limit. (%u > %u)\n",
+			__func__, blk_rq_sectors(rq), max_sectors);
+		return BLK_STS_IOERR;
+	}
+
+	/*
+	 * The queue settings related to segment counting may differ from the
+	 * original queue.
+	 */
+	rq->nr_phys_segments = blk_recalc_rq_segments(rq);
+	if (rq->nr_phys_segments > queue_max_segments(q)) {
+		printk(KERN_ERR "%s: over max segments limit. (%hu > %hu)\n",
+			__func__, rq->nr_phys_segments, queue_max_segments(q));
+		return BLK_STS_IOERR;
+	}
+
+	return BLK_STS_OK;
+}
+
+/**
+ * blk_insert_cloned_request - Helper for stacking drivers to submit a request
+ * @q:  the queue to submit the request
+ * @rq: the request being queued
+ */
+blk_status_t blk_insert_cloned_request(struct request_queue *q, struct request *rq)
+{
+	blk_status_t ret;
+
+	ret = blk_cloned_rq_check_limits(q, rq);
+	if (ret != BLK_STS_OK)
+		return ret;
+
+	if (rq->rq_disk &&
+	    should_fail_request(rq->rq_disk->part0, blk_rq_bytes(rq)))
+		return BLK_STS_IOERR;
+
+	if (blk_crypto_insert_cloned_request(rq))
+		return BLK_STS_IOERR;
+
+	blk_account_io_start(rq);
+
+	/*
+	 * Since we have a scheduler attached on the top device,
+	 * bypass a potential scheduler on the bottom device for
+	 * insert.
+	 */
+	return blk_mq_request_issue_directly(rq, true);
+}
+EXPORT_SYMBOL_GPL(blk_insert_cloned_request);
+
+/**
+ * blk_rq_unprep_clone - Helper function to free all bios in a cloned request
+ * @rq: the clone request to be cleaned up
+ *
+ * Description:
+ *     Free all bios in @rq for a cloned request.
+ */
+void blk_rq_unprep_clone(struct request *rq)
+{
+	struct bio *bio;
+
+	while ((bio = rq->bio) != NULL) {
+		rq->bio = bio->bi_next;
+
+		bio_put(bio);
+	}
+}
+EXPORT_SYMBOL_GPL(blk_rq_unprep_clone);
+
+/**
+ * blk_rq_prep_clone - Helper function to setup clone request
+ * @rq: the request to be setup
+ * @rq_src: original request to be cloned
+ * @bs: bio_set that bios for clone are allocated from
+ * @gfp_mask: memory allocation mask for bio
+ * @bio_ctr: setup function to be called for each clone bio.
+ *           Returns %0 for success, non %0 for failure.
+ * @data: private data to be passed to @bio_ctr
+ *
+ * Description:
+ *     Clones bios in @rq_src to @rq, and copies attributes of @rq_src to @rq.
+ *     Also, pages which the original bios are pointing to are not copied
+ *     and the cloned bios just point same pages.
+ *     So cloned bios must be completed before original bios, which means
+ *     the caller must complete @rq before @rq_src.
+ */
+int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
+		      struct bio_set *bs, gfp_t gfp_mask,
+		      int (*bio_ctr)(struct bio *, struct bio *, void *),
+		      void *data)
+{
+	struct bio *bio, *bio_src;
+
+	if (!bs)
+		bs = &fs_bio_set;
+
+	__rq_for_each_bio(bio_src, rq_src) {
+		bio = bio_clone_fast(bio_src, gfp_mask, bs);
+		if (!bio)
+			goto free_and_out;
+
+		if (bio_ctr && bio_ctr(bio, bio_src, data))
+			goto free_and_out;
+
+		if (rq->bio) {
+			rq->biotail->bi_next = bio;
+			rq->biotail = bio;
+		} else {
+			rq->bio = rq->biotail = bio;
+		}
+		bio = NULL;
+	}
+
+	/* Copy attributes of the original request to the clone request. */
+	rq->__sector = blk_rq_pos(rq_src);
+	rq->__data_len = blk_rq_bytes(rq_src);
+	if (rq_src->rq_flags & RQF_SPECIAL_PAYLOAD) {
+		rq->rq_flags |= RQF_SPECIAL_PAYLOAD;
+		rq->special_vec = rq_src->special_vec;
+	}
+	rq->nr_phys_segments = rq_src->nr_phys_segments;
+	rq->ioprio = rq_src->ioprio;
+
+	if (rq->bio && blk_crypto_rq_bio_prep(rq, rq->bio, gfp_mask) < 0)
+		goto free_and_out;
+
+	return 0;
+
+free_and_out:
+	if (bio)
+		bio_put(bio);
+	blk_rq_unprep_clone(rq);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
+
 static size_t order_to_size(unsigned int order)
 {
 	return (size_t)PAGE_SIZE << order;
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 08fb5922e611b..6e25303dbebe8 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -65,9 +65,6 @@ void blk_mq_request_bypass_insert(struct request *rq, bool at_head,
 				  bool run_queue);
 void blk_mq_insert_requests(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *ctx,
 				struct list_head *list);
-
-/* Used by blk_insert_cloned_request() to issue request directly */
-blk_status_t blk_mq_request_issue_directly(struct request *rq, bool last);
 void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
 				    struct list_head *list);
 
diff --git a/block/blk.h b/block/blk.h
index 6a039e6c7d077..c5fc3f97d1e5a 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -454,4 +454,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg);
 
 extern const struct address_space_operations def_blk_aops;
 
+#ifdef CONFIG_FAIL_MAKE_REQUEST
+bool should_fail_request(struct block_device *part, unsigned int bytes);
+#else /* CONFIG_FAIL_MAKE_REQUEST */
+static inline bool should_fail_request(struct block_device *part,
+					unsigned int bytes)
+{
+	return false;
+}
+#endif /* CONFIG_FAIL_MAKE_REQUEST */
+
 #endif /* BLK_INTERNAL_H */
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:12 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:12 +0200
Subject: [PATCH 07/12] block: move blk_rq_init to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-8-hch@lst.de>

blk_rq_init deals with a request structure, so move it to blk-mq.c

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 17 -----------------
 block/blk-mq.c   | 17 +++++++++++++++++
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 8ae6ba9ec1050..1ee942266df8d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -109,23 +109,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(blk_queue_flag_test_and_set);
 
-void blk_rq_init(struct request_queue *q, struct request *rq)
-{
-	memset(rq, 0, sizeof(*rq));
-
-	INIT_LIST_HEAD(&rq->queuelist);
-	rq->q = q;
-	rq->__sector = (sector_t) -1;
-	INIT_HLIST_NODE(&rq->hash);
-	RB_CLEAR_NODE(&rq->rb_node);
-	rq->tag = BLK_MQ_NO_TAG;
-	rq->internal_tag = BLK_MQ_NO_TAG;
-	rq->start_time_ns = ktime_get_ns();
-	rq->part = NULL;
-	blk_crypto_rq_set_defaults(rq);
-}
-EXPORT_SYMBOL(blk_rq_init);
-
 #define REQ_OP_NAME(name) [REQ_OP_##name] = #name
 static const char *const blk_op_name[] = {
 	REQ_OP_NAME(READ),
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 923231023fe84..a0505099b2ce2 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -316,6 +316,23 @@ void blk_mq_wake_waiters(struct request_queue *q)
 			blk_mq_tag_wakeup_all(hctx->tags, true);
 }
 
+void blk_rq_init(struct request_queue *q, struct request *rq)
+{
+	memset(rq, 0, sizeof(*rq));
+
+	INIT_LIST_HEAD(&rq->queuelist);
+	rq->q = q;
+	rq->__sector = (sector_t) -1;
+	INIT_HLIST_NODE(&rq->hash);
+	RB_CLEAR_NODE(&rq->rb_node);
+	rq->tag = BLK_MQ_NO_TAG;
+	rq->internal_tag = BLK_MQ_NO_TAG;
+	rq->start_time_ns = ktime_get_ns();
+	rq->part = NULL;
+	blk_crypto_rq_set_defaults(rq);
+}
+EXPORT_SYMBOL(blk_rq_init);
+
 static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
 		unsigned int tag, u64 alloc_time_ns)
 {
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:13 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:13 +0200
Subject: [PATCH 08/12] block: move blk_steal_bios to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-9-hch@lst.de>

Keep all the request based code together.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 21 ---------------------
 block/blk-mq.c   | 21 +++++++++++++++++++++
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 1ee942266df8d..98cb9d69a4068 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1191,27 +1191,6 @@ void disk_end_io_acct(struct gendisk *disk, unsigned int op,
 }
 EXPORT_SYMBOL(disk_end_io_acct);
 
-/*
- * Steal bios from a request and add them to a bio list.
- * The request must not have been partially completed before.
- */
-void blk_steal_bios(struct bio_list *list, struct request *rq)
-{
-	if (rq->bio) {
-		if (list->tail)
-			list->tail->bi_next = rq->bio;
-		else
-			list->head = rq->bio;
-		list->tail = rq->biotail;
-
-		rq->bio = NULL;
-		rq->biotail = NULL;
-	}
-
-	rq->__data_len = 0;
-}
-EXPORT_SYMBOL_GPL(blk_steal_bios);
-
 /**
  * blk_lld_busy - Check if underlying low-level drivers of a device are busy
  * @q : the queue of the device being checked
diff --git a/block/blk-mq.c b/block/blk-mq.c
index a0505099b2ce2..06fb74166aded 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2910,6 +2910,27 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
 }
 EXPORT_SYMBOL_GPL(blk_rq_prep_clone);
 
+/*
+ * Steal bios from a request and add them to a bio list.
+ * The request must not have been partially completed before.
+ */
+void blk_steal_bios(struct bio_list *list, struct request *rq)
+{
+	if (rq->bio) {
+		if (list->tail)
+			list->tail->bi_next = rq->bio;
+		else
+			list->head = rq->bio;
+		list->tail = rq->biotail;
+
+		rq->bio = NULL;
+		rq->biotail = NULL;
+	}
+
+	rq->__data_len = 0;
+}
+EXPORT_SYMBOL_GPL(blk_steal_bios);
+
 static size_t order_to_size(unsigned int order)
 {
 	return (size_t)PAGE_SIZE << order;
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:14 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:14 +0200
Subject: [PATCH 09/12] block: move blk_account_io_{start,done} to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-10-hch@lst.de>

These are only used for request based I/O, so move them where they are
used.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 27 +--------------------------
 block/blk-mq.c   | 42 ++++++++++++++++++++++++++++++++++++++++++
 block/blk.h      | 21 +--------------------
 3 files changed, 44 insertions(+), 46 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 98cb9d69a4068..5ca47d25a2ef2 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1088,8 +1088,7 @@ int iocb_bio_iopoll(struct kiocb *kiocb, struct io_comp_batch *iob,
 }
 EXPORT_SYMBOL_GPL(iocb_bio_iopoll);
 
-static void update_io_ticks(struct block_device *part, unsigned long now,
-		bool end)
+void update_io_ticks(struct block_device *part, unsigned long now, bool end)
 {
 	unsigned long stamp;
 again:
@@ -1104,30 +1103,6 @@ static void update_io_ticks(struct block_device *part, unsigned long now,
 	}
 }
 
-void __blk_account_io_done(struct request *req, u64 now)
-{
-	const int sgrp = op_stat_group(req_op(req));
-
-	part_stat_lock();
-	update_io_ticks(req->part, jiffies, true);
-	part_stat_inc(req->part, ios[sgrp]);
-	part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns);
-	part_stat_unlock();
-}
-
-void __blk_account_io_start(struct request *rq)
-{
-	/* passthrough requests can hold bios that do not have ->bi_bdev set */
-	if (rq->bio && rq->bio->bi_bdev)
-		rq->part = rq->bio->bi_bdev;
-	else
-		rq->part = rq->rq_disk->part0;
-
-	part_stat_lock();
-	update_io_ticks(rq->part, jiffies, false);
-	part_stat_unlock();
-}
-
 static unsigned long __part_start_io_acct(struct block_device *part,
 					  unsigned int sectors, unsigned int op)
 {
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 06fb74166aded..7df80c4da3777 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -790,6 +790,48 @@ bool blk_update_request(struct request *req, blk_status_t error,
 }
 EXPORT_SYMBOL_GPL(blk_update_request);
 
+static void __blk_account_io_done(struct request *req, u64 now)
+{
+	const int sgrp = op_stat_group(req_op(req));
+
+	part_stat_lock();
+	update_io_ticks(req->part, jiffies, true);
+	part_stat_inc(req->part, ios[sgrp]);
+	part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns);
+	part_stat_unlock();
+}
+
+static inline void blk_account_io_done(struct request *req, u64 now)
+{
+	/*
+	 * Account IO completion.  flush_rq isn't accounted as a
+	 * normal IO on queueing nor completion.  Accounting the
+	 * containing request is enough.
+	 */
+	if (blk_do_io_stat(req) && req->part &&
+	    !(req->rq_flags & RQF_FLUSH_SEQ))
+		__blk_account_io_done(req, now);
+}
+
+static void __blk_account_io_start(struct request *rq)
+{
+	/* passthrough requests can hold bios that do not have ->bi_bdev set */
+	if (rq->bio && rq->bio->bi_bdev)
+		rq->part = rq->bio->bi_bdev;
+	else
+		rq->part = rq->rq_disk->part0;
+
+	part_stat_lock();
+	update_io_ticks(rq->part, jiffies, false);
+	part_stat_unlock();
+}
+
+static inline void blk_account_io_start(struct request *req)
+{
+	if (blk_do_io_stat(req))
+		__blk_account_io_start(req);
+}
+
 static inline void __blk_mq_end_request_acct(struct request *rq, u64 now)
 {
 	if (rq->rq_flags & RQF_STATS) {
diff --git a/block/blk.h b/block/blk.h
index c5fc3f97d1e5a..8bcca0538faac 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -222,9 +222,6 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
 bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
 			struct bio *bio, unsigned int nr_segs);
 
-void __blk_account_io_start(struct request *req);
-void __blk_account_io_done(struct request *req, u64 now);
-
 /*
  * Plug flush limits
  */
@@ -315,23 +312,7 @@ static inline bool blk_do_io_stat(struct request *rq)
 	return (rq->rq_flags & RQF_IO_STAT) && rq->rq_disk;
 }
 
-static inline void blk_account_io_done(struct request *req, u64 now)
-{
-	/*
-	 * Account IO completion.  flush_rq isn't accounted as a
-	 * normal IO on queueing nor completion.  Accounting the
-	 * containing request is enough.
-	 */
-	if (blk_do_io_stat(req) && req->part &&
-	    !(req->rq_flags & RQF_FLUSH_SEQ))
-		__blk_account_io_done(req, now);
-}
-
-static inline void blk_account_io_start(struct request *req)
-{
-	if (blk_do_io_stat(req))
-		__blk_account_io_start(req);
-}
+void update_io_ticks(struct block_device *part, unsigned long now, bool end);
 
 static inline void req_set_nomerge(struct request_queue *q, struct request *req)
 {
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:15 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:15 +0200
Subject: [PATCH 10/12] block: move blk_dump_rq_flags to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-11-hch@lst.de>

blk_dump_rq_flags deals with a request, so move it to blk-mq.c.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 14 --------------
 block/blk-mq.c   | 14 ++++++++++++++
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 5ca47d25a2ef2..9547a75e7a7aa 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -217,20 +217,6 @@ void blk_print_req_error(struct request *req, blk_status_t status)
 		IOPRIO_PRIO_CLASS(req->ioprio));
 }
 
-void blk_dump_rq_flags(struct request *rq, char *msg)
-{
-	printk(KERN_INFO "%s: dev %s: flags=%llx\n", msg,
-		rq->rq_disk ? rq->rq_disk->disk_name : "?",
-		(unsigned long long) rq->cmd_flags);
-
-	printk(KERN_INFO "  sector %llu, nr/cnr %u/%u\n",
-	       (unsigned long long)blk_rq_pos(rq),
-	       blk_rq_sectors(rq), blk_rq_cur_sectors(rq));
-	printk(KERN_INFO "  bio %p, biotail %p, len %u\n",
-	       rq->bio, rq->biotail, blk_rq_bytes(rq));
-}
-EXPORT_SYMBOL(blk_dump_rq_flags);
-
 /**
  * blk_sync_queue - cancel any pending callbacks on a queue
  * @q: the queue
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 7df80c4da3777..425cd134ac358 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -648,6 +648,20 @@ void blk_mq_free_plug_rqs(struct blk_plug *plug)
 	}
 }
 
+void blk_dump_rq_flags(struct request *rq, char *msg)
+{
+	printk(KERN_INFO "%s: dev %s: flags=%llx\n", msg,
+		rq->rq_disk ? rq->rq_disk->disk_name : "?",
+		(unsigned long long) rq->cmd_flags);
+
+	printk(KERN_INFO "  sector %llu, nr/cnr %u/%u\n",
+	       (unsigned long long)blk_rq_pos(rq),
+	       blk_rq_sectors(rq), blk_rq_cur_sectors(rq));
+	printk(KERN_INFO "  bio %p, biotail %p, len %u\n",
+	       rq->bio, rq->biotail, blk_rq_bytes(rq));
+}
+EXPORT_SYMBOL(blk_dump_rq_flags);
+
 static void req_bio_endio(struct request *rq, struct bio *bio,
 			  unsigned int nbytes, blk_status_t error)
 {
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:16 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:16 +0200
Subject: [PATCH 11/12] block: move blk_print_req_error to blk-mq.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-12-hch@lst.de>

This function is only used by the request completion path.  Factor out
a blk_status_to_str to keep blk_errors private in blk-core.c.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 15 +++------------
 block/blk-mq.c   | 13 +++++++++++++
 block/blk.h      |  2 +-
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index 9547a75e7a7aa..ebcea0dac973d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -199,22 +199,13 @@ int blk_status_to_errno(blk_status_t status)
 }
 EXPORT_SYMBOL_GPL(blk_status_to_errno);
 
-void blk_print_req_error(struct request *req, blk_status_t status)
+const char *blk_status_to_str(blk_status_t status)
 {
 	int idx = (__force int)status;
 
 	if (WARN_ON_ONCE(idx >= ARRAY_SIZE(blk_errors)))
-		return;
-
-	printk_ratelimited(KERN_ERR
-		"%s error, dev %s, sector %llu op 0x%x:(%s) flags 0x%x "
-		"phys_seg %u prio class %u\n",
-		blk_errors[idx].name,
-		req->rq_disk ? req->rq_disk->disk_name : "?",
-		blk_rq_pos(req), req_op(req), blk_op_str(req_op(req)),
-		req->cmd_flags & ~REQ_OP_MASK,
-		req->nr_phys_segments,
-		IOPRIO_PRIO_CLASS(req->ioprio));
+		return "<null>";
+	return blk_errors[idx].name;
 }
 
 /**
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 425cd134ac358..3edd4ee2007b0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -698,6 +698,19 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
 	}
 }
 
+static void blk_print_req_error(struct request *req, blk_status_t status)
+{
+	printk_ratelimited(KERN_ERR
+		"%s error, dev %s, sector %llu op 0x%x:(%s) flags 0x%x "
+		"phys_seg %u prio class %u\n",
+		blk_status_to_str(status),
+		req->rq_disk ? req->rq_disk->disk_name : "?",
+		blk_rq_pos(req), req_op(req), blk_op_str(req_op(req)),
+		req->cmd_flags & ~REQ_OP_MASK,
+		req->nr_phys_segments,
+		IOPRIO_PRIO_CLASS(req->ioprio));
+}
+
 /**
  * blk_update_request - Complete multiple bytes without completing the request
  * @req:      the request being processed
diff --git a/block/blk.h b/block/blk.h
index 8bcca0538faac..573e308851d27 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -215,7 +215,7 @@ static inline void blk_integrity_del(struct gendisk *disk)
 
 unsigned long blk_rq_timeout(unsigned long timeout);
 void blk_add_timer(struct request *req);
-void blk_print_req_error(struct request *req, blk_status_t status);
+const char *blk_status_to_str(blk_status_t status);
 
 bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
 		unsigned int nr_segs, bool *same_queue_rq);
-- 
2.30.2



From hch at lst.de  Mon Oct 25 00:05:17 2021
From: hch at lst.de (Christoph Hellwig)
Date: Mon, 25 Oct 2021 09:05:17 +0200
Subject: [PATCH 12/12] block: don't include blk-mq headers in blk-core.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <20211025070517.1548584-13-hch@lst.de>

All request based code is in the blk-mq files now.

Signed-off-by: Christoph Hellwig <hch at lst.de>
---
 block/blk-core.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/block/blk-core.c b/block/blk-core.c
index ebcea0dac973d..94b76d62a4396 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/bio.h>
 #include <linux/blkdev.h>
-#include <linux/blk-mq.h>
 #include <linux/blk-pm.h>
 #include <linux/blk-integrity.h>
 #include <linux/highmem.h>
@@ -47,8 +46,6 @@
 #include <trace/events/block.h>
 
 #include "blk.h"
-#include "blk-mq.h"
-#include "blk-mq-sched.h"
 #include "blk-pm.h"
 #include "blk-throttle.h"
 
-- 
2.30.2



From courierdeliveryservice8400 at gmail.com  Mon Oct 25 00:19:04 2021
From: courierdeliveryservice8400 at gmail.com (Peace Of Mind Trust)
Date: Mon, 25 Oct 2021 10:19:04 +0300
Subject: =?UTF-8?Q?Wohlt=C3=A4tigkeitsspende_f=C3=BCr_Covid=2D19?=
Message-ID: <CAGZ6buMut5w6iqHPx2YyGg9SbsVdskwBoOOmELRXVKRJ8zYNvQ@mail.gmail.com>

-- 
Hallo, lieber Beg?nstigter
Sie haben eine Spende von 2.000.000,00 ? aus dem Frieden von Mind
Trust Foundation (PMT).
Bitte kontaktieren Sie uns ?ber: pomtfoundation1 at gmail.com Weitere
Informationen zum Anhalten dieser Spendenfonds

mit bestem Gru?
Peace Of Mind Trust (PMT)


From kernel at kempniu.pl  Mon Oct 25 01:21:04 2021
From: kernel at kempniu.pl (=?UTF-8?q?Micha=C5=82=20K=C4=99pie=C5=84?=)
Date: Mon, 25 Oct 2021 10:21:04 +0200
Subject: [PATCH] mtdchar: prevent unbounded allocation in MEMWRITE ioctl
Message-ID: <20211025082104.8017-1-kernel@kempniu.pl>

In the mtdchar_write_ioctl() function, memdup_user() is called with its
'len' parameter set to verbatim values provided by user space via a
struct mtd_write_req.  Both the 'len' and 'ooblen' fields of that
structure are 64-bit unsigned integers, which means the MEMWRITE ioctl
can trigger unbounded kernel memory allocation requests.

Fix by iterating over the buffers provided by user space in a loop,
processing at most mtd->erasesize bytes in each iteration.  Adopt some
checks from mtd_check_oob_ops() to retain backward user space
compatibility.

Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Micha? K?pie? <kernel at kempniu.pl>
---
Fixing this problem was suggested last month, during a discussion about
a new MEMREAD ioctl. [1] [2]

My primary objective was to not break user space, i.e. to not change
externally visible behavior compared to the current code.  The main
problem I faced was that splitting the input data into chunks makes the
MEMWRITE ioctl a _wrapper_ for mtd_write_oob() rather than a direct
_interface_ to it and yet from the user space perspective it still needs
to behave as if nothing changed.

Despite my efforts, the patch does _not_ retain absolute backward
compatibility and I do not know whether this is acceptable.
Specifically, multi-eraseblock-sized writes (requiring multiple loop
iterations to be processed) which succeeded with the original code _may_
now return errors and/or write different contents to the device than the
original code, depending on the MTD mode of operation requested and on
whether the start offset is page-aligned.  The documentation for struct
mtd_oob_ops warns about even multi-page write requests, but...

Example:

    MTD device parameters:

      - mtd->writesize = 2048
      - mtd->erasesize = 131072
      - 64 bytes of raw OOB space per page

    struct mtd_write_req req = {
        .start = 2048,
        .len = 262144,
        .ooblen = 64,
        .usr_data = ...,
        .usr_oob = ...,
        .mode = MTD_OPS_RAW,
    };

    (This is a 128-page write with OOB data supplied for just one page.)

    Current mtdchar_write_ioctl() returns 0 for this request and writes
    128 pages of data and 1 page's worth of OOB data (64 bytes) to the
    MTD device.

    Patched mtdchar_write_ioctl() may return an error because the
    original request gets split into two chunks (<data_len, oob_len>):

        <131072, 64>
        <131072, 0>

    and the second chunk with zero OOB data length may make the MTD
    driver unhappy in raw mode (resulting in only the first 64 pages of
    data and 1 page's worth of OOB data getting written to the MTD
    device).

    Is an ioctl like this considered a "degenerate" one and therefore
    acceptable to break or not?

At any rate, the revised code feels brittle to me and I would not be
particularly surprised if I missed more cases in which it produces
different results than the original code.

I keep on wondering whether the benefits of this change are worth the
extra code complexity, but fortunately it is not my call to make :)
Perhaps I am missing something and my proposal can be simplified?  Or
maybe the way I approached this is completely wrong?  Any thoughts on
this are welcome.

As the outcome of the discussion around this patch will have a
significant influence on the shape of the v2 of the MEMREAD ioctl, I
decided to submit this one first as a standalone patch.

[1] https://lists.infradead.org/pipermail/linux-mtd/2021-September/088485.html
[2] https://lists.infradead.org/pipermail/linux-mtd/2021-September/088544.html

 drivers/mtd/mtdchar.c | 93 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 70 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 155e991d9d75..a3afc390e254 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -578,9 +578,10 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 	struct mtd_write_req req;
-	struct mtd_oob_ops ops = {};
 	const void __user *usr_data, *usr_oob;
-	int ret;
+	uint8_t *datbuf = NULL, *oobbuf = NULL;
+	size_t datbuf_len, oobbuf_len;
+	int ret = 0;
 
 	if (copy_from_user(&req, argp, sizeof(req)))
 		return -EFAULT;
@@ -590,33 +591,79 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd,
 
 	if (!master->_write_oob)
 		return -EOPNOTSUPP;
-	ops.mode = req.mode;
-	ops.len = (size_t)req.len;
-	ops.ooblen = (size_t)req.ooblen;
-	ops.ooboffs = 0;
-
-	if (usr_data) {
-		ops.datbuf = memdup_user(usr_data, ops.len);
-		if (IS_ERR(ops.datbuf))
-			return PTR_ERR(ops.datbuf);
-	} else {
-		ops.datbuf = NULL;
+
+	if (!usr_data)
+		req.len = 0;
+
+	if (!usr_oob)
+		req.ooblen = 0;
+
+	if (req.start + req.len > mtd->size)
+		return -EINVAL;
+
+	datbuf_len = min_t(size_t, req.len, mtd->erasesize);
+	if (datbuf_len > 0) {
+		datbuf = kmalloc(datbuf_len, GFP_KERNEL);
+		if (!datbuf)
+			return -ENOMEM;
 	}
 
-	if (usr_oob) {
-		ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
-		if (IS_ERR(ops.oobbuf)) {
-			kfree(ops.datbuf);
-			return PTR_ERR(ops.oobbuf);
+	oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize);
+	if (oobbuf_len > 0) {
+		oobbuf = kmalloc(oobbuf_len, GFP_KERNEL);
+		if (!oobbuf) {
+			kfree(datbuf);
+			return -ENOMEM;
 		}
-	} else {
-		ops.oobbuf = NULL;
 	}
 
-	ret = mtd_write_oob(mtd, (loff_t)req.start, &ops);
+	while (req.len > 0 || (!usr_data && req.ooblen > 0)) {
+		struct mtd_oob_ops ops = {
+			.mode = req.mode,
+			.len = min_t(size_t, req.len, datbuf_len),
+			.ooblen = min_t(size_t, req.ooblen, oobbuf_len),
+			.datbuf = req.len ? datbuf : NULL,
+			.oobbuf = req.ooblen ? oobbuf : NULL,
+		};
 
-	kfree(ops.datbuf);
-	kfree(ops.oobbuf);
+		/*
+		 * For writes which are not OOB-only, adjust the amount of OOB
+		 * data written according to the number of data pages written.
+		 * This is necessary to prevent OOB data from being skipped
+		 * over in data+OOB writes requiring multiple mtd_write_oob()
+		 * calls to be completed.
+		 */
+		if (ops.len > 0 && ops.ooblen > 0) {
+			u32 oob_per_page = mtd_oobavail(mtd, &ops);
+			uint32_t pages_to_write = mtd_div_by_ws(ops.len, mtd);
+
+			if (mtd_mod_by_ws(req.start + ops.len, mtd))
+				pages_to_write++;
+
+			ops.ooblen = min_t(size_t, ops.ooblen,
+					   pages_to_write * oob_per_page);
+		}
+
+		if (copy_from_user(datbuf, usr_data, ops.len) ||
+		    copy_from_user(oobbuf, usr_oob, ops.ooblen)) {
+			ret = -EFAULT;
+			break;
+		}
+
+		ret = mtd_write_oob(mtd, req.start, &ops);
+		if (ret)
+			break;
+
+		req.start += ops.retlen;
+		req.len -= ops.retlen;
+		usr_data += ops.retlen;
+
+		req.ooblen -= ops.oobretlen;
+		usr_oob += ops.oobretlen;
+	}
+
+	kfree(datbuf);
+	kfree(oobbuf);
 
 	return ret;
 }
-- 
2.33.1



From sean at geanix.com  Mon Oct 25 02:27:49 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 25 Oct 2021 11:27:49 +0200
Subject: [PATCH v3 1/4] mtd: rawnand: nand_bbt: hide suspend/resume hooks
 while scanning bbt
In-Reply-To: <20211025092752.2824678-1-sean@geanix.com>
References: <20211025092752.2824678-1-sean@geanix.com>
Message-ID: <20211025092752.2824678-2-sean@geanix.com>

From: Boris Brezillon <boris.brezillon at collabora.com>

The BBT scan logic use the MTD helpers before the MTD layer had a
chance to initialize the device, and that leads to issues when
accessing the uninitialized suspend lock. Let's temporarily set the
suspend/resume hooks to NULL to skip the lock acquire/release step.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Tested-by: Sean Nyekjaer <sean at geanix.com>
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_bbt.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index b7ad030225f8..93d385703469 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -1397,8 +1397,28 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
  */
 int nand_create_bbt(struct nand_chip *this)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
+	int (*suspend) (struct mtd_info *) = mtd->_suspend;
+	void (*resume) (struct mtd_info *) = mtd->_resume;
 	int ret;
 
+	/*
+	 * The BBT scan logic use the MTD helpers before the MTD layer had a
+	 * chance to initialize the device, and that leads to issues when
+	 * accessing the uninitialized suspend lock. Let's temporarily set the
+	 * suspend/resume hooks to NULL to skip the lock acquire/release step.
+	 *
+	 * FIXME: This is an ugly hack, so please don't copy this pattern to
+	 * other MTD implementations. The proper fix would be to implement a
+	 * generic BBT scan logic at the NAND level that's not using any of the
+	 * MTD helpers to access pages. We also might consider doing a two
+	 * step initialization at the MTD level (mtd_device_init() +
+	 * mtd_device_register()) so some of the fields are initialized
+	 * early.
+	 */
+	mtd->_suspend = NULL;
+	mtd->_resume = NULL;
+
 	/* Is a flash based bad block table requested? */
 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
 		/* Use the default pattern descriptors */
@@ -1422,7 +1442,13 @@ int nand_create_bbt(struct nand_chip *this)
 			return ret;
 	}
 
-	return nand_scan_bbt(this, this->badblock_pattern);
+	ret = nand_scan_bbt(this, this->badblock_pattern);
+
+	/* Restore the suspend/resume hooks. */
+	mtd->_suspend = suspend;
+	mtd->_resume = resume;
+
+	return ret;
 }
 EXPORT_SYMBOL(nand_create_bbt);
 
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 02:27:48 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 25 Oct 2021 11:27:48 +0200
Subject: [PATCH v3 0/4] mtd: core: protect access to mtd devices while in
 suspend
Message-ID: <20211025092752.2824678-1-sean@geanix.com>

Follow-up on discussion in:
https://lkml.org/lkml/2021/10/4/41
https://lkml.org/lkml/2021/10/11/435

Changes since v2:
 - added signoff's to patch from Boris
 - removed accidential line break
 - kept tests consistent: master->master.suspended == 0 -> !master->master.suspended
 - added comments to mtdconcat patch
 - moved mtdconcat before ('mtd: core: protect access to MTD devices while in suspend')

Changes since v1:
 - removed __mtd_suspend/__mtd_resume functions as they are not used by
   mtdconcat anymore.
 - only master mtd_info is used for mtd_{start,end}_access(). Warn if we
   got mtd's.
 - added Boris patch for using uninitialized _suspend/_resume hooks when
   bbt scanning
 - mtdconcat uses device _suspend/_resume hooks
 - I don't really like the macro proposal from Boris
   mtd_no_suspend_void_call()/mtd_no_suspend_ret_call() I think they
   make the code complex to read and the macro's doesn't fit every
   where anyway...

Changes since from rfc v1/v2:
 - added access protection for all device access hooks in mtd_info.
 - added Suggested-by to [1/3] patch.
 - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
   from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
   to be blamed.
 - tested on a kernel with LOCKDEP enabled.

Boris Brezillon (1):
  mtd: rawnand: nand_bbt: hide suspend/resume hooks while scanning bbt

Sean Nyekjaer (3):
  mtd: mtdconcat: add suspend lock handling
  mtd: core: protect access to MTD devices while in suspend
  mtd: rawnand: remove suspended check

 drivers/mtd/mtdconcat.c          |  15 +++-
 drivers/mtd/mtdcore.c            | 124 +++++++++++++++++++++++++++----
 drivers/mtd/nand/raw/nand_base.c |  52 ++++---------
 drivers/mtd/nand/raw/nand_bbt.c  |  28 ++++++-
 include/linux/mtd/mtd.h          |  81 ++++++++++++++++----
 include/linux/mtd/rawnand.h      |   5 +-
 6 files changed, 230 insertions(+), 75 deletions(-)

-- 
2.33.0



From sean at geanix.com  Mon Oct 25 02:27:50 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 25 Oct 2021 11:27:50 +0200
Subject: [PATCH v3 2/4] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211025092752.2824678-1-sean@geanix.com>
References: <20211025092752.2824678-1-sean@geanix.com>
Message-ID: <20211025092752.2824678-3-sean@geanix.com>

Use MTD hooks to control suspend/resume of MTD devices.
concat_{suspend,resume} will be called from mtd_{suspend,resume},
which already have taken the suspend/resume lock.
It's safe to proceed with calling MTD device hooks directly from here.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdconcat.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index f685a581df48..37532f529820 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -566,9 +566,15 @@ static int concat_suspend(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		if ((rc = mtd_suspend(subdev)) < 0)
+		/*
+		 * Call MTD hook directly from here,
+		 * mtd_suspend() have the suspend/resume lock.
+		 */
+		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
+		if (rc < 0)
 			return rc;
 	}
+
 	return rc;
 }
 
@@ -579,7 +585,12 @@ static void concat_resume(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		mtd_resume(subdev);
+		/*
+		 * Call MTD hook directly from here,
+		 * mtd_resume() have the suspend/resume lock.
+		 */
+		if (subdev->_resume)
+			subdev->_resume(subdev);
 	}
 }
 
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 02:27:52 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 25 Oct 2021 11:27:52 +0200
Subject: [PATCH v3 4/4] mtd: rawnand: remove suspended check
In-Reply-To: <20211025092752.2824678-1-sean@geanix.com>
References: <20211025092752.2824678-1-sean@geanix.com>
Message-ID: <20211025092752.2824678-5-sean@geanix.com>

Access is protected in upper MTD layer when MTD devices are suspended.

Commit ("mtd: core: protect access to MTD devices while in suspend")
introduces access protection, so it's safe to remove suspended checks.

Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_base.c | 52 ++++++++------------------------
 include/linux/mtd/rawnand.h      |  5 +--
 2 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..aa2874ae3c4a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  * @chip: NAND chip structure
  *
  * Lock the device and its controller for exclusive access
- *
- * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
 	mutex_lock(&chip->controller->lock);
-
-	return 0;
 }
 
 /**
@@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
-
+		nand_get_device(chip);
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
 	}
@@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4345,13 +4332,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	int ret = 0;
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 	if (nand_region_is_secured(chip, instr->addr, instr->len))
 		return -EIO;
 
-	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	/* Grab the lock */
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 	pr_debug("%s: called\n", __func__);
 
-	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	/* Grab the lock */
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
 	mutex_lock(&chip->lock);
 	if (chip->ops.suspend)
 		ret = chip->ops.suspend(chip);
-	if (!ret)
-		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
+
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		if (chip->ops.resume)
-			chip->ops.resume(chip);
-		chip->suspended = 0;
-	} else {
-		pr_err("%s called for a chip which is not in suspended state\n",
-			__func__);
-	}
+	if (chip->ops.resume)
+		chip->ops.resume(chip);
 	mutex_unlock(&chip->lock);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..1198a6548912 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1237,9 +1237,7 @@ struct nand_secure_region {
  * @pagecache.page: Page number currently in the cache. -1 means no page is
  *                  currently cached
  * @buf_align: Minimum buffer alignment required by a platform
- * @lock: Lock protecting the suspended field. Also used to serialize accesses
- *        to the NAND device
- * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @lock: Lock to serialize accesses to the NAND device
  * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
  *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
  *          NAND Controller drivers should not modify this value, but they're
@@ -1293,7 +1291,6 @@ struct nand_chip {
 
 	/* Internals */
 	struct mutex lock;
-	unsigned int suspended : 1;
 	int cur_cs;
 	int read_retries;
 	struct nand_secure_region *secure_regions;
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 02:27:51 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Mon, 25 Oct 2021 11:27:51 +0200
Subject: [PATCH v3 3/4] mtd: core: protect access to MTD devices while in
 suspend
In-Reply-To: <20211025092752.2824678-1-sean@geanix.com>
References: <20211025092752.2824678-1-sean@geanix.com>
Message-ID: <20211025092752.2824678-4-sean@geanix.com>

Prevent MTD access while in a suspended state. Also
prevent suspending a device which is still currently in use.

Commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") allows the
rawnand layer to return errors rather than waiting in a blocking wait.

Tested on a iMX6ULL.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdcore.c   | 124 +++++++++++++++++++++++++++++++++++-----
 include/linux/mtd/mtd.h |  81 +++++++++++++++++++++-----
 2 files changed, 176 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 153229198947..8e6b7e858ada 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -777,6 +777,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
 	INIT_LIST_HEAD(&mtd->partitions);
 	mutex_init(&mtd->master.partitions_lock);
 	mutex_init(&mtd->master.chrdev_lock);
+	init_waitqueue_head(&mtd->master.resume_wq);
+	init_rwsem(&mtd->master.suspend_lock);
 }
 
 static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
@@ -1267,7 +1269,9 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	adjinstr.addr += mst_ofs;
 
+	mtd_start_access(master);
 	ret = master->_erase(master, &adjinstr);
+	mtd_end_access(master);
 
 	if (adjinstr.fail_addr != MTD_FAIL_ADDR_UNKNOWN) {
 		instr->fail_addr = adjinstr.fail_addr - mst_ofs;
@@ -1289,6 +1293,7 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	      void **virt, resource_size_t *phys)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	*virt = NULL;
@@ -1301,8 +1306,12 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	if (!len)
 		return 0;
 
+	mtd_start_access(master);
 	from = mtd_get_master_ofs(mtd, from);
-	return master->_point(master, from, len, retlen, virt, phys);
+	ret = master->_point(master, from, len, retlen, virt, phys);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_point);
 
@@ -1310,6 +1319,7 @@ EXPORT_SYMBOL_GPL(mtd_point);
 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unpoint)
 		return -EOPNOTSUPP;
@@ -1317,7 +1327,12 @@ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
-	return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+
+	mtd_start_access(master);
+	ret =  master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unpoint);
 
@@ -1372,6 +1387,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_read_oob_std handles mtd access protection */
 	ret = mtd_read_oob(mtd, from, &ops);
 	*retlen = ops.retlen;
 
@@ -1388,6 +1404,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_write_oob_std handles mtd access protection */
 	ret = mtd_write_oob(mtd, to, &ops);
 	*retlen = ops.retlen;
 
@@ -1406,6 +1423,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 		    const u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_panic_write)
@@ -1419,8 +1437,12 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	if (!master->oops_panic_write)
 		master->oops_panic_write = true;
 
-	return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
-				    retlen, buf);
+	mtd_start_access(master);
+	ret = master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
+				   retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
@@ -1464,11 +1486,13 @@ static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
 	int ret;
 
 	from = mtd_get_master_ofs(mtd, from);
+	mtd_start_access(master);
 	if (master->_read_oob)
 		ret = master->_read_oob(master, from, ops);
 	else
 		ret = master->_read(master, from, ops->len, &ops->retlen,
 				    ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1480,11 +1504,13 @@ static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
 	int ret;
 
 	to = mtd_get_master_ofs(mtd, to);
+	mtd_start_access(master);
 	if (master->_write_oob)
 		ret = master->_write_oob(master, to, ops);
 	else
 		ret = master->_write(master, to, ops->len, &ops->retlen,
 				     ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1992,12 +2018,18 @@ int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_fact_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_fact_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_get_fact_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
 
@@ -2005,13 +2037,19 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_fact_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_fact_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_fact_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
 
@@ -2019,12 +2057,18 @@ int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_user_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_user_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret =  master->_get_user_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
 
@@ -2032,13 +2076,19 @@ int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_user_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_user_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
 
@@ -2053,7 +2103,11 @@ int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
+
+	mtd_start_access(master);
 	ret = master->_write_user_prot_reg(master, to, len, retlen, buf);
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
@@ -2068,24 +2122,36 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_lock_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_lock_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
 
 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_erase_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_erase_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_erase_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 
@@ -2093,6 +2159,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock)
 		return -EOPNOTSUPP;
@@ -2106,13 +2173,18 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock);
 
 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unlock)
 		return -EOPNOTSUPP;
@@ -2126,13 +2198,18 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unlock);
 
 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_is_locked)
 		return -EOPNOTSUPP;
@@ -2146,13 +2223,18 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
 
 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2162,13 +2244,18 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isreserved);
 
 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2178,7 +2265,11 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
 
@@ -2197,7 +2288,10 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
+	mtd_start_access(master);
 	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..b074106e2d8e 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -231,6 +231,8 @@ struct mtd_master {
 	struct mutex partitions_lock;
 	struct mutex chrdev_lock;
 	unsigned int suspended : 1;
+	wait_queue_head_t resume_wq;
+	struct rw_semaphore suspend_lock;
 };
 
 struct mtd_info {
@@ -476,10 +478,47 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
 }
 
+static inline void mtd_start_access(struct mtd_info *master)
+{
+	WARN_ON_ONCE(master != mtd_get_master(master));
+
+	/*
+	 * Don't take the suspend_lock on devices that don't
+	 * implement the suspend hook. Otherwise, lockdep will
+	 * complain about nested locks when trying to suspend MTD
+	 * partitions or MTD devices created by gluebi which are
+	 * backed by real devices.
+	 */
+	if (!master->_suspend)
+		return;
+
+	/*
+	 * Wait until the device is resumed. Should we have a
+	 * non-blocking mode here?
+	 */
+	while (1) {
+		down_read(&master->master.suspend_lock);
+		if (!master->master.suspended)
+			return;
+
+		up_read(&master->master.suspend_lock);
+		wait_event(master->master.resume_wq, !master->master.suspended);
+	}
+}
+
+static inline void mtd_end_access(struct mtd_info *master)
+{
+	if (!master->_suspend)
+		return;
+
+	up_read(&master->master.suspend_lock);
+}
+
 static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 				     loff_t ofs, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_max_bad_blocks)
 		return -ENOTSUPP;
@@ -487,8 +526,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 	if (mtd->size < (len + ofs) || ofs < 0)
 		return -EINVAL;
 
-	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
-				       len);
+	mtd_start_access(master);
+	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
+				      len);
+	mtd_end_access(master);
+
+	return ret;
 }
 
 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
@@ -546,30 +589,40 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
-	int ret;
-
-	if (master->master.suspended)
-		return 0;
+	int ret = 0;
 
-	ret = master->_suspend ? master->_suspend(master) : 0;
-	if (ret)
+	if (!master->_suspend)
 		return ret;
 
-	master->master.suspended = 1;
-	return 0;
+	down_write(&master->master.suspend_lock);
+	if (!master->master.suspended) {
+		ret = master->_suspend(master);
+		if (!ret)
+			master->master.suspended = 1;
+	}
+	up_write(&master->master.suspend_lock);
+
+	return ret;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 
-	if (!master->master.suspended)
+	if (!master->_suspend)
 		return;
 
-	if (master->_resume)
-		master->_resume(master);
+	down_write(&master->master.suspend_lock);
+	if (master->master.suspended) {
+		if (master->_resume)
+			master->_resume(master);
+
+		master->master.suspended = 0;
 
-	master->master.suspended = 0;
+		/* The MTD dev has been resumed, wake up all waiters. */
+		wake_up_all(&master->master.resume_wq);
+	}
+	up_write(&master->master.suspend_lock);
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
-- 
2.33.0



From havasiefr at gmail.com  Mon Oct 25 02:35:12 2021
From: havasiefr at gmail.com (Kristof Havasi)
Date: Mon, 25 Oct 2021 11:35:12 +0200
Subject: UBIFS panic during brown-out
In-Reply-To: <1035601262.21954.1634838266590.JavaMail.zimbra@nod.at>
References: <CADBnMviweAwc1oFz2-4KtGBAQb3hii1ZkJpZDELXY_CASpd53w@mail.gmail.com>
 <1041553131.62488.1633978966122.JavaMail.zimbra@nod.at>
 <CADBnMvibQS+PZW-fJY2E+mVw4C48BuBF4PoB704L6PRfG4Absw@mail.gmail.com>
 <1040411488.65265.1634045778705.JavaMail.zimbra@nod.at>
 <CADBnMvidNZEiJfSTLe-rj+V0N=EtW8jTrYXzc2KRJKNS-zkCjg@mail.gmail.com>
 <CADBnMvhCmNQsYRVAveuf=Ri820bLyLdcrA71Nywh0mVL+X8Fng@mail.gmail.com>
 <CADBnMviZDXD4p6U4fPDsMFsY1OJYEcjkNGTXDRbbM0mKDVpaAQ@mail.gmail.com>
 <1035601262.21954.1634838266590.JavaMail.zimbra@nod.at>
Message-ID: <CADBnMvidrikjUWU5TvM3+ifMXE9i=m-Huv34oCDBhprvLqCGQg@mail.gmail.com>

Dear Richard,

On Thu, 21 Oct 2021 at 19:44, Richard Weinberger <richard at nod.at> wrote:
>
> Kristof,
>
> ----- Urspr?ngliche Mail -----
> > Von: "Kristof Havasi" <havasiefr at gmail.com>
> > An: "richard" <richard at nod.at>
> > CC: "linux-mtd" <linux-mtd at lists.infradead.org>
> > Gesendet: Donnerstag, 21. Oktober 2021 17:33:15
> > Betreff: Re: UBIFS panic during brown-out
>
> > Dear Richard,
> >
> > I noticed that I forgot to Cc linux-mtd from the previous emails.
> >
> > Latest update: we could reproduce the bug with a v5.10 port.
> > The same EPERM error is hit.
> >
> > Happy to hear any hints on how I can support in fixing this issue.
>
> so I fear you found a bug in the UBIFS auth code.
> Is it possible to share the filesystem and they keymaterial with me?

I used our build server to generate the test images, where we use one-time
throw-away keys/certs for each build. Anyway, I managed to retrieve
the key materials
for the failing v5.10-based test.

We have the following layout on the flash:
0000 - [XXX] partition for bootstrap (at91)
[XXX]-           partition for UBI image

where the UBI image has:
- vol-0 DTB0 [ro]
- vol-1 DTB1 [ro]
- vol-2 Kernel0 [ro]
- vol-3 Kernel1 [ro]
- vol-4 RootFS [dyn, autoresize]

I don't know how to extract only the rootFS from the "bricked" device.
But I could dump the flash of that device and create a link for you
with that and the keys/certs.
Would that help?

>
> Thanks,
> //richard

Best Regards,
Krist?f


From S.Riedmueller at phytec.de  Mon Oct 25 02:39:15 2021
From: S.Riedmueller at phytec.de (=?utf-8?B?U3RlZmFuIFJpZWRtw7xsbGVy?=)
Date: Mon, 25 Oct 2021 09:39:15 +0000
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211022143514.lplk6jaxklq3rxry@umbrella>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
 <20211013050148.2w373kpbfaeuxbwm@umbrella>
 <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>
 <20211022143514.lplk6jaxklq3rxry@umbrella>
Message-ID: <a14524533eccd185224e1c2ec61895e1dbbf7ff8.camel@phytec.de>

Hi Han,

On Fri, 2021-10-22 at 09:35 -0500, han.xu at nxp.com wrote:
> On 21/10/22 08:45AM, Stefan Riedm?ller wrote:
> > Hi Han,
> > 
> > sorry it took me some time to get back to you.
> > 
> > On Wed, 2021-10-13 at 00:01 -0500, Han Xu wrote:
> > > On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> > > > According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> > > > when doing a gpmi_io clk rate change. So gate the clocks off before
> > > > the rate change in nfc_apply_timings and ungate them again after the
> > > > change.
> > > > 
> > > > Otherwise this rate change can lead to an unresponsive GPMI core which
> > > > results in DMA timeouts and failed driver probe:
> > > > 
> > > > [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> > > > ...
> > > > [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> > > > ...
> > > > [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read:
> > > > -22
> > > > [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > ...
> > > > 
> > > > Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> > > > ---
> > > > Hi,
> > > > 
> > > > I'm not sure about the error handling here, if it is actually
> > > > neccessary.
> > > > So some feedback would be nice here.
> > > > 
> > > > Thanks,
> > > > Stefan
> > > > ---
> > > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
> > > >  1 file changed, 19 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > index a1f7000f033e..326c8a895f1f 100644
> > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct
> > > > gpmi_nand_data *this,
> > > >  			      (use_half_period ?
> > > > BM_GPMI_CTRL1_HALF_PERIOD :
> > > > 0);
> > > >  }
> > > >  
> > > > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > >  {
> > > >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > >  	struct resources *r = &this->resources;
> > > >  	void __iomem *gpmi_regs = r->gpmi_regs;
> > > >  	unsigned int dll_wait_time_us;
> > > > +	int ret;
> > > > +
> > > > +	if (GPMI_IS_MX6Q(this)) {
> > > 
> > > Not only for 6Q but for GPMI_IS_MX6
> > 
> > Can you confirm that i.MX 6SX and i.MX 7 are affected by the ERR007117
> > erratum
> > as well? Because the i.MX 6UL/ULL are included by the GPMI_IS_MX6Q
> > already.
> 
> i.MX6SX has the glitch issue for sure, but I can double check if it's due to
> the
> same errata. I will also go check if the errata will affect i.MX7

Thanks, that'll be great!

I'll wait for your response.

Thanks,
Stefan

> 
> > Or do we need another macro for i.MX 6UL/ULL as Christian has suggested
> > earlier?
> > 
> > Thanks,
> > Stefan
> > 
> > > > +		ret = __gpmi_enable_clk(this, false);
> > > > +		if (ret)
> > > > +			return ret;
> > > > +	}
> > > >  
> > > >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > > >  
> > > > +	if (GPMI_IS_MX6Q(this)) {
> > > > +		ret = __gpmi_enable_clk(this, true);
> > > > +		if (ret)
> > > > +			return ret;
> > > > +	}
> > > > +
> > > >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > >  
> > > > @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct
> > > > gpmi_nand_data *this)
> > > >  
> > > >  	/* Wait for the DLL to settle. */
> > > >  	udelay(dll_wait_time_us);
> > > > +
> > > > +	return 0;
> > > >  }
> > > >  
> > > >  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > > > @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip
> > > > *chip,
> > > >  	 */
> > > >  	if (this->hw.must_apply_timings) {
> > > >  		this->hw.must_apply_timings = false;
> > > > -		gpmi_nfc_apply_timings(this);
> > > > +		ret = gpmi_nfc_apply_timings(this);
> > > > +		if (ret)
> > > > +			return ret;
> > > >  	}
> > > >  
> > > >  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op-
> > > > >ninstrs);
> > > > -- 
> > > > 2.25.1
> > > > 

From mika.westerberg at linux.intel.com  Mon Oct 25 02:43:20 2021
From: mika.westerberg at linux.intel.com (Mika Westerberg)
Date: Mon, 25 Oct 2021 12:43:20 +0300
Subject: [PATCH v3 2/3] mtd: spi-nor: intel-spi: Convert to SPI MEM
In-Reply-To: <20211020114153.0f99c5df@collabora.com>
References: <20211013114432.31352-1-mika.westerberg@linux.intel.com>
 <20211013114432.31352-3-mika.westerberg@linux.intel.com>
 <20211020114153.0f99c5df@collabora.com>
Message-ID: <YXZ8OJFICqYSatZX@lahna>

On Wed, Oct 20, 2021 at 11:41:53AM +0200, Boris Brezillon wrote:
> On Wed, 13 Oct 2021 14:44:31 +0300
> Mika Westerberg <mika.westerberg at linux.intel.com> wrote:
> 
> > The preferred way to implement SPI-NOR controller drivers is through SPI
> > subsubsystem utilizing the SPI MEM core functions. This converts the
> > Intel SPI flash controller driver over the SPI MEM by moving the driver
> > from SPI-NOR subsystem to SPI subsystem and in one go make it use the
> > SPI MEM functions. The driver name will be changed from intel-spi to
> > spi-intel to match the convention used in the SPI subsystem.
> > 
> 
> I skimmed over the driver changes, and I'm skeptical about this "let's
> convert all spi-nor controller drivers into spi-mem drivers even if
> they don't fit the spi-mem model" strategy. Clearly, the intel
> controller is much more limited than any other spi-mem controller (I
> mean feature-wise not perf-wise of course). The fact that you have to
> check the opcode to decide whether the operation is supported or not,
> or the way you deduce when to issue an erase vs a regular read/write is
> kind of hack-ish. Not saying we shouldn't support this case in spi-mem,
> but it should at least be done in a more controlled way. Maybe with an
> explicit array of supported spi_mem operations, and driver specific
> hooks for each of these operations so anything falling outside is
> clearly identified and rejected (we have this sort of things in the raw
> NAND framework).

I'm not fan of this either but this was requirement from the SPI-NOR
maintainers before any new features can be added, and we have a bunch of
new hardware that needs to be supported :(

Sure, I can take a look at the array you suggest if that helps to get
things moving. Any objections anyone for doing this?

> > Signed-off-by: Mika Westerberg <mika.westerberg at linux.intel.com>
> > Reviewed-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> > ---
> 
> > +static bool intel_spi_supports_mem_op(struct spi_mem *mem,
> > +				      const struct spi_mem_op *op)
> > +{
> > +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> > +
> > +	if (op->cmd.dtr)
> > +		return false;
> > +
> > +	/*
> > +	 * The Intel controller supports widths up to 4 but it handles
> > +	 * them automatically and does not expose them to software. Here
> > +	 * we accept anything up to 4.
> > +	 */
> > +	if (op->cmd.buswidth > 4 ||
> > +	    (op->addr.nbytes && op->addr.buswidth > 4) ||
> > +	    (op->dummy.nbytes && op->dummy.buswidth > 4))
> > +		return false;
> > +
> > +	if (ispi->swseq_reg && ispi->locked) {
> > +		int i;
> > +
> > +		/* Check if it is in the locked opcodes list */
> > +		for (i = 0; i < ARRAY_SIZE(ispi->opcodes); i++) {
> > +			if (ispi->opcodes[i] == op->cmd.opcode)
> > +				goto check_opcode;
> >  		}
> >  
> > -		return 0;
> > +		return false;
> >  	}
> >  
> > -	/* Not needed with HW sequencer erase, make sure it is cleared */
> > -	ispi->atomic_preopcode = 0;
> > +check_opcode:
> > +	switch (op->cmd.opcode) {
> > +	case SPINOR_OP_RDID:
> > +	case SPINOR_OP_RDSR:
> > +	case SPINOR_OP_WRSR:
> > +		return true;
> 
> Ouch. I hate how spi-nor specific stuff leak into the supposedly
> spi-mem generic driver. Now if we want to allow such specialization, we
> should at least make sure the whole operation is consistent instead of
> checking the opcode, address, dummy and data cycles separately.

OK.

> > -	while (len > 0) {
> > -		writel(offs, ispi->base + FADDR);
> > +	case SPINOR_OP_READ:
> > +	case SPINOR_OP_READ_FAST:
> > +	case SPINOR_OP_READ_4B:
> > +	case SPINOR_OP_READ_FAST_4B:
> > +		return true;
> >  
> > -		val = readl(ispi->base + HSFSTS_CTL);
> > -		val &= ~(HSFSTS_CTL_FDBC_MASK | HSFSTS_CTL_FCYCLE_MASK);
> > -		val |= HSFSTS_CTL_AEL | HSFSTS_CTL_FCERR | HSFSTS_CTL_FDONE;
> > -		val |= cmd;
> > -		val |= HSFSTS_CTL_FGO;
> > -		writel(val, ispi->base + HSFSTS_CTL);
> > +	case SPINOR_OP_PP:
> > +	case SPINOR_OP_PP_4B:
> > +	case SPINOR_OP_WREN:
> > +	case SPINOR_OP_WRDI:
> > +		return true;
> >  
> > -		ret = intel_spi_wait_hw_busy(ispi);
> > -		if (ret)
> > -			return ret;
> > +	case SPINOR_OP_SE:
> > +	case SPINOR_OP_SE_4B:
> > +		return ispi->erase_64k;
> >  
> > -		status = readl(ispi->base + HSFSTS_CTL);
> > -		if (status & HSFSTS_CTL_FCERR)
> > -			return -EIO;
> > -		else if (status & HSFSTS_CTL_AEL)
> > -			return -EACCES;
> > +	case SPINOR_OP_BE_4K:
> > +	case SPINOR_OP_BE_4K_4B:
> > +		return true;
> > +	}
> >  
> > -		offs += erase_size;
> > -		len -= erase_size;
> > +	return false;
> > +}
> > +
> > +static int intel_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
> > +{
> > +	struct intel_spi *ispi = spi_master_get_devdata(mem->spi->master);
> > +	size_t nbytes = op->data.nbytes;
> > +	u8 opcode = op->cmd.opcode;
> > +
> > +	if (op->addr.nbytes) {
> > +		if  (op->data.dir == SPI_MEM_DATA_IN)
> > +			return intel_spi_read(ispi, op->addr.val, nbytes,
> > +					      op->data.buf.in);
> > +		if (op->data.dir == SPI_MEM_DATA_OUT)
> > +			return intel_spi_write(ispi, op->addr.val, nbytes,
> > +					       op->data.buf.out);
> > +		if (op->data.dir == SPI_MEM_NO_DATA)
> > +			return intel_spi_erase(ispi, opcode, op->addr.val);
> 
> That's risky IMHO, how can you be sure that NO_DATA means erase? Again,
> it looks like the whole operation should be checked, not just the data
> field.

intel_spi_erase() does further checks based on the opcode:

        switch (opcode) {
        case SPINOR_OP_SE:
                cmd = HSFSTS_CTL_FCYCLE_ERASE_64K;
                break;

        case SPINOR_OP_BE_4K:
                cmd = HSFSTS_CTL_FCYCLE_ERASE;
                break;

        default:
                return -EINVAL;
        }

I should probably add comment on the caller to make it clear though.


From Tudor.Ambarus at microchip.com  Mon Oct 25 05:18:10 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Mon, 25 Oct 2021 12:18:10 +0000
Subject: [PATCH v2 17/35] mtd: spi-nor: Introduce
 spi_nor_nonsfdp_flags_init()
In-Reply-To: <b06ac5238d85f62ebe588f161e34cf59@walle.cc>
References: <20210727045222.905056-1-tudor.ambarus@microchip.com>
 <20210727045222.905056-18-tudor.ambarus@microchip.com>
 <20210817102429.kmhuef5hxumllxjj@ti.com>
 <4af8b3edebbe398dff1f8ef0bb98f2bc@walle.cc>
 <20211022121010.mzul7qsxi6s4ru2w@ti.com>
 <eed6741d-cbb2-4f67-2780-6ba107eec0f8@microchip.com>
 <5a1497c9b2f07b2e6b91deb8ef17646f@walle.cc>
 <9bf93cbf-fc57-54ae-2439-45e4d75dc0b7@microchip.com>
 <b06ac5238d85f62ebe588f161e34cf59@walle.cc>
Message-ID: <8ce9a228-3d38-1be7-a987-fd20208539d8@microchip.com>

On 10/24/21 8:05 PM, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2021-10-22 15:25, schrieb Tudor.Ambarus at microchip.com:
>> On 10/22/21 3:59 PM, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know
>>> the content is safe
>>>
>>> Am 2021-10-22 14:42, schrieb Tudor.Ambarus at microchip.com:
>>>> On 10/22/21 3:10 PM, Pratyush Yadav wrote:
>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you
>>>>> know
>>>>> the content is safe
>>>>>
>>>>> On 22/10/21 01:21PM, Michael Walle wrote:
>>>>>> Am 2021-08-17 12:24, schrieb Pratyush Yadav:
>>>>>>> On 27/07/21 07:52AM, Tudor Ambarus wrote:
>>>>>>>> Used to initialize the NOR flags for settings that are not
>>>>>>>> defined
>>>>>>>> in the JESD216 SFDP standard, thus can not be retrieved when
>>>>>>>> parsing
>>>>>>>> SFDP. No functional change.
>>>>>>>
>>>>>>> I am worried if the order in which these flags are set can cause
>>>>>>> some
>>>>>>> subtle bugs.
>>>>>>>
>>>>>>> I can see one instance of it with SNOR_F_HAS_LOCK.
>>>>>>> spi_nor_late_init_params() checks for SNOR_F_HAS_LOCK and if there
>>>>>>> are
>>>>>>> no locking ops specified, it sets the default locking ops. This
>>>>>>> works
>>>>>>> fine before this patch because the flag is set before the function
>>>>>>> is
>>>>>>> called. But now, the flag will be set _after_ the function is
>>>>>>> called,
>>>>>>> and so you will never be able to set the default flags.
>>>>>>
>>>>>> Maybe we should just forbid to look at the SNOR_F_ flags in these
>>>>>> functions. Instead the information could also be deduced by looking
>>>>>> at
>>>>>> the SPI_NOR_ flags.
>>>>
>>>> not true.
>>>
>>> I guess you mean that some init flash init functions might set it,
>>> too.
>>> Right? IMHO this goes into the spaghetti code direction again.
>>> spi_nor_late_init_params() must not look at the SNOR_F_ flags. There
>>> are too much inter-function dependencies and it is really hard to
>>> follow the call chain.
>>
>> I don't think I understand what you are referring to. The flash_info
>> flags
>> are used just to set their SNOR_F correspondents. Take
>> SNOR_F_4B_OPCODES for
>> example. A flash that can't discover 4b opcodes support when parsing
>> SFDP,
>> will set the SPI_NOR_4B_OPCODES flash_info flag. Flashes that can
>> discover it,
>> will ignore/not set the SPI_NOR_4B_OPCODES flag, and let the SFDP do
>> its thing:
>> the SFDP code will set the SNOR_F_4B_OPCODES flag. The only flags that
>> are used
>> across the SPI NOR core are the nor->flags (SNOR_F).
> 
> Sorry, I wasn't clear enough. I was talking about checking (already set)
> SNOR_F
> flags in all these init functions ({flash,manufacturer)->post_sfdp(),
> (flash,manufacturer)->late_init, ..). If we didn't allow this, then
> we would avoid all these "subtle bugs" which happen because some of
> these
> functions depend on another being called first. I.e. all the called
> functions within spi_nor_init_params() may only add SNOR_F flags, but
> must
> not actually use them. [I see that spi_nor_sfdp_init_params() will
> remove SNOR_F_4B_OPCODES. Mhh.]

Keeping the setting of SNOR_F flags based on the flash_info flags as late
as we can assures the reader that SNOR_F flags are not used across the
init params chain. It also indicates that the flash can't set the SNOR_F
capability by parsing SFDP, so it needed explicit flags at declaration.
It is clearer who sets and when.

> 
> Btw. I wonder what is the difference between a member being in "struct
> spi_nor"
> and being in "struct spi_nor_flash_parameter". Apparently, it should
> contain the properties which can be set/changed in the fixups or by
> parsing the SFPD. But then there are also the flags which are also
> changed in the fixups.
> 
> Maybe we should pass the "struct nor" as const and a second parameter
> "struct spi_nor_flash_parameter *params" which can be updated by the
> called function. This way we can be sure the functions won't change
> anything else. I don't suggest to do that right now, just to start
> a discussion.

I'll let this for other time, maybe a separate thread.

> 
>>> The locking ops should also go into the (static) flash init which only
>>> depends on the SPI_NOR_ flags. If SNOR_F_HAS_LOCK will be added at
>>
>> we don't have to specify the locking methods, we have generic ones. A
>> single
>> flag is enough.
> 
> Hm, I'm not really sure we need that SNOR_F_HAS_LOCK flag at all.
> "if (nor->params->locking_ops)" should be the same. At least the current
> code
> which checks the info->flags for SPI_NOR_HAS_LOCK will set the default
> locking ops instead of just setting the SNOR_F_HAS_LOCK.

SNOR_F_HAS_LOCK is kept for consistency. The core driver operates just on SNOR_F
flags. Here it's the same idea, I would like to set the locking ops as late in
the init chain as possible, to indicate that the locking ops are not needed earlier.

> 
>>> in an init function, then this code should also take care of setting
>>
>> what init function? We're just setting some flags.
> 
> all the functions called in spi_nor_init_params().
> 
>>> the correct locking ops. Maybe both can be set together with a helper.
> 
> -michael


From lkp at intel.com  Mon Oct 25 07:57:12 2021
From: lkp at intel.com (kernel test robot)
Date: Mon, 25 Oct 2021 22:57:12 +0800
Subject: [PATCH 05/11] ubifs: Rename whiteout atomically
In-Reply-To: <20211025034116.3544321-6-chengzhihao1@huawei.com>
References: <20211025034116.3544321-6-chengzhihao1@huawei.com>
Message-ID: <202110252236.yJkEIfMt-lkp@intel.com>

Hi Zhihao,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linux/master]
[also build test WARNING on linus/master rw-ubifs/next v5.15-rc6 next-20211025]
[cannot apply to rw-ubifs/fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Zhihao-Cheng/Some-bugfixs-for-ubifs-ubi/20211025-113114
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2f111a6fd5b5297b4e92f53798ca086f7c7d33a4
config: i386-randconfig-a006-20211025 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project a461fa64bb37cffd73f683c74f6b0780379fc2ca)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/8a6ca5bc1be93cca9c7b0167a71bdd338f854600
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Zhihao-Cheng/Some-bugfixs-for-ubifs-ubi/20211025-113114
        git checkout 8a6ca5bc1be93cca9c7b0167a71bdd338f854600
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All warnings (new ones prefixed by >>):

>> fs/ubifs/dir.c:357:22: warning: variable 'ui' set but not used [-Wunused-but-set-variable]
           struct ubifs_inode *ui;
                               ^
   1 warning generated.


vim +/ui +357 fs/ubifs/dir.c

   351	
   352	static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry,
   353					     umode_t mode)
   354	{
   355		int err;
   356		struct inode *inode;
 > 357		struct ubifs_inode *ui;
   358		struct ubifs_info *c = dir->i_sb->s_fs_info;
   359		struct fscrypt_name nm;
   360	
   361		/*
   362		 * Create an inode('nlink = 1') for whiteout without updating journal,
   363		 * let ubifs_jnl_rename() store it on flash to complete rename whiteout
   364		 * atomically.
   365		 */
   366	
   367		dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
   368			dentry, mode, dir->i_ino);
   369	
   370		err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
   371		if (err)
   372			return ERR_PTR(err);
   373	
   374		inode = ubifs_new_inode(c, dir, mode);
   375		if (IS_ERR(inode)) {
   376			err = PTR_ERR(inode);
   377			goto out_free;
   378		}
   379		ui = ubifs_inode(inode);
   380	
   381		init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
   382		ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
   383	
   384		err = ubifs_init_security(dir, inode, &dentry->d_name);
   385		if (err)
   386			goto out_inode;
   387	
   388		/* The dir size is updated by do_rename. */
   389		insert_inode_hash(inode);
   390	
   391		return inode;
   392	
   393	out_inode:
   394		make_bad_inode(inode);
   395		iput(inode);
   396	out_free:
   397		fscrypt_free_filename(&nm);
   398		ubifs_err(c, "cannot create whiteout file, error %d", err);
   399		return ERR_PTR(err);
   400	}
   401	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 34879 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211025/94ad192e/attachment-0001.gz>

From boris.brezillon at collabora.com  Mon Oct 25 07:59:57 2021
From: boris.brezillon at collabora.com (Boris Brezillon)
Date: Mon, 25 Oct 2021 16:59:57 +0200
Subject: [PATCH v3 2/4] mtd: mtdconcat: add suspend lock handling
In-Reply-To: <20211025092752.2824678-3-sean@geanix.com>
References: <20211025092752.2824678-1-sean@geanix.com>
 <20211025092752.2824678-3-sean@geanix.com>
Message-ID: <20211025165957.349a6580@collabora.com>

Hello Sean,

On Mon, 25 Oct 2021 11:27:50 +0200
Sean Nyekjaer <sean at geanix.com> wrote:

The subject is misleading, how about 'mtd: mtdconcat: Don't use
mtd_{suspend,resume}()'

> Use MTD hooks to control suspend/resume of MTD devices.
> concat_{suspend,resume} will be called from mtd_{suspend,resume},
> which already have taken the suspend/resume lock.
> It's safe to proceed with calling MTD device hooks directly from here.

"
The MTD suspend logic will soon be adjusted to automatically wait for
device wake-up before issuing IOs. In order to do that a new read-write
lock will be added and taken in write-mode in the
mtd_{suspend,resume}() path. Since mtdconcat.c itself is an MTD device,
calling mtd_suspend/resume() on subdevices from the mtdconcat
->_{suspend,resume}() hook will lead to a nested lock, which lockdep
will complain about if we don't add a proper annotation. Let's keep
things simple and replace those mtd_{suspend,resume}(subdev) calls by
subdev->_{suspend,resume}() ones to avoid this situation.
"

> 
> Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")

Again, this commit doesn't fix anything.

> Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
> Signed-off-by: Sean Nyekjaer <sean at geanix.com>
> ---
>  drivers/mtd/mtdconcat.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
> index f685a581df48..37532f529820 100644
> --- a/drivers/mtd/mtdconcat.c
> +++ b/drivers/mtd/mtdconcat.c
> @@ -566,9 +566,15 @@ static int concat_suspend(struct mtd_info *mtd)
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		if ((rc = mtd_suspend(subdev)) < 0)
> +		/*
> +		 * Call MTD hook directly from here,
> +		 * mtd_suspend() have the suspend/resume lock.

		/*
		 * Call the MTD hook directly to avoid a nested lock
		 * on ->suspend_lock.
		 */

> +		 */
> +		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
> +		if (rc < 0)
>  			return rc;
>  	}
> +
>  	return rc;
>  }
>  
> @@ -579,7 +585,12 @@ static void concat_resume(struct mtd_info *mtd)
>  
>  	for (i = 0; i < concat->num_subdev; i++) {
>  		struct mtd_info *subdev = concat->subdev[i];
> -		mtd_resume(subdev);
> +		/*
> +		 * Call MTD hook directly from here,
> +		 * mtd_resume() have the suspend/resume lock.
> +		 */

Ditto.

> +		if (subdev->_resume)
> +			subdev->_resume(subdev);
>  	}
>  }
>  



From mcgrof at kernel.org  Mon Oct 25 08:58:36 2021
From: mcgrof at kernel.org (Luis Chamberlain)
Date: Mon, 25 Oct 2021 08:58:36 -0700
Subject: [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <24bc86d0-9d8d-8c8a-7f74-a87f9089342b@infradead.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <a31970d6-8631-9d9d-a36f-8f4fcebfb1e6@infradead.org>
 <YW2duaTqf3qUbTIm@bombadil.infradead.org>
 <24bc86d0-9d8d-8c8a-7f74-a87f9089342b@infradead.org>
Message-ID: <YXbULG63hZcBdoQD@bombadil.infradead.org>

On Thu, Oct 21, 2021 at 08:10:49PM -0700, Geoff Levand wrote:
> Hi Luis,
> 
> On 10/18/21 9:15 AM, Luis Chamberlain wrote:
> > On Sun, Oct 17, 2021 at 08:26:33AM -0700, Geoff Levand wrote:
> >> Hi Luis,
> >>
> >> On 10/15/21 4:52 PM, Luis Chamberlain wrote:
> >>> This patch set consists of al the straggler drivers for which we have
> >>> have no patch reviews done for yet. I'd like to ask for folks to please
> >>> consider chiming in, specially if you're the maintainer for the driver.
> >>> Additionally if you can specify if you'll take the patch in yourself or
> >>> if you want Jens to take it, that'd be great too.
> >>
> >> Do you have a git repo with the patch set applied that I can use to test with?
> > 
> > Sure, although the second to last patch is in a state of flux given
> > the ataflop driver currently is broken and so we're seeing how to fix
> > that first:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux-next.git/log/?h=20211011-for-axboe-add-disk-error-handling
> 
> That branch has so many changes applied on top of the base v5.15-rc4
> that the patches I need to apply to test on PS3 with don't apply.
> 
> Do you have something closer to say v5.15-rc5?  Preferred would be
> just your add_disk() error handling patches plus what they depend
> on.

If you just want to test the ps3 changes, I've put this branch together
just for yo, its based on v5.15-rc6:

https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=20211025-ps3-add-disk

  Luis


From minchan at kernel.org  Mon Oct 25 09:55:04 2021
From: minchan at kernel.org (Minchan Kim)
Date: Mon, 25 Oct 2021 09:55:04 -0700
Subject: [PATCH 08/13] zram: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-9-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-9-mcgrof@kernel.org>
Message-ID: <YXbhaO5QAOi96E8j@google.com>

On Fri, Oct 15, 2021 at 04:52:14PM -0700, Luis Chamberlain wrote:
> We never checked for errors on add_disk() as this function
> returned void. Now that this is fixed, use the shiny new
> error handling.
> 
> Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
Acked-by: Minchan Kim <minchan at kernel.org>


From p.yadav at ti.com  Mon Oct 25 12:51:26 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Tue, 26 Oct 2021 01:21:26 +0530
Subject: [PATCH v1] dt-bindings: mtd: spi-nor: use unevaluatedProperties:
 false
In-Reply-To: <YVs1XZmeIdix1m1V@robh.at.kernel.org>
References: <20210924180705.14021-1-p.yadav@ti.com>
 <YVs1XZmeIdix1m1V@robh.at.kernel.org>
Message-ID: <20211025195124.nx2whsynpokyg7ot@ti.com>

On 04/10/21 12:09PM, Rob Herring wrote:
> On Fri, Sep 24, 2021 at 11:37:05PM +0530, Pratyush Yadav wrote:
> > Many SPI controllers need to add properties to slave devices. This could
> > be the delay in clock or data lines, etc. These properties are
> > controller specific but need to be defined in the slave node because
> > they are per-slave and there can be multiple slaves attached to a
> > controller.
> > 
> > If these properties are not added to the slave binding, then the dtbs
> > check emits a warning. But these properties do not make much sense in
> > the slave binding because they are controller-specific and they will
> > just pollute every slave binding.
> > 
> > One option is to add a separate schema that collects all such properties
> > from all such controllers. Slave bindings can simply refer to this
> > binding and they should be rid of the warnings.
> > 
> > There are some limitations with this approach:
> > 
> > 1. There is no way to specify required properties. The schema would
> > contain properties for all controllers and there would be no way to know
> > which controller is being used.
> > 
> > 2. There would be no way to restrict additional properties. Since this
> > schema will be used with an allOf operator, additionalProperties would
> > need to be true. In addition, the slave schema will have to set
> > unevaluatedProperties: false.
> 
> I don't see what is the problem. If there's a $ref, then 
> unevaluatedProperties is what should be used.
> 
> > 
> > A much simpler option would be to make controller schemas specify those
> > properties in patternProperties and set unevaluatedProperties to false
> > on slave schemas, which is done in the previous approach anyway. This
> > approach would have the same limitations as the 2nd limitation in the
> > previous approach. But it does not have the 1st limitation since the
> > properties of all controllers are not collected in a single schema, but
> > instead reside in the same schema as the controller. It also has the
> > added benefit of being much simpler.
> > 
> > The SPI NOR binding is taken as the first one to follow this. Other
> > bindings like SPI NAND can follow in later patches.
> > 
> > Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
> > 
> > ---
> > I sent the first approach mentioned in the commit message some time ago
> > [0]. When re-rolling this series I realized that if we are going to use
> > unevaluatedProperties: false, then it would be much simpler to just keep
> > everything else as-is. This has clear positives with no negatives
> > relative to [0], as explained in the commit message.
> > 
> > [0] https://lore.kernel.org/all/20210609111707.9555-1-p.yadav at ti.com/T/#u
> > 
> >  Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > index ed590d7c6e37..81be0620b264 100644
> > --- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > +++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
> > @@ -88,7 +88,7 @@ patternProperties:
> >    "^otp(-[0-9]+)?$":
> >      type: object
> > 
> > -additionalProperties: false
> > +unevaluatedProperties: false
> 
> This only works until unevaluatedProperties support is actually 
> implemented. Then it's back to the same warnings. In the mean time, we'd 
> be allowing any extra random properties to be added for everyone.

Ok, I didn't know that. I don't understand the validation frameworks all 
that well. I will go back to the method you suggested. Thanks.

> 
> Rob

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.


From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:24 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:24 +0100
Subject: [PATCH v2 0/7] Add SPI Multi I/O Bus Controller support for RZ/G2L
Message-ID: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>

Hi All,

This patch series adds a couple of fixes for rpc-if driver and
adds support for RZ/G2L SoC, where the SPI Multi I/O Bus Controller
is identical to the RPC-IF block found on R-Car Gen3 SoC's.

Cheers,
Prabhakar

Changes for v2:
* Rebased the patches on linux-next
* Split patch 5 from v1
* Included RB tags
* Fixed review comments pointed by Wolfram

v1:
https://patchwork.kernel.org/project/linux-renesas-soc/cover/
20210928140721.8805-1-prabhakar.mahadev-lad.rj at bp.renesas.com/

Lad Prabhakar (7):
  dt-bindings: memory: renesas,rpc-if: Add support for the R9A07G044
  dt-bindings: memory: renesas,rpc-if: Add optional interrupts property
  spi: spi-rpc-if: Check return value of rpcif_sw_init()
  mtd: hyperbus: rpc-if: Check return value of rpcif_sw_init()
  memory: renesas-rpc-if: Return error in case devm_ioremap_resource()
    fails
  memory: renesas-rpc-if: Drop usage of RPCIF_DIRMAP_SIZE macro
  memory: renesas-rpc-if: Add support for RZ/G2L

 .../memory-controllers/renesas,rpc-if.yaml    | 54 +++++++++----
 drivers/memory/renesas-rpc-if.c               | 80 +++++++++++++++----
 drivers/mtd/hyperbus/rpc-if.c                 |  8 +-
 drivers/spi/spi-rpc-if.c                      |  8 +-
 include/memory/renesas-rpc-if.h               |  8 +-
 5 files changed, 124 insertions(+), 34 deletions(-)

-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:25 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:25 +0100
Subject: [PATCH v2 1/7] dt-bindings: memory: renesas,
 rpc-if: Add support for the R9A07G044
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-2-prabhakar.mahadev-lad.rj@bp.renesas.com>

SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
the RPC-IF interface found on R-Car Gen3 SoC's.

This patch adds a new compatible string to identify the RZ/G2L family
so that the timing values on RZ/G2L can be adjusted.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Rob Herring <robh at kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v1->v2:
 * Rebased patch on top of V3U bindings
 * Included RB tags
---
 .../memory-controllers/renesas,rpc-if.yaml    | 53 +++++++++++++------
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
index 9da80e8f2444..43391a2d5bc5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
@@ -24,17 +24,23 @@ allOf:
 
 properties:
   compatible:
-    items:
-      - enum:
-          - renesas,r8a774a1-rpc-if       # RZ/G2M
-          - renesas,r8a774b1-rpc-if       # RZ/G2N
-          - renesas,r8a774c0-rpc-if       # RZ/G2E
-          - renesas,r8a774e1-rpc-if       # RZ/G2H
-          - renesas,r8a77970-rpc-if       # R-Car V3M
-          - renesas,r8a77980-rpc-if       # R-Car V3H
-          - renesas,r8a77995-rpc-if       # R-Car D3
-          - renesas,r8a779a0-rpc-if       # R-Car V3U
-      - const: renesas,rcar-gen3-rpc-if   # a generic R-Car gen3 or RZ/G2 device
+    oneOf:
+      - items:
+          - enum:
+              - renesas,r8a774a1-rpc-if       # RZ/G2M
+              - renesas,r8a774b1-rpc-if       # RZ/G2N
+              - renesas,r8a774c0-rpc-if       # RZ/G2E
+              - renesas,r8a774e1-rpc-if       # RZ/G2H
+              - renesas,r8a77970-rpc-if       # R-Car V3M
+              - renesas,r8a77980-rpc-if       # R-Car V3H
+              - renesas,r8a77995-rpc-if       # R-Car D3
+              - renesas,r8a779a0-rpc-if       # R-Car V3U
+          - const: renesas,rcar-gen3-rpc-if   # a generic R-Car gen3 or RZ/G2{E,H,M,N} device
+
+      - items:
+          - enum:
+              - renesas,r9a07g044-rpc-if      # RZ/G2{L,LC}
+          - const: renesas,rzg2l-rpc-if       # RZ/G2L family
 
   reg:
     items:
@@ -48,8 +54,7 @@ properties:
       - const: dirmap
       - const: wbuf
 
-  clocks:
-    maxItems: 1
+  clocks: true
 
   power-domains:
     maxItems: 1
@@ -67,8 +72,6 @@ patternProperties:
             - cfi-flash
             - jedec,spi-nor
 
-unevaluatedProperties: false
-
 required:
   - compatible
   - reg
@@ -79,6 +82,26 @@ required:
   - '#address-cells'
   - '#size-cells'
 
+if:
+  properties:
+    compatible:
+      contains:
+        enum:
+          - renesas,rzg2l-rpc-if
+then:
+  properties:
+    clocks:
+      items:
+        - description: SPI Multi IO Register access clock (SPI_CLK2)
+        - description: SPI Multi IO Main clock (SPI_CLK).
+
+else:
+  properties:
+    clocks:
+      maxItems: 1
+
+unevaluatedProperties: false
+
 examples:
   - |
     #include <dt-bindings/clock/renesas-cpg-mssr.h>
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:26 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:26 +0100
Subject: [PATCH v2 2/7] dt-bindings: memory: renesas,
 rpc-if: Add optional interrupts property
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-3-prabhakar.mahadev-lad.rj@bp.renesas.com>

For completeness add optional interrupts property.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Reviewed-by: Rob Herring <robh at kernel.org>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v1->v2:
 * Included RB tags
---
 .../devicetree/bindings/memory-controllers/renesas,rpc-if.yaml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
index 43391a2d5bc5..294f1036420d 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
@@ -56,6 +56,9 @@ properties:
 
   clocks: true
 
+  interrupts:
+    maxItems: 1
+
   power-domains:
     maxItems: 1
 
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:27 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:27 +0100
Subject: [PATCH v2 3/7] spi: spi-rpc-if: Check return value of rpcif_sw_init()
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-4-prabhakar.mahadev-lad.rj@bp.renesas.com>

rpcif_sw_init() can fail so make sure we check the return value
of it and on error exit rpcif_spi_probe() callback with error code.

Fixes: eb8d6d464a27 ("spi: add Renesas RPC-IF driver")
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v1->v2:
 * Included RB tags
---
 drivers/spi/spi-rpc-if.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index c53138ce0030..83796a4ead34 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -139,7 +139,9 @@ static int rpcif_spi_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	rpc = spi_controller_get_devdata(ctlr);
-	rpcif_sw_init(rpc, parent);
+	error = rpcif_sw_init(rpc, parent);
+	if (error)
+		return error;
 
 	platform_set_drvdata(pdev, ctlr);
 
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:28 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:28 +0100
Subject: [PATCH v2 4/7] mtd: hyperbus: rpc-if: Check return value of
 rpcif_sw_init()
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-5-prabhakar.mahadev-lad.rj@bp.renesas.com>

rpcif_sw_init() can fail so make sure we check the return value
of it and on error exit rpcif_hb_probe() callback with error code.

Fixes: 5de15b610f78 ("mtd: hyperbus: add Renesas RPC-IF driver")
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
---
v1->v2:
 * Included RB tags
---
 drivers/mtd/hyperbus/rpc-if.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
index ecb050ba95cd..367b0d72bf62 100644
--- a/drivers/mtd/hyperbus/rpc-if.c
+++ b/drivers/mtd/hyperbus/rpc-if.c
@@ -124,7 +124,9 @@ static int rpcif_hb_probe(struct platform_device *pdev)
 	if (!hyperbus)
 		return -ENOMEM;
 
-	rpcif_sw_init(&hyperbus->rpc, pdev->dev.parent);
+	error = rpcif_sw_init(&hyperbus->rpc, pdev->dev.parent);
+	if (error)
+		return error;
 
 	platform_set_drvdata(pdev, hyperbus);
 
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:29 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:29 +0100
Subject: [PATCH v2 5/7] memory: renesas-rpc-if: Return error in case
 devm_ioremap_resource() fails
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-6-prabhakar.mahadev-lad.rj@bp.renesas.com>

Make sure we return error in case devm_ioremap_resource() fails for dirmap
resource.

Fixes: ca7d8b980b67 ("memory: add Renesas RPC-IF driver")
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
v1->v2:
 * New patch (split from patch 5 of v1)
 * Included RB tags
---
 drivers/memory/renesas-rpc-if.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index 7435baad0007..ff8bcbccac63 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -243,7 +243,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
 	rpc->dirmap = devm_ioremap_resource(&pdev->dev, res);
 	if (IS_ERR(rpc->dirmap))
-		rpc->dirmap = NULL;
+		return PTR_ERR(rpc->dirmap);
 	rpc->size = resource_size(res);
 
 	rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:30 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:30 +0100
Subject: [PATCH v2 6/7] memory: renesas-rpc-if: Drop usage of
 RPCIF_DIRMAP_SIZE macro
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-7-prabhakar.mahadev-lad.rj@bp.renesas.com>

RPCIF_DIRMAP_SIZE may differ on various SoC's. Instead of using
RPCIF_DIRMAP_SIZE macro use resource size to get dirmap size
which is already part of struct rpcif.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
v1->v2:
 * New patch (split from patch 5 of v1)
 * Included RB tags
---
 drivers/memory/renesas-rpc-if.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index ff8bcbccac63..0c56decc91f2 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -147,8 +147,6 @@
 #define RPCIF_PHYINT		0x0088	/* R/W */
 #define RPCIF_PHYINT_WPVAL	BIT(1)
 
-#define RPCIF_DIRMAP_SIZE	0x4000000
-
 static const struct regmap_range rpcif_volatile_ranges[] = {
 	regmap_reg_range(RPCIF_SMRDR0, RPCIF_SMRDR1),
 	regmap_reg_range(RPCIF_SMWDR0, RPCIF_SMWDR1),
@@ -588,8 +586,8 @@ static void memcpy_fromio_readw(void *to,
 
 ssize_t rpcif_dirmap_read(struct rpcif *rpc, u64 offs, size_t len, void *buf)
 {
-	loff_t from = offs & (RPCIF_DIRMAP_SIZE - 1);
-	size_t size = RPCIF_DIRMAP_SIZE - from;
+	loff_t from = offs & (rpc->size - 1);
+	size_t size = rpc->size - from;
 
 	if (len > size)
 		len = size;
-- 
2.17.1



From prabhakar.mahadev-lad.rj at bp.renesas.com  Mon Oct 25 13:56:31 2021
From: prabhakar.mahadev-lad.rj at bp.renesas.com (Lad Prabhakar)
Date: Mon, 25 Oct 2021 21:56:31 +0100
Subject: [PATCH v2 7/7] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <20211025205631.21151-8-prabhakar.mahadev-lad.rj@bp.renesas.com>

SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
the RPC-IF interface found on R-Car Gen3 SoC's.

This patch adds a new compatible string for the RZ/G2L family so
that the timing values on RZ/G2L can be adjusted.

Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
---
v1->v2:
 * Updated macros as suggested by Wolfram
---
 drivers/memory/renesas-rpc-if.c | 72 ++++++++++++++++++++++++++++-----
 drivers/mtd/hyperbus/rpc-if.c   |  4 +-
 drivers/spi/spi-rpc-if.c        |  4 +-
 include/memory/renesas-rpc-if.h |  8 +++-
 4 files changed, 75 insertions(+), 13 deletions(-)

diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index 0c56decc91f2..8c51145c0f5c 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_device.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
 
@@ -27,8 +28,8 @@
 #define RPCIF_CMNCR_MOIIO_HIZ	(RPCIF_CMNCR_MOIIO0(3) | \
 				 RPCIF_CMNCR_MOIIO1(3) | \
 				 RPCIF_CMNCR_MOIIO2(3) | RPCIF_CMNCR_MOIIO3(3))
-#define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* undocumented */
-#define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* undocumented */
+#define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* documented for RZ/G2L */
+#define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* documented for RZ/G2L */
 #define RPCIF_CMNCR_IO0FV(val)	(((val) & 0x3) << 8)
 #define RPCIF_CMNCR_IOFV_HIZ	(RPCIF_CMNCR_IO0FV(3) | RPCIF_CMNCR_IO2FV(3) | \
 				 RPCIF_CMNCR_IO3FV(3))
@@ -126,6 +127,9 @@
 #define RPCIF_SMDRENR_OPDRE	BIT(4)
 #define RPCIF_SMDRENR_SPIDRE	BIT(0)
 
+#define RPCIF_PHYADD		0x0070	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
+#define RPCIF_PHYWR		0x0074	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
+
 #define RPCIF_PHYCNT		0x007C	/* R/W */
 #define RPCIF_PHYCNT_CAL	BIT(31)
 #define RPCIF_PHYCNT_OCTA(v)	(((v) & 0x3) << 22)
@@ -133,10 +137,12 @@
 #define RPCIF_PHYCNT_OCT	BIT(20)
 #define RPCIF_PHYCNT_DDRCAL	BIT(19)
 #define RPCIF_PHYCNT_HS		BIT(18)
-#define RPCIF_PHYCNT_STRTIM(v)	(((v) & 0x7) << 15)
+#define RPCIF_PHYCNT_CKSEL(v)	(((v) & 0x3) << 16) /* valid only for RZ/G2L */
+#define RPCIF_PHYCNT_STRTIM(v)	(((v) & 0x7) << 15) /* valid for R-Car and RZ/G2{E,H,M,N} */
 #define RPCIF_PHYCNT_WBUF2	BIT(4)
 #define RPCIF_PHYCNT_WBUF	BIT(2)
 #define RPCIF_PHYCNT_PHYMEM(v)	(((v) & 0x3) << 0)
+#define RPCIF_PHYCNT_PHYMEM_MASK GENMASK(1, 0)
 
 #define RPCIF_PHYOFFSET1	0x0080	/* R/W */
 #define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)
@@ -244,18 +250,46 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
 		return PTR_ERR(rpc->dirmap);
 	rpc->size = resource_size(res);
 
+	rpc->type = (enum rpcif_type)of_device_get_match_data(dev);
 	rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
 
 	return PTR_ERR_OR_ZERO(rpc->rstc);
 }
 EXPORT_SYMBOL(rpcif_sw_init);
 
-void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
+static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc)
+{
+	u32 data;
+
+	regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000);
+	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000);
+	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
+	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000022);
+	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
+	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000024);
+
+	regmap_read(rpc->regmap, RPCIF_PHYCNT, &data);
+	regmap_write(rpc->regmap, RPCIF_PHYCNT, data | RPCIF_PHYCNT_CKSEL(3));
+	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00000030);
+	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032);
+}
+
+int rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
 {
 	u32 dummy;
 
 	pm_runtime_get_sync(rpc->dev);
 
+	if (rpc->type == RPCIF_RZ_G2L) {
+		int ret;
+
+		ret = reset_control_reset(rpc->rstc);
+		if (ret)
+			return ret;
+		usleep_range(200, 300);
+		rpcif_rzg2l_timing_adjust_sdr(rpc);
+	}
+
 	/*
 	 * NOTE: The 0x260 are undocumented bits, but they must be set.
 	 *	 RPCIF_PHYCNT_STRTIM is strobe timing adjustment bits,
@@ -264,8 +298,15 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
 	 *	 On H3 ES1.x, the value should be 0, while on others,
 	 *	 the value should be 7.
 	 */
-	regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
-		     RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
+	if (rpc->type == RPCIF_RCAR_GEN3) {
+		regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
+			     RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
+	} else {
+		regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
+		dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
+		dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
+		regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
+	}
 
 	/*
 	 * NOTE: The 0x1511144 are undocumented bits, but they must be set
@@ -282,9 +323,17 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
 		regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
 				   RPCIF_PHYINT_WPVAL, 0);
 
-	regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
-		     RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
-		     RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
+	if (rpc->type == RPCIF_RCAR_GEN3)
+		regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
+			     RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
+			     RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
+	else
+		regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
+			     RPCIF_CMNCR_MOIIO3(1) | RPCIF_CMNCR_MOIIO2(1) |
+			     RPCIF_CMNCR_MOIIO1(1) | RPCIF_CMNCR_MOIIO0(1) |
+			     RPCIF_CMNCR_IO3FV(2) | RPCIF_CMNCR_IO2FV(2) |
+			     RPCIF_CMNCR_IO0FV(2) | RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
+
 	/* Set RCF after BSZ update */
 	regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF);
 	/* Dummy read according to spec */
@@ -295,6 +344,8 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
 	pm_runtime_put(rpc->dev);
 
 	rpc->bus_size = hyperflash ? 2 : 1;
+
+	return 0;
 }
 EXPORT_SYMBOL(rpcif_hw_init);
 
@@ -657,7 +708,8 @@ static int rpcif_remove(struct platform_device *pdev)
 }
 
 static const struct of_device_id rpcif_of_match[] = {
-	{ .compatible = "renesas,rcar-gen3-rpc-if", },
+	{ .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
+	{ .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
 	{},
 };
 MODULE_DEVICE_TABLE(of, rpcif_of_match);
diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
index 367b0d72bf62..40bca89268c3 100644
--- a/drivers/mtd/hyperbus/rpc-if.c
+++ b/drivers/mtd/hyperbus/rpc-if.c
@@ -132,7 +132,9 @@ static int rpcif_hb_probe(struct platform_device *pdev)
 
 	rpcif_enable_rpm(&hyperbus->rpc);
 
-	rpcif_hw_init(&hyperbus->rpc, true);
+	error = rpcif_hw_init(&hyperbus->rpc, true);
+	if (error)
+		return error;
 
 	hyperbus->hbdev.map.size = hyperbus->rpc.size;
 	hyperbus->hbdev.map.virt = hyperbus->rpc.dirmap;
diff --git a/drivers/spi/spi-rpc-if.c b/drivers/spi/spi-rpc-if.c
index 83796a4ead34..fe82f3575df4 100644
--- a/drivers/spi/spi-rpc-if.c
+++ b/drivers/spi/spi-rpc-if.c
@@ -156,7 +156,9 @@ static int rpcif_spi_probe(struct platform_device *pdev)
 	ctlr->mode_bits = SPI_CPOL | SPI_CPHA | SPI_TX_QUAD | SPI_RX_QUAD;
 	ctlr->flags = SPI_CONTROLLER_HALF_DUPLEX;
 
-	rpcif_hw_init(rpc, false);
+	error = rpcif_hw_init(rpc, false);
+	if (error)
+		return error;
 
 	error = spi_register_controller(ctlr);
 	if (error) {
diff --git a/include/memory/renesas-rpc-if.h b/include/memory/renesas-rpc-if.h
index 77c694a19149..7c93f5177532 100644
--- a/include/memory/renesas-rpc-if.h
+++ b/include/memory/renesas-rpc-if.h
@@ -57,6 +57,11 @@ struct rpcif_op {
 	} data;
 };
 
+enum rpcif_type {
+	RPCIF_RCAR_GEN3,
+	RPCIF_RZ_G2L,
+};
+
 struct rpcif {
 	struct device *dev;
 	void __iomem *base;
@@ -64,6 +69,7 @@ struct rpcif {
 	struct regmap *regmap;
 	struct reset_control *rstc;
 	size_t size;
+	enum rpcif_type type;
 	enum rpcif_data_dir dir;
 	u8 bus_size;
 	void *buffer;
@@ -78,7 +84,7 @@ struct rpcif {
 };
 
 int rpcif_sw_init(struct rpcif *rpc, struct device *dev);
-void rpcif_hw_init(struct rpcif *rpc, bool hyperflash);
+int rpcif_hw_init(struct rpcif *rpc, bool hyperflash);
 void rpcif_prepare(struct rpcif *rpc, const struct rpcif_op *op, u64 *offs,
 		   size_t *len);
 int rpcif_manual_xfer(struct rpcif *rpc);
-- 
2.17.1



From ennoerlangen at gmail.com  Mon Oct 25 13:57:24 2021
From: ennoerlangen at gmail.com (Andreas Oetken)
Date: Mon, 25 Oct 2021 22:57:24 +0200
Subject: [PATCH] drivers: mtd: Fixed breaking list in __mtd_del_partition.
Message-ID: <20211025205724.3306739-1-andreas.oetken@siemens-energy.com>

Not the child partition should be removed from the partition list
but the partition itself. Otherwise the partition list gets broken
and any subsequent remove operations leads to a kernel panic.

Signed-off-by: Andreas Oetken <andreas.oetken at siemens-energy.com>
---
 drivers/mtd/mtdpart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 95d47422bbf20..5725818fa199f 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -313,7 +313,7 @@ static int __mtd_del_partition(struct mtd_info *mtd)
 	if (err)
 		return err;
 
-	list_del(&child->part.node);
+	list_del(&mtd->part.node);
 	free_partition(mtd);
 
 	return 0;
-- 
2.30.2



From sean at geanix.com  Mon Oct 25 22:55:48 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 26 Oct 2021 07:55:48 +0200
Subject: [PATCH v4 1/4] mtd: rawnand: nand_bbt: hide suspend/resume hooks
 while scanning bbt
In-Reply-To: <20211026055551.3053598-1-sean@geanix.com>
References: <20211026055551.3053598-1-sean@geanix.com>
Message-ID: <20211026055551.3053598-2-sean@geanix.com>

From: Boris Brezillon <boris.brezillon at collabora.com>

The BBT scan logic use the MTD helpers before the MTD layer had a
chance to initialize the device, and that leads to issues when
accessing the uninitialized suspend lock. Let's temporarily set the
suspend/resume hooks to NULL to skip the lock acquire/release step.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Tested-by: Sean Nyekjaer <sean at geanix.com>
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_bbt.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c
index b7ad030225f8..93d385703469 100644
--- a/drivers/mtd/nand/raw/nand_bbt.c
+++ b/drivers/mtd/nand/raw/nand_bbt.c
@@ -1397,8 +1397,28 @@ static int nand_create_badblock_pattern(struct nand_chip *this)
  */
 int nand_create_bbt(struct nand_chip *this)
 {
+	struct mtd_info *mtd = nand_to_mtd(this);
+	int (*suspend) (struct mtd_info *) = mtd->_suspend;
+	void (*resume) (struct mtd_info *) = mtd->_resume;
 	int ret;
 
+	/*
+	 * The BBT scan logic use the MTD helpers before the MTD layer had a
+	 * chance to initialize the device, and that leads to issues when
+	 * accessing the uninitialized suspend lock. Let's temporarily set the
+	 * suspend/resume hooks to NULL to skip the lock acquire/release step.
+	 *
+	 * FIXME: This is an ugly hack, so please don't copy this pattern to
+	 * other MTD implementations. The proper fix would be to implement a
+	 * generic BBT scan logic at the NAND level that's not using any of the
+	 * MTD helpers to access pages. We also might consider doing a two
+	 * step initialization at the MTD level (mtd_device_init() +
+	 * mtd_device_register()) so some of the fields are initialized
+	 * early.
+	 */
+	mtd->_suspend = NULL;
+	mtd->_resume = NULL;
+
 	/* Is a flash based bad block table requested? */
 	if (this->bbt_options & NAND_BBT_USE_FLASH) {
 		/* Use the default pattern descriptors */
@@ -1422,7 +1442,13 @@ int nand_create_bbt(struct nand_chip *this)
 			return ret;
 	}
 
-	return nand_scan_bbt(this, this->badblock_pattern);
+	ret = nand_scan_bbt(this, this->badblock_pattern);
+
+	/* Restore the suspend/resume hooks. */
+	mtd->_suspend = suspend;
+	mtd->_resume = resume;
+
+	return ret;
 }
 EXPORT_SYMBOL(nand_create_bbt);
 
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 22:55:49 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 26 Oct 2021 07:55:49 +0200
Subject: [PATCH v4 2/4] mtd: mtdconcat: don't use mtd_{suspend,resume}()
In-Reply-To: <20211026055551.3053598-1-sean@geanix.com>
References: <20211026055551.3053598-1-sean@geanix.com>
Message-ID: <20211026055551.3053598-3-sean@geanix.com>

From: Boris Brezillon <boris.brezillon at collabora.com>

The MTD suspend logic will soon be adjusted to automatically wait for
device wake-up before issuing IOs. In order to do that a new read-write
lock will be added and taken in write-mode in the
mtd_{suspend,resume}() path. Since mtdconcat.c itself is an MTD device,
calling mtd_suspend/resume() on subdevices from the mtdconcat
->_{suspend,resume}() hook will lead to a nested lock, which lockdep
will complain about if we don't add a proper annotation. Let's keep
things simple and replace those mtd_{suspend,resume}(subdev) calls by
subdev->_{suspend,resume}() ones to avoid this situation.

Tested-by: Sean Nyekjaer <sean at geanix.com>
Signed-off-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdconcat.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index f685a581df48..f4a4274489b4 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -566,9 +566,15 @@ static int concat_suspend(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		if ((rc = mtd_suspend(subdev)) < 0)
+		/*
+		 * Call the MTD hook directly to avoid a nested lock
+		 * on ->suspend_lock.
+		 */
+		rc = subdev->_suspend ? subdev->_suspend(subdev) : 0;
+		if (rc < 0)
 			return rc;
 	}
+
 	return rc;
 }
 
@@ -579,7 +585,12 @@ static void concat_resume(struct mtd_info *mtd)
 
 	for (i = 0; i < concat->num_subdev; i++) {
 		struct mtd_info *subdev = concat->subdev[i];
-		mtd_resume(subdev);
+		/*
+		 * Call the MTD hook directly to avoid a nested lock
+		 * on ->resume_lock.
+		 */
+		if (subdev->_resume)
+			subdev->_resume(subdev);
 	}
 }
 
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 22:55:47 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 26 Oct 2021 07:55:47 +0200
Subject: [PATCH v4 0/4] mtd: core: protect access to mtd devices while in
 suspend
Message-ID: <20211026055551.3053598-1-sean@geanix.com>

Follow-up on discussion in:
https://lkml.org/lkml/2021/10/4/41
https://lkml.org/lkml/2021/10/11/435

Changes since v3:
 - edited commit msg and author for mtdconcat patch

Changes since v2:
 - added signoff's to patch from Boris
 - removed accidential line break
 - kept tests consistent: master->master.suspended == 0 -> !master->master.suspended
 - added comments to mtdconcat patch
 - moved mtdconcat before ('mtd: core: protect access to MTD devices while in suspend')

Changes since v1:
 - removed __mtd_suspend/__mtd_resume functions as they are not used by
   mtdconcat anymore.
 - only master mtd_info is used for mtd_{start,end}_access(). Warn if we
   got mtd's.
 - added Boris patch for using uninitialized _suspend/_resume hooks when
   bbt scanning
 - mtdconcat uses device _suspend/_resume hooks
 - I don't really like the macro proposal from Boris
   mtd_no_suspend_void_call()/mtd_no_suspend_ret_call() I think they
   make the code complex to read and the macro's doesn't fit every
   where anyway...

Changes since from rfc v1/v2:
 - added access protection for all device access hooks in mtd_info.
 - added Suggested-by to [1/3] patch.
 - removed refereces to commit ef347c0cfd61 ("mtd: rawnand: gpmi: Implement exec_op")
   from commit msg as commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") is 
   to be blamed.
 - tested on a kernel with LOCKDEP enabled.

Boris Brezillon (2):
  mtd: rawnand: nand_bbt: hide suspend/resume hooks while scanning bbt
  mtd: mtdconcat: don't use mtd_{suspend,resume}()

Sean Nyekjaer (2):
  mtd: core: protect access to MTD devices while in suspend
  mtd: rawnand: remove suspended check

 drivers/mtd/mtdconcat.c          |  15 +++-
 drivers/mtd/mtdcore.c            | 124 +++++++++++++++++++++++++++----
 drivers/mtd/nand/raw/nand_base.c |  52 ++++---------
 drivers/mtd/nand/raw/nand_bbt.c  |  28 ++++++-
 include/linux/mtd/mtd.h          |  81 ++++++++++++++++----
 include/linux/mtd/rawnand.h      |   5 +-
 6 files changed, 230 insertions(+), 75 deletions(-)

-- 
2.33.0



From sean at geanix.com  Mon Oct 25 22:55:51 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 26 Oct 2021 07:55:51 +0200
Subject: [PATCH v4 4/4] mtd: rawnand: remove suspended check
In-Reply-To: <20211026055551.3053598-1-sean@geanix.com>
References: <20211026055551.3053598-1-sean@geanix.com>
Message-ID: <20211026055551.3053598-5-sean@geanix.com>

Access is protected in upper MTD layer when MTD devices are suspended.

Commit ("mtd: core: protect access to MTD devices while in suspend")
introduces access protection, so it's safe to remove suspended checks.

Reviewed-by: Miquel Raynal <miquel.raynal at bootlin.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/nand/raw/nand_base.c | 52 ++++++++------------------------
 include/linux/mtd/rawnand.h      |  5 +--
 2 files changed, 14 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index 3d6c6e880520..aa2874ae3c4a 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -332,19 +332,11 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs)
  * @chip: NAND chip structure
  *
  * Lock the device and its controller for exclusive access
- *
- * Return: -EBUSY if the chip has been suspended, 0 otherwise
  */
-static int nand_get_device(struct nand_chip *chip)
+static void nand_get_device(struct nand_chip *chip)
 {
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		mutex_unlock(&chip->lock);
-		return -EBUSY;
-	}
 	mutex_lock(&chip->controller->lock);
-
-	return 0;
 }
 
 /**
@@ -573,10 +565,7 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
 		nand_erase_nand(chip, &einfo, 0);
 
 		/* Write bad block marker to OOB */
-		ret = nand_get_device(chip);
-		if (ret)
-			return ret;
-
+		nand_get_device(chip);
 		ret = nand_markbad_bbm(chip, ofs);
 		nand_release_device(chip);
 	}
@@ -3756,9 +3745,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 	    ops->mode != MTD_OPS_RAW)
 		return -ENOTSUPP;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	if (!ops->datbuf)
 		ret = nand_do_read_oob(chip, from, ops);
@@ -4345,13 +4332,11 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 			  struct mtd_oob_ops *ops)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
-	int ret;
+	int ret = 0;
 
 	ops->retlen = 0;
 
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	switch (ops->mode) {
 	case MTD_OPS_PLACE_OOB:
@@ -4410,10 +4395,8 @@ int nand_erase_nand(struct nand_chip *chip, struct erase_info *instr,
 	if (nand_region_is_secured(chip, instr->addr, instr->len))
 		return -EIO;
 
-	/* Grab the lock and see if the device is available */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	/* Grab the lock */
+	nand_get_device(chip);
 
 	/* Shift to get first page */
 	page = (int)(instr->addr >> chip->page_shift);
@@ -4499,8 +4482,8 @@ static void nand_sync(struct mtd_info *mtd)
 
 	pr_debug("%s: called\n", __func__);
 
-	/* Grab the lock and see if the device is available */
-	WARN_ON(nand_get_device(chip));
+	/* Grab the lock */
+	nand_get_device(chip);
 	/* Release it and go back */
 	nand_release_device(chip);
 }
@@ -4517,9 +4500,7 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
 	int ret;
 
 	/* Select the NAND device */
-	ret = nand_get_device(chip);
-	if (ret)
-		return ret;
+	nand_get_device(chip);
 
 	nand_select_target(chip, chipnr);
 
@@ -4565,8 +4546,6 @@ static int nand_suspend(struct mtd_info *mtd)
 	mutex_lock(&chip->lock);
 	if (chip->ops.suspend)
 		ret = chip->ops.suspend(chip);
-	if (!ret)
-		chip->suspended = 1;
 	mutex_unlock(&chip->lock);
 
 	return ret;
@@ -4580,15 +4559,10 @@ static void nand_resume(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 
+
 	mutex_lock(&chip->lock);
-	if (chip->suspended) {
-		if (chip->ops.resume)
-			chip->ops.resume(chip);
-		chip->suspended = 0;
-	} else {
-		pr_err("%s called for a chip which is not in suspended state\n",
-			__func__);
-	}
+	if (chip->ops.resume)
+		chip->ops.resume(chip);
 	mutex_unlock(&chip->lock);
 }
 
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
index b2f9dd3cbd69..1198a6548912 100644
--- a/include/linux/mtd/rawnand.h
+++ b/include/linux/mtd/rawnand.h
@@ -1237,9 +1237,7 @@ struct nand_secure_region {
  * @pagecache.page: Page number currently in the cache. -1 means no page is
  *                  currently cached
  * @buf_align: Minimum buffer alignment required by a platform
- * @lock: Lock protecting the suspended field. Also used to serialize accesses
- *        to the NAND device
- * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @lock: Lock to serialize accesses to the NAND device
  * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
  *          should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
  *          NAND Controller drivers should not modify this value, but they're
@@ -1293,7 +1291,6 @@ struct nand_chip {
 
 	/* Internals */
 	struct mutex lock;
-	unsigned int suspended : 1;
 	int cur_cs;
 	int read_retries;
 	struct nand_secure_region *secure_regions;
-- 
2.33.0



From sean at geanix.com  Mon Oct 25 22:55:50 2021
From: sean at geanix.com (Sean Nyekjaer)
Date: Tue, 26 Oct 2021 07:55:50 +0200
Subject: [PATCH v4 3/4] mtd: core: protect access to MTD devices while in
 suspend
In-Reply-To: <20211026055551.3053598-1-sean@geanix.com>
References: <20211026055551.3053598-1-sean@geanix.com>
Message-ID: <20211026055551.3053598-4-sean@geanix.com>

Prevent MTD access while in a suspended state. Also
prevent suspending a device which is still currently in use.

Commit 013e6292aaf5 ("mtd: rawnand: Simplify the locking") allows the
rawnand layer to return errors rather than waiting in a blocking wait.

Tested on a iMX6ULL.

Fixes: 013e6292aaf5 ("mtd: rawnand: Simplify the locking")
Suggested-by: Boris Brezillon <boris.brezillon at collabora.com>
Signed-off-by: Sean Nyekjaer <sean at geanix.com>
---
 drivers/mtd/mtdcore.c   | 124 +++++++++++++++++++++++++++++++++++-----
 include/linux/mtd/mtd.h |  81 +++++++++++++++++++++-----
 2 files changed, 176 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 153229198947..8e6b7e858ada 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -777,6 +777,8 @@ static void mtd_set_dev_defaults(struct mtd_info *mtd)
 	INIT_LIST_HEAD(&mtd->partitions);
 	mutex_init(&mtd->master.partitions_lock);
 	mutex_init(&mtd->master.chrdev_lock);
+	init_waitqueue_head(&mtd->master.resume_wq);
+	init_rwsem(&mtd->master.suspend_lock);
 }
 
 static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
@@ -1267,7 +1269,9 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 	adjinstr.addr += mst_ofs;
 
+	mtd_start_access(master);
 	ret = master->_erase(master, &adjinstr);
+	mtd_end_access(master);
 
 	if (adjinstr.fail_addr != MTD_FAIL_ADDR_UNKNOWN) {
 		instr->fail_addr = adjinstr.fail_addr - mst_ofs;
@@ -1289,6 +1293,7 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	      void **virt, resource_size_t *phys)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	*virt = NULL;
@@ -1301,8 +1306,12 @@ int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	if (!len)
 		return 0;
 
+	mtd_start_access(master);
 	from = mtd_get_master_ofs(mtd, from);
-	return master->_point(master, from, len, retlen, virt, phys);
+	ret = master->_point(master, from, len, retlen, virt, phys);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_point);
 
@@ -1310,6 +1319,7 @@ EXPORT_SYMBOL_GPL(mtd_point);
 int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unpoint)
 		return -EOPNOTSUPP;
@@ -1317,7 +1327,12 @@ int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
 		return -EINVAL;
 	if (!len)
 		return 0;
-	return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+
+	mtd_start_access(master);
+	ret =  master->_unpoint(master, mtd_get_master_ofs(mtd, from), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unpoint);
 
@@ -1372,6 +1387,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_read_oob_std handles mtd access protection */
 	ret = mtd_read_oob(mtd, from, &ops);
 	*retlen = ops.retlen;
 
@@ -1388,6 +1404,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	};
 	int ret;
 
+	/* mtd_write_oob_std handles mtd access protection */
 	ret = mtd_write_oob(mtd, to, &ops);
 	*retlen = ops.retlen;
 
@@ -1406,6 +1423,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 		    const u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_panic_write)
@@ -1419,8 +1437,12 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
 	if (!master->oops_panic_write)
 		master->oops_panic_write = true;
 
-	return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
-				    retlen, buf);
+	mtd_start_access(master);
+	ret = master->_panic_write(master, mtd_get_master_ofs(mtd, to), len,
+				   retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_panic_write);
 
@@ -1464,11 +1486,13 @@ static int mtd_read_oob_std(struct mtd_info *mtd, loff_t from,
 	int ret;
 
 	from = mtd_get_master_ofs(mtd, from);
+	mtd_start_access(master);
 	if (master->_read_oob)
 		ret = master->_read_oob(master, from, ops);
 	else
 		ret = master->_read(master, from, ops->len, &ops->retlen,
 				    ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1480,11 +1504,13 @@ static int mtd_write_oob_std(struct mtd_info *mtd, loff_t to,
 	int ret;
 
 	to = mtd_get_master_ofs(mtd, to);
+	mtd_start_access(master);
 	if (master->_write_oob)
 		ret = master->_write_oob(master, to, ops);
 	else
 		ret = master->_write(master, to, ops->len, &ops->retlen,
 				     ops->datbuf);
+	mtd_end_access(master);
 
 	return ret;
 }
@@ -1992,12 +2018,18 @@ int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_fact_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_fact_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_get_fact_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
 
@@ -2005,13 +2037,19 @@ int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_fact_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_fact_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_fact_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
 
@@ -2019,12 +2057,18 @@ int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
 			   struct otp_info *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_get_user_prot_info)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_get_user_prot_info(master, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret =  master->_get_user_prot_info(master, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
 
@@ -2032,13 +2076,19 @@ int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
 			   size_t *retlen, u_char *buf)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	*retlen = 0;
 	if (!master->_read_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_read_user_prot_reg(master, from, len, retlen, buf);
+
+	mtd_start_access(master);
+	ret = master->_read_user_prot_reg(master, from, len, retlen, buf);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
 
@@ -2053,7 +2103,11 @@ int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
+
+	mtd_start_access(master);
 	ret = master->_write_user_prot_reg(master, to, len, retlen, buf);
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
@@ -2068,24 +2122,36 @@ EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_lock_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_lock_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
 
 int mtd_erase_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_erase_user_prot_reg)
 		return -EOPNOTSUPP;
 	if (!len)
 		return 0;
-	return master->_erase_user_prot_reg(master, from, len);
+
+	mtd_start_access(master);
+	ret = master->_erase_user_prot_reg(master, from, len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 
@@ -2093,6 +2159,7 @@ EXPORT_SYMBOL_GPL(mtd_erase_user_prot_reg);
 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_lock)
 		return -EOPNOTSUPP;
@@ -2106,13 +2173,18 @@ int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_lock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_lock);
 
 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_unlock)
 		return -EOPNOTSUPP;
@@ -2126,13 +2198,18 @@ int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_unlock);
 
 int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_is_locked)
 		return -EOPNOTSUPP;
@@ -2146,13 +2223,18 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 		len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize;
 	}
 
-	return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_start_access(master);
+	ret = master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len);
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_is_locked);
 
 int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2162,13 +2244,18 @@ int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isreserved);
 
 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (ofs < 0 || ofs >= mtd->size)
 		return -EINVAL;
@@ -2178,7 +2265,11 @@ int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
-	return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_start_access(master);
+	ret = master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_block_isbad);
 
@@ -2197,7 +2288,10 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
 	if (mtd->flags & MTD_SLC_ON_MLC_EMULATION)
 		ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize;
 
+	mtd_start_access(master);
 	ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs));
+	mtd_end_access(master);
+
 	if (ret)
 		return ret;
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..b074106e2d8e 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -231,6 +231,8 @@ struct mtd_master {
 	struct mutex partitions_lock;
 	struct mutex chrdev_lock;
 	unsigned int suspended : 1;
+	wait_queue_head_t resume_wq;
+	struct rw_semaphore suspend_lock;
 };
 
 struct mtd_info {
@@ -476,10 +478,47 @@ static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
 	return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
 }
 
+static inline void mtd_start_access(struct mtd_info *master)
+{
+	WARN_ON_ONCE(master != mtd_get_master(master));
+
+	/*
+	 * Don't take the suspend_lock on devices that don't
+	 * implement the suspend hook. Otherwise, lockdep will
+	 * complain about nested locks when trying to suspend MTD
+	 * partitions or MTD devices created by gluebi which are
+	 * backed by real devices.
+	 */
+	if (!master->_suspend)
+		return;
+
+	/*
+	 * Wait until the device is resumed. Should we have a
+	 * non-blocking mode here?
+	 */
+	while (1) {
+		down_read(&master->master.suspend_lock);
+		if (!master->master.suspended)
+			return;
+
+		up_read(&master->master.suspend_lock);
+		wait_event(master->master.resume_wq, !master->master.suspended);
+	}
+}
+
+static inline void mtd_end_access(struct mtd_info *master)
+{
+	if (!master->_suspend)
+		return;
+
+	up_read(&master->master.suspend_lock);
+}
+
 static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 				     loff_t ofs, size_t len)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
+	int ret;
 
 	if (!master->_max_bad_blocks)
 		return -ENOTSUPP;
@@ -487,8 +526,12 @@ static inline int mtd_max_bad_blocks(struct mtd_info *mtd,
 	if (mtd->size < (len + ofs) || ofs < 0)
 		return -EINVAL;
 
-	return master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
-				       len);
+	mtd_start_access(master);
+	ret = master->_max_bad_blocks(master, mtd_get_master_ofs(mtd, ofs),
+				      len);
+	mtd_end_access(master);
+
+	return ret;
 }
 
 int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
@@ -546,30 +589,40 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
 static inline int mtd_suspend(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
-	int ret;
-
-	if (master->master.suspended)
-		return 0;
+	int ret = 0;
 
-	ret = master->_suspend ? master->_suspend(master) : 0;
-	if (ret)
+	if (!master->_suspend)
 		return ret;
 
-	master->master.suspended = 1;
-	return 0;
+	down_write(&master->master.suspend_lock);
+	if (!master->master.suspended) {
+		ret = master->_suspend(master);
+		if (!ret)
+			master->master.suspended = 1;
+	}
+	up_write(&master->master.suspend_lock);
+
+	return ret;
 }
 
 static inline void mtd_resume(struct mtd_info *mtd)
 {
 	struct mtd_info *master = mtd_get_master(mtd);
 
-	if (!master->master.suspended)
+	if (!master->_suspend)
 		return;
 
-	if (master->_resume)
-		master->_resume(master);
+	down_write(&master->master.suspend_lock);
+	if (master->master.suspended) {
+		if (master->_resume)
+			master->_resume(master);
+
+		master->master.suspended = 0;
 
-	master->master.suspended = 0;
+		/* The MTD dev has been resumed, wake up all waiters. */
+		wake_up_all(&master->master.resume_wq);
+	}
+	up_write(&master->master.suspend_lock);
 }
 
 static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
-- 
2.33.0



From miquel.raynal at bootlin.com  Tue Oct 26 00:31:41 2021
From: miquel.raynal at bootlin.com (Miquel Raynal)
Date: Tue, 26 Oct 2021 09:31:41 +0200
Subject: [PATCH] drivers: mtd: Fixed breaking list in __mtd_del_partition.
In-Reply-To: <20211025205724.3306739-1-andreas.oetken@siemens-energy.com>
References: <20211025205724.3306739-1-andreas.oetken@siemens-energy.com>
Message-ID: <20211026093141.64be4e38@xps13>

Hi Andreas,

ennoerlangen at gmail.com wrote on Mon, 25 Oct 2021 22:57:24 +0200:

> Not the child partition should be removed from the partition list
> but the partition itself. Otherwise the partition list gets broken
> and any subsequent remove operations leads to a kernel panic.
> 

Can you please Add a couple of Fixes: + Cc: stable tags?

> Signed-off-by: Andreas Oetken <andreas.oetken at siemens-energy.com>
> ---
>  drivers/mtd/mtdpart.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index 95d47422bbf20..5725818fa199f 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -313,7 +313,7 @@ static int __mtd_del_partition(struct mtd_info *mtd)
>  	if (err)
>  		return err;
>  
> -	list_del(&child->part.node);
> +	list_del(&mtd->part.node);
>  	free_partition(mtd);
>  
>  	return 0;


Thanks,
Miqu?l


From ennoerlangen at gmail.com  Tue Oct 26 01:46:07 2021
From: ennoerlangen at gmail.com (Andreas Oetken)
Date: Tue, 26 Oct 2021 10:46:07 +0200
Subject: [PATCH] drivers: mtd: Fixed breaking list in __mtd_del_partition.
Message-ID: <20211026084607.3473482-1-andreas.oetken@siemens-energy.com>

Not the child partition should be removed from the partition list
but the partition itself. Otherwise the partition list gets broken
and any subsequent remove operations leads to a kernel panic.

Signed-off-by: Andreas Oetken <andreas.oetken at siemens-energy.com>
---
 drivers/mtd/mtdpart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 95d47422bbf20..5725818fa199f 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -313,7 +313,7 @@ static int __mtd_del_partition(struct mtd_info *mtd)
 	if (err)
 		return err;
 
-	list_del(&child->part.node);
+	list_del(&mtd->part.node);
 	free_partition(mtd);
 
 	return 0;
-- 
2.30.2



From ennoerlangen at gmail.com  Tue Oct 26 01:49:19 2021
From: ennoerlangen at gmail.com (Andreas Oetken)
Date: Tue, 26 Oct 2021 10:49:19 +0200
Subject: [PATCH v3] drivers: mtd: Fixed breaking list in __mtd_del_partition.
Message-ID: <20211026084919.3476294-1-andreas.oetken@siemens-energy.com>

Not the child partition should be removed from the partition list
but the partition itself. Otherwise the partition list gets broken
and any subsequent remove operations leads to a kernel panic.

Fixes: 46b5889cc2c5 ("mtd: implement proper partition handling")
Signed-off-by: Andreas Oetken <andreas.oetken at siemens-energy.com>
Cc: stable at vger.kernel.org
---
 drivers/mtd/mtdpart.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 95d47422bbf20..5725818fa199f 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -313,7 +313,7 @@ static int __mtd_del_partition(struct mtd_info *mtd)
 	if (err)
 		return err;
 
-	list_del(&child->part.node);
+	list_del(&mtd->part.node);
 	free_partition(mtd);
 
 	return 0;
-- 
2.30.2



From krzysztof.kozlowski at canonical.com  Tue Oct 26 07:46:58 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Tue, 26 Oct 2021 16:46:58 +0200
Subject: [PATCH v2 7/7] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <20211025205631.21151-8-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20211025205631.21151-8-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <3739744b-0a10-6d6b-8d1c-9c82b6afe0b3@canonical.com>

On 25/10/2021 22:56, Lad Prabhakar wrote:
> SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
> the RPC-IF interface found on R-Car Gen3 SoC's.
> 
> This patch adds a new compatible string for the RZ/G2L family so
> that the timing values on RZ/G2L can be adjusted.
> 
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> ---
> v1->v2:
>  * Updated macros as suggested by Wolfram
> ---
>  drivers/memory/renesas-rpc-if.c | 72 ++++++++++++++++++++++++++++-----
>  drivers/mtd/hyperbus/rpc-if.c   |  4 +-
>  drivers/spi/spi-rpc-if.c        |  4 +-
>  include/memory/renesas-rpc-if.h |  8 +++-
>  4 files changed, 75 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
> index 0c56decc91f2..8c51145c0f5c 100644
> --- a/drivers/memory/renesas-rpc-if.c
> +++ b/drivers/memory/renesas-rpc-if.c
> @@ -12,6 +12,7 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/of.h>
> +#include <linux/of_device.h>
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
>  
> @@ -27,8 +28,8 @@
>  #define RPCIF_CMNCR_MOIIO_HIZ	(RPCIF_CMNCR_MOIIO0(3) | \
>  				 RPCIF_CMNCR_MOIIO1(3) | \
>  				 RPCIF_CMNCR_MOIIO2(3) | RPCIF_CMNCR_MOIIO3(3))
> -#define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* undocumented */
> -#define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* undocumented */
> +#define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* documented for RZ/G2L */
> +#define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* documented for RZ/G2L */
>  #define RPCIF_CMNCR_IO0FV(val)	(((val) & 0x3) << 8)
>  #define RPCIF_CMNCR_IOFV_HIZ	(RPCIF_CMNCR_IO0FV(3) | RPCIF_CMNCR_IO2FV(3) | \
>  				 RPCIF_CMNCR_IO3FV(3))
> @@ -126,6 +127,9 @@
>  #define RPCIF_SMDRENR_OPDRE	BIT(4)
>  #define RPCIF_SMDRENR_SPIDRE	BIT(0)
>  
> +#define RPCIF_PHYADD		0x0070	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
> +#define RPCIF_PHYWR		0x0074	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
> +
>  #define RPCIF_PHYCNT		0x007C	/* R/W */
>  #define RPCIF_PHYCNT_CAL	BIT(31)
>  #define RPCIF_PHYCNT_OCTA(v)	(((v) & 0x3) << 22)
> @@ -133,10 +137,12 @@
>  #define RPCIF_PHYCNT_OCT	BIT(20)
>  #define RPCIF_PHYCNT_DDRCAL	BIT(19)
>  #define RPCIF_PHYCNT_HS		BIT(18)
> -#define RPCIF_PHYCNT_STRTIM(v)	(((v) & 0x7) << 15)
> +#define RPCIF_PHYCNT_CKSEL(v)	(((v) & 0x3) << 16) /* valid only for RZ/G2L */
> +#define RPCIF_PHYCNT_STRTIM(v)	(((v) & 0x7) << 15) /* valid for R-Car and RZ/G2{E,H,M,N} */
>  #define RPCIF_PHYCNT_WBUF2	BIT(4)
>  #define RPCIF_PHYCNT_WBUF	BIT(2)
>  #define RPCIF_PHYCNT_PHYMEM(v)	(((v) & 0x3) << 0)
> +#define RPCIF_PHYCNT_PHYMEM_MASK GENMASK(1, 0)
>  
>  #define RPCIF_PHYOFFSET1	0x0080	/* R/W */
>  #define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)
> @@ -244,18 +250,46 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
>  		return PTR_ERR(rpc->dirmap);
>  	rpc->size = resource_size(res);
>  
> +	rpc->type = (enum rpcif_type)of_device_get_match_data(dev);
>  	rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
>  
>  	return PTR_ERR_OR_ZERO(rpc->rstc);
>  }
>  EXPORT_SYMBOL(rpcif_sw_init);
>  
> -void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> +static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc)
> +{
> +	u32 data;
> +
> +	regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000);
> +	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000);
> +	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
> +	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000022);
> +	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
> +	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000024);
> +
> +	regmap_read(rpc->regmap, RPCIF_PHYCNT, &data);
> +	regmap_write(rpc->regmap, RPCIF_PHYCNT, data | RPCIF_PHYCNT_CKSEL(3));
> +	regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00000030);
> +	regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032);
> +}
> +
> +int rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
>  {
>  	u32 dummy;
>  
>  	pm_runtime_get_sync(rpc->dev);
>  
> +	if (rpc->type == RPCIF_RZ_G2L) {
> +		int ret;
> +
> +		ret = reset_control_reset(rpc->rstc);
> +		if (ret)
> +			return ret;
> +		usleep_range(200, 300);
> +		rpcif_rzg2l_timing_adjust_sdr(rpc);
> +	}
> +
>  	/*
>  	 * NOTE: The 0x260 are undocumented bits, but they must be set.
>  	 *	 RPCIF_PHYCNT_STRTIM is strobe timing adjustment bits,
> @@ -264,8 +298,15 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
>  	 *	 On H3 ES1.x, the value should be 0, while on others,
>  	 *	 the value should be 7.
>  	 */
> -	regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> -		     RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> +	if (rpc->type == RPCIF_RCAR_GEN3) {
> +		regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> +			     RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> +	} else {
> +		regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> +		dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> +		dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> +		regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> +	}
>  
>  	/*
>  	 * NOTE: The 0x1511144 are undocumented bits, but they must be set
> @@ -282,9 +323,17 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
>  		regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
>  				   RPCIF_PHYINT_WPVAL, 0);
>  
> -	regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> -		     RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
> -		     RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> +	if (rpc->type == RPCIF_RCAR_GEN3)
> +		regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> +			     RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
> +			     RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> +	else
> +		regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> +			     RPCIF_CMNCR_MOIIO3(1) | RPCIF_CMNCR_MOIIO2(1) |
> +			     RPCIF_CMNCR_MOIIO1(1) | RPCIF_CMNCR_MOIIO0(1) |
> +			     RPCIF_CMNCR_IO3FV(2) | RPCIF_CMNCR_IO2FV(2) |
> +			     RPCIF_CMNCR_IO0FV(2) | RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> +
>  	/* Set RCF after BSZ update */
>  	regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF);
>  	/* Dummy read according to spec */
> @@ -295,6 +344,8 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
>  	pm_runtime_put(rpc->dev);
>  
>  	rpc->bus_size = hyperflash ? 2 : 1;
> +
> +	return 0;
>  }
>  EXPORT_SYMBOL(rpcif_hw_init);
>  
> @@ -657,7 +708,8 @@ static int rpcif_remove(struct platform_device *pdev)
>  }
>  
>  static const struct of_device_id rpcif_of_match[] = {
> -	{ .compatible = "renesas,rcar-gen3-rpc-if", },
> +	{ .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
> +	{ .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
>  	{},
>  };
>  MODULE_DEVICE_TABLE(of, rpcif_of_match);
> diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
> index 367b0d72bf62..40bca89268c3 100644
> --- a/drivers/mtd/hyperbus/rpc-if.c
> +++ b/drivers/mtd/hyperbus/rpc-if.c
> @@ -132,7 +132,9 @@ static int rpcif_hb_probe(struct platform_device *pdev)
>  
>  	rpcif_enable_rpm(&hyperbus->rpc);
>  
> -	rpcif_hw_init(&hyperbus->rpc, true);
> +	error = rpcif_hw_init(&hyperbus->rpc, true);
> +	if (error)
> +		return error;
>  

Not related to this patch, but the concept used here looks fragile. The
child driver calls also rpcif_sw_init() and ignores the error code. What
happens in case of rpcif_sw_init() failure or child probe deferral?
Since the SW and HW init is called in context of child device, the
parent won't do anything. Then, second bind of child device (manual or
because of deferral) will fail on devm_reset_control_get_exclusive()
with -EBUSY.

Initializing parent's resources should be rather done from parent's
context (so renesas-rpc-if.c) to handle properly deferred probe and
other failures. Doing it from a child, breaks encapsulation and
separation of devices.

Is there any reason why memory/renesas-rpc-if.c cannot do SW and HW init?

Best regards,
Krzysztof


From krzysztof.kozlowski at canonical.com  Tue Oct 26 07:48:13 2021
From: krzysztof.kozlowski at canonical.com (Krzysztof Kozlowski)
Date: Tue, 26 Oct 2021 16:48:13 +0200
Subject: [PATCH v2 0/7] Add SPI Multi I/O Bus Controller support for RZ/G2L
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <02123905-675a-0fda-086e-c2401c202fce@canonical.com>

On 25/10/2021 22:56, Lad Prabhakar wrote:
> Hi All,
> 
> This patch series adds a couple of fixes for rpc-if driver and
> adds support for RZ/G2L SoC, where the SPI Multi I/O Bus Controller
> is identical to the RPC-IF block found on R-Car Gen3 SoC's.
> 
> Cheers,
> Prabhakar
> 
> Changes for v2:
> * Rebased the patches on linux-next
> * Split patch 5 from v1
> * Included RB tags
> * Fixed review comments pointed by Wolfram
> 
> v1:
> https://patchwork.kernel.org/project/linux-renesas-soc/cover/
> 20210928140721.8805-1-prabhakar.mahadev-lad.rj at bp.renesas.com/
> 

Patches look good but you sent them too late for this cycle. I'll take
the memory controller parts after the merge window.


Best regards,
Krzysztof


From twoerner at gmail.com  Tue Oct 26 08:03:50 2021
From: twoerner at gmail.com (Trevor Woerner)
Date: Tue, 26 Oct 2021 11:03:50 -0400
Subject: [PATCH 0/3] mtdblock: Advertise about UBI and UBI block
In-Reply-To: <20210801234509.18774-1-ezequiel@collabora.com>
References: <20210801234509.18774-1-ezequiel@collabora.com>
Message-ID: <20211026150350.GA5136@localhost>

On Sun 2021-08-01 @ 08:45:02 PM, Ezequiel Garcia wrote:
> Hi Richard, and everyone else:
> 
> Browsing the internet for "JFFS2 mtd" results in tutorials, articles
> and github.gists0 that point to mtdblock.
> 
> In fact, even the MTD wiki mentions that JFFS2
> needs mtdblock to mount a rootfs:
> 
>   http://www.linux-mtd.infradead.org/faq/jffs2.html
> 
> Moreover, I suspect there may be lots of users
> that still believe mtdblock is somehow needed to
> mount SquashFS.
> 
> I've taken a verbose route and added a pr_warn
> warning if the devices are NAND. I don't think using
> NAND without UBI is too wise, and given the amount
> of outdated tutorials I believe some advertising
> will help.

Not all NAND partitions on a device will contain linux root filesystems. For a
linux root filesystem perhaps using UBI/UBIFS is preferred, yet these messages
print out for each and every NAND partition:

	[    0.900827] Creating 8 MTD partitions on "nxp_lpc3220_slc":
	[    0.906431] 0x000000000000-0x000000020000 : "bootrom"
	[    0.913523] mtdblock: MTD device 'bootrom' is NAND, please consider using UBI block devices instead.
	[    0.933334] 0x000000020000-0x000000080000 : "uboot"
	[    0.940439] mtdblock: MTD device 'uboot' is NAND, please consider using UBI block devices instead.
	[    0.963322] 0x000000080000-0x000000440000 : "fbkernel"
	[    0.970655] mtdblock: MTD device 'fbkernel' is NAND, please consider using UBI block devices instead.
	[    0.993361] 0x000000440000-0x000000920000 : "fbrootfs"
	[    1.000725] mtdblock: MTD device 'fbrootfs' is NAND, please consider using UBI block devices instead.
	[    1.023315] 0x000000920000-0x000000ce0000 : "c_kernel"
	[    1.030722] mtdblock: MTD device 'c_kernel' is NAND, please consider using UBI block devices instead.
	[    1.053444] 0x000000ce0000-0x000000d00000 : "c__atags"
	[    1.060742] mtdblock: MTD device 'c__atags' is NAND, please consider using UBI block devices instead.
	[    1.083349] 0x000000d00000-0x000001000000 : "c_rootfs"
	[    1.090702] mtdblock: MTD device 'c_rootfs' is NAND, please consider using UBI block devices instead.
	[    1.113335] 0x000001000000-0x000020000000 : "mender"
	[    1.131627] mtdblock: MTD device 'mender' is NAND, please consider using UBI block devices instead.

NAND tends to be something found on older devices, the firmware/bootloaders
of older devices couldn't possibly understand UBI/UBIFS so many of these
partitions need be "raw" partitions, or use something that predates UBI.

Ironically my "mender" partition contains a UBI (with multiple UBIFSes inside)
yet I got the same "please use UBI" message as all the others (lol)

I'm specifying my partitions in DT with:

partitions {
        compatible = "fixed-partitions";
        #address-cells = <1>;
        #size-cells = <1>;

        mtd0 at 0       { label = "bootrom";   reg = <0x00000000 0x00020000>; };
        mtd1 at 20000   { label = "uboot";     reg = <0x00020000 0x00060000>; };
        mtd2 at 80000   { label = "fbkernel";  reg = <0x00080000 0x003c0000>; };
        mtd3 at 440000  { label = "fbrootfs";  reg = <0x00440000 0x004e0000>; };
        mtd4 at 920000  { label = "c_kernel";  reg = <0x00920000 0x003c0000>; };
        mtd5 at ce0000  { label = "c__atags";  reg = <0x00ce0000 0x00020000>; };
        mtd6 at d00000  { label = "c_rootfs";  reg = <0x00d00000 0x00300000>; };
        mtd7 at 1000000 { label = "mender";    reg = <0x01000000 0x1f000000>; };
};

which is why, I assume, I'm getting these messages. Is there a UBI-friendly
way to define them to avoid these messages?

Best regards,
	Trevor


From kuntemrjoshua at gmail.com  Tue Oct 26 11:19:38 2021
From: kuntemrjoshua at gmail.com (Douglas Momoh)
Date: Tue, 26 Oct 2021 19:19:38 +0100
Subject: Good day
Message-ID: <CAFhr1xChZCyU9LNqsVXO=3bymsdoibv2UyTyVYmxt54ASDZYNw@mail.gmail.com>

-- 
A mail was sent to you sometime last week with the expectation of
having a retune mail from you but to my surprise you never bothered to replied.
Kindly reply for further explanations.

Respectfully yours,
Mr Douglas Momoh.


From richard at nod.at  Tue Oct 26 12:01:32 2021
From: richard at nod.at (Richard Weinberger)
Date: Tue, 26 Oct 2021 21:01:32 +0200 (CEST)
Subject: [PATCH 0/3] mtdblock: Advertise about UBI and UBI block
In-Reply-To: <20211026150350.GA5136@localhost>
References: <20210801234509.18774-1-ezequiel@collabora.com>
 <20211026150350.GA5136@localhost>
Message-ID: <876982414.38679.1635274892099.JavaMail.zimbra@nod.at>

Trevor,

----- Urspr?ngliche Mail -----
> Von: "Trevor Woerner" <twoerner at gmail.com>
> An: "Ezequiel Garcia" <ezequiel at collabora.com>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel" <linux-kernel at vger.kernel.org>, "richard"
> <richard at nod.at>, "Miquel Raynal" <miquel.raynal at bootlin.com>, "Vignesh Raghavendra" <vigneshr at ti.com>
> Gesendet: Dienstag, 26. Oktober 2021 17:03:50
> Betreff: Re: [PATCH 0/3] mtdblock: Advertise about UBI and UBI block

> On Sun 2021-08-01 @ 08:45:02 PM, Ezequiel Garcia wrote:
>> Hi Richard, and everyone else:
>> 
>> Browsing the internet for "JFFS2 mtd" results in tutorials, articles
>> and github.gists0 that point to mtdblock.
>> 
>> In fact, even the MTD wiki mentions that JFFS2
>> needs mtdblock to mount a rootfs:
>> 
>>   http://www.linux-mtd.infradead.org/faq/jffs2.html
>> 
>> Moreover, I suspect there may be lots of users
>> that still believe mtdblock is somehow needed to
>> mount SquashFS.
>> 
>> I've taken a verbose route and added a pr_warn
>> warning if the devices are NAND. I don't think using
>> NAND without UBI is too wise, and given the amount
>> of outdated tutorials I believe some advertising
>> will help.
> 
> Not all NAND partitions on a device will contain linux root filesystems. For a
> linux root filesystem perhaps using UBI/UBIFS is preferred, yet these messages
> print out for each and every NAND partition:
> 
>	[    0.900827] Creating 8 MTD partitions on "nxp_lpc3220_slc":
>	[    0.906431] 0x000000000000-0x000000020000 : "bootrom"
>	[    0.913523] mtdblock: MTD device 'bootrom' is NAND, please consider using UBI
>	block devices instead.
>	[    0.933334] 0x000000020000-0x000000080000 : "uboot"
>	[    0.940439] mtdblock: MTD device 'uboot' is NAND, please consider using UBI
>	block devices instead.
>	[    0.963322] 0x000000080000-0x000000440000 : "fbkernel"
>	[    0.970655] mtdblock: MTD device 'fbkernel' is NAND, please consider using
>	UBI block devices instead.
>	[    0.993361] 0x000000440000-0x000000920000 : "fbrootfs"
>	[    1.000725] mtdblock: MTD device 'fbrootfs' is NAND, please consider using
>	UBI block devices instead.
>	[    1.023315] 0x000000920000-0x000000ce0000 : "c_kernel"
>	[    1.030722] mtdblock: MTD device 'c_kernel' is NAND, please consider using
>	UBI block devices instead.
>	[    1.053444] 0x000000ce0000-0x000000d00000 : "c__atags"
>	[    1.060742] mtdblock: MTD device 'c__atags' is NAND, please consider using
>	UBI block devices instead.
>	[    1.083349] 0x000000d00000-0x000001000000 : "c_rootfs"
>	[    1.090702] mtdblock: MTD device 'c_rootfs' is NAND, please consider using
>	UBI block devices instead.
>	[    1.113335] 0x000001000000-0x000020000000 : "mender"
>	[    1.131627] mtdblock: MTD device 'mender' is NAND, please consider using UBI
>	block devices instead.
> 
> NAND tends to be something found on older devices, the firmware/bootloaders
> of older devices couldn't possibly understand UBI/UBIFS so many of these
> partitions need be "raw" partitions, or use something that predates UBI.
> 
> Ironically my "mender" partition contains a UBI (with multiple UBIFSes inside)
> yet I got the same "please use UBI" message as all the others (lol)
> 
> I'm specifying my partitions in DT with:
> 
> partitions {
>        compatible = "fixed-partitions";
>        #address-cells = <1>;
>        #size-cells = <1>;
> 
>        mtd0 at 0       { label = "bootrom";   reg = <0x00000000 0x00020000>; };
>        mtd1 at 20000   { label = "uboot";     reg = <0x00020000 0x00060000>; };
>        mtd2 at 80000   { label = "fbkernel";  reg = <0x00080000 0x003c0000>; };
>        mtd3 at 440000  { label = "fbrootfs";  reg = <0x00440000 0x004e0000>; };
>        mtd4 at 920000  { label = "c_kernel";  reg = <0x00920000 0x003c0000>; };
>        mtd5 at ce0000  { label = "c__atags";  reg = <0x00ce0000 0x00020000>; };
>        mtd6 at d00000  { label = "c_rootfs";  reg = <0x00d00000 0x00300000>; };
>        mtd7 at 1000000 { label = "mender";    reg = <0x01000000 0x1f000000>; };
> };
> 
> which is why, I assume, I'm getting these messages. Is there a UBI-friendly
> way to define them to avoid these messages?

Hmm, maybe it makes sense to advertise it only once and not for each mtdblock device.

Thanks,
//richard


From broonie at kernel.org  Tue Oct 26 12:07:03 2021
From: broonie at kernel.org (Mark Brown)
Date: Tue, 26 Oct 2021 20:07:03 +0100
Subject: (subset) [PATCH v2 0/7] Add SPI Multi I/O Bus Controller support
 for RZ/G2L
In-Reply-To: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <163527522326.2033998.11228661564873952732.b4-ty@kernel.org>

On Mon, 25 Oct 2021 21:56:24 +0100, Lad Prabhakar wrote:
> This patch series adds a couple of fixes for rpc-if driver and
> adds support for RZ/G2L SoC, where the SPI Multi I/O Bus Controller
> is identical to the RPC-IF block found on R-Car Gen3 SoC's.
> 
> Cheers,
> Prabhakar
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[3/7] spi: spi-rpc-if: Check return value of rpcif_sw_init()
      commit: 0b0a281ed7001d4c4f4c47bdc84680c4997761ca

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


From richard at nod.at  Tue Oct 26 12:36:43 2021
From: richard at nod.at (Richard Weinberger)
Date: Tue, 26 Oct 2021 21:36:43 +0200 (CEST)
Subject: [PATCH v2] ubifs: ubifs to export filesystem error counters
In-Reply-To: <20211010042239.2888-1-schaecsn@gmx.net>
References: <20211010042239.2888-1-schaecsn@gmx.net>
Message-ID: <2065858791.38760.1635277003599.JavaMail.zimbra@nod.at>

Stefan,

----- Urspr?ngliche Mail -----
> Von: "schaecsn" <schaecsn at gmx.net>
> An: "richard" <richard at nod.at>, "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel"
> <linux-kernel at vger.kernel.org>
> CC: "schaecsn" <schaecsn at gmx.net>, "Stefan Schaeckeler" <sschaeck at cisco.com>
> Gesendet: Sonntag, 10. Oktober 2021 06:22:39
> Betreff: [PATCH v2] ubifs: ubifs to export filesystem error counters

> Not all ubifs filesystem errors are propagated to userspace.
> 
> Export bad magic, bad node and crc errors via sysfs. This allows userspace
> to notice filesystem errors:
> 
> /sys/fs/ubifs/ubiX_Y/errors_magic
> /sys/fs/ubifs/ubiX_Y/errors_node
> /sys/fs/ubifs/ubiX_Y/errors_crc
> 
> The counters are reset to 0 with a remount.
> 
> Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
> ---
> Changes in v2:
>  - merged sysfs.h header into ubifs.h.
>  - io.c: wrapped incrementing error counters into new functions
>    record_*_error().
>  - sysfs.c: removed sysfs write callback for clearing stats.
>  - sysfs.c: ubifs_sysfs_register(): free c->stats on error.
>  - sysfs.c: ubifs_attr_show(): use sysfs_emit().
> 
> fs/ubifs/Makefile |   2 +-
> fs/ubifs/io.c     |  21 +++++++
> fs/ubifs/super.c  |  16 ++++-
> fs/ubifs/sysfs.c  | 153 ++++++++++++++++++++++++++++++++++++++++++++++
> fs/ubifs/ubifs.h  |  35 +++++++++++
> 5 files changed, 225 insertions(+), 2 deletions(-)
> create mode 100644 fs/ubifs/sysfs.c

Queued for 5.16.

I just noticed forgot to request sysfs documentation in Documentation/ABI/.
Can you please send a followup patch?

Thanks,
//richard


From chaitanyak at nvidia.com  Tue Oct 26 16:55:08 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Tue, 26 Oct 2021 23:55:08 +0000
Subject: [PATCH 01/12] block: move blk_rq_err_bytes to scsi
In-Reply-To: <20211025070517.1548584-2-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-2-hch@lst.de>
Message-ID: <e93f8426-7871-7967-283a-2c98526b0936@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> blk_rq_err_bytes is only used by the scsi midlayer, so move it there.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

make sense to not bloat the the block layer code...

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>


From chaitanyak at nvidia.com  Tue Oct 26 16:56:53 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Tue, 26 Oct 2021 23:56:53 +0000
Subject: [PATCH 02/12] block: remove blk_{get,put}_request
In-Reply-To: <20211025070517.1548584-3-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-3-hch@lst.de>
Message-ID: <04dd1425-7043-ca0a-479f-83b6afbdb813@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> These are now pointless wrappers around blk_mq_{alloc,free}_request,
> so remove them.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>


From chaitanyak at nvidia.com  Tue Oct 26 16:58:07 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Tue, 26 Oct 2021 23:58:07 +0000
Subject: [PATCH 04/12] block: remove blk-exec.c
In-Reply-To: <20211025070517.1548584-5-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-5-hch@lst.de>
Message-ID: <06aa0694-fa50-b82e-7b4f-f6429f902451@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> All this code is tightly coupled to the blk-mq core, so move it
> there.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>




From chaitanyak at nvidia.com  Tue Oct 26 17:00:33 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:00:33 +0000
Subject: [PATCH 05/12] blk-mq: move blk_mq_flush_plug_list
In-Reply-To: <20211025070517.1548584-6-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-6-hch@lst.de>
Message-ID: <8dbbeb46-3cea-8fe1-9a9a-687fca133570@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> Move blk_mq_flush_plug_list and blk_mq_plug_issue_direct down in blk-mq.c
> to prepare for marking blk_mq_request_issue_directly static without the
> need of a forward declaration.
> 

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>


From chaitanyak at nvidia.com  Tue Oct 26 17:01:34 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:01:34 +0000
Subject: [PATCH 06/12] block: move request based cloning helpers to
 blk-mq.c
In-Reply-To: <20211025070517.1548584-7-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-7-hch@lst.de>
Message-ID: <7b98c0b8-e437-c1dd-ae09-91efce787c26@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> Keep all the request based code together.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>


From chaitanyak at nvidia.com  Tue Oct 26 17:01:59 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:01:59 +0000
Subject: [PATCH 07/12] block: move blk_rq_init to blk-mq.c
In-Reply-To: <20211025070517.1548584-8-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-8-hch@lst.de>
Message-ID: <c4524ae3-26d0-3f12-ed82-7611e56b8d04@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> blk_rq_init deals with a request structure, so move it to blk-mq.c
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>




From chaitanyak at nvidia.com  Tue Oct 26 17:02:32 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:02:32 +0000
Subject: [PATCH 08/12] block: move blk_steal_bios to blk-mq.c
In-Reply-To: <20211025070517.1548584-9-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-9-hch@lst.de>
Message-ID: <4e3879b3-cb6a-d7cc-099e-dc1739e2d520@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> Keep all the request based code together.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>




From chaitanyak at nvidia.com  Tue Oct 26 17:04:26 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:04:26 +0000
Subject: [PATCH 09/12] block: move blk_account_io_{start, done} to blk-mq.c
In-Reply-To: <20211025070517.1548584-10-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-10-hch@lst.de>
Message-ID: <4b45ff4f-4514-fd25-5f7c-aa99ddeb505a@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> These are only used for request based I/O, so move them where they are
> used.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>


From chaitanyak at nvidia.com  Tue Oct 26 17:04:54 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:04:54 +0000
Subject: [PATCH 10/12] block: move blk_dump_rq_flags to blk-mq.c
In-Reply-To: <20211025070517.1548584-11-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-11-hch@lst.de>
Message-ID: <f4fc40da-ec63-8764-d4a2-ee583381795e@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> blk_dump_rq_flags deals with a request, so move it to blk-mq.c.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>




From chaitanyak at nvidia.com  Tue Oct 26 17:06:38 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:06:38 +0000
Subject: [PATCH 11/12] block: move blk_print_req_error to blk-mq.c
In-Reply-To: <20211025070517.1548584-12-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-12-hch@lst.de>
Message-ID: <e3123131-fb96-1163-ea56-021252501efe@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> This function is only used by the request completion path.  Factor out
> a blk_status_to_str to keep blk_errors private in blk-core.c.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From chaitanyak at nvidia.com  Tue Oct 26 17:07:03 2021
From: chaitanyak at nvidia.com (Chaitanya Kulkarni)
Date: Wed, 27 Oct 2021 00:07:03 +0000
Subject: [PATCH 12/12] block: don't include blk-mq headers in blk-core.c
In-Reply-To: <20211025070517.1548584-13-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
 <20211025070517.1548584-13-hch@lst.de>
Message-ID: <31b6e649-0970-1762-4ba5-7c7bb2c903e5@nvidia.com>

On 10/25/21 12:05 AM, Christoph Hellwig wrote:
> All request based code is in the blk-mq files now.
> 
> Signed-off-by: Christoph Hellwig <hch at lst.de>
> ---

Looks good.

Reviewed-by: Chaitanya Kulkarni <kch at nvidia.com>



From wpopov at gmail.com  Tue Oct 26 19:03:38 2021
From: wpopov at gmail.com (Wagner Popov dos Santos)
Date: Tue, 26 Oct 2021 23:03:38 -0300
Subject: [PATCH 1/2] jffs2: solving deadlock between GC and new inodes
Message-ID: <20211027020339.65303-1-wpopov@gmail.com>

Correct AB-BA deadlock between the GC kthread and a process
that is creating a new file, symlink, and etc.

Create a new JFFS2 inode state to signalizing that the inode
can't be acquired by the GC because is being created. When this
state happens, the GC releases the alloc_sem, sleep, and then
tries again.

To create a new file, the JFSS2 request a new locked inode
to the Linux's FS layer and then insert inside of some JFFS2's
Erase Block. To finish the creation, the process needs to
acquire the alloc_sem semaphore. Just at the end that the
inode is released by the JFFS2. If the GC starts to process an
Erase Block that contains an inode that is being created, can
occur an AB-BA deadlock if the GC acquires the alloc_sem before
the end of the inode's creation because the CG needs to acquire
all inodes inside the EB to finish the iteration.

This deadlock can occur more frequently with partition mounted
with sync flag (not usual).

Signed-off-by: Wagner Popov dos Santos <wpopov at gmail.com>
---
 fs/jffs2/dir.c       |  4 ++++
 fs/jffs2/gc.c        | 10 ++++++++++
 fs/jffs2/nodelist.h  |  1 +
 fs/jffs2/readinode.c |  1 +
 fs/jffs2/wbuf.c      |  3 ++-
 fs/jffs2/write.c     |  6 +++++-
 6 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index f20cff1194bb..57299cd8a0d7 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -210,6 +210,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
 		  f->inocache->pino_nlink, inode->i_mapping->nrpages);
 
 	d_instantiate_new(dentry, inode);
+	jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
 	return 0;
 
  fail:
@@ -430,6 +431,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
 	jffs2_complete_reservation(c);
 
 	d_instantiate_new(dentry, inode);
+	jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
 	return 0;
 
  fail:
@@ -574,6 +576,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	jffs2_complete_reservation(c);
 
 	d_instantiate_new(dentry, inode);
+	jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
 	return 0;
 
  fail:
@@ -745,6 +748,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
 	jffs2_complete_reservation(c);
 
 	d_instantiate_new(dentry, inode);
+	jffs2_set_inocache_state(c, f->inocache, INO_STATE_PRESENT);
 	return 0;
 
  fail:
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 9ed0f26cf023..72090843fa19 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -208,6 +208,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 			spin_unlock(&c->inocache_lock);
 			BUG();
 
+			/* fall through */
+		case INO_STATE_CREATING:
 		case INO_STATE_READING:
 			/* We need to wait for it to finish, lest we move on
 			   and trigger the BUG() above while we haven't yet
@@ -394,6 +396,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
 		spin_unlock(&c->inocache_lock);
 		BUG();
 
+		/* fall through */
+	case INO_STATE_CREATING:
+		/* We can't process this inode while it is being created
+		 * to avoid a deadlock condition the inode is locked.
+		 * However, to finish the creation we need to unlock the
+		 * alloc_sem() and because we dropped the alloc_sem we must
+		 * return to start again from the beginning.
+		 */
 	case INO_STATE_READING:
 		/* Someone's currently trying to read it. We must wait for
 		   them to finish and then go through the full iget() route
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 0637271f3770..0033eeee27e4 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -192,6 +192,7 @@ struct jffs2_inode_cache {
 #define INO_STATE_GC		4	/* GCing a 'pristine' node */
 #define INO_STATE_READING	5	/* In read_inode() */
 #define INO_STATE_CLEARING	6	/* In clear_inode() */
+#define INO_STATE_CREATING	7	/* Inode locked! GC can't touch */
 
 #define INO_FLAGS_XATTR_CHECKED	0x01	/* has no duplicate xattr_ref */
 #define INO_FLAGS_IS_DIR	0x02	/* is a directory */
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 389ea53ea487..3a841645bc86 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -1336,6 +1336,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 			goto retry_inocache;
 
 		case INO_STATE_READING:
+		case INO_STATE_CREATING:
 		case INO_STATE_PRESENT:
 			/* Eep. This should never happen. It can
 			happen if Linux calls read_inode() again
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index c6821a509481..860fe878c324 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -518,7 +518,8 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 								      (void *)(buf?:c->wbuf) + (ref_offset(raw) - start));
 			} else if (unlikely(ic->state != INO_STATE_PRESENT &&
 					    ic->state != INO_STATE_CHECKEDABSENT &&
-					    ic->state != INO_STATE_GC)) {
+					    ic->state != INO_STATE_GC &&
+					    ic->state != INO_STATE_CREATING)) {
 				JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state);
 				BUG();
 			}
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
index cda9a361368e..ec48947ac916 100644
--- a/fs/jffs2/write.c
+++ b/fs/jffs2/write.c
@@ -35,7 +35,11 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
 	f->inocache = ic;
 	f->inocache->pino_nlink = 1; /* Will be overwritten shortly for directories */
 	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
-	f->inocache->state = INO_STATE_PRESENT;
+	f->inocache->state = INO_STATE_CREATING;
+	/* The initial state can't be INO_STATE_PRESENT to avoid a deadlock in
+	 * GC because the new inode is still locked and the GC needs to lock
+	 * the inode to get it.
+	 */
 
 	jffs2_add_ino_cache(c, f->inocache);
 	jffs2_dbg(1, "%s(): Assigned ino# %d\n", __func__, f->inocache->ino);
-- 
2.20.1



From wpopov at gmail.com  Tue Oct 26 19:03:39 2021
From: wpopov at gmail.com (Wagner Popov dos Santos)
Date: Tue, 26 Oct 2021 23:03:39 -0300
Subject: [PATCH 2/2] jffs2: solving deadlock on sync function
In-Reply-To: <20211027020339.65303-1-wpopov@gmail.com>
References: <20211027020339.65303-1-wpopov@gmail.com>
Message-ID: <20211027020339.65303-2-wpopov@gmail.com>

Correcting AB-BA deadlock in jffs2_fsync() involving alloc_sem
semaphore and inodes.

The function jffs2_fsync() can't lock the inode because some
process, or even the same process, that call the CG will acquire
alloc_sem semaphore and will try to acquire the inode if it is
inside the Erase Block that is marked to be processed.

Fixes: 02c24a82187d ("fs: push i_mutex and filemap_write_and_wait down into ->fsync() handlers")

Signed-off-by: Wagner Popov dos Santos <wpopov at gmail.com>
---
 fs/jffs2/file.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index 7d8654a1472e..7f139704cb8d 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -39,10 +39,14 @@ int jffs2_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
 	if (ret)
 		return ret;
 
-	inode_lock(inode);
-	/* Trigger GC to flush any pending writes for this inode */
+	/* Trigger GC to flush any pending writes for this inode
+	 *
+	 * We need to leave the inode unlocked to avoid a deadlock condition
+	 * because the function jffs2_garbage_collect_pass() can try to lock
+	 * the same inode if it is inside the erase block that GC is
+	 * processing.
+	 */
 	jffs2_flush_wbuf_gc(c, inode->i_ino);
-	inode_unlock(inode);
 
 	return 0;
 }
-- 
2.20.1



From patrice.chotard at foss.st.com  Tue Oct 26 23:10:42 2021
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Wed, 27 Oct 2021 08:10:42 +0200
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
Message-ID: <e8ddc63b-a0b5-79ae-6aff-19810cf74920@foss.st.com>

Hi Krzysztof

On 10/20/21 9:45 AM, Krzysztof Kozlowski wrote:
> On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
>> From: Patrice Chotard <patrice.chotard at foss.st.com>
>>
>> Not all @st.com email address are concerned, only people who have
>> a specific @foss.st.com email will see their entry updated.
>> For some people, who left the company, remove their email.
>>
> 
> Please split simple address change from maintainer updates (removal,
> addition).

ok

> 
> Also would be nice to see here explained *why* are you doing this.

Our @foss.st.com address are dedicated for upstream activities, 
i will add a comment about this.

Thanks
Patrice

> 
> Best regards,
> Krzysztof
> 


From patrice.chotard at foss.st.com  Tue Oct 26 23:11:45 2021
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Wed, 27 Oct 2021 08:11:45 +0200
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <878ryoc4dc.wl-maz@kernel.org>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
 <878ryoc4dc.wl-maz@kernel.org>
Message-ID: <82492eb2-5a5e-39a2-a058-5e2ba75323e0@foss.st.com>

Hi Marc

On 10/20/21 1:39 PM, Marc Zyngier wrote:
> On Wed, 20 Oct 2021 08:45:02 +0100,
> Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> wrote:
>>
>> On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
>>> From: Patrice Chotard <patrice.chotard at foss.st.com>
>>>
>>> Not all @st.com email address are concerned, only people who have
>>> a specific @foss.st.com email will see their entry updated.
>>> For some people, who left the company, remove their email.
>>>
>>
>> Please split simple address change from maintainer updates (removal,
>> addition).
>>
>> Also would be nice to see here explained *why* are you doing this.
> 
> And why this can't be done with a single update to .mailmap, like
> anyone else does.

Thanks for the tips, yes, it will be simpler.

Thanks
Patrice

> 
> 	M.
> 


From geert at linux-m68k.org  Wed Oct 27 00:17:39 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 27 Oct 2021 09:17:39 +0200
Subject: [PATCH v2 5/7] memory: renesas-rpc-if: Return error in case
 devm_ioremap_resource() fails
In-Reply-To: <20211025205631.21151-6-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20211025205631.21151-6-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdUjsVRwB0_TH5HD8CrPsM15K1RLatP_ABODMe2bQ4C2ow@mail.gmail.com>

Hi Prabhakar,

CC seebe

On Mon, Oct 25, 2021 at 10:57 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> Make sure we return error in case devm_ioremap_resource() fails for dirmap
> resource.
>
> Fixes: ca7d8b980b67 ("memory: add Renesas RPC-IF driver")
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>

Thanks for your patch!

> --- a/drivers/memory/renesas-rpc-if.c
> +++ b/drivers/memory/renesas-rpc-if.c
> @@ -243,7 +243,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
>         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
>         rpc->dirmap = devm_ioremap_resource(&pdev->dev, res);
>         if (IS_ERR(rpc->dirmap))
> -               rpc->dirmap = NULL;
> +               return PTR_ERR(rpc->dirmap);

IIRC, it was intentional to make the dirmap optional (because the
device can be used without and/or because some variants on other SoCs
lack it?).  Unfortunately this is not reflected in the DT bindings
(yet?).  All code using the dirmap does check if rpc->dirmap is
valid first.

>         rpc->size = resource_size(res);
>
>         rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From geert at linux-m68k.org  Wed Oct 27 00:21:24 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 27 Oct 2021 09:21:24 +0200
Subject: [PATCH v2 5/7] memory: renesas-rpc-if: Return error in case
 devm_ioremap_resource() fails
In-Reply-To: <CAMuHMdUjsVRwB0_TH5HD8CrPsM15K1RLatP_ABODMe2bQ4C2ow@mail.gmail.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20211025205631.21151-6-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <CAMuHMdUjsVRwB0_TH5HD8CrPsM15K1RLatP_ABODMe2bQ4C2ow@mail.gmail.com>
Message-ID: <CAMuHMdX4HfLUfDk2eZkBugP_ysL3w+qvZqKSR3e47HG4RTggXw@mail.gmail.com>

On Wed, Oct 27, 2021 at 9:17 AM Geert Uytterhoeven <geert at linux-m68k.org> wrote:
> On Mon, Oct 25, 2021 at 10:57 PM Lad Prabhakar
> <prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> > Make sure we return error in case devm_ioremap_resource() fails for dirmap
> > resource.
> >
> > Fixes: ca7d8b980b67 ("memory: add Renesas RPC-IF driver")
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> > Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> > Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
>
> Thanks for your patch!
>
> > --- a/drivers/memory/renesas-rpc-if.c
> > +++ b/drivers/memory/renesas-rpc-if.c
> > @@ -243,7 +243,7 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
> >         res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dirmap");
> >         rpc->dirmap = devm_ioremap_resource(&pdev->dev, res);
> >         if (IS_ERR(rpc->dirmap))
> > -               rpc->dirmap = NULL;
> > +               return PTR_ERR(rpc->dirmap);
>
> IIRC, it was intentional to make the dirmap optional (because the
> device can be used without and/or because some variants on other SoCs
> lack it?).  Unfortunately this is not reflected in the DT bindings
> (yet?).  All code using the dirmap does check if rpc->dirmap is
> valid first.
>
> >         rpc->size = resource_size(res);

Of course this will crash if the dirmap is not present, so for now it's better
to just bail out.

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

> >
> >         rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From geert at linux-m68k.org  Wed Oct 27 00:22:12 2021
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 27 Oct 2021 09:22:12 +0200
Subject: [PATCH v2 6/7] memory: renesas-rpc-if: Drop usage of
 RPCIF_DIRMAP_SIZE macro
In-Reply-To: <20211025205631.21151-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20211025205631.21151-7-prabhakar.mahadev-lad.rj@bp.renesas.com>
Message-ID: <CAMuHMdVt0o++AiP=A0jsZPUAfvWgn1V8ZwtGT2ha-v1zw1cY_Q@mail.gmail.com>

On Mon, Oct 25, 2021 at 10:57 PM Lad Prabhakar
<prabhakar.mahadev-lad.rj at bp.renesas.com> wrote:
> RPCIF_DIRMAP_SIZE may differ on various SoC's. Instead of using
> RPCIF_DIRMAP_SIZE macro use resource size to get dirmap size
> which is already part of struct rpcif.
>
> Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> Reviewed-by: Wolfram Sang <wsa+renesas at sang-engineering.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From hch at lst.de  Wed Oct 27 00:42:07 2021
From: hch at lst.de (Christoph Hellwig)
Date: Wed, 27 Oct 2021 09:42:07 +0200
Subject: [PATCH 5/5] mm: simplify bdi refcounting
In-Reply-To: <20211022090203.GF1026@quack2.suse.cz>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-6-hch@lst.de> <20211022090203.GF1026@quack2.suse.cz>
Message-ID: <20211027074207.GA12793@lst.de>

On Fri, Oct 22, 2021 at 11:02:03AM +0200, Jan Kara wrote:
> On Thu 21-10-21 14:44:41, Christoph Hellwig wrote:
> > Move grabbing and releasing the bdi refcount out of the common
> > wb_init/wb_exit helpers into code that is only used for the non-default
> > memcg driven bdi_writeback structures.
> > 
> > Signed-off-by: Christoph Hellwig <hch at lst.de>
> 
> Can we perhaps add a comment to struct bdi_writeback definition (or maybe
> wb_init()?) mentioning that it holds a reference to 'bdi' if it is
> bdi_writeback struct for a cgroup? I don't see it mentioned anywhere and
> now that you've changed the code, it isn't that obvious from the code
> either... Otherwise the patch looks good so feel free to add:

Like this?

diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 33207004cfded..a3d7dd1cc30a1 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -103,6 +103,9 @@ struct wb_completion {
  * change as blkcg is disabled and enabled higher up in the hierarchy, a wb
  * is tested for blkcg after lookup and removed from index on mismatch so
  * that a new wb for the combination can be created.
+ *
+ * Each bdi_writeback that is no embedded into the backing_dev_info must hold
+ * a reference to the parent backing_dev_info.  See cgwb_create() for details.
  */
 struct bdi_writeback {
 	struct backing_dev_info *bdi;	/* our parent bdi */


From jack at suse.cz  Wed Oct 27 02:47:53 2021
From: jack at suse.cz (Jan Kara)
Date: Wed, 27 Oct 2021 11:47:53 +0200
Subject: [PATCH 5/5] mm: simplify bdi refcounting
In-Reply-To: <20211027074207.GA12793@lst.de>
References: <20211021124441.668816-1-hch@lst.de>
 <20211021124441.668816-6-hch@lst.de>
 <20211022090203.GF1026@quack2.suse.cz>
 <20211027074207.GA12793@lst.de>
Message-ID: <20211027094753.GB28650@quack2.suse.cz>

On Wed 27-10-21 09:42:07, Christoph Hellwig wrote:
> On Fri, Oct 22, 2021 at 11:02:03AM +0200, Jan Kara wrote:
> > On Thu 21-10-21 14:44:41, Christoph Hellwig wrote:
> > > Move grabbing and releasing the bdi refcount out of the common
> > > wb_init/wb_exit helpers into code that is only used for the non-default
> > > memcg driven bdi_writeback structures.
> > > 
> > > Signed-off-by: Christoph Hellwig <hch at lst.de>
> > 
> > Can we perhaps add a comment to struct bdi_writeback definition (or maybe
> > wb_init()?) mentioning that it holds a reference to 'bdi' if it is
> > bdi_writeback struct for a cgroup? I don't see it mentioned anywhere and
> > now that you've changed the code, it isn't that obvious from the code
> > either... Otherwise the patch looks good so feel free to add:
> 
> Like this?
> 
> diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
> index 33207004cfded..a3d7dd1cc30a1 100644
> --- a/include/linux/backing-dev-defs.h
> +++ b/include/linux/backing-dev-defs.h
> @@ -103,6 +103,9 @@ struct wb_completion {
>   * change as blkcg is disabled and enabled higher up in the hierarchy, a wb
>   * is tested for blkcg after lookup and removed from index on mismatch so
>   * that a new wb for the combination can be created.
> + *
> + * Each bdi_writeback that is no embedded into the backing_dev_info must hold
				 ^^^ not

> + * a reference to the parent backing_dev_info.  See cgwb_create() for details.
>   */

Otherwise looks nice. Thanks!

								Honza

-- 
Jan Kara <jack at suse.com>
SUSE Labs, CR


From shiva.linuxworks at gmail.com  Wed Oct 27 03:33:48 2021
From: shiva.linuxworks at gmail.com (shiva.linuxworks at gmail.com)
Date: Wed, 27 Oct 2021 10:33:48 +0000
Subject: [PATCH 0/4] enabling Advanced protection and security features
Message-ID: <20211027103352.8879-1-sshivamurthy@micron.com>

From: Shivamurthy Shastri <sshivamurthy at micron.com>

Standard protection features in SPI NOR flashes are legacy and offer a
simple way to protect the memory array against accidental or unwanted
modification of its content.

These patches enable the support for advanced sector protection which
protects memory from accidentally corrupting code and data stored, and
it also prevents malicious attacks that could intentionally modify the
code or data stored in the memory.

Micron Flashes offer some of the advanced protection methods using
volatile lock bits, non-volatile lock bits, global freeze bits, and
password.

Shivamurthy Shastri (4):
  mtd: spi-nor: micron-st: add advanced protection and security features
  mtd: spi-nor: add advanced protection and security features support
  mtd: add advanced protection and security ioctls
  mtd: spi-nor: micron-st: add mt25qu128abb and mt25ql128abb

 drivers/mtd/mtdchar.c            | 145 ++++++++++++++++++
 drivers/mtd/spi-nor/Makefile     |   2 +-
 drivers/mtd/spi-nor/advprotsec.c | 209 ++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c       |   2 +
 drivers/mtd/spi-nor/core.h       |  20 +++
 drivers/mtd/spi-nor/micron-st.c  | 245 +++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h          |  19 +++
 include/uapi/mtd/mtd-abi.h       |  11 ++
 8 files changed, 652 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi-nor/advprotsec.c

-- 
2.25.1



From shiva.linuxworks at gmail.com  Wed Oct 27 03:33:49 2021
From: shiva.linuxworks at gmail.com (shiva.linuxworks at gmail.com)
Date: Wed, 27 Oct 2021 10:33:49 +0000
Subject: [PATCH 1/4] mtd: spi-nor: micron-st: add advanced protection and
 security features
In-Reply-To: <20211027103352.8879-1-sshivamurthy@micron.com>
References: <20211027103352.8879-1-sshivamurthy@micron.com>
Message-ID: <20211027103352.8879-2-sshivamurthy@micron.com>

From: Shivamurthy Shastri <sshivamurthy at micron.com>

Micron SPI NOR flashes are enabled with advanced sector protection
features, using volatile lock bits, non-volatile lock bits, global
freeze bits and password.

Advanced sector protection and security features offers additional
levels of protection against accidentally corrupting code and data
stored, and it also prevents malicious attacks that could intentionally
modify or corrupt the code or data stored.

Signed-off-by: Shivamurthy Shastri <sshivamurthy at micron.com>
---
 drivers/mtd/spi-nor/core.h      |  20 +++
 drivers/mtd/spi-nor/micron-st.c | 238 ++++++++++++++++++++++++++++++++
 2 files changed, 258 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3348e1dd1445..f6890973cb4a 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -187,6 +187,24 @@ struct spi_nor_locking_ops {
 	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
 };
 
+struct spi_nor_sec_ops {
+	int (*secure_read)(struct spi_nor *nor, size_t len, u8 *buf);
+	int (*secure_write)(struct spi_nor *nor, size_t len, u8 *buf);
+	int (*read_nvlock_bits)(struct spi_nor *nor, u32 addr, size_t len,
+				u8 *buf);
+	int (*read_vlock_bits)(struct spi_nor *nor, u32 addr, size_t len,
+			       u8 *buf);
+	int (*read_global_freeze_bits)(struct spi_nor *nor, size_t len,
+				       u8 *buf);
+	int (*read_password)(struct spi_nor *nor, size_t len, u8 *buf);
+	int (*write_global_freeze_bits)(struct spi_nor *nor, size_t len,
+					u8 *buf);
+	int (*write_vlock_bits)(struct spi_nor *nor, u32 addr, size_t len,
+				u8 *buf);
+	int (*write_nvlock_bits)(struct spi_nor *nor, u32 addr);
+	int (*erase_nvlock_bits)(struct spi_nor *nor);
+};
+
 /**
  * struct spi_nor_otp_organization - Structure to describe the SPI NOR OTP regions
  * @len:	size of one OTP region in bytes.
@@ -285,6 +303,8 @@ struct spi_nor_flash_parameter {
 	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
 
 	const struct spi_nor_locking_ops *locking_ops;
+
+	const struct spi_nor_sec_ops *sec_ops;
 };
 
 /**
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index c224e59820a1..b5d82e85fb92 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -16,6 +16,23 @@
 #define SPINOR_MT_OCT_DTR	0xe7	/* Enable Octal DTR. */
 #define SPINOR_MT_EXSPI		0xff	/* Enable Extended SPI (default) */
 
+#define AUTHENTA_ID		0x8c
+#define AUTHENTA_ID_BYTE	0x05
+
+#define SPINOR_OP_SECURE_READ			0x96
+#define SPINOR_OP_SECURE_WRITE			0x9b
+
+#define SPINOR_OP_RD_VOL_LOCK_BITS		0xe8
+#define SPINOR_OP_WR_VOL_LOCK_BITS		0xe5
+#define SPINOR_OP_RD_NV_LOCK_BITS		0xe2
+#define SPINOR_OP_WR_NV_LOCK_BITS		0xe3
+#define SPINOR_OP_ER_NV_LOCK_BITS		0xe4
+
+#define SPINOR_OP_RD_GLOBAL_FREEZE_BITS		0xa7
+#define SPINOR_OP_WR_GLOBAL_FREEZE_BITS		0xa6
+
+#define SPINOR_OP_RD_PASSWORD			0x27
+
 static int spi_nor_micron_octal_dtr_enable(struct spi_nor *nor, bool enable)
 {
 	struct spi_mem_op op;
@@ -247,12 +264,233 @@ static int st_micron_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 	return spi_nor_write_disable(nor);
 }
 
+/**
+ * authenta_secure_read() - read the secure packet from authenta SPI NOR
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @len: number of bytes to read
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_secure_read(struct spi_nor *nor, size_t len, u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SECURE_READ, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_DUMMY(1, 1),
+			   SPI_MEM_OP_DATA_IN(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_secure_write() - write the secure packet to authenta SPI NOR
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @len: number of bytes to be written
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_secure_write(struct spi_nor *nor, size_t len, u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SECURE_WRITE, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_read_vlock_bits() - read the volatile lock bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @addr: address for volatile lock bits
+ * @len: number of bytes to read
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_read_vlock_bits(struct spi_nor *nor, u32 addr,
+				    size_t len, u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_VOL_LOCK_BITS, 1),
+			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_IN(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_write_vlock_bits() - write data to the volatile lock bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @addr: address for volatile lock bits
+ * @len: number of bytes to be written
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_write_vlock_bits(struct spi_nor *nor, u32 addr, size_t len,
+				     u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_VOL_LOCK_BITS, 1),
+			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_read_nvlock_bits() - read the non-volatile lock bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @addr: address for non-volatile lock bits
+ * @len: number of bytes to be written
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_read_nvlock_bits(struct spi_nor *nor, u32 addr,
+				     size_t len, u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_NV_LOCK_BITS, 1),
+			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_IN(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_write_nvlock_bits() - write to the non-volatile lock bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @addr: address for non-volatile lock bits
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_write_nvlock_bits(struct spi_nor *nor, u32 addr)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_NV_LOCK_BITS, 1),
+			   SPI_MEM_OP_ADDR(nor->addr_width, addr, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_NO_DATA);
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_erase_nvlock_bits() - erase the non-volatile lock bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_erase_nvlock_bits(struct spi_nor *nor)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_ER_NV_LOCK_BITS, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_NO_DATA);
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_read_global_freeze_bits() - read the global freeze bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @len: number of bytes to read
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_read_global_freeze_bits(struct spi_nor *nor, size_t len,
+					    u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_GLOBAL_FREEZE_BITS, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_IN(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_write_global_freeze_bits() - write data to the global freeze bits
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @len: number of bytes to be written
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_write_global_freeze_bits(struct spi_nor *nor, size_t len,
+					     u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_GLOBAL_FREEZE_BITS, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+/**
+ * authenta_read_password() - read the password
+ *
+ * @nor: pointer to 'struct spi_nor'
+ * @len: number of bytes to read
+ * @buf: pointer to dst buffer
+ *
+ * Return: 0 in case of success, a negative error code otherwise.
+ */
+static int authenta_read_password(struct spi_nor *nor, size_t len, u8 *buf)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_PASSWORD, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_IN(len, buf, 1));
+
+	return spi_mem_exec_op(nor->spimem, &op);
+}
+
+static const struct spi_nor_sec_ops authenta_ops = {
+	.secure_read = authenta_secure_read,
+	.secure_write = authenta_secure_write,
+	.read_vlock_bits = authenta_read_vlock_bits,
+	.write_vlock_bits = authenta_write_vlock_bits,
+	.read_nvlock_bits = authenta_read_nvlock_bits,
+	.write_nvlock_bits = authenta_write_nvlock_bits,
+	.erase_nvlock_bits = authenta_erase_nvlock_bits,
+	.read_global_freeze_bits = authenta_read_global_freeze_bits,
+	.write_global_freeze_bits = authenta_write_global_freeze_bits,
+	.read_password = authenta_read_password,
+};
+
 static void micron_st_default_init(struct spi_nor *nor)
 {
 	nor->flags |= SNOR_F_HAS_LOCK;
 	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
 	nor->params->quad_enable = NULL;
 	nor->params->set_4byte_addr_mode = st_micron_set_4byte_addr_mode;
+
+	if (nor->info->id[AUTHENTA_ID_BYTE] == AUTHENTA_ID)
+		nor->params->sec_ops = &authenta_ops;
 }
 
 static const struct spi_nor_fixups micron_st_fixups = {
-- 
2.25.1



From shiva.linuxworks at gmail.com  Wed Oct 27 03:33:50 2021
From: shiva.linuxworks at gmail.com (shiva.linuxworks at gmail.com)
Date: Wed, 27 Oct 2021 10:33:50 +0000
Subject: [PATCH 2/4] mtd: spi-nor: add advanced protection and security
 features support
In-Reply-To: <20211027103352.8879-1-sshivamurthy@micron.com>
References: <20211027103352.8879-1-sshivamurthy@micron.com>
Message-ID: <20211027103352.8879-3-sshivamurthy@micron.com>

From: Shivamurthy Shastri <sshivamurthy at micron.com>

Added functionalities to support advanced securtiy and protection
features in new SPI NOR flashes.

Signed-off-by: Shivamurthy Shastri <sshivamurthy at micron.com>
---
 drivers/mtd/spi-nor/Makefile     |   2 +-
 drivers/mtd/spi-nor/advprotsec.c | 209 +++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c       |   2 +
 include/linux/mtd/mtd.h          |  19 +++
 4 files changed, 231 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/spi-nor/advprotsec.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 6b904e439372..8e96e2c65c7a 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 
-spi-nor-objs			:= core.o sfdp.o swp.o otp.o sysfs.o
+spi-nor-objs			:= core.o sfdp.o swp.o otp.o advprotsec.o sysfs.o
 spi-nor-objs			+= atmel.o
 spi-nor-objs			+= catalyst.o
 spi-nor-objs			+= eon.o
diff --git a/drivers/mtd/spi-nor/advprotsec.c b/drivers/mtd/spi-nor/advprotsec.c
new file mode 100644
index 000000000000..4dc8e67b16ef
--- /dev/null
+++ b/drivers/mtd/spi-nor/advprotsec.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI NOR Advanced Sector Protection and Security Features
+ *
+ * Copyright (C) 2021 Micron Technology, Inc.
+ */
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int spi_nor_secure_read(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_read(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_secure_write(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->secure_write(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_vlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_vlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_vlock_bits(nor, addr, len, buf);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_nvlock_bits(struct mtd_info *mtd, u32 addr, size_t len,
+				    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_nvlock_bits(nor, addr, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_nvlock_bits(struct mtd_info *mtd, u32 addr)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_nvlock_bits(nor, addr);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_erase_nvlock_bits(struct mtd_info *mtd)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->erase_nvlock_bits(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_disable(nor);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					   u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_write_global_freeze_bits(struct mtd_info *mtd, size_t len,
+					    u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->write_global_freeze_bits(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static int spi_nor_read_password(struct mtd_info *mtd, size_t len, u8 *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	int ret;
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = nor->params->sec_ops->read_password(nor, len, buf);
+
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+void spi_nor_register_security_ops(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+
+	if (!nor->params->sec_ops)
+		return;
+
+	mtd->_secure_packet_read = spi_nor_secure_read;
+	mtd->_secure_packet_write = spi_nor_secure_write;
+	mtd->_read_vlock_bits = spi_nor_read_vlock_bits;
+	mtd->_write_vlock_bits = spi_nor_write_vlock_bits;
+	mtd->_read_nvlock_bits = spi_nor_read_nvlock_bits;
+	mtd->_write_nvlock_bits = spi_nor_write_nvlock_bits;
+	mtd->_erase_nvlock_bits = spi_nor_erase_nvlock_bits;
+	mtd->_read_global_freeze_bits = spi_nor_read_global_freeze_bits;
+	mtd->_write_global_freeze_bits = spi_nor_write_global_freeze_bits;
+	mtd->_read_password = spi_nor_read_password;
+}
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index cc08bd707378..864f3c7783b3 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3199,6 +3199,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 
 	spi_nor_register_locking_ops(nor);
 
+	spi_nor_register_security_ops(nor);
+
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 88227044fc86..bce358c9fb94 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -360,6 +360,25 @@ struct mtd_info {
 	int (*_get_device) (struct mtd_info *mtd);
 	void (*_put_device) (struct mtd_info *mtd);
 
+	/*
+	 * Security Operations
+	 */
+	int (*_secure_packet_read)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_secure_packet_write)(struct mtd_info *mtd, size_t len, u8 *buf);
+	int (*_read_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				u8 *buf);
+	int (*_write_vlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_read_nvlock_bits)(struct mtd_info *mtd, u32 addr, size_t len,
+				 u8 *buf);
+	int (*_write_nvlock_bits)(struct mtd_info *mtd, u32 addr);
+	int (*_erase_nvlock_bits)(struct mtd_info *mtd);
+	int (*_read_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					u8 *buf);
+	int (*_write_global_freeze_bits)(struct mtd_info *mtd, size_t len,
+					 u8 *buf);
+	int (*_read_password)(struct mtd_info *mtd, size_t len, u8 *buf);
+
 	/*
 	 * flag indicates a panic write, low level drivers can take appropriate
 	 * action if required to ensure writes go through
-- 
2.25.1



From shiva.linuxworks at gmail.com  Wed Oct 27 03:33:51 2021
From: shiva.linuxworks at gmail.com (shiva.linuxworks at gmail.com)
Date: Wed, 27 Oct 2021 10:33:51 +0000
Subject: [PATCH 3/4] mtd: add advanced protection and security ioctls
In-Reply-To: <20211027103352.8879-1-sshivamurthy@micron.com>
References: <20211027103352.8879-1-sshivamurthy@micron.com>
Message-ID: <20211027103352.8879-4-sshivamurthy@micron.com>

From: Shivamurthy Shastri <sshivamurthy at micron.com>

Added new ioctls for advanced protection and security features.
These features are currently supported by new Micron SPI NOR flashes.

Signed-off-by: Shivamurthy Shastri <sshivamurthy at micron.com>
---
 drivers/mtd/mtdchar.c      | 145 +++++++++++++++++++++++++++++++++++++
 include/uapi/mtd/mtd-abi.h |  11 +++
 2 files changed, 156 insertions(+)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 155e991d9d75..97b97b80276d 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -654,6 +654,16 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 	case MTDFILEMODE:
 	case BLKPG:
 	case BLKRRPART:
+	case SECURE_PACKET_READ:
+	case SECURE_PACKET_WRITE:
+	case RD_VLOCK_BITS:
+	case WR_VLOCK_BITS:
+	case RD_NVLOCK_BITS:
+	case WR_NVLOCK_BITS:
+	case ER_NVLOCK_BITS:
+	case RD_GLOBAL_FREEZE_BITS:
+	case WR_GLOBAL_FREEZE_BITS:
+	case RD_PASSWORD:
 		break;
 
 	/* "dangerous" commands */
@@ -1017,6 +1027,141 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg)
 		ret = 0;
 		break;
 	}
+	case SECURE_PACKET_READ:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		ret = master->_secure_packet_read(master, buf.length, oobbuf);
+		if (copy_to_user(buf.ptr, oobbuf, buf.length))
+			ret = -EFAULT;
+		break;
+	}
+
+	case SECURE_PACKET_WRITE:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = memdup_user(buf.ptr, buf.length);
+		ret = master->_secure_packet_write(master, buf.length, oobbuf);
+		break;
+	}
+
+	case RD_VLOCK_BITS:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		ret = master->_read_vlock_bits(master, buf.start, buf.length,
+					       oobbuf);
+		if (copy_to_user(buf.ptr, oobbuf, buf.length))
+			ret = -EFAULT;
+		break;
+	}
+
+	case WR_VLOCK_BITS:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = memdup_user(buf.ptr, buf.length);
+		ret = master->_write_vlock_bits(master, buf. start, buf.length,
+						oobbuf);
+		break;
+	}
+
+	case RD_NVLOCK_BITS:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		ret = master->_read_nvlock_bits(master, buf.start, buf.length,
+						oobbuf);
+		if (copy_to_user(buf.ptr, oobbuf, buf.length))
+			ret = -EFAULT;
+		break;
+	}
+
+	case WR_NVLOCK_BITS:
+	{
+		struct mtd_oob_buf buf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		ret = master->_write_nvlock_bits(master, buf.start);
+		break;
+	}
+
+	case ER_NVLOCK_BITS:
+	{
+		ret = master->_erase_nvlock_bits(master);
+		break;
+	}
+
+	case RD_GLOBAL_FREEZE_BITS:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		ret = master->_read_global_freeze_bits(master, buf.length,
+						       oobbuf);
+		if (copy_to_user(buf.ptr, oobbuf, buf.length))
+			ret = -EFAULT;
+		break;
+	}
+
+	case WR_GLOBAL_FREEZE_BITS:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = memdup_user(buf.ptr, buf.length);
+		ret = master->_write_global_freeze_bits(master, buf.length,
+							oobbuf);
+		break;
+	}
+
+	case RD_PASSWORD:
+	{
+		struct mtd_oob_buf buf;
+		u8 *oobbuf;
+
+		if (copy_from_user(&buf, argp, sizeof(buf)))
+			ret = -EFAULT;
+
+		oobbuf = kmalloc(buf.length, GFP_KERNEL);
+		ret = master->_read_password(master, buf.length, oobbuf);
+		if (copy_to_user(buf.ptr, oobbuf, buf.length))
+			ret = -EFAULT;
+		break;
+	}
 	}
 
 	return ret;
diff --git a/include/uapi/mtd/mtd-abi.h b/include/uapi/mtd/mtd-abi.h
index b869990c2db2..dbd7bf60d484 100644
--- a/include/uapi/mtd/mtd-abi.h
+++ b/include/uapi/mtd/mtd-abi.h
@@ -208,6 +208,17 @@ struct otp_info {
 /* Erase a given range of user data (must be in mode %MTD_FILE_MODE_OTP_USER) */
 #define OTPERASE		_IOW('M', 25, struct otp_info)
 
+#define SECURE_PACKET_READ	_IOWR('M', 26, struct mtd_oob_buf)
+#define SECURE_PACKET_WRITE	_IOWR('M', 27, struct mtd_oob_buf)
+#define RD_VLOCK_BITS		_IOWR('M', 28, struct mtd_oob_buf)
+#define WR_VLOCK_BITS		_IOWR('M', 29, struct mtd_oob_buf)
+#define RD_NVLOCK_BITS		_IOWR('M', 30, struct mtd_oob_buf)
+#define WR_NVLOCK_BITS		_IOWR('M', 31, struct mtd_oob_buf)
+#define ER_NVLOCK_BITS		_IO('M', 32)
+#define RD_GLOBAL_FREEZE_BITS	_IOWR('M', 33, struct mtd_oob_buf)
+#define WR_GLOBAL_FREEZE_BITS	_IOWR('M', 34, struct mtd_oob_buf)
+#define RD_PASSWORD		_IOWR('M', 35, struct mtd_oob_buf)
+
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
  * interfaces
-- 
2.25.1



From shiva.linuxworks at gmail.com  Wed Oct 27 03:33:52 2021
From: shiva.linuxworks at gmail.com (shiva.linuxworks at gmail.com)
Date: Wed, 27 Oct 2021 10:33:52 +0000
Subject: [PATCH 4/4] mtd: spi-nor: micron-st: add mt25qu128abb and mt25ql128abb
In-Reply-To: <20211027103352.8879-1-sshivamurthy@micron.com>
References: <20211027103352.8879-1-sshivamurthy@micron.com>
Message-ID: <20211027103352.8879-5-sshivamurthy@micron.com>

From: Shivamurthy Shastri <sshivamurthy at micron.com>

Added new Micron SPI NOR flashes to structure flash_info, which supports
advanced protection and security features.

Signed-off-by: Shivamurthy Shastri <sshivamurthy at micron.com>
---
 drivers/mtd/spi-nor/micron-st.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index b5d82e85fb92..2bebd76b091a 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -158,10 +158,17 @@ static const struct flash_info st_parts[] = {
 			      SECT_4K | SPI_NOR_QUAD_READ) },
 	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128,
 			      SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "mt25qu128abb", INFO6(0x20bb18, 0x12008c, 64 * 1024,  256,
+				SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+				SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
+				SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
 	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
+	{ "mt25ql128abb", INFO6(0x20ba18, 0x12008c, 64 * 1024,  256,
+				SECT_4K | USE_FSR | SPI_NOR_HAS_LOCK |
+				SPI_NOR_QUAD_READ) },
 	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
-- 
2.25.1



From richard at nod.at  Wed Oct 27 03:54:09 2021
From: richard at nod.at (Richard Weinberger)
Date: Wed, 27 Oct 2021 12:54:09 +0200 (CEST)
Subject: [PATCH 0/4] enabling Advanced protection and security features
In-Reply-To: <20211027103352.8879-1-sshivamurthy@micron.com>
References: <20211027103352.8879-1-sshivamurthy@micron.com>
Message-ID: <771780049.41543.1635332049033.JavaMail.zimbra@nod.at>

----- Urspr?ngliche Mail -----
> Von: "shiva linuxworks" <shiva.linuxworks at gmail.com>
> An: "Tudor Ambarus" <tudor.ambarus at microchip.com>, "Michael Walle" <michael at walle.cc>, "Pratyush Yadav"
> <p.yadav at ti.com>, "Miquel Raynal" <miquel.raynal at bootlin.com>, "richard" <richard at nod.at>, "Vignesh Raghavendra"
> <vigneshr at ti.com>
> CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel" <linux-kernel at vger.kernel.org>, "Shivamurthy Shastri"
> <sshivamurthy at micron.com>
> Gesendet: Mittwoch, 27. Oktober 2021 12:33:48
> Betreff: [PATCH 0/4] enabling Advanced protection and security features

> From: Shivamurthy Shastri <sshivamurthy at micron.com>
> 
> Standard protection features in SPI NOR flashes are legacy and offer a
> simple way to protect the memory array against accidental or unwanted
> modification of its content.
> 
> These patches enable the support for advanced sector protection which
> protects memory from accidentally corrupting code and data stored, and
> it also prevents malicious attacks that could intentionally modify the
> code or data stored in the memory.
> 
> Micron Flashes offer some of the advanced protection methods using
> volatile lock bits, non-volatile lock bits, global freeze bits, and
> password.

Can you please point us to the technical documentation of these features?
I'm especially interested in the password feature.

Thanks,
//richard


From patrice.chotard at foss.st.com  Wed Oct 27 06:56:35 2021
From: patrice.chotard at foss.st.com (Patrice CHOTARD)
Date: Wed, 27 Oct 2021 15:56:35 +0200
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <82492eb2-5a5e-39a2-a058-5e2ba75323e0@foss.st.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
 <878ryoc4dc.wl-maz@kernel.org>
 <82492eb2-5a5e-39a2-a058-5e2ba75323e0@foss.st.com>
Message-ID: <865a4055-5c2f-0793-bdce-9f04eac167d2@foss.st.com>

Hi Marc

+Joe Perches

On 10/27/21 8:11 AM, Patrice CHOTARD wrote:
> Hi Marc
> 
> On 10/20/21 1:39 PM, Marc Zyngier wrote:
>> On Wed, 20 Oct 2021 08:45:02 +0100,
>> Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> wrote:
>>>
>>> On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
>>>> From: Patrice Chotard <patrice.chotard at foss.st.com>
>>>>
>>>> Not all @st.com email address are concerned, only people who have
>>>> a specific @foss.st.com email will see their entry updated.
>>>> For some people, who left the company, remove their email.
>>>>
>>>
>>> Please split simple address change from maintainer updates (removal,
>>> addition).
>>>
>>> Also would be nice to see here explained *why* are you doing this.
>>
>> And why this can't be done with a single update to .mailmap, like
>> anyone else does.
> 
> Thanks for the tips, yes, it will be simpler.
> 
> Thanks
> Patrice
> 
>>
>> 	M.
>>

I made a try by updating .mailmap with adding a new entry with my @foss.st.com email :

 Pali Roh?r <pali at kernel.org> <pali.rohar at gmail.com>
 Paolo 'Blaisorblade' Giarrusso <blaisorblade at yahoo.it>
+Patrice Chotard <patrice.chotard at foss.st.com> <patrice.chotard at st.com>
 Patrick Mochel <mochel at digitalimplant.org>
 Paul Burton <paulburton at kernel.org> <paul.burton at imgtec.com>

But when running ./scripts/get_maintainer.pl Documentation/devicetree/bindings/arm/sti.yaml, by old email is still displayed

Rob Herring <robh+dt at kernel.org> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
Patrice Chotard <patrice.chotard at st.com> (in file)
devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
linux-kernel at vger.kernel.org (open list)

By default, the get_maintainer.pl script is using .mailmap file ($email_use_mailmap = 1).

It seems there is an issue with get_maintainer.pl and maintainer name/e-mail found in yaml file ?

Thanks
Patrice


From maz at kernel.org  Wed Oct 27 07:21:28 2021
From: maz at kernel.org (Marc Zyngier)
Date: Wed, 27 Oct 2021 15:21:28 +0100
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <865a4055-5c2f-0793-bdce-9f04eac167d2@foss.st.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
 <878ryoc4dc.wl-maz@kernel.org>
 <82492eb2-5a5e-39a2-a058-5e2ba75323e0@foss.st.com>
 <865a4055-5c2f-0793-bdce-9f04eac167d2@foss.st.com>
Message-ID: <874k92blav.wl-maz@kernel.org>

On Wed, 27 Oct 2021 14:56:35 +0100,
Patrice CHOTARD <patrice.chotard at foss.st.com> wrote:
> 
> Hi Marc
> 
> +Joe Perches
> 
> On 10/27/21 8:11 AM, Patrice CHOTARD wrote:
> > Hi Marc
> > 
> > On 10/20/21 1:39 PM, Marc Zyngier wrote:
> >> On Wed, 20 Oct 2021 08:45:02 +0100,
> >> Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> wrote:
> >>>
> >>> On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
> >>>> From: Patrice Chotard <patrice.chotard at foss.st.com>
> >>>>
> >>>> Not all @st.com email address are concerned, only people who have
> >>>> a specific @foss.st.com email will see their entry updated.
> >>>> For some people, who left the company, remove their email.
> >>>>
> >>>
> >>> Please split simple address change from maintainer updates (removal,
> >>> addition).
> >>>
> >>> Also would be nice to see here explained *why* are you doing this.
> >>
> >> And why this can't be done with a single update to .mailmap, like
> >> anyone else does.
> > 
> > Thanks for the tips, yes, it will be simpler.
> > 
> > Thanks
> > Patrice
> > 
> >>
> >> 	M.
> >>
> 
> I made a try by updating .mailmap with adding a new entry with my @foss.st.com email :
> 
>  Pali Roh?r <pali at kernel.org> <pali.rohar at gmail.com>
>  Paolo 'Blaisorblade' Giarrusso <blaisorblade at yahoo.it>
> +Patrice Chotard <patrice.chotard at foss.st.com> <patrice.chotard at st.com>
>  Patrick Mochel <mochel at digitalimplant.org>
>  Paul Burton <paulburton at kernel.org> <paul.burton at imgtec.com>
> 
> But when running ./scripts/get_maintainer.pl Documentation/devicetree/bindings/arm/sti.yaml, by old email is still displayed
> 
> Rob Herring <robh+dt at kernel.org> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> Patrice Chotard <patrice.chotard at st.com> (in file)
> devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> linux-kernel at vger.kernel.org (open list)
> 
> By default, the get_maintainer.pl script is using .mailmap file
> ($email_use_mailmap = 1).
> 
> It seems there is an issue with get_maintainer.pl and maintainer
> name/e-mail found in yaml file ?

Try this (warning though: my Perl-foo is non-existent).

	M.

diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 2075db0c08b8..2a84a3fb0130 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -986,6 +986,7 @@ sub get_maintainers {
 	    my ($name, $address) = parse_email($email);
 
 	    my $tmp_email = format_email($name, $address, $email_usename);
+	    $tmp_email = mailmap_email($tmp_email);
 	    push_email_address($tmp_email, '');
 	    add_role($tmp_email, 'in file');
 	}

-- 
Without deviation from the norm, progress is not possible.


From prabhakar.csengg at gmail.com  Wed Oct 27 09:16:53 2021
From: prabhakar.csengg at gmail.com (Lad, Prabhakar)
Date: Wed, 27 Oct 2021 17:16:53 +0100
Subject: [PATCH v2 7/7] memory: renesas-rpc-if: Add support for RZ/G2L
In-Reply-To: <3739744b-0a10-6d6b-8d1c-9c82b6afe0b3@canonical.com>
References: <20211025205631.21151-1-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <20211025205631.21151-8-prabhakar.mahadev-lad.rj@bp.renesas.com>
 <3739744b-0a10-6d6b-8d1c-9c82b6afe0b3@canonical.com>
Message-ID: <CA+V-a8u16Xu6Ygn5m0cgKB7qtwrco7AW=7QnTODP4gcZWve8Ew@mail.gmail.com>

Hi Krzysztof,

Thank you for the review.


On Tue, Oct 26, 2021 at 3:47 PM Krzysztof Kozlowski
<krzysztof.kozlowski at canonical.com> wrote:
>
> On 25/10/2021 22:56, Lad Prabhakar wrote:
> > SPI Multi I/O Bus Controller on RZ/G2L SoC is almost identical to
> > the RPC-IF interface found on R-Car Gen3 SoC's.
> >
> > This patch adds a new compatible string for the RZ/G2L family so
> > that the timing values on RZ/G2L can be adjusted.
> >
> > Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
> > Reviewed-by: Biju Das <biju.das.jz at bp.renesas.com>
> > ---
> > v1->v2:
> >  * Updated macros as suggested by Wolfram
> > ---
> >  drivers/memory/renesas-rpc-if.c | 72 ++++++++++++++++++++++++++++-----
> >  drivers/mtd/hyperbus/rpc-if.c   |  4 +-
> >  drivers/spi/spi-rpc-if.c        |  4 +-
> >  include/memory/renesas-rpc-if.h |  8 +++-
> >  4 files changed, 75 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
> > index 0c56decc91f2..8c51145c0f5c 100644
> > --- a/drivers/memory/renesas-rpc-if.c
> > +++ b/drivers/memory/renesas-rpc-if.c
> > @@ -12,6 +12,7 @@
> >  #include <linux/module.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/of.h>
> > +#include <linux/of_device.h>
> >  #include <linux/regmap.h>
> >  #include <linux/reset.h>
> >
> > @@ -27,8 +28,8 @@
> >  #define RPCIF_CMNCR_MOIIO_HIZ        (RPCIF_CMNCR_MOIIO0(3) | \
> >                                RPCIF_CMNCR_MOIIO1(3) | \
> >                                RPCIF_CMNCR_MOIIO2(3) | RPCIF_CMNCR_MOIIO3(3))
> > -#define RPCIF_CMNCR_IO3FV(val)       (((val) & 0x3) << 14) /* undocumented */
> > -#define RPCIF_CMNCR_IO2FV(val)       (((val) & 0x3) << 12) /* undocumented */
> > +#define RPCIF_CMNCR_IO3FV(val)       (((val) & 0x3) << 14) /* documented for RZ/G2L */
> > +#define RPCIF_CMNCR_IO2FV(val)       (((val) & 0x3) << 12) /* documented for RZ/G2L */
> >  #define RPCIF_CMNCR_IO0FV(val)       (((val) & 0x3) << 8)
> >  #define RPCIF_CMNCR_IOFV_HIZ (RPCIF_CMNCR_IO0FV(3) | RPCIF_CMNCR_IO2FV(3) | \
> >                                RPCIF_CMNCR_IO3FV(3))
> > @@ -126,6 +127,9 @@
> >  #define RPCIF_SMDRENR_OPDRE  BIT(4)
> >  #define RPCIF_SMDRENR_SPIDRE BIT(0)
> >
> > +#define RPCIF_PHYADD         0x0070  /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
> > +#define RPCIF_PHYWR          0x0074  /* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
> > +
> >  #define RPCIF_PHYCNT         0x007C  /* R/W */
> >  #define RPCIF_PHYCNT_CAL     BIT(31)
> >  #define RPCIF_PHYCNT_OCTA(v) (((v) & 0x3) << 22)
> > @@ -133,10 +137,12 @@
> >  #define RPCIF_PHYCNT_OCT     BIT(20)
> >  #define RPCIF_PHYCNT_DDRCAL  BIT(19)
> >  #define RPCIF_PHYCNT_HS              BIT(18)
> > -#define RPCIF_PHYCNT_STRTIM(v)       (((v) & 0x7) << 15)
> > +#define RPCIF_PHYCNT_CKSEL(v)        (((v) & 0x3) << 16) /* valid only for RZ/G2L */
> > +#define RPCIF_PHYCNT_STRTIM(v)       (((v) & 0x7) << 15) /* valid for R-Car and RZ/G2{E,H,M,N} */
> >  #define RPCIF_PHYCNT_WBUF2   BIT(4)
> >  #define RPCIF_PHYCNT_WBUF    BIT(2)
> >  #define RPCIF_PHYCNT_PHYMEM(v)       (((v) & 0x3) << 0)
> > +#define RPCIF_PHYCNT_PHYMEM_MASK GENMASK(1, 0)
> >
> >  #define RPCIF_PHYOFFSET1     0x0080  /* R/W */
> >  #define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)
> > @@ -244,18 +250,46 @@ int rpcif_sw_init(struct rpcif *rpc, struct device *dev)
> >               return PTR_ERR(rpc->dirmap);
> >       rpc->size = resource_size(res);
> >
> > +     rpc->type = (enum rpcif_type)of_device_get_match_data(dev);
> >       rpc->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
> >
> >       return PTR_ERR_OR_ZERO(rpc->rstc);
> >  }
> >  EXPORT_SYMBOL(rpcif_sw_init);
> >
> > -void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> > +static void rpcif_rzg2l_timing_adjust_sdr(struct rpcif *rpc)
> > +{
> > +     u32 data;
> > +
> > +     regmap_write(rpc->regmap, RPCIF_PHYWR, 0xa5390000);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000000);
> > +     regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000022);
> > +     regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00008080);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000024);
> > +
> > +     regmap_read(rpc->regmap, RPCIF_PHYCNT, &data);
> > +     regmap_write(rpc->regmap, RPCIF_PHYCNT, data | RPCIF_PHYCNT_CKSEL(3));
> > +     regmap_write(rpc->regmap, RPCIF_PHYWR, 0x00000030);
> > +     regmap_write(rpc->regmap, RPCIF_PHYADD, 0x80000032);
> > +}
> > +
> > +int rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> >  {
> >       u32 dummy;
> >
> >       pm_runtime_get_sync(rpc->dev);
> >
> > +     if (rpc->type == RPCIF_RZ_G2L) {
> > +             int ret;
> > +
> > +             ret = reset_control_reset(rpc->rstc);
> > +             if (ret)
> > +                     return ret;
> > +             usleep_range(200, 300);
> > +             rpcif_rzg2l_timing_adjust_sdr(rpc);
> > +     }
> > +
> >       /*
> >        * NOTE: The 0x260 are undocumented bits, but they must be set.
> >        *       RPCIF_PHYCNT_STRTIM is strobe timing adjustment bits,
> > @@ -264,8 +298,15 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> >        *       On H3 ES1.x, the value should be 0, while on others,
> >        *       the value should be 7.
> >        */
> > -     regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> > -                  RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> > +     if (rpc->type == RPCIF_RCAR_GEN3) {
> > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, RPCIF_PHYCNT_STRTIM(7) |
> > +                          RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260);
> > +     } else {
> > +             regmap_read(rpc->regmap, RPCIF_PHYCNT, &dummy);
> > +             dummy &= ~RPCIF_PHYCNT_PHYMEM_MASK;
> > +             dummy |= RPCIF_PHYCNT_PHYMEM(hyperflash ? 3 : 0) | 0x260;
> > +             regmap_write(rpc->regmap, RPCIF_PHYCNT, dummy);
> > +     }
> >
> >       /*
> >        * NOTE: The 0x1511144 are undocumented bits, but they must be set
> > @@ -282,9 +323,17 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> >               regmap_update_bits(rpc->regmap, RPCIF_PHYINT,
> >                                  RPCIF_PHYINT_WPVAL, 0);
> >
> > -     regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> > -                  RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
> > -                  RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> > +     if (rpc->type == RPCIF_RCAR_GEN3)
> > +             regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> > +                          RPCIF_CMNCR_MOIIO_HIZ | RPCIF_CMNCR_IOFV_HIZ |
> > +                          RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> > +     else
> > +             regmap_write(rpc->regmap, RPCIF_CMNCR, RPCIF_CMNCR_SFDE |
> > +                          RPCIF_CMNCR_MOIIO3(1) | RPCIF_CMNCR_MOIIO2(1) |
> > +                          RPCIF_CMNCR_MOIIO1(1) | RPCIF_CMNCR_MOIIO0(1) |
> > +                          RPCIF_CMNCR_IO3FV(2) | RPCIF_CMNCR_IO2FV(2) |
> > +                          RPCIF_CMNCR_IO0FV(2) | RPCIF_CMNCR_BSZ(hyperflash ? 1 : 0));
> > +
> >       /* Set RCF after BSZ update */
> >       regmap_write(rpc->regmap, RPCIF_DRCR, RPCIF_DRCR_RCF);
> >       /* Dummy read according to spec */
> > @@ -295,6 +344,8 @@ void rpcif_hw_init(struct rpcif *rpc, bool hyperflash)
> >       pm_runtime_put(rpc->dev);
> >
> >       rpc->bus_size = hyperflash ? 2 : 1;
> > +
> > +     return 0;
> >  }
> >  EXPORT_SYMBOL(rpcif_hw_init);
> >
> > @@ -657,7 +708,8 @@ static int rpcif_remove(struct platform_device *pdev)
> >  }
> >
> >  static const struct of_device_id rpcif_of_match[] = {
> > -     { .compatible = "renesas,rcar-gen3-rpc-if", },
> > +     { .compatible = "renesas,rcar-gen3-rpc-if", .data = (void *)RPCIF_RCAR_GEN3 },
> > +     { .compatible = "renesas,rzg2l-rpc-if", .data = (void *)RPCIF_RZ_G2L },
> >       {},
> >  };
> >  MODULE_DEVICE_TABLE(of, rpcif_of_match);
> > diff --git a/drivers/mtd/hyperbus/rpc-if.c b/drivers/mtd/hyperbus/rpc-if.c
> > index 367b0d72bf62..40bca89268c3 100644
> > --- a/drivers/mtd/hyperbus/rpc-if.c
> > +++ b/drivers/mtd/hyperbus/rpc-if.c
> > @@ -132,7 +132,9 @@ static int rpcif_hb_probe(struct platform_device *pdev)
> >
> >       rpcif_enable_rpm(&hyperbus->rpc);
> >
> > -     rpcif_hw_init(&hyperbus->rpc, true);
> > +     error = rpcif_hw_init(&hyperbus->rpc, true);
> > +     if (error)
> > +             return error;
> >
>
> Not related to this patch, but the concept used here looks fragile. The
> child driver calls also rpcif_sw_init() and ignores the error code. What
> happens in case of rpcif_sw_init() failure or child probe deferral?
> Since the SW and HW init is called in context of child device, the
> parent won't do anything. Then, second bind of child device (manual or
> because of deferral) will fail on devm_reset_control_get_exclusive()
> with -EBUSY.
>
> Initializing parent's resources should be rather done from parent's
> context (so renesas-rpc-if.c) to handle properly deferred probe and
> other failures. Doing it from a child, breaks encapsulation and
> separation of devices.
>
Agree with the above.

> Is there any reason why memory/renesas-rpc-if.c cannot do SW and HW init?
>
I'll investigate this to avoid the above issues.

Cheers,
Prabhakar

> Best regards,
> Krzysztof


From joe at perches.com  Wed Oct 27 09:57:50 2021
From: joe at perches.com (Joe Perches)
Date: Wed, 27 Oct 2021 09:57:50 -0700
Subject: dt-bindings: treewide: Update @st.com email address to
 @foss.st.com
In-Reply-To: <865a4055-5c2f-0793-bdce-9f04eac167d2@foss.st.com>
References: <20211020065000.21312-1-patrice.chotard@foss.st.com>
 <22fb6f19-21eb-dcb5-fa31-bb243d4a7eaf@canonical.com>
 <878ryoc4dc.wl-maz@kernel.org>
 <82492eb2-5a5e-39a2-a058-5e2ba75323e0@foss.st.com>
 <865a4055-5c2f-0793-bdce-9f04eac167d2@foss.st.com>
Message-ID: <20ffb5604269f9add568b343701d42097c599c89.camel@perches.com>

On Wed, 2021-10-27 at 15:56 +0200, Patrice CHOTARD wrote:
> On 10/27/21 8:11 AM, Patrice CHOTARD wrote:
> > On 10/20/21 1:39 PM, Marc Zyngier wrote:
> > > On Wed, 20 Oct 2021 08:45:02 +0100,
> > > Krzysztof Kozlowski <krzysztof.kozlowski at canonical.com> wrote:
> > > > On 20/10/2021 08:50, patrice.chotard at foss.st.com wrote:
> > > > > From: Patrice Chotard <patrice.chotard at foss.st.com>
> > > > > 
> > > > > Not all @st.com email address are concerned, only people who have
> > > > > a specific @foss.st.com email will see their entry updated.
> > > > > For some people, who left the company, remove their email.
> > > > Also would be nice to see here explained *why* are you doing this.
> > > 
> > > And why this can't be done with a single update to .mailmap, like
> > > anyone else does.
> > 
> > Thanks for the tips, yes, it will be simpler.
> 
> I made a try by updating .mailmap with adding a new entry with my @foss.st.com email :
> 
>  Pali Roh?r <pali at kernel.org> <pali.rohar at gmail.com>
>  Paolo 'Blaisorblade' Giarrusso <blaisorblade at yahoo.it>
> +Patrice Chotard <patrice.chotard at foss.st.com> <patrice.chotard at st.com>
>  Patrick Mochel <mochel at digitalimplant.org>
>  Paul Burton <paulburton at kernel.org> <paul.burton at imgtec.com>
> 
> But when running ./scripts/get_maintainer.pl Documentation/devicetree/bindings/arm/sti.yaml, by old email is still displayed
> 
> Rob Herring <robh+dt at kernel.org> (maintainer:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> Patrice Chotard <patrice.chotard at st.com> (in file)
> devicetree at vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS)
> linux-kernel at vger.kernel.org (open list)
> 
> By default, the get_maintainer.pl script is using .mailmap file ($email_use_mailmap = 1).
> 
> It seems there is an issue with get_maintainer.pl and maintainer name/e-mail found in yaml file ?

I'm of two minds whether it's an "issue" actually.

get_maintainer is not the only tool used to create email
address lists.

Some actually read files like MAINTAINERS or .dts or .yaml
files directly to find maintainer addresses.

So If your name and email address is listed in an source file
where nominally active email addresses are entered then I
believe .mailmap should not modify it.

So I believe email addresses in each file should be updated
in preference to using a mailmap entry for nominally active
email addresses in these files.

---

$ cat Documentation/devicetree/bindings/arm/sti.yaml
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/sti.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: ST STi Platforms Device Tree Bindings

maintainers:
  - Patrice Chotard <patrice.chotard at st.com>





From lkp at intel.com  Wed Oct 27 14:00:54 2021
From: lkp at intel.com (kernel test robot)
Date: Thu, 28 Oct 2021 05:00:54 +0800
Subject: [PATCH 2/4] mtd: spi-nor: add advanced protection and security
 features support
In-Reply-To: <20211027103352.8879-3-sshivamurthy@micron.com>
References: <20211027103352.8879-3-sshivamurthy@micron.com>
Message-ID: <202110280523.Yro5FIjm-lkp@intel.com>

Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on mtd/mtd/next]
[also build test WARNING on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: arc-randconfig-r043-20211027 (attached as .config)
compiler: arc-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All warnings (new ones prefixed by >>):

>> drivers/mtd/spi-nor/advprotsec.c:192:6: warning: no previous prototype for 'spi_nor_register_security_ops' [-Wmissing-prototypes]
     192 | void spi_nor_register_security_ops(struct spi_nor *nor)
         |      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/spi_nor_register_security_ops +192 drivers/mtd/spi-nor/advprotsec.c

   191	
 > 192	void spi_nor_register_security_ops(struct spi_nor *nor)

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 27867 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211028/c78b3989/attachment-0001.gz>

From lkp at intel.com  Wed Oct 27 16:01:49 2021
From: lkp at intel.com (kernel test robot)
Date: Thu, 28 Oct 2021 07:01:49 +0800
Subject: [PATCH 2/4] mtd: spi-nor: add advanced protection and security
 features support
In-Reply-To: <20211027103352.8879-3-sshivamurthy@micron.com>
References: <20211027103352.8879-3-sshivamurthy@micron.com>
Message-ID: <202110280745.RO0wUxhh-lkp@intel.com>

Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mtd/mtd/next]
[also build test ERROR on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: i386-randconfig-a002-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All error/warnings (new ones prefixed by >>):

>> drivers/mtd/spi-nor/core.c:3202:2: error: implicit declaration of function 'spi_nor_register_security_ops' [-Werror,-Wimplicit-function-declaration]
           spi_nor_register_security_ops(nor);
           ^
   drivers/mtd/spi-nor/core.c:3202:2: note: did you mean 'spi_nor_register_locking_ops'?
   drivers/mtd/spi-nor/core.h:572:6: note: 'spi_nor_register_locking_ops' declared here
   void spi_nor_register_locking_ops(struct spi_nor *nor);
        ^
   1 error generated.
--
>> drivers/mtd/spi-nor/advprotsec.c:192:6: warning: no previous prototype for function 'spi_nor_register_security_ops' [-Wmissing-prototypes]
   void spi_nor_register_security_ops(struct spi_nor *nor)
        ^
   drivers/mtd/spi-nor/advprotsec.c:192:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void spi_nor_register_security_ops(struct spi_nor *nor)
   ^
   static 
   1 warning generated.


vim +/spi_nor_register_security_ops +3202 drivers/mtd/spi-nor/core.c

  3073	
  3074	int spi_nor_scan(struct spi_nor *nor, const char *name,
  3075			 const struct spi_nor_hwcaps *hwcaps)
  3076	{
  3077		const struct flash_info *info;
  3078		struct device *dev = nor->dev;
  3079		struct mtd_info *mtd = &nor->mtd;
  3080		struct device_node *np = spi_nor_get_flash_node(nor);
  3081		int ret;
  3082		int i;
  3083	
  3084		ret = spi_nor_check(nor);
  3085		if (ret)
  3086			return ret;
  3087	
  3088		/* Reset SPI protocol for all commands. */
  3089		nor->reg_proto = SNOR_PROTO_1_1_1;
  3090		nor->read_proto = SNOR_PROTO_1_1_1;
  3091		nor->write_proto = SNOR_PROTO_1_1_1;
  3092	
  3093		/*
  3094		 * We need the bounce buffer early to read/write registers when going
  3095		 * through the spi-mem layer (buffers have to be DMA-able).
  3096		 * For spi-mem drivers, we'll reallocate a new buffer if
  3097		 * nor->page_size turns out to be greater than PAGE_SIZE (which
  3098		 * shouldn't happen before long since NOR pages are usually less
  3099		 * than 1KB) after spi_nor_scan() returns.
  3100		 */
  3101		nor->bouncebuf_size = PAGE_SIZE;
  3102		nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
  3103					      GFP_KERNEL);
  3104		if (!nor->bouncebuf)
  3105			return -ENOMEM;
  3106	
  3107		info = spi_nor_get_flash_info(nor, name);
  3108		if (IS_ERR(info))
  3109			return PTR_ERR(info);
  3110	
  3111		nor->info = info;
  3112	
  3113		spi_nor_debugfs_init(nor, info);
  3114	
  3115		mutex_init(&nor->lock);
  3116	
  3117		/*
  3118		 * Make sure the XSR_RDY flag is set before calling
  3119		 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
  3120		 * with Atmel SPI NOR.
  3121		 */
  3122		if (info->flags & SPI_NOR_XSR_RDY)
  3123			nor->flags |=  SNOR_F_READY_XSR_RDY;
  3124	
  3125		if (info->flags & SPI_NOR_HAS_LOCK)
  3126			nor->flags |= SNOR_F_HAS_LOCK;
  3127	
  3128		mtd->_write = spi_nor_write;
  3129	
  3130		/* Init flash parameters based on flash_info struct and SFDP */
  3131		ret = spi_nor_init_params(nor);
  3132		if (ret)
  3133			return ret;
  3134	
  3135		if (!mtd->name)
  3136			mtd->name = dev_name(dev);
  3137		mtd->priv = nor;
  3138		mtd->type = MTD_NORFLASH;
  3139		mtd->writesize = nor->params->writesize;
  3140		mtd->flags = MTD_CAP_NORFLASH;
  3141		mtd->size = nor->params->size;
  3142		mtd->_erase = spi_nor_erase;
  3143		mtd->_read = spi_nor_read;
  3144		mtd->_suspend = spi_nor_suspend;
  3145		mtd->_resume = spi_nor_resume;
  3146		mtd->_get_device = spi_nor_get_device;
  3147		mtd->_put_device = spi_nor_put_device;
  3148	
  3149		if (info->flags & USE_FSR)
  3150			nor->flags |= SNOR_F_USE_FSR;
  3151		if (info->flags & SPI_NOR_HAS_TB) {
  3152			nor->flags |= SNOR_F_HAS_SR_TB;
  3153			if (info->flags & SPI_NOR_TB_SR_BIT6)
  3154				nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
  3155		}
  3156	
  3157		if (info->flags & NO_CHIP_ERASE)
  3158			nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
  3159		if (info->flags & USE_CLSR)
  3160			nor->flags |= SNOR_F_USE_CLSR;
  3161		if (info->flags & SPI_NOR_SWP_IS_VOLATILE)
  3162			nor->flags |= SNOR_F_SWP_IS_VOLATILE;
  3163	
  3164		if (info->flags & SPI_NOR_4BIT_BP) {
  3165			nor->flags |= SNOR_F_HAS_4BIT_BP;
  3166			if (info->flags & SPI_NOR_BP3_SR_BIT6)
  3167				nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
  3168		}
  3169	
  3170		if (info->flags & SPI_NOR_NO_ERASE)
  3171			mtd->flags |= MTD_NO_ERASE;
  3172	
  3173		mtd->dev.parent = dev;
  3174		nor->page_size = nor->params->page_size;
  3175		mtd->writebufsize = nor->page_size;
  3176	
  3177		if (of_property_read_bool(np, "broken-flash-reset"))
  3178			nor->flags |= SNOR_F_BROKEN_RESET;
  3179	
  3180		/*
  3181		 * Configure the SPI memory:
  3182		 * - select op codes for (Fast) Read, Page Program and Sector Erase.
  3183		 * - set the number of dummy cycles (mode cycles + wait states).
  3184		 * - set the SPI protocols for register and memory accesses.
  3185		 */
  3186		ret = spi_nor_setup(nor, hwcaps);
  3187		if (ret)
  3188			return ret;
  3189	
  3190		if (info->flags & SPI_NOR_4B_OPCODES)
  3191			nor->flags |= SNOR_F_4B_OPCODES;
  3192	
  3193		if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
  3194			nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
  3195	
  3196		ret = spi_nor_set_addr_width(nor);
  3197		if (ret)
  3198			return ret;
  3199	
  3200		spi_nor_register_locking_ops(nor);
  3201	
> 3202		spi_nor_register_security_ops(nor);
  3203	
  3204		/* Send all the required SPI flash commands to initialize device */
  3205		ret = spi_nor_init(nor);
  3206		if (ret)
  3207			return ret;
  3208	
  3209		/* Configure OTP parameters and ops */
  3210		spi_nor_otp_init(nor);
  3211	
  3212		dev_info(dev, "%s (%lld Kbytes)\n", info->name,
  3213				(long long)mtd->size >> 10);
  3214	
  3215		dev_dbg(dev,
  3216			"mtd .name = %s, .size = 0x%llx (%lldMiB), "
  3217			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
  3218			mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
  3219			mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
  3220	
  3221		if (mtd->numeraseregions)
  3222			for (i = 0; i < mtd->numeraseregions; i++)
  3223				dev_dbg(dev,
  3224					"mtd.eraseregions[%d] = { .offset = 0x%llx, "
  3225					".erasesize = 0x%.8x (%uKiB), "
  3226					".numblocks = %d }\n",
  3227					i, (long long)mtd->eraseregions[i].offset,
  3228					mtd->eraseregions[i].erasesize,
  3229					mtd->eraseregions[i].erasesize / 1024,
  3230					mtd->eraseregions[i].numblocks);
  3231		return 0;
  3232	}
  3233	EXPORT_SYMBOL_GPL(spi_nor_scan);
  3234	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 30528 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211028/fd91df54/attachment-0001.gz>

From lkp at intel.com  Wed Oct 27 21:43:31 2021
From: lkp at intel.com (kernel test robot)
Date: Thu, 28 Oct 2021 12:43:31 +0800
Subject: [PATCH 2/4] mtd: spi-nor: add advanced protection and security
 features support
In-Reply-To: <20211027103352.8879-3-sshivamurthy@micron.com>
References: <20211027103352.8879-3-sshivamurthy@micron.com>
Message-ID: <202110281232.7MTZXvdX-lkp@intel.com>

Hi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on mtd/mtd/next]
[also build test ERROR on mtd/mtd/fixes v5.15-rc7 next-20211027]
[cannot apply to mtd/spi-nor/next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next
config: i386-buildonly-randconfig-r005-20211027 (attached as .config)
compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 5db7568a6a1fcb408eb8988abdaff2a225a8eb72)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d26eac1611c4409954b4d0c44215e1a53aa7605a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review shiva-linuxworks-gmail-com/enabling-Advanced-protection-and-security-features/20211027-183458
        git checkout d26eac1611c4409954b4d0c44215e1a53aa7605a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All errors (new ones prefixed by >>):

>> drivers/mtd/spi-nor/core.c:3202:2: error: implicit declaration of function 'spi_nor_register_security_ops' [-Werror,-Wimplicit-function-declaration]
           spi_nor_register_security_ops(nor);
           ^
   drivers/mtd/spi-nor/core.c:3202:2: note: did you mean 'spi_nor_register_locking_ops'?
   drivers/mtd/spi-nor/core.h:572:6: note: 'spi_nor_register_locking_ops' declared here
   void spi_nor_register_locking_ops(struct spi_nor *nor);
        ^
   1 error generated.
--
>> drivers/mtd/spi-nor/advprotsec.c:192:6: error: no previous prototype for function 'spi_nor_register_security_ops' [-Werror,-Wmissing-prototypes]
   void spi_nor_register_security_ops(struct spi_nor *nor)
        ^
   drivers/mtd/spi-nor/advprotsec.c:192:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   void spi_nor_register_security_ops(struct spi_nor *nor)
   ^
   static 
   1 error generated.


vim +/spi_nor_register_security_ops +3202 drivers/mtd/spi-nor/core.c

  3073	
  3074	int spi_nor_scan(struct spi_nor *nor, const char *name,
  3075			 const struct spi_nor_hwcaps *hwcaps)
  3076	{
  3077		const struct flash_info *info;
  3078		struct device *dev = nor->dev;
  3079		struct mtd_info *mtd = &nor->mtd;
  3080		struct device_node *np = spi_nor_get_flash_node(nor);
  3081		int ret;
  3082		int i;
  3083	
  3084		ret = spi_nor_check(nor);
  3085		if (ret)
  3086			return ret;
  3087	
  3088		/* Reset SPI protocol for all commands. */
  3089		nor->reg_proto = SNOR_PROTO_1_1_1;
  3090		nor->read_proto = SNOR_PROTO_1_1_1;
  3091		nor->write_proto = SNOR_PROTO_1_1_1;
  3092	
  3093		/*
  3094		 * We need the bounce buffer early to read/write registers when going
  3095		 * through the spi-mem layer (buffers have to be DMA-able).
  3096		 * For spi-mem drivers, we'll reallocate a new buffer if
  3097		 * nor->page_size turns out to be greater than PAGE_SIZE (which
  3098		 * shouldn't happen before long since NOR pages are usually less
  3099		 * than 1KB) after spi_nor_scan() returns.
  3100		 */
  3101		nor->bouncebuf_size = PAGE_SIZE;
  3102		nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
  3103					      GFP_KERNEL);
  3104		if (!nor->bouncebuf)
  3105			return -ENOMEM;
  3106	
  3107		info = spi_nor_get_flash_info(nor, name);
  3108		if (IS_ERR(info))
  3109			return PTR_ERR(info);
  3110	
  3111		nor->info = info;
  3112	
  3113		spi_nor_debugfs_init(nor, info);
  3114	
  3115		mutex_init(&nor->lock);
  3116	
  3117		/*
  3118		 * Make sure the XSR_RDY flag is set before calling
  3119		 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
  3120		 * with Atmel SPI NOR.
  3121		 */
  3122		if (info->flags & SPI_NOR_XSR_RDY)
  3123			nor->flags |=  SNOR_F_READY_XSR_RDY;
  3124	
  3125		if (info->flags & SPI_NOR_HAS_LOCK)
  3126			nor->flags |= SNOR_F_HAS_LOCK;
  3127	
  3128		mtd->_write = spi_nor_write;
  3129	
  3130		/* Init flash parameters based on flash_info struct and SFDP */
  3131		ret = spi_nor_init_params(nor);
  3132		if (ret)
  3133			return ret;
  3134	
  3135		if (!mtd->name)
  3136			mtd->name = dev_name(dev);
  3137		mtd->priv = nor;
  3138		mtd->type = MTD_NORFLASH;
  3139		mtd->writesize = nor->params->writesize;
  3140		mtd->flags = MTD_CAP_NORFLASH;
  3141		mtd->size = nor->params->size;
  3142		mtd->_erase = spi_nor_erase;
  3143		mtd->_read = spi_nor_read;
  3144		mtd->_suspend = spi_nor_suspend;
  3145		mtd->_resume = spi_nor_resume;
  3146		mtd->_get_device = spi_nor_get_device;
  3147		mtd->_put_device = spi_nor_put_device;
  3148	
  3149		if (info->flags & USE_FSR)
  3150			nor->flags |= SNOR_F_USE_FSR;
  3151		if (info->flags & SPI_NOR_HAS_TB) {
  3152			nor->flags |= SNOR_F_HAS_SR_TB;
  3153			if (info->flags & SPI_NOR_TB_SR_BIT6)
  3154				nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
  3155		}
  3156	
  3157		if (info->flags & NO_CHIP_ERASE)
  3158			nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
  3159		if (info->flags & USE_CLSR)
  3160			nor->flags |= SNOR_F_USE_CLSR;
  3161		if (info->flags & SPI_NOR_SWP_IS_VOLATILE)
  3162			nor->flags |= SNOR_F_SWP_IS_VOLATILE;
  3163	
  3164		if (info->flags & SPI_NOR_4BIT_BP) {
  3165			nor->flags |= SNOR_F_HAS_4BIT_BP;
  3166			if (info->flags & SPI_NOR_BP3_SR_BIT6)
  3167				nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
  3168		}
  3169	
  3170		if (info->flags & SPI_NOR_NO_ERASE)
  3171			mtd->flags |= MTD_NO_ERASE;
  3172	
  3173		mtd->dev.parent = dev;
  3174		nor->page_size = nor->params->page_size;
  3175		mtd->writebufsize = nor->page_size;
  3176	
  3177		if (of_property_read_bool(np, "broken-flash-reset"))
  3178			nor->flags |= SNOR_F_BROKEN_RESET;
  3179	
  3180		/*
  3181		 * Configure the SPI memory:
  3182		 * - select op codes for (Fast) Read, Page Program and Sector Erase.
  3183		 * - set the number of dummy cycles (mode cycles + wait states).
  3184		 * - set the SPI protocols for register and memory accesses.
  3185		 */
  3186		ret = spi_nor_setup(nor, hwcaps);
  3187		if (ret)
  3188			return ret;
  3189	
  3190		if (info->flags & SPI_NOR_4B_OPCODES)
  3191			nor->flags |= SNOR_F_4B_OPCODES;
  3192	
  3193		if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
  3194			nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
  3195	
  3196		ret = spi_nor_set_addr_width(nor);
  3197		if (ret)
  3198			return ret;
  3199	
  3200		spi_nor_register_locking_ops(nor);
  3201	
> 3202		spi_nor_register_security_ops(nor);
  3203	
  3204		/* Send all the required SPI flash commands to initialize device */
  3205		ret = spi_nor_init(nor);
  3206		if (ret)
  3207			return ret;
  3208	
  3209		/* Configure OTP parameters and ops */
  3210		spi_nor_otp_init(nor);
  3211	
  3212		dev_info(dev, "%s (%lld Kbytes)\n", info->name,
  3213				(long long)mtd->size >> 10);
  3214	
  3215		dev_dbg(dev,
  3216			"mtd .name = %s, .size = 0x%llx (%lldMiB), "
  3217			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
  3218			mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
  3219			mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
  3220	
  3221		if (mtd->numeraseregions)
  3222			for (i = 0; i < mtd->numeraseregions; i++)
  3223				dev_dbg(dev,
  3224					"mtd.eraseregions[%d] = { .offset = 0x%llx, "
  3225					".erasesize = 0x%.8x (%uKiB), "
  3226					".numblocks = %d }\n",
  3227					i, (long long)mtd->eraseregions[i].offset,
  3228					mtd->eraseregions[i].erasesize,
  3229					mtd->eraseregions[i].erasesize / 1024,
  3230					mtd->eraseregions[i].numblocks);
  3231		return 0;
  3232	}
  3233	EXPORT_SYMBOL_GPL(spi_nor_scan);
  3234	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 40094 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211028/3df11d8d/attachment-0001.gz>

From schaecsn at gmx.net  Wed Oct 27 23:21:24 2021
From: schaecsn at gmx.net (Stefan Schaeckeler)
Date: Wed, 27 Oct 2021 23:21:24 -0700
Subject: [PATCH v3] ubifs: ubifs to export filesystem error counters
Message-ID: <20211028062124.12539-1-schaecsn@gmx.net>

From: Stefan Schaeckeler <sschaeck at cisco.com>

Not all ubifs filesystem errors are propagated to userspace.

Export bad magic, bad node and crc errors via sysfs. This allows userspace
to notice filesystem errors:

 /sys/fs/ubifs/ubiX_Y/errors_magic
 /sys/fs/ubifs/ubiX_Y/errors_node
 /sys/fs/ubifs/ubiX_Y/errors_crc

The counters are reset to 0 with a remount.

Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
---
Changes in v3:
  - Added Documentation/ABI/testing/sysfs-fs-ubifs
  - Added Documentation/ABI/testing/sysfs-fs-ubifs to MAINTAINERS

Changes in v2:
  - Merged sysfs.h header into ubifs.h.
  - io.c: wrapped incrementing error counters into new functions
    record_*_error().
  - sysfs.c: removed sysfs write callback for clearing stats.
  - sysfs.c: ubifs_sysfs_register(): free c->stats on error.
  - sysfs.c: use sysfs_emit().

 Documentation/ABI/testing/sysfs-fs-ubifs |  35 ++++++
 MAINTAINERS                              |   1 +
 fs/ubifs/Makefile                        |   2 +-
 fs/ubifs/io.c                            |  21 ++++
 fs/ubifs/super.c                         |  16 ++-
 fs/ubifs/sysfs.c                         | 153 +++++++++++++++++++++++
 fs/ubifs/ubifs.h                         |  35 ++++++
 7 files changed, 261 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-fs-ubifs
 create mode 100644 fs/ubifs/sysfs.c

diff --git a/Documentation/ABI/testing/sysfs-fs-ubifs b/Documentation/ABI/testing/sysfs-fs-ubifs
new file mode 100644
index 000000000000..19a8ebf7fe61
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-ubifs
@@ -0,0 +1,35 @@
+What:		/sys/fs/ubifsX_Y/error_magic
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes magic errors: every node starts with a magic number.
+
+		This counter keeps track of the number of accesses of nodes
+		with a corrupted magic number.
+
+		The counter is reset to 0 with a remount.
+
+What:		/sys/fs/ubifsX_Y/error_node
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes node errors. Every node embeds its type.
+
+		This counter keeps track of the number of accesses of nodes
+		with a corrupted node type.
+
+		The counter is reset to 0 with a remount.
+
+What:		/sys/fs/ubifsX_Y/error_crc
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes crc errors: every node embeds a crc checksum.
+
+		This counter keeps track of the number of accesses of nodes
+		with a bad crc checksum.
+
+		The counter is reset to 0 with a remount.
diff --git a/MAINTAINERS b/MAINTAINERS
index b43662a9a5f3..a8f0e3e38b2e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19105,6 +19105,7 @@ S:	Supported
 W:	http://www.linux-mtd.infradead.org/doc/ubifs.html
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
+F:	Documentation/ABI/testing/sysfs-fs-ubifs
 F:	Documentation/filesystems/ubifs-authentication.rst
 F:	Documentation/filesystems/ubifs.rst
 F:	fs/ubifs/
diff --git a/fs/ubifs/Makefile b/fs/ubifs/Makefile
index 5c4b845754a7..314c80b24a76 100644
--- a/fs/ubifs/Makefile
+++ b/fs/ubifs/Makefile
@@ -5,7 +5,7 @@ ubifs-y += shrinker.o journal.o file.o dir.o super.o sb.o io.o
 ubifs-y += tnc.o master.o scan.o replay.o log.o commit.o gc.o orphan.o
 ubifs-y += budget.o find.o tnc_commit.o compress.o lpt.o lprops.o
 ubifs-y += recovery.o ioctl.o lpt_commit.o tnc_misc.o debug.o
-ubifs-y += misc.o
+ubifs-y += misc.o sysfs.o
 ubifs-$(CONFIG_FS_ENCRYPTION) += crypto.o
 ubifs-$(CONFIG_UBIFS_FS_XATTR) += xattr.o
 ubifs-$(CONFIG_UBIFS_FS_AUTHENTICATION) += auth.o
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 00b61dba62b7..789a7813f3fa 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -194,6 +194,24 @@ int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
 	return err;
 }

+static void record_magic_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->magic_errors++;
+}
+
+static void record_node_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->node_errors++;
+}
+
+static void record_crc_error(struct ubifs_stats_info *stats)
+{
+	if (stats)
+		stats->crc_errors++;
+}
+
 /**
  * ubifs_check_node - check node.
  * @c: UBIFS file-system description object
@@ -238,6 +256,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 		if (!quiet)
 			ubifs_err(c, "bad magic %#08x, expected %#08x",
 				  magic, UBIFS_NODE_MAGIC);
+		record_magic_error(c->stats);
 		err = -EUCLEAN;
 		goto out;
 	}
@@ -246,6 +265,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 	if (type < 0 || type >= UBIFS_NODE_TYPES_CNT) {
 		if (!quiet)
 			ubifs_err(c, "bad node type %d", type);
+		record_node_error(c->stats);
 		goto out;
 	}

@@ -270,6 +290,7 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int len,
 		if (!quiet)
 			ubifs_err(c, "bad CRC: calculated %#08x, read %#08x",
 				  crc, node_crc);
+		record_crc_error(c->stats);
 		err = -EUCLEAN;
 		goto out;
 	}
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f0fb25727d96..a4e3a143fb1b 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1264,6 +1264,10 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		return err;

+	err = ubifs_sysfs_register(c);
+	if (err)
+		goto out_debugging;
+
 	err = check_volume_empty(c);
 	if (err)
 		goto out_free;
@@ -1641,6 +1645,8 @@ static int mount_ubifs(struct ubifs_info *c)
 	vfree(c->sbuf);
 	kfree(c->bottom_up_buf);
 	kfree(c->sup_node);
+	ubifs_sysfs_unregister(c);
+out_debugging:
 	ubifs_debugging_exit(c);
 	return err;
 }
@@ -1684,6 +1690,7 @@ static void ubifs_umount(struct ubifs_info *c)
 	kfree(c->bottom_up_buf);
 	kfree(c->sup_node);
 	ubifs_debugging_exit(c);
+	ubifs_sysfs_unregister(c);
 }

 /**
@@ -2436,14 +2443,20 @@ static int __init ubifs_init(void)

 	dbg_debugfs_init();

+	err = ubifs_sysfs_init();
+	if (err)
+		goto out_dbg;
+
 	err = register_filesystem(&ubifs_fs_type);
 	if (err) {
 		pr_err("UBIFS error (pid %d): cannot register file system, error %d",
 		       current->pid, err);
-		goto out_dbg;
+		goto out_sysfs;
 	}
 	return 0;

+out_sysfs:
+	ubifs_sysfs_exit();
 out_dbg:
 	dbg_debugfs_exit();
 	ubifs_compressors_exit();
@@ -2462,6 +2475,7 @@ static void __exit ubifs_exit(void)
 	WARN_ON(atomic_long_read(&ubifs_clean_zn_cnt) != 0);

 	dbg_debugfs_exit();
+	ubifs_sysfs_exit();
 	ubifs_compressors_exit();
 	unregister_shrinker(&ubifs_shrinker_info);

diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
new file mode 100644
index 000000000000..0eb3d7d12450
--- /dev/null
+++ b/fs/ubifs/sysfs.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * This file is part of UBIFS.
+ *
+ * Copyright (C) 2021 Cisco Systems
+ *
+ * Author: Stefan Schaeckeler
+ */
+
+
+#include <linux/fs.h>
+#include "ubifs.h"
+
+enum attr_id_t {
+	attr_errors_magic,
+	attr_errors_node,
+	attr_errors_crc,
+};
+
+struct ubifs_attr {
+	struct attribute attr;
+	enum attr_id_t attr_id;
+};
+
+#define UBIFS_ATTR(_name, _mode, _id)					\
+static struct ubifs_attr ubifs_attr_##_name = {				\
+	.attr = {.name = __stringify(_name), .mode = _mode },		\
+	.attr_id = attr_##_id,						\
+}
+
+#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
+
+UBIFS_ATTR_FUNC(errors_magic, 0444);
+UBIFS_ATTR_FUNC(errors_crc, 0444);
+UBIFS_ATTR_FUNC(errors_node, 0444);
+
+#define ATTR_LIST(name) (&ubifs_attr_##name.attr)
+
+static struct attribute *ubifs_attrs[] = {
+	ATTR_LIST(errors_magic),
+	ATTR_LIST(errors_node),
+	ATTR_LIST(errors_crc),
+	NULL,
+};
+
+static ssize_t ubifs_attr_show(struct kobject *kobj,
+			       struct attribute *attr, char *buf)
+{
+	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
+					      kobj);
+
+	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
+
+	switch (a->attr_id) {
+	case attr_errors_magic:
+		return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
+	case attr_errors_node:
+		return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
+	case attr_errors_crc:
+		return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
+	}
+	return 0;
+};
+
+static void ubifs_sb_release(struct kobject *kobj)
+{
+	struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
+
+	complete(&c->kobj_unregister);
+}
+
+static const struct sysfs_ops ubifs_attr_ops = {
+	.show	= ubifs_attr_show,
+};
+
+static struct kobj_type ubifs_sb_ktype = {
+	.default_attrs	= ubifs_attrs,
+	.sysfs_ops	= &ubifs_attr_ops,
+	.release	= ubifs_sb_release,
+};
+
+static struct kobj_type ubifs_ktype = {
+	.sysfs_ops	= &ubifs_attr_ops,
+};
+
+static struct kset ubifs_kset = {
+	.kobj	= {.ktype = &ubifs_ktype},
+};
+
+int ubifs_sysfs_register(struct ubifs_info *c)
+{
+	int ret, n;
+	char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];
+
+	c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
+	if (!c->stats) {
+		ret = -ENOMEM;
+		goto out_last;
+	}
+	n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
+		     c->vi.ubi_num, c->vi.vol_id);
+
+	if (n == UBIFS_DFS_DIR_LEN) {
+		/* The array size is too small */
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+	c->kobj.kset = &ubifs_kset;
+	init_completion(&c->kobj_unregister);
+
+	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
+				   "%s", dfs_dir_name);
+	if (ret)
+		goto out_put;
+
+	return 0;
+
+out_put:
+	kobject_put(&c->kobj);
+	wait_for_completion(&c->kobj_unregister);
+out_free:
+	kfree(c->stats);
+out_last:
+	ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
+		  c->vi.ubi_num, c->vi.vol_id, ret);
+	return ret;
+}
+
+void ubifs_sysfs_unregister(struct ubifs_info *c)
+{
+	kobject_del(&c->kobj);
+	kobject_put(&c->kobj);
+	wait_for_completion(&c->kobj_unregister);
+
+	kfree(c->stats);
+}
+
+int __init ubifs_sysfs_init(void)
+{
+	int ret;
+
+	kobject_set_name(&ubifs_kset.kobj, "ubifs");
+	ubifs_kset.kobj.parent = fs_kobj;
+	ret = kset_register(&ubifs_kset);
+
+	return ret;
+}
+
+void ubifs_sysfs_exit(void)
+{
+	kset_unregister(&ubifs_kset);
+}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index c38066ce9ab0..f55828c0a300 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -27,6 +27,8 @@
 #include <linux/security.h>
 #include <linux/xattr.h>
 #include <linux/random.h>
+#include <linux/sysfs.h>
+#include <linux/completion.h>
 #include <crypto/hash_info.h>
 #include <crypto/hash.h>
 #include <crypto/algapi.h>
@@ -155,6 +157,13 @@
 #define UBIFS_HMAC_ARR_SZ 0
 #endif

+/*
+ * The UBIFS sysfs directory name pattern and maximum name length (3 for "ubi"
+ * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
+ */
+#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
+#define UBIFS_DFS_DIR_LEN  (3 + 1 + 2*2 + 1)
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
@@ -990,6 +999,18 @@ struct ubifs_budg_info {
 	int dent_budget;
 };

+/**
+ * ubifs_stats_info - per-FS statistics information.
+ * @magic_errors: number of bad magic numbers (will be reset with a new mount).
+ * @node_errors: number of bad nodes (will be reset with a new mount).
+ * @crc_errors: number of bad crcs (will be reset with a new mount).
+ */
+struct ubifs_stats_info {
+	unsigned int magic_errors;
+	unsigned int node_errors;
+	unsigned int crc_errors;
+};
+
 struct ubifs_debug_info;

 /**
@@ -1251,6 +1272,10 @@ struct ubifs_debug_info;
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg: debugging-related information
+ * @stats: statistics exported over sysfs
+ *
+ * @kobj: kobject for /sys/fs/ubifs/
+ * @kobj_unregister: completion to unregister sysfs kobject
  */
 struct ubifs_info {
 	struct super_block *vfs_sb;
@@ -1286,6 +1311,9 @@ struct ubifs_info {
 	spinlock_t cs_lock;
 	wait_queue_head_t cmt_wq;

+	struct kobject kobj;
+	struct completion kobj_unregister;
+
 	unsigned int big_lpt:1;
 	unsigned int space_fixup:1;
 	unsigned int double_hash:1;
@@ -1493,6 +1521,7 @@ struct ubifs_info {
 	struct ubifs_mount_opts mount_opts;

 	struct ubifs_debug_info *dbg;
+	struct ubifs_stats_info *stats;
 };

 extern struct list_head ubifs_infos;
@@ -2072,6 +2101,12 @@ void ubifs_compress(const struct ubifs_info *c, const void *in_buf, int in_len,
 int ubifs_decompress(const struct ubifs_info *c, const void *buf, int len,
 		     void *out, int *out_len, int compr_type);

+/* sysfs.c */
+int ubifs_sysfs_init(void);
+void ubifs_sysfs_exit(void);
+int ubifs_sysfs_register(struct ubifs_info *c);
+void ubifs_sysfs_unregister(struct ubifs_info *c);
+
 #include "debug.h"
 #include "misc.h"
 #include "key.h"
--
2.33.0



From richard at nod.at  Thu Oct 28 00:16:16 2021
From: richard at nod.at (Richard Weinberger)
Date: Thu, 28 Oct 2021 09:16:16 +0200 (CEST)
Subject: [PATCH v3] ubifs: ubifs to export filesystem error counters
In-Reply-To: <20211028062124.12539-1-schaecsn@gmx.net>
References: <20211028062124.12539-1-schaecsn@gmx.net>
Message-ID: <791707806.43634.1635405376333.JavaMail.zimbra@nod.at>

Stefan,

----- Urspr?ngliche Mail -----
> Von: "schaecsn" <schaecsn at gmx.net>
> An: "richard" <richard at nod.at>, "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel"
> <linux-kernel at vger.kernel.org>
> CC: "Stefan Schaeckeler" <sschaeck at cisco.com>
> Gesendet: Donnerstag, 28. Oktober 2021 08:21:24
> Betreff: [PATCH v3] ubifs: ubifs to export filesystem error counters

> From: Stefan Schaeckeler <sschaeck at cisco.com>
> 
> Not all ubifs filesystem errors are propagated to userspace.
> 
> Export bad magic, bad node and crc errors via sysfs. This allows userspace
> to notice filesystem errors:
> 
> /sys/fs/ubifs/ubiX_Y/errors_magic
> /sys/fs/ubifs/ubiX_Y/errors_node
> /sys/fs/ubifs/ubiX_Y/errors_crc
> 
> The counters are reset to 0 with a remount.
> 
> Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
> ---
> Changes in v3:
>  - Added Documentation/ABI/testing/sysfs-fs-ubifs
>  - Added Documentation/ABI/testing/sysfs-fs-ubifs to MAINTAINERS

I asked for just the Documentation. v2 of your patch is already in linux-next. :-)

Thanks,
//richard


From schaecsn at gmx.net  Thu Oct 28 00:44:04 2021
From: schaecsn at gmx.net (Stefan Schaeckeler)
Date: Thu, 28 Oct 2021 00:44:04 -0700
Subject: [PATCH] ubifs: document sysfs nodes
Message-ID: <20211028074404.9739-1-schaecsn@gmx.net>

From: Stefan Schaeckeler <sschaeck at cisco.com>

Add documentation for the new sysfs nodes

 /sys/fs/ubifs/ubiX_Y/errors_magic
 /sys/fs/ubifs/ubiX_Y/errors_node
 /sys/fs/ubifs/ubiX_Y/errors_crc

Signed-off-by: Stefan Schaeckeler <sschaeck at cisco.com>
---
 Documentation/ABI/testing/sysfs-fs-ubifs | 35 ++++++++++++++++++++++++
 MAINTAINERS                              |  1 +
 2 files changed, 36 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-fs-ubifs

diff --git a/Documentation/ABI/testing/sysfs-fs-ubifs b/Documentation/ABI/testing/sysfs-fs-ubifs
new file mode 100644
index 000000000000..19a8ebf7fe61
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-ubifs
@@ -0,0 +1,35 @@
+What:		/sys/fs/ubifsX_Y/error_magic
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes magic errors: every node starts with a magic number.
+
+		This counter keeps track of the number of accesses of nodes
+		with a corrupted magic number.
+
+		The counter is reset to 0 with a remount.
+
+What:		/sys/fs/ubifsX_Y/error_node
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes node errors. Every node embeds its type.
+
+		This counter keeps track of the number of accesses of nodes
+		with a corrupted node type.
+
+		The counter is reset to 0 with a remount.
+
+What:		/sys/fs/ubifsX_Y/error_crc
+Date:		October 2021
+KernelVersion:	5.16
+Contact:	linux-mtd at lists.infradead.org
+Description:
+		Exposes crc errors: every node embeds a crc checksum.
+
+		This counter keeps track of the number of accesses of nodes
+		with a bad crc checksum.
+
+		The counter is reset to 0 with a remount.
diff --git a/MAINTAINERS b/MAINTAINERS
index b43662a9a5f3..a8f0e3e38b2e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -19105,6 +19105,7 @@ S:	Supported
 W:	http://www.linux-mtd.infradead.org/doc/ubifs.html
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git next
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs.git fixes
+F:	Documentation/ABI/testing/sysfs-fs-ubifs
 F:	Documentation/filesystems/ubifs-authentication.rst
 F:	Documentation/filesystems/ubifs.rst
 F:	fs/ubifs/
--
2.33.0



From S.Riedmueller at phytec.de  Thu Oct 28 02:28:00 2021
From: S.Riedmueller at phytec.de (=?utf-8?B?U3RlZmFuIFJpZWRtw7xsbGVy?=)
Date: Thu, 28 Oct 2021 09:28:00 +0000
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <20211022143514.lplk6jaxklq3rxry@umbrella>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
 <20211013050148.2w373kpbfaeuxbwm@umbrella>
 <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>
 <20211022143514.lplk6jaxklq3rxry@umbrella>
Message-ID: <3c7415036ad62278e144da43198490c3c57d5721.camel@phytec.de>

Hi Han,

On Fri, 2021-10-22 at 09:35 -0500, han.xu at nxp.com wrote:
> On 21/10/22 08:45AM, Stefan Riedm?ller wrote:
> > Hi Han,
> > 
> > sorry it took me some time to get back to you.
> > 
> > On Wed, 2021-10-13 at 00:01 -0500, Han Xu wrote:
> > > On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> > > > According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> > > > when doing a gpmi_io clk rate change. So gate the clocks off before
> > > > the rate change in nfc_apply_timings and ungate them again after the
> > > > change.
> > > > 
> > > > Otherwise this rate change can lead to an unresponsive GPMI core which
> > > > results in DMA timeouts and failed driver probe:
> > > > 
> > > > [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> > > > ...
> > > > [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> > > > ...
> > > > [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read:
> > > > -22
> > > > [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > ...
> > > > 
> > > > Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> > > > ---
> > > > Hi,
> > > > 
> > > > I'm not sure about the error handling here, if it is actually
> > > > neccessary.
> > > > So some feedback would be nice here.
> > > > 
> > > > Thanks,
> > > > Stefan
> > > > ---
> > > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
> > > >  1 file changed, 19 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > index a1f7000f033e..326c8a895f1f 100644
> > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct
> > > > gpmi_nand_data *this,
> > > >  			      (use_half_period ?
> > > > BM_GPMI_CTRL1_HALF_PERIOD :
> > > > 0);
> > > >  }
> > > >  
> > > > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > >  {
> > > >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > >  	struct resources *r = &this->resources;
> > > >  	void __iomem *gpmi_regs = r->gpmi_regs;
> > > >  	unsigned int dll_wait_time_us;
> > > > +	int ret;
> > > > +
> > > > +	if (GPMI_IS_MX6Q(this)) {
> > > 
> > > Not only for 6Q but for GPMI_IS_MX6
> > 
> > Can you confirm that i.MX 6SX and i.MX 7 are affected by the ERR007117
> > erratum
> > as well? Because the i.MX 6UL/ULL are included by the GPMI_IS_MX6Q
> > already.
> 
> i.MX6SX has the glitch issue for sure, but I can double check if it's due to
> the
> same errata. I will also go check if the errata will affect i.MX7

Any updates yet?

Thanks,
Stefan

> 
> > Or do we need another macro for i.MX 6UL/ULL as Christian has suggested
> > earlier?
> > 
> > Thanks,
> > Stefan
> > 
> > > > +		ret = __gpmi_enable_clk(this, false);
> > > > +		if (ret)
> > > > +			return ret;
> > > > +	}
> > > >  
> > > >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > > >  
> > > > +	if (GPMI_IS_MX6Q(this)) {
> > > > +		ret = __gpmi_enable_clk(this, true);
> > > > +		if (ret)
> > > > +			return ret;
> > > > +	}
> > > > +
> > > >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > >  
> > > > @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct
> > > > gpmi_nand_data *this)
> > > >  
> > > >  	/* Wait for the DLL to settle. */
> > > >  	udelay(dll_wait_time_us);
> > > > +
> > > > +	return 0;
> > > >  }
> > > >  
> > > >  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > > > @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip
> > > > *chip,
> > > >  	 */
> > > >  	if (this->hw.must_apply_timings) {
> > > >  		this->hw.must_apply_timings = false;
> > > > -		gpmi_nfc_apply_timings(this);
> > > > +		ret = gpmi_nfc_apply_timings(this);
> > > > +		if (ret)
> > > > +			return ret;
> > > >  	}
> > > >  
> > > >  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op-
> > > > >ninstrs);
> > > > -- 
> > > > 2.25.1
> > > > 

From p.yadav at ti.com  Thu Oct 28 05:45:15 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 28 Oct 2021 18:15:15 +0530
Subject: [PATCH v2 0/3] Add bindings for slave-specific SPI controller
 properties
Message-ID: <20211028124518.17370-1-p.yadav@ti.com>

Hi,

This series adds bindings for slave-specific SPI controller properties.
See patch 1 for more info on the motivations behind this.

This is the best approach that I came up with with my limited knowledge
of JSON schema. It has some limitations that are mentioned in patch 1. I
don't know of any better ways to model this. Suggestions are welcome!

Changes in v2:
- Move other subnode properties listed in spi-controller.yaml to
  spi-slave-props.yaml
- Move the Cadence controller-specific properties out of
  spi-slave-props.yaml. They will be added in a separate file.
- Add a reference to spi-slave-props.yaml in spi-controller.yaml.
- Update description.

Pratyush Yadav (3):
  spi: dt-bindings: add schema listing slave-specific properties
  spi: dt-bindings: cdns,qspi-nor: Move slave-specific properties out
  dt-bindings: mtd: spi-nor: Add a reference to spi-slave-props.yaml

 .../bindings/mtd/jedec,spi-nor.yaml           |  3 +-
 .../spi/cdns,qspi-nor-slave-props.yaml        | 42 +++++++++
 .../bindings/spi/cdns,qspi-nor.yaml           | 33 -------
 .../bindings/spi/spi-controller.yaml          | 69 +-------------
 .../bindings/spi/spi-slave-props.yaml         | 93 +++++++++++++++++++
 5 files changed, 139 insertions(+), 101 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/cdns,qspi-nor-slave-props.yaml
 create mode 100644 Documentation/devicetree/bindings/spi/spi-slave-props.yaml

-- 
2.33.1.835.ge9e5ba39a7



From p.yadav at ti.com  Thu Oct 28 05:45:16 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 28 Oct 2021 18:15:16 +0530
Subject: [PATCH v2 1/3] spi: dt-bindings: add schema listing slave-specific
 properties
In-Reply-To: <20211028124518.17370-1-p.yadav@ti.com>
References: <20211028124518.17370-1-p.yadav@ti.com>
Message-ID: <20211028124518.17370-2-p.yadav@ti.com>

Many SPI controllers need to add properties to slave devices. This could
be the delay in clock or data lines, etc. These properties are
controller specific but need to be defined in the slave node because
they are per-slave and there can be multiple slaves attached to a
controller.

If these properties are not added to the slave binding, then the dtbs
check emits a warning. But these properties do not make much sense in
the slave binding because they are controller-specific and they will
just pollute every slave binding. So this binding is added to collect
all such properties from all such controllers. Slave bindings should
simply refer to this binding and they should be rid of the warnings.

There are some limitations with this approach. Firstly, there is no way
to specify required properties. The schema contains properties for all
controllers and there is no way to know which controller is being used.
Secondly, there is no way to restrict additional properties. Since this
schema will be used with an allOf operator, additionalProperties needs
to be true. In addition, the slave schema will have to set
unevaluatedProperties: false.

Despite these limitations, this appears to be the best solution to this
problem that doesn't involve modifying existing tools or schema specs.

Signed-off-by: Pratyush Yadav <p.yadav at ti.com>

---

Changes in v2:
- Move other subnode properties listed in spi-controller.yaml to
  spi-slave-props.yaml
- Move the Cadence controller-specific properties out of
  spi-slave-props.yaml. They will be added in a separate file.
- Add a reference to spi-slave-props.yaml in spi-controller.yaml.
- Update description.

 .../bindings/spi/spi-controller.yaml          | 69 +-------------
 .../bindings/spi/spi-slave-props.yaml         | 91 +++++++++++++++++++
 2 files changed, 93 insertions(+), 67 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-slave-props.yaml

diff --git a/Documentation/devicetree/bindings/spi/spi-controller.yaml b/Documentation/devicetree/bindings/spi/spi-controller.yaml
index 8246891602e7..ff770657e214 100644
--- a/Documentation/devicetree/bindings/spi/spi-controller.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-controller.yaml
@@ -94,73 +94,8 @@ patternProperties:
   "^.*@[0-9a-f]+$":
     type: object
 
-    properties:
-      compatible:
-        description:
-          Compatible of the SPI device.
-
-      reg:
-        minItems: 1
-        maxItems: 256
-        items:
-          minimum: 0
-          maximum: 256
-        description:
-          Chip select used by the device.
-
-      spi-3wire:
-        $ref: /schemas/types.yaml#/definitions/flag
-        description:
-          The device requires 3-wire mode.
-
-      spi-cpha:
-        $ref: /schemas/types.yaml#/definitions/flag
-        description:
-          The device requires shifted clock phase (CPHA) mode.
-
-      spi-cpol:
-        $ref: /schemas/types.yaml#/definitions/flag
-        description:
-          The device requires inverse clock polarity (CPOL) mode.
-
-      spi-cs-high:
-        $ref: /schemas/types.yaml#/definitions/flag
-        description:
-          The device requires the chip select active high.
-
-      spi-lsb-first:
-        $ref: /schemas/types.yaml#/definitions/flag
-        description:
-          The device requires the LSB first mode.
-
-      spi-max-frequency:
-        $ref: /schemas/types.yaml#/definitions/uint32
-        description:
-          Maximum SPI clocking speed of the device in Hz.
-
-      spi-rx-bus-width:
-        description:
-          Bus width to the SPI bus used for read transfers.
-          If 0 is provided, then no RX will be possible on this device.
-        $ref: /schemas/types.yaml#/definitions/uint32
-        enum: [0, 1, 2, 4, 8]
-        default: 1
-
-      spi-rx-delay-us:
-        description:
-          Delay, in microseconds, after a read transfer.
-
-      spi-tx-bus-width:
-        description:
-          Bus width to the SPI bus used for write transfers.
-          If 0 is provided, then no TX will be possible on this device.
-        $ref: /schemas/types.yaml#/definitions/uint32
-        enum: [0, 1, 2, 4, 8]
-        default: 1
-
-      spi-tx-delay-us:
-        description:
-          Delay, in microseconds, after a write transfer.
+    allOf:
+      - $ref: spi-slave-props.yaml
 
     required:
       - compatible
diff --git a/Documentation/devicetree/bindings/spi/spi-slave-props.yaml b/Documentation/devicetree/bindings/spi/spi-slave-props.yaml
new file mode 100644
index 000000000000..5166ec9b0353
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-slave-props.yaml
@@ -0,0 +1,91 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/spi-slave-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Slave-specific properties for a SPI bus.
+
+description: |
+  Many SPI controllers need to add properties to slave devices. They could be
+  common properties like spi-max-frequency, spi-cpha, etc. or they could be
+  controller specific like delay in clock or data lines, etc. These properties
+  need to be defined in the slave node because they are per-slave and there can
+  be multiple slaves attached to a controller. All those properties are listed
+  here. The controller specific properties should go in their own separate
+  schema that should be referenced from here.
+
+maintainers:
+  - Pratyush Yadav <p.yadav at ti.com>
+
+properties:
+  compatible:
+    description:
+      Compatible of the SPI device.
+
+  reg:
+    minItems: 1
+    maxItems: 256
+    items:
+      minimum: 0
+      maximum: 256
+    description:
+      Chip select used by the device.
+
+  spi-3wire:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      The device requires 3-wire mode.
+
+  spi-cpha:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      The device requires shifted clock phase (CPHA) mode.
+
+  spi-cpol:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      The device requires inverse clock polarity (CPOL) mode.
+
+  spi-cs-high:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      The device requires the chip select active high.
+
+  spi-lsb-first:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      The device requires the LSB first mode.
+
+  spi-max-frequency:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Maximum SPI clocking speed of the device in Hz.
+
+  spi-rx-bus-width:
+    description:
+      Bus width to the SPI bus used for read transfers.
+      If 0 is provided, then no RX will be possible on this device.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 4, 8]
+    default: 1
+
+  spi-rx-delay-us:
+    description:
+      Delay, in microseconds, after a read transfer.
+
+  spi-tx-bus-width:
+    description:
+      Bus width to the SPI bus used for write transfers.
+      If 0 is provided, then no TX will be possible on this device.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1, 2, 4, 8]
+    default: 1
+
+  spi-tx-delay-us:
+    description:
+      Delay, in microseconds, after a write transfer.
+
+# The controller specific properties go here.
+
+additionalProperties: true
-- 
2.33.1.835.ge9e5ba39a7



From p.yadav at ti.com  Thu Oct 28 05:45:17 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 28 Oct 2021 18:15:17 +0530
Subject: [PATCH v2 2/3] spi: dt-bindings: cdns,
 qspi-nor: Move slave-specific properties out
In-Reply-To: <20211028124518.17370-1-p.yadav@ti.com>
References: <20211028124518.17370-1-p.yadav@ti.com>
Message-ID: <20211028124518.17370-3-p.yadav@ti.com>

The spi-slave-props.yaml schema contains slave-specific properties
for SPI controllers that should be present in the slave node. Move
slave-specific properties to a separate file and refer to it in
spi-slave-props.yaml.

Signed-off-by: Pratyush Yadav <p.yadav at ti.com>

---

Changes in v2:
- New in v2.

 .../spi/cdns,qspi-nor-slave-props.yaml        | 42 +++++++++++++++++++
 .../bindings/spi/cdns,qspi-nor.yaml           | 33 ---------------
 .../bindings/spi/spi-slave-props.yaml         |  2 +
 3 files changed, 44 insertions(+), 33 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/cdns,qspi-nor-slave-props.yaml

diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor-slave-props.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor-slave-props.yaml
new file mode 100644
index 000000000000..263382a5729a
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor-slave-props.yaml
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/cdns,qspi-nor-slave-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Slave-specific properties for the Cadence QSPI controller.
+
+description:
+  See spi-slave-props.yaml for more info.
+
+maintainers:
+  - Pratyush Yadav <p.yadav at ti.com>
+
+properties:
+  # cdns,qspi-nor.yaml
+  cdns,read-delay:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Delay for read capture logic, in clock cycles.
+
+  cdns,tshsl-ns:
+    description:
+      Delay in nanoseconds for the length that the master mode chip select
+      outputs are de-asserted between transactions.
+
+  cdns,tsd2d-ns:
+    description:
+      Delay in nanoseconds between one chip select being de-activated
+      and the activation of another.
+
+  cdns,tchsh-ns:
+    description:
+      Delay in nanoseconds between last bit of current transaction and
+      deasserting the device chip select (qspi_n_ss_out).
+
+  cdns,tslch-ns:
+    description:
+      Delay in nanoseconds between setting qspi_n_ss_out low and
+      first bit transfer.
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
index ca155abbda7a..a439e3ed753f 100644
--- a/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
+++ b/Documentation/devicetree/bindings/spi/cdns,qspi-nor.yaml
@@ -86,39 +86,6 @@ properties:
     items:
       enum: [ qspi, qspi-ocp ]
 
-# subnode's properties
-patternProperties:
-  "@[0-9a-f]+$":
-    type: object
-    description:
-      Flash device uses the below defined properties in the subnode.
-
-    properties:
-      cdns,read-delay:
-        $ref: /schemas/types.yaml#/definitions/uint32
-        description:
-          Delay for read capture logic, in clock cycles.
-
-      cdns,tshsl-ns:
-        description:
-          Delay in nanoseconds for the length that the master mode chip select
-          outputs are de-asserted between transactions.
-
-      cdns,tsd2d-ns:
-        description:
-          Delay in nanoseconds between one chip select being de-activated
-          and the activation of another.
-
-      cdns,tchsh-ns:
-        description:
-          Delay in nanoseconds between last bit of current transaction and
-          deasserting the device chip select (qspi_n_ss_out).
-
-      cdns,tslch-ns:
-        description:
-          Delay in nanoseconds between setting qspi_n_ss_out low and
-          first bit transfer.
-
 required:
   - compatible
   - reg
diff --git a/Documentation/devicetree/bindings/spi/spi-slave-props.yaml b/Documentation/devicetree/bindings/spi/spi-slave-props.yaml
index 5166ec9b0353..4cc12a161da9 100644
--- a/Documentation/devicetree/bindings/spi/spi-slave-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-slave-props.yaml
@@ -87,5 +87,7 @@ properties:
       Delay, in microseconds, after a write transfer.
 
 # The controller specific properties go here.
+allOf:
+  - $ref: cdns,qspi-nor-slave-props.yaml#
 
 additionalProperties: true
-- 
2.33.1.835.ge9e5ba39a7



From p.yadav at ti.com  Thu Oct 28 05:45:18 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Thu, 28 Oct 2021 18:15:18 +0530
Subject: [PATCH v2 3/3] dt-bindings: mtd: spi-nor: Add a reference to
 spi-slave-props.yaml
In-Reply-To: <20211028124518.17370-1-p.yadav@ti.com>
References: <20211028124518.17370-1-p.yadav@ti.com>
Message-ID: <20211028124518.17370-4-p.yadav@ti.com>

The spi-slave-props.yaml schema contains slave-specific properties
for SPI controllers that should be present in the slave node. Add a
reference to that so its constraints are followed.

additionalProperties: false cannot be used since it marks the controller
properties as unknown. Use unevaluatedProperties: false instead. This
has the side effect of allowing extra properties that are not specified
in the schema. The alternative is to list all the controller properties
in this schema but that would mean every slave binding would have to
repeat the same set of properties for each controller.

Signed-off-by: Pratyush Yadav <p.yadav at ti.com>

---

(no changes since v1)

 Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
index ed590d7c6e37..e69a8fbb91f1 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
@@ -11,6 +11,7 @@ maintainers:
 
 allOf:
   - $ref: "mtd.yaml#"
+  - $ref: /schemas/spi/spi-slave-props.yaml#
 
 properties:
   compatible:
@@ -88,7 +89,7 @@ patternProperties:
   "^otp(-[0-9]+)?$":
     type: object
 
-additionalProperties: false
+unevaluatedProperties: false
 
 examples:
   - |
-- 
2.33.1.835.ge9e5ba39a7



From twoerner at gmail.com  Thu Oct 28 06:31:19 2021
From: twoerner at gmail.com (Trevor Woerner)
Date: Thu, 28 Oct 2021 09:31:19 -0400
Subject: [PATCH 0/3] mtdblock: Advertise about UBI and UBI block
In-Reply-To: <876982414.38679.1635274892099.JavaMail.zimbra@nod.at>
References: <20210801234509.18774-1-ezequiel@collabora.com>
 <20211026150350.GA5136@localhost>
 <876982414.38679.1635274892099.JavaMail.zimbra@nod.at>
Message-ID: <20211028133119.GA21237@localhost>

On Tue 2021-10-26 @ 09:01:32 PM, Richard Weinberger wrote:
> Trevor,
> 
> ----- Urspr?ngliche Mail -----
> > Von: "Trevor Woerner" <twoerner at gmail.com>
> > An: "Ezequiel Garcia" <ezequiel at collabora.com>
> > CC: "linux-mtd" <linux-mtd at lists.infradead.org>, "linux-kernel" <linux-kernel at vger.kernel.org>, "richard"
> > <richard at nod.at>, "Miquel Raynal" <miquel.raynal at bootlin.com>, "Vignesh Raghavendra" <vigneshr at ti.com>
> > Gesendet: Dienstag, 26. Oktober 2021 17:03:50
> > Betreff: Re: [PATCH 0/3] mtdblock: Advertise about UBI and UBI block
> 
> > On Sun 2021-08-01 @ 08:45:02 PM, Ezequiel Garcia wrote:
> >> Hi Richard, and everyone else:
> >> 
> >> Browsing the internet for "JFFS2 mtd" results in tutorials, articles
> >> and github.gists0 that point to mtdblock.
> >> 
> >> In fact, even the MTD wiki mentions that JFFS2
> >> needs mtdblock to mount a rootfs:
> >> 
> >>   http://www.linux-mtd.infradead.org/faq/jffs2.html
> >> 
> >> Moreover, I suspect there may be lots of users
> >> that still believe mtdblock is somehow needed to
> >> mount SquashFS.
> >> 
> >> I've taken a verbose route and added a pr_warn
> >> warning if the devices are NAND. I don't think using
> >> NAND without UBI is too wise, and given the amount
> >> of outdated tutorials I believe some advertising
> >> will help.
> > 
> > Not all NAND partitions on a device will contain linux root filesystems. For a
> > linux root filesystem perhaps using UBI/UBIFS is preferred, yet these messages
> > print out for each and every NAND partition:
> > 
> >	[    0.900827] Creating 8 MTD partitions on "nxp_lpc3220_slc":
> >	[    0.906431] 0x000000000000-0x000000020000 : "bootrom"
> >	[    0.913523] mtdblock: MTD device 'bootrom' is NAND, please consider using UBI
> >	block devices instead.
> >	[    0.933334] 0x000000020000-0x000000080000 : "uboot"
> >	[    0.940439] mtdblock: MTD device 'uboot' is NAND, please consider using UBI
> >	block devices instead.
> >	[    0.963322] 0x000000080000-0x000000440000 : "fbkernel"
> >	[    0.970655] mtdblock: MTD device 'fbkernel' is NAND, please consider using
> >	UBI block devices instead.
> >	[    0.993361] 0x000000440000-0x000000920000 : "fbrootfs"
> >	[    1.000725] mtdblock: MTD device 'fbrootfs' is NAND, please consider using
> >	UBI block devices instead.
> >	[    1.023315] 0x000000920000-0x000000ce0000 : "c_kernel"
> >	[    1.030722] mtdblock: MTD device 'c_kernel' is NAND, please consider using
> >	UBI block devices instead.
> >	[    1.053444] 0x000000ce0000-0x000000d00000 : "c__atags"
> >	[    1.060742] mtdblock: MTD device 'c__atags' is NAND, please consider using
> >	UBI block devices instead.
> >	[    1.083349] 0x000000d00000-0x000001000000 : "c_rootfs"
> >	[    1.090702] mtdblock: MTD device 'c_rootfs' is NAND, please consider using
> >	UBI block devices instead.
> >	[    1.113335] 0x000001000000-0x000020000000 : "mender"
> >	[    1.131627] mtdblock: MTD device 'mender' is NAND, please consider using UBI
> >	block devices instead.
> > 
> > NAND tends to be something found on older devices, the firmware/bootloaders
> > of older devices couldn't possibly understand UBI/UBIFS so many of these
> > partitions need be "raw" partitions, or use something that predates UBI.
> > 
> > Ironically my "mender" partition contains a UBI (with multiple UBIFSes inside)
> > yet I got the same "please use UBI" message as all the others (lol)
> > 
> > I'm specifying my partitions in DT with:
> > 
> > partitions {
> >        compatible = "fixed-partitions";
> >        #address-cells = <1>;
> >        #size-cells = <1>;
> > 
> >        mtd0 at 0       { label = "bootrom";   reg = <0x00000000 0x00020000>; };
> >        mtd1 at 20000   { label = "uboot";     reg = <0x00020000 0x00060000>; };
> >        mtd2 at 80000   { label = "fbkernel";  reg = <0x00080000 0x003c0000>; };
> >        mtd3 at 440000  { label = "fbrootfs";  reg = <0x00440000 0x004e0000>; };
> >        mtd4 at 920000  { label = "c_kernel";  reg = <0x00920000 0x003c0000>; };
> >        mtd5 at ce0000  { label = "c__atags";  reg = <0x00ce0000 0x00020000>; };
> >        mtd6 at d00000  { label = "c_rootfs";  reg = <0x00d00000 0x00300000>; };
> >        mtd7 at 1000000 { label = "mender";    reg = <0x01000000 0x1f000000>; };
> > };
> > 
> > which is why, I assume, I'm getting these messages. Is there a UBI-friendly
> > way to define them to avoid these messages?
> 
> Hmm, maybe it makes sense to advertise it only once and not for each mtdblock device.

Are there known bugs or issues using ubi/jffs2/squashfs on top of mtdblock? Is
mtdblock being deprecated? If so I could certainly understand warning users of
the situation.

Is there a safe/easy way to update an older device in a way that wipes
the entire flash while running from flash? If not then having the kernel
perpetually advertising that I'm not using my flash a certain way isn't very
useful, especially if there aren't any underlying reasons why my usage isn't
valid.


From robh at kernel.org  Thu Oct 28 14:25:28 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:25:28 -0500
Subject: [PATCH 01/18] dt-bindings: mtd: nand-controller: Fix the reg
 property description
In-Reply-To: <20211020142809.349347-2-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-2-miquel.raynal@bootlin.com>
Message-ID: <YXsVSIuS0/LOqnUH@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:52 +0200, Miquel Raynal wrote:
> The reg property of a NAND device always references the chip-select(s).
> The ready/busy lines are described in the nand-rb property. I believe
> this was a harmless copy/paste error during the conversion to yaml.
> 
> Fixes: 212e49693592 ("dt-bindings: mtd: Add YAML schemas for the generic NAND options")
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  Documentation/devicetree/bindings/mtd/nand-controller.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Acked-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Thu Oct 28 14:26:17 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:26:17 -0500
Subject: [PATCH 02/18] dt-bindings: mtd: nand-controller: Fix a comment
 in the examples
In-Reply-To: <20211020142809.349347-3-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-3-miquel.raynal@bootlin.com>
Message-ID: <YXsVeTmJBWnrWysb@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:53 +0200, Miquel Raynal wrote:
> The controller properties should be in the controller 'parent' node,
> while properties in the children nodes are specific to the NAND
> *chip*. This error was already present during the yaml conversion.
> 
> Fixes: 2d472aba15ff ("mtd: nand: document the NAND controller/NAND chip DT representation")
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  Documentation/devicetree/bindings/mtd/nand-controller.yaml | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

Acked-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Thu Oct 28 14:28:30 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:28:30 -0500
Subject: [PATCH 04/18] dt-bindings: mtd: spi-nand: Convert spi-nand
 description file to yaml
In-Reply-To: <20211020142809.349347-5-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-5-miquel.raynal@bootlin.com>
Message-ID: <YXsV/l+/vU1fBanY@robh.at.kernel.org>

On Wed, Oct 20, 2021 at 04:27:55PM +0200, Miquel Raynal wrote:
> Let's get rid of spi-nand.txt by converting it to yaml schema. While at
> converting this file, let's actually pull all the generic properties
> from nand-chip.yaml which might apply to a SPI-NAND chip.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../devicetree/bindings/mtd/spi-nand.txt      |  5 ----
>  .../devicetree/bindings/mtd/spi-nand.yaml     | 27 +++++++++++++++++++
>  2 files changed, 27 insertions(+), 5 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.txt
>  create mode 100644 Documentation/devicetree/bindings/mtd/spi-nand.yaml

Reviewed-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Thu Oct 28 14:31:27 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:31:27 -0500
Subject: [PATCH 05/18] dt-bindings: vendor-prefixes: Clarify Macronix
 prefix
In-Reply-To: <20211020142809.349347-6-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-6-miquel.raynal@bootlin.com>
Message-ID: <YXsWrwPrDJh+d9ay@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:56 +0200, Miquel Raynal wrote:
> When looking at compatible prefixes, Macronix is sometimes referred as
> "mxicy":
> - mxicy,mx25r1635f
> - mxicy,mx25u6435f
> - mxicy,mx25v8035f
> - mxicy,mx25f0a-spi
> and sometimes as "mxic":
> - mxic,multi-itfc-v009-nand-controller
> - mxic,enable-randomizer-otp
> 
> The oldest prefix that is also the one preferred by Macronix engineers
> is "mxicy", so document the other one and mark it deprecated.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 3 +++
>  1 file changed, 3 insertions(+)
> 

Reviewed-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Thu Oct 28 14:32:05 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:32:05 -0500
Subject: [PATCH 06/18] dt-bindings: spi: mxic: The interrupt property is
 not mandatory
In-Reply-To: <20211020142809.349347-7-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-7-miquel.raynal@bootlin.com>
Message-ID: <YXsW1Q1dh2+e2ONB@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:57 +0200, Miquel Raynal wrote:
> The interrupt property is not mandatory at all, this property should not
> be part of the required properties list, so move it into the optional
> properties list.
> 
> Fixes: 326e5c8d4a87 ("dt-binding: spi: Document Macronix controller bindings")
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  Documentation/devicetree/bindings/spi/spi-mxic.txt | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 

Reviewed-by: Rob Herring <robh at kernel.org>


From robh at kernel.org  Thu Oct 28 14:34:26 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:34:26 -0500
Subject: [PATCH 07/18] dt-bindings: spi: mxic: Convert to yaml
In-Reply-To: <20211020142809.349347-8-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-8-miquel.raynal@bootlin.com>
Message-ID: <YXsXYssDTKv2L4EL@robh.at.kernel.org>

On Wed, Oct 20, 2021 at 04:27:58PM +0200, Miquel Raynal wrote:
> Straightforward conversion from regular text to yaml schema of the
> Macronix SPI controller DT bindings.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../bindings/spi/mxicy,mx25f0a-spi.yaml       | 67 +++++++++++++++++++
>  .../devicetree/bindings/spi/spi-mxic.txt      | 36 ----------
>  2 files changed, 67 insertions(+), 36 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
>  delete mode 100644 Documentation/devicetree/bindings/spi/spi-mxic.txt
> 
> diff --git a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
> new file mode 100644
> index 000000000000..4036c14fc533
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
> @@ -0,0 +1,67 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spi/mxicy,mx25f0a-spi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Macronix SPI controller device tree bindings
> +
> +maintainers:
> +  - Miquel Raynal <miquel.raynal at bootlin.com>
> +
> +allOf:
> +  - $ref: "spi-controller.yaml#"
> +
> +properties:
> +  compatible:
> +    const: mxicy,mx25f0a-spi
> +
> +  reg:
> +    minItems: 2
> +    maxItems: 2
> +
> +  reg-names:
> +    items:
> +      - const: regs
> +      - const: dirmap
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  clocks:
> +    minItems: 3
> +    maxItems: 3
> +
> +  clock-names:
> +    items:
> +      - const: send_clk
> +      - const: send_dly_clk
> +      - const: ps_clk
> +

> +  "#address-cells":
> +    const: 1
> +  "#size-cells":
> +    const: 0

Can drop these as spi-controller.yaml already defines them.

> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +  - clock-names

> +  - "#address-cells"
> +  - "#size-cells"

And makes them required.

With that,

Reviewed-by: Rob Herring <robh at kernel.org>

> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    spi at 43c30000 {
> +      compatible = "mxicy,mx25f0a-spi";
> +      reg = <0x43c30000 0x10000>, <0xa0000000 0x20000000>;
> +      reg-names = "regs", "dirmap";
> +      clocks = <&clkwizard 0>, <&clkwizard 1>, <&clkc 18>;
> +      clock-names = "send_clk", "send_dly_clk", "ps_clk";
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +    };


From robh at kernel.org  Thu Oct 28 14:38:43 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:38:43 -0500
Subject: [PATCH 09/18] dt-bindings: spi: mxic: Document the
 nand-ecc-engine property
In-Reply-To: <20211020142809.349347-10-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-10-miquel.raynal@bootlin.com>
Message-ID: <YXsYY6JaglRjan+L@robh.at.kernel.org>

On Wed, Oct 20, 2021 at 04:28:00PM +0200, Miquel Raynal wrote:
> This SPI controller supports interacting with an external ECC
> engine. The nand-ecc-engine property already exist in the NAND world but
> also applies to SPI controller nodes which have external correction
> capabilities like Macronix's.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml          | 6 ++++++
>  1 file changed, 6 insertions(+)

This should come before patch 8. The example would fail if 
'unevaluatedProperties' did anything.

Reviewed-by: Rob Herring <robh at kernel.org>

> 
> diff --git a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
> index 4036c14fc533..01618a77627d 100644
> --- a/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
> +++ b/Documentation/devicetree/bindings/spi/mxicy,mx25f0a-spi.yaml
> @@ -43,6 +43,12 @@ properties:
>    "#size-cells":
>      const: 0
>  
> +  nand-ecc-engine:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +    description: NAND ECC engine used by the SPI controller in order to perform
> +      on-the-fly correction when using a SPI-NAND memory.
> +
>  required:
>    - compatible
>    - reg
> -- 
> 2.27.0
> 
> 


From robh at kernel.org  Thu Oct 28 14:35:13 2021
From: robh at kernel.org (Rob Herring)
Date: Thu, 28 Oct 2021 16:35:13 -0500
Subject: [PATCH 08/18] dt-bindings: mtd: Describe Macronix NAND ECC engine
In-Reply-To: <20211020142809.349347-9-miquel.raynal@bootlin.com>
References: <20211020142809.349347-1-miquel.raynal@bootlin.com>
 <20211020142809.349347-9-miquel.raynal@bootlin.com>
Message-ID: <YXsXkfGNtMFLPMA2@robh.at.kernel.org>

On Wed, 20 Oct 2021 16:27:59 +0200, Miquel Raynal wrote:
> Describe Macronix NAND ECC engine. This engine may be used as an
> external engine or can be pipelined with either a raw NAND controller or
> a SPI controller. Both hardware designs with a SPI controller are shown
> in the examples.
> 
> Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
> ---
>  .../bindings/mtd/mxicy,nand-ecc-engine.yaml   | 77 +++++++++++++++++++
>  1 file changed, 77 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mtd/mxicy,nand-ecc-engine.yaml
> 

Reviewed-by: Rob Herring <robh at kernel.org>


From lkp at intel.com  Thu Oct 28 22:33:57 2021
From: lkp at intel.com (kernel test robot)
Date: Fri, 29 Oct 2021 13:33:57 +0800
Subject: [PATCH 05/11] ubifs: Rename whiteout atomically
In-Reply-To: <20211025034116.3544321-6-chengzhihao1@huawei.com>
References: <20211025034116.3544321-6-chengzhihao1@huawei.com>
Message-ID: <202110291316.uquoyGjm-lkp@intel.com>

Hi Zhihao,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linux/master]
[also build test ERROR on linus/master rw-ubifs/next v5.15-rc7 next-20211028]
[cannot apply to rw-ubifs/fixes]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Zhihao-Cheng/Some-bugfixs-for-ubifs-ubi/20211025-113114
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 2f111a6fd5b5297b4e92f53798ca086f7c7d33a4
config: x86_64-buildonly-randconfig-r004-20211028 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/8a6ca5bc1be93cca9c7b0167a71bdd338f854600
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Zhihao-Cheng/Some-bugfixs-for-ubifs-ubi/20211025-113114
        git checkout 8a6ca5bc1be93cca9c7b0167a71bdd338f854600
        # save the attached .config to linux build tree
        make W=1 ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp at intel.com>

All errors (new ones prefixed by >>):

   fs/ubifs/dir.c: In function 'create_whiteout':
>> fs/ubifs/dir.c:357:22: error: variable 'ui' set but not used [-Werror=unused-but-set-variable]
     357 |  struct ubifs_inode *ui;
         |                      ^~
   cc1: all warnings being treated as errors


vim +/ui +357 fs/ubifs/dir.c

   351	
   352	static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry,
   353					     umode_t mode)
   354	{
   355		int err;
   356		struct inode *inode;
 > 357		struct ubifs_inode *ui;
   358		struct ubifs_info *c = dir->i_sb->s_fs_info;
   359		struct fscrypt_name nm;
   360	
   361		/*
   362		 * Create an inode('nlink = 1') for whiteout without updating journal,
   363		 * let ubifs_jnl_rename() store it on flash to complete rename whiteout
   364		 * atomically.
   365		 */
   366	
   367		dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
   368			dentry, mode, dir->i_ino);
   369	
   370		err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
   371		if (err)
   372			return ERR_PTR(err);
   373	
   374		inode = ubifs_new_inode(c, dir, mode);
   375		if (IS_ERR(inode)) {
   376			err = PTR_ERR(inode);
   377			goto out_free;
   378		}
   379		ui = ubifs_inode(inode);
   380	
   381		init_special_inode(inode, inode->i_mode, WHITEOUT_DEV);
   382		ubifs_assert(c, inode->i_op == &ubifs_file_inode_operations);
   383	
   384		err = ubifs_init_security(dir, inode, &dentry->d_name);
   385		if (err)
   386			goto out_inode;
   387	
   388		/* The dir size is updated by do_rename. */
   389		insert_inode_hash(inode);
   390	
   391		return inode;
   392	
   393	out_inode:
   394		make_bad_inode(inode);
   395		iput(inode);
   396	out_free:
   397		fscrypt_free_filename(&nm);
   398		ubifs_err(c, "cannot create whiteout file, error %d", err);
   399		return ERR_PTR(err);
   400	}
   401	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 35706 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20211029/f121457a/attachment-0001.gz>

From axboe at kernel.dk  Fri Oct 29 05:52:41 2021
From: axboe at kernel.dk (Jens Axboe)
Date: Fri, 29 Oct 2021 06:52:41 -0600
Subject: (subset) move all struct request releated code out of blk-core.c
In-Reply-To: <20211025070517.1548584-1-hch@lst.de>
References: <20211025070517.1548584-1-hch@lst.de>
Message-ID: <163551196149.84649.4583690575292414176.b4-ty@kernel.dk>

On Mon, 25 Oct 2021 09:05:05 +0200, Christoph Hellwig wrote:
> this series (against the for-5.16/passthrough-flag branch) removes the
> remaining struct request related code from blk-core.c and cleans up a
> few related bits around that.
> 
> Diffstat:
>  b/block/Makefile                     |    2
>  b/block/blk-core.c                   |  362 ----------------------
>  b/block/blk-mq.c                     |  573 +++++++++++++++++++++++++++++------
>  b/block/blk-mq.h                     |    3
>  b/block/blk.h                        |   33 --
>  b/drivers/block/paride/pd.c          |    4
>  b/drivers/block/pktcdvd.c            |    2
>  b/drivers/block/virtio_blk.c         |    4
>  b/drivers/md/dm-mpath.c              |    4
>  b/drivers/mmc/core/block.c           |   20 -
>  b/drivers/mtd/mtd_blkdevs.c          |   10
>  b/drivers/mtd/ubi/block.c            |    6
>  b/drivers/scsi/scsi_bsg.c            |    2
>  b/drivers/scsi/scsi_error.c          |    2
>  b/drivers/scsi/scsi_ioctl.c          |    4
>  b/drivers/scsi/scsi_lib.c            |   46 ++
>  b/drivers/scsi/sg.c                  |    6
>  b/drivers/scsi/sr.c                  |    2
>  b/drivers/scsi/st.c                  |    4
>  b/drivers/scsi/ufs/ufshcd.c          |   20 -
>  b/drivers/scsi/ufs/ufshpb.c          |    8
>  b/drivers/target/target_core_pscsi.c |    4
>  b/include/linux/blk-mq.h             |   16
>  block/blk-exec.c                     |  116 -------
>  24 files changed, 597 insertions(+), 656 deletions(-)
> 
> [...]

Applied, thanks!

[02/12] block: remove blk_{get,put}_request
        commit: 0bf6d96cb8294094ce1e44cbe8cf65b0899d0a3a

Best regards,
-- 
Jens Axboe




From geoff at infradead.org  Fri Oct 29 08:05:06 2021
From: geoff at infradead.org (Geoff Levand)
Date: Fri, 29 Oct 2021 08:05:06 -0700
Subject: [PATCH 10/13] ps3disk: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-11-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-11-mcgrof@kernel.org>
Message-ID: <01e79b30-8ac0-c384-d57d-7c79e7f244c2@infradead.org>

Hi Luis,

On 10/15/21 4:52 PM, Luis Chamberlain wrote:
> We never checked for errors on add_disk() as this function
> returned void. Now that this is fixed, use the shiny new
> error handling.
> 
> Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>

I tested your 20211011-for-axboe-add-disk-error-handling branch
on PS3 and the ps3disk changes seem to be working OK.

Tested-by: Geoff Levand <geoff at infradead.org>


From geoff at infradead.org  Fri Oct 29 08:09:59 2021
From: geoff at infradead.org (Geoff Levand)
Date: Fri, 29 Oct 2021 08:09:59 -0700
Subject: [PATCH 11/13] ps3vram: add error handling support for add_disk()
In-Reply-To: <20211015235219.2191207-12-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-12-mcgrof@kernel.org>
Message-ID: <2b782451-f931-27bb-1114-2aba450c5879@infradead.org>

Hi Luis,

On 10/15/21 4:52 PM, Luis Chamberlain wrote:
> We never checked for errors on add_disk() as this function
> returned void. Now that this is fixed, use the shiny new
> error handling.

I didn't yet test this ps3vram related change, but based
on the ps3disk testing I think this change will be OK.

Acked-by: Geoff Levand <geoff at infradead.org>


From pintu.ping at gmail.com  Fri Oct 29 08:51:33 2021
From: pintu.ping at gmail.com (Pintu Agarwal)
Date: Fri, 29 Oct 2021 21:21:33 +0530
Subject: Kernel 4.14: Using dm-verity with squashfs rootfs - mounting issue
In-Reply-To: <YTinqiH9h+Q9bYsr@kroah.com>
References: <CAOuPNLhh_LkLQ8mSA4eoUDLCLzHo5zHXsiQZXUB_-T_F1_v6-g@mail.gmail.com>
 <alpine.LRH.2.02.2107211300520.10897@file01.intranet.prod.int.rdu2.redhat.com>
 <CAOuPNLi-xz_4P+v45CHLx00ztbSwU3_maf4tuuyso5RHyeOytg@mail.gmail.com>
 <CAOuPNLg0m-Q7Vhp4srbQrjXHsxVhOr-K2dvnNqzdR6Dr4kioqA@mail.gmail.com>
 <20210830185541.715f6a39@windsurf>
 <CAOuPNLhTidgLNWUbtUgdESYcKcE1C4SOdzKeQVhFGQvEoc0QEg@mail.gmail.com>
 <20210830211224.76391708@windsurf>
 <CAOuPNLgMd0AThhmSknbmKqp3_P8PFhBGr-jW0Mqjb6K6NchEMg@mail.gmail.com>
 <CAOuPNLiW10-E6F_Ndte7U9NPBKa9Y_UuLhgdwAYTc0eYMk5Mqg@mail.gmail.com>
 <CAOuPNLj2Xmx52Gtzx5oEKif4Qz-Tz=vaxhRvHQG-5emO7ewRhg@mail.gmail.com>
 <YTinqiH9h+Q9bYsr@kroah.com>
Message-ID: <CAOuPNLhzfGDoQsEZB5eH30WvH2w9hyMEU8Bt81SzK-scaAwgwA@mail.gmail.com>

Hi All,

On Wed, 8 Sept 2021 at 17:38, Greg KH <gregkh at linuxfoundation.org> wrote:

> > > > > No, but you can backport it easily. Back at
> > > > > http://lists.infradead.org/pipermail/openwrt-devel/2019-November/025967.html
> > > > > I provided backports of this feature to OpenWrt, for the 4.14 and 4.19
> > > > > kernels.
> >
> > Can you please let me know where to get the below patches for
> > backporting to our kernel:
> >  create mode 100644
> > target/linux/generic/backport-4.14/390-dm-add-support-to-directly-boot-to-a-mapped-device.patch
> >  create mode 100644
> > target/linux/generic/backport-4.14/391-dm-init-fix-max-devices-targets-checks.patch
> >  create mode 100644
> > target/linux/generic/backport-4.14/392-dm-ioctl-fix-hang-in-early-create-error-condition.patch
> >  create mode 100644
> > target/linux/generic/backport-4.14/393-Documentation-dm-init-fix-multi-device-example.patch
>
> If you are stuck on an older kernel version, then you need to get
> support from the vendor that is forcing you to be on that kernel
> version, as you are already paying them for support.  Please take
> advantage of that, as no one knows what is really in "your kernel".
>

This is to update this thread that now I am able to successfully
bring-up dm-verity with NAND+ubiblock+squashfs on our 4.14 kernel
itself without backporting the patches.
Now, I am able to boot dm-verity using both initramfs and bootloader approach.
The initramfs booting issue was our internal issue which was related
to Kernel size configuration in UEFI.
The bootloader approach issue was related to system image size issue,
where we need to pass the exact image size to find the verity-metadata
offset at the end of system image.

However, I felt that dm-verity documentation still needs to be
enhanced further with a better example.
With the 5.4 Kernel, I may further explore the option of using
dm-mod.create option, then I might get more clarity on how best to use
it.

Thank you all for your help and support!

Regards,
Pintu


From pintu.ping at gmail.com  Fri Oct 29 09:12:56 2021
From: pintu.ping at gmail.com (Pintu Agarwal)
Date: Fri, 29 Oct 2021 21:42:56 +0530
Subject: MTD: How to get actual image size from MTD partition
In-Reply-To: <CAOuPNLjJMCyxK8mvnBo2aZQXSNqY47YeXCxWmtPECq-=csz6bQ@mail.gmail.com>
References: <CAOuPNLjzyG_2wGDYmwgeoQuuQ7cykJ11THf8jMrOFXZ7vXheJQ@mail.gmail.com>
 <CAOuPNLh_KY4NaVWSEV2JPp8fx0iy8E1MU8GHT-w7-hMXrvSaeA@mail.gmail.com>
 <1556211076.48404.1626763215205.JavaMail.zimbra@nod.at>
 <CAOuPNLhti3tocN-_D7Q0QaAx5acHpb3AQyWaUKgQPNW3XWu58g@mail.gmail.com>
 <2132615832.4458.1626900868118.JavaMail.zimbra@nod.at>
 <CAOuPNLhCMT7QTF+QadJyGDFNshH9VjEAzWStRpe8itw7HXve=A@mail.gmail.com>
 <CAFLxGvywv29u6DJZrJxnJJmUDSQ4xpbT0u5LNKY1uGKyQom+WA@mail.gmail.com>
 <CAAEAJfCY+X-G=7Oe9NqrJ4yQZ29DBA78jOFAX44GD0g6=s7qhg@mail.gmail.com>
 <1668790824.35266.1627559144878.JavaMail.zimbra@nod.at>
 <CAAEAJfDDtGcUquyP7Jn0Urttt4kSfAQbJ_qPQ90ROtWLavW9EA@mail.gmail.com>
 <CAOuPNLj+DSigRY_AgHQnGKCK-Vm4ykQBR8UfnTi2UObORTcBFg@mail.gmail.com>
 <CAOuPNLgfJGzp-RJBjydFDL1ZAvOd7=-MgXhnsb2eb_xFSLC66w@mail.gmail.com>
 <CAAEAJfBuut7VSbrrz6CxOC+Cke36eGGv8VUvfdbfLwvSBxOAAA@mail.gmail.com>
 <CAOuPNLjJMCyxK8mvnBo2aZQXSNqY47YeXCxWmtPECq-=csz6bQ@mail.gmail.com>
Message-ID: <CAOuPNLghc1ktLrOEf8PN+snMB3QZG-LwzPbd3kGzrhGz8mEAVg@mail.gmail.com>

Hi All,

On Mon, 30 Aug 2021 at 21:28, Pintu Agarwal <pintu.ping at gmail.com> wrote:
>
> On Sun, 22 Aug 2021 at 19:51, Ezequiel Garcia
> <ezequiel at vanguardiasur.com.ar> wrote:
>
> > In other words, IMO it's best to expose the NAND through UBI
> > for both read-only and read-write access, using a single UBI device,
> > and then creating UBI volumes as needed. This will allow UBI
> > to spread wear leveling across the whole device, which is expected
> > to increase the flash lifetime.
> >
> > For instance, just as some silly example, you could have something like this:
> >
> >                                | RootFS SquashFS  |
> >                                | UBI block        | UBIFS User R-W area
> > ------------------------------------------------------------------------
> > Kernel A | Kernel B | RootFS A | RootFS B         | User
> > ------------------------------------------------------------------------
> >                                  UBIX
> > ------------------------------------------------------------------------
> >                                  /dev/mtdX
> >
> > This setup allows safe kernel and rootfs upgrading. The RootFS is read-only
> > via SquashFS and there's a read-write user area. UBI is supporting all
> > the volumes, handling bad blocks and wear leveling.
> >
> Dear Ezequiel,
> Thank you so much for your reply.
>
> This is exactly what we are also doing :)
> In our system we have a mix of raw and ubi partitions.
> The ubi partitioning is done almost exactly the same way.
> Only for the rootfs (squashfs) I see we were using /mtd/block<id> to
> mount the rootfs.
> Now, I understood we should change it to use /dev/ubiblock<id>
> This might have several benefits, but one most important could be,
> using ubiblock can handle bad-blocks/wear-leveling automatically,
> whereas mtdblocks access the flash directly ?
> I found some references for these..
> So, this seems good for my proposal.
>
> Another thing that is still open for us is:
> How do we calculate the exact image size from a raw mtd partition ?
> For example, support for one of the raw nand partitions, the size is
> defined as 15MB but we flash the actual image of size only 2.5MB.
> So, in the runtime how to determine the image size as ~2.5MB (at least
> roughly) ?
> Is it still possible ?
>

I am happy to inform you that using "ubiblock" for squashfs mounting
seems very helpful for us.
We have seen almost the double performance boost when using ubiblock
for rootfs as well as other read-only volume mounting.

However, we have found few issues while defining the read only volume as STATIC.
With static volume we see that OTA update is failing during "fsync".
That is ota_fsync is failing from here:
https://gerrit.pixelexperience.org/plugins/gitiles/bootable_recovery/+/ff6df890a2a01bf3bf56d3f430b17a5ef69055cf%5E%21/otafault/ota_io.cpp
int status = fsync(fd);
if (status == -1 && errno == EIO)
*
{ have_eio_error = true; }
*
return status;
}

Is this the known issue with static volume?

For now we are using dynamic volume itself but the problem is that
with dynamic volume we cannot get the exact image size from:
$ cat /sys/class/ubi/ubi0_0/data_bytes
==> In case of dynamic volume this will return the total volume size.
==> Thus our md5 integrity check does not match exactly with the
flashed image size.

Is there an alternate way to handle this issue ?


Thanks,
Pintu


From ezequiel at vanguardiasur.com.ar  Fri Oct 29 09:48:46 2021
From: ezequiel at vanguardiasur.com.ar (Ezequiel Garcia)
Date: Fri, 29 Oct 2021 13:48:46 -0300
Subject: MTD: How to get actual image size from MTD partition
In-Reply-To: <CAOuPNLghc1ktLrOEf8PN+snMB3QZG-LwzPbd3kGzrhGz8mEAVg@mail.gmail.com>
References: <CAOuPNLjzyG_2wGDYmwgeoQuuQ7cykJ11THf8jMrOFXZ7vXheJQ@mail.gmail.com>
 <CAOuPNLh_KY4NaVWSEV2JPp8fx0iy8E1MU8GHT-w7-hMXrvSaeA@mail.gmail.com>
 <1556211076.48404.1626763215205.JavaMail.zimbra@nod.at>
 <CAOuPNLhti3tocN-_D7Q0QaAx5acHpb3AQyWaUKgQPNW3XWu58g@mail.gmail.com>
 <2132615832.4458.1626900868118.JavaMail.zimbra@nod.at>
 <CAOuPNLhCMT7QTF+QadJyGDFNshH9VjEAzWStRpe8itw7HXve=A@mail.gmail.com>
 <CAFLxGvywv29u6DJZrJxnJJmUDSQ4xpbT0u5LNKY1uGKyQom+WA@mail.gmail.com>
 <CAAEAJfCY+X-G=7Oe9NqrJ4yQZ29DBA78jOFAX44GD0g6=s7qhg@mail.gmail.com>
 <1668790824.35266.1627559144878.JavaMail.zimbra@nod.at>
 <CAAEAJfDDtGcUquyP7Jn0Urttt4kSfAQbJ_qPQ90ROtWLavW9EA@mail.gmail.com>
 <CAOuPNLj+DSigRY_AgHQnGKCK-Vm4ykQBR8UfnTi2UObORTcBFg@mail.gmail.com>
 <CAOuPNLgfJGzp-RJBjydFDL1ZAvOd7=-MgXhnsb2eb_xFSLC66w@mail.gmail.com>
 <CAAEAJfBuut7VSbrrz6CxOC+Cke36eGGv8VUvfdbfLwvSBxOAAA@mail.gmail.com>
 <CAOuPNLjJMCyxK8mvnBo2aZQXSNqY47YeXCxWmtPECq-=csz6bQ@mail.gmail.com>
 <CAOuPNLghc1ktLrOEf8PN+snMB3QZG-LwzPbd3kGzrhGz8mEAVg@mail.gmail.com>
Message-ID: <CAAEAJfDS3FK19xMs-7LcEjDe7Fx1XW6HZJGyb6Ff=zs2ZKHpJA@mail.gmail.com>

On Fri, 29 Oct 2021 at 13:13, Pintu Agarwal <pintu.ping at gmail.com> wrote:
>
> Hi All,
>
> On Mon, 30 Aug 2021 at 21:28, Pintu Agarwal <pintu.ping at gmail.com> wrote:
> >
> > On Sun, 22 Aug 2021 at 19:51, Ezequiel Garcia
> > <ezequiel at vanguardiasur.com.ar> wrote:
> >
> > > In other words, IMO it's best to expose the NAND through UBI
> > > for both read-only and read-write access, using a single UBI device,
> > > and then creating UBI volumes as needed. This will allow UBI
> > > to spread wear leveling across the whole device, which is expected
> > > to increase the flash lifetime.
> > >
> > > For instance, just as some silly example, you could have something like this:
> > >
> > >                                | RootFS SquashFS  |
> > >                                | UBI block        | UBIFS User R-W area
> > > ------------------------------------------------------------------------
> > > Kernel A | Kernel B | RootFS A | RootFS B         | User
> > > ------------------------------------------------------------------------
> > >                                  UBIX
> > > ------------------------------------------------------------------------
> > >                                  /dev/mtdX
> > >
> > > This setup allows safe kernel and rootfs upgrading. The RootFS is read-only
> > > via SquashFS and there's a read-write user area. UBI is supporting all
> > > the volumes, handling bad blocks and wear leveling.
> > >
> > Dear Ezequiel,
> > Thank you so much for your reply.
> >
> > This is exactly what we are also doing :)
> > In our system we have a mix of raw and ubi partitions.
> > The ubi partitioning is done almost exactly the same way.
> > Only for the rootfs (squashfs) I see we were using /mtd/block<id> to
> > mount the rootfs.
> > Now, I understood we should change it to use /dev/ubiblock<id>
> > This might have several benefits, but one most important could be,
> > using ubiblock can handle bad-blocks/wear-leveling automatically,
> > whereas mtdblocks access the flash directly ?
> > I found some references for these..
> > So, this seems good for my proposal.
> >
> > Another thing that is still open for us is:
> > How do we calculate the exact image size from a raw mtd partition ?
> > For example, support for one of the raw nand partitions, the size is
> > defined as 15MB but we flash the actual image of size only 2.5MB.
> > So, in the runtime how to determine the image size as ~2.5MB (at least
> > roughly) ?
> > Is it still possible ?
> >
>
> I am happy to inform you that using "ubiblock" for squashfs mounting
> seems very helpful for us.
> We have seen almost the double performance boost when using ubiblock
> for rootfs as well as other read-only volume mounting.
>
> However, we have found few issues while defining the read only volume as STATIC.
> With static volume we see that OTA update is failing during "fsync".
> That is ota_fsync is failing from here:
> https://gerrit.pixelexperience.org/plugins/gitiles/bootable_recovery/+/ff6df890a2a01bf3bf56d3f430b17a5ef69055cf%5E%21/otafault/ota_io.cpp
> int status = fsync(fd);
> if (status == -1 && errno == EIO)
> *
> { have_eio_error = true; }
> *
> return status;
> }
>
> Is this the known issue with static volume?
>

I don't know exactly how you are updating your volume,
the right way is using UBI_IOCVOLUP.

See http://www.linux-mtd.infradead.org/doc/ubi.html#L_volupdate

If you google around I'm sure you'll find some articles about this,
but I'm not sure if they'll go into details and subtleties.

There are probably a few different ways to do firmware upgrade
when you are on top of static volumes (and you want to be on top
of static volumes if it's read-only, because AFAIK they give you an
extra data-integrity guarantee).

One way, would be to have two static volumes A/B. The system
uses normally the A volume, and then you doUBI_IOCVOLUP
(or ubiupdatevol) to update the B volume. After the update is succesful
you run the atomic volume rename and flip A->B, B->A.

(If you don't have enough space to hold two A/B volumes....
 ... you'll have to find some other solution, I have no idea about that.)

Hope it helps,
Eze


From tudor.ambarus at microchip.com  Fri Oct 29 10:26:09 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:09 +0300
Subject: [PATCH v3 01/25] mtd: spi-nor: core: Fix spi_nor_flash_parameter otp
 description
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-2-tudor.ambarus@microchip.com>

Update the description of the otp member of the
struct spi_nor_flash_parameter.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
---
 drivers/mtd/spi-nor/core.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3348e1dd1445..da3fd3636d3c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -250,7 +250,7 @@ struct spi_nor_otp {
  *                      higher index in the array, the higher priority.
  * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
  *                      Table.
- * @otp_info:		describes the OTP regions.
+ * @otp:		SPI NOR OTP info.
  * @octal_dtr_enable:	enables SPI NOR octal DTR mode.
  * @quad_enable:	enables SPI NOR quad mode.
  * @set_4byte_addr_mode: puts the SPI NOR in 4 byte addressing mode.
@@ -262,7 +262,6 @@ struct spi_nor_otp {
  *                      e.g. different opcodes, specific address calculation,
  *                      page size, etc.
  * @locking_ops:	SPI NOR locking methods.
- * @otp:		SPI NOR OTP methods.
  */
 struct spi_nor_flash_parameter {
 	u64				size;
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:08 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:08 +0300
Subject: [PATCH v3 00/25] mtd: spi-nor: Clean params init
Message-ID: <20211029172633.886453-1-tudor.ambarus@microchip.com>

Clean spi_nor_scan() and the flash parameters initialization code. 
Tested all the flashes from patch set. If someone can test the
locking ops on few flashes would be great. It seems that my flashes
have the non volatile bits weared out.

This patch set is split from:
https://lore.kernel.org/linux-mtd/20210727045222.905056-1-tudor.ambarus at microchip.com/
The ID collision series will be set in a dedicated patch set that will
depend on this one.

Changes in v3:
- move late_init() in struct spi_nor_fixups and update patches accordingly.     
R-b tags were dropped.
- new patch "mtd: spi-nor: sst: Get rid of SST_WRITE flash_info flag"
moves manufacturer specific flag out of the core.
- update methods description to make it clear who sets when
- introduce flash_info flag masks to make it clear when one should be set.
- rework "parse SFDP first idea".

Tudor Ambarus (25):
  mtd: spi-nor: core: Fix spi_nor_flash_parameter otp description
  mtd: spi-nor: core: Use container_of to get the pointer to struct
    spi_nor
  mtd: spi-nor: Introduce spi_nor_set_mtd_info()
  mtd: spi-nor: Get rid of nor->page_size
  mtd: spi-nor: core: Introduce the late_init() hook
  mtd: spi-nor: atmel: Use flash late_init() for locking
  mtd: spi-nor: sst: Use flash late_init() for locking
  mtd: spi-nor: winbond: Use manufacturer late_init() for OTP ops
  mtd: spi-nor: xilinx: Use manufacturer late_init() to set setup method
  mtd: spi-nor: sst: Use manufacturer late_init() to set _write()
  mtd: spi-nor: spansion: Use manufacturer late_init()
  mtd: spi-nor: core: Call spi_nor_post_sfdp_fixups() only when SFDP is
    defined
  mtd: spi-nor: sst: Get rid of SST_WRITE flash_info flag
  mtd: spi-nor: Introduce flash_info flags masks
  mtd: spi-nor: Introduce spi_nor_nonsfdp_init_flags()
  mtd: spi-nor: Introduce spi_nor_init_fixup_flags()
  mtd: spi-nor: core: Introduce SPI_NOR_PARSE_SFDP
  mtd: spi-nor: core: Init flash params based on SFDP first for new
    flash additions
  mtd: spi-nor: core: Move spi_nor_set_addr_width() in spi_nor_setup()
  mtd: spi-nor: sst: sst26vf064b: Init flash based on SFDP
  mtd: spi-nor: winbond: w25q256jvm: Init flash based on SFDP
  mtd: spi-nor: spansion: s25fl256s0: Skip SFDP parsing
  mtd: spi-nor: gigadevice: gd25q256: Init flash based on SFDP
  mtd: spi-nor: issi: is25lp256: Init flash based on SFDP
  mtd: spi-nor: macronix: mx25l25635e: Init flash based on SFDP

 drivers/mtd/spi-nor/atmel.c      |   8 +-
 drivers/mtd/spi-nor/core.c       | 480 +++++++++++++++++--------------
 drivers/mtd/spi-nor/core.h       | 106 ++++---
 drivers/mtd/spi-nor/gigadevice.c |   7 +-
 drivers/mtd/spi-nor/issi.c       |   6 +-
 drivers/mtd/spi-nor/macronix.c   |  15 +-
 drivers/mtd/spi-nor/micron-st.c  |  20 +-
 drivers/mtd/spi-nor/otp.c        |   2 +-
 drivers/mtd/spi-nor/spansion.c   |  15 +-
 drivers/mtd/spi-nor/sst.c        | 105 ++++---
 drivers/mtd/spi-nor/swp.c        |   2 +-
 drivers/mtd/spi-nor/winbond.c    |   7 +-
 drivers/mtd/spi-nor/xilinx.c     |  21 +-
 include/linux/mtd/spi-nor.h      |   2 -
 14 files changed, 460 insertions(+), 336 deletions(-)

-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:10 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:10 +0300
Subject: [PATCH v3 02/25] mtd: spi-nor: core: Use container_of to get the
 pointer to struct spi_nor
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-3-tudor.ambarus@microchip.com>

"struct mtd_info mtd" is member of "struct spi_nor", there's no need
to use "mtd->priv". Get the pointer to the containing struct spi_nor
by using container_of. While here, make the function inline and
get rid of the __maybe_unused.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 1 -
 drivers/mtd/spi-nor/core.h | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index cc08bd707378..277d1fde84c8 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3134,7 +3134,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 
 	if (!mtd->name)
 		mtd->name = dev_name(dev);
-	mtd->priv = nor;
 	mtd->type = MTD_NORFLASH;
 	mtd->writesize = nor->params->writesize;
 	mtd->flags = MTD_CAP_NORFLASH;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index da3fd3636d3c..223a03769950 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -551,9 +551,9 @@ void spi_nor_try_unlock_all(struct spi_nor *nor);
 void spi_nor_register_locking_ops(struct spi_nor *nor);
 void spi_nor_otp_init(struct spi_nor *nor);
 
-static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
+static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
-	return mtd->priv;
+	return container_of(mtd, struct spi_nor, mtd);
 }
 
 #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:12 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:12 +0300
Subject: [PATCH v3 04/25] mtd: spi-nor: Get rid of nor->page_size
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-5-tudor.ambarus@microchip.com>

nor->page_size duplicated what nor->params->page_size indicates
for no good reason. page_size is a flash parameter of fixed value
and it is better suited to be found in nor->params->page_size.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
---
 drivers/mtd/spi-nor/core.c   | 20 +++++++++-----------
 drivers/mtd/spi-nor/xilinx.c | 17 ++++++++++-------
 include/linux/mtd/spi-nor.h  |  2 --
 3 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index ae971c773334..13515ad12bf1 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1952,6 +1952,7 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 	struct spi_nor *nor = mtd_to_spi_nor(mtd);
 	size_t page_offset, page_remain, i;
 	ssize_t ret;
+	u32 page_size = nor->params->page_size;
 
 	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
 
@@ -1968,16 +1969,15 @@ static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
 		 * calculated with an AND operation. On the other cases we
 		 * need to do a modulus operation (more expensive).
 		 */
-		if (is_power_of_2(nor->page_size)) {
-			page_offset = addr & (nor->page_size - 1);
+		if (is_power_of_2(page_size)) {
+			page_offset = addr & (page_size - 1);
 		} else {
 			uint64_t aux = addr;
 
-			page_offset = do_div(aux, nor->page_size);
+			page_offset = do_div(aux, page_size);
 		}
 		/* the size of data remaining on the first page */
-		page_remain = min_t(size_t,
-				    nor->page_size - page_offset, len - i);
+		page_remain = min_t(size_t, page_size - page_offset, len - i);
 
 		addr = spi_nor_convert_addr(nor, addr);
 
@@ -3087,7 +3087,7 @@ static void spi_nor_set_mtd_info(struct spi_nor *nor)
 	if (nor->info->flags & SPI_NOR_NO_ERASE)
 		mtd->flags |= MTD_NO_ERASE;
 	mtd->writesize = nor->params->writesize;
-	mtd->writebufsize = nor->page_size;
+	mtd->writebufsize = nor->params->page_size;
 	mtd->size = nor->params->size;
 	mtd->_erase = spi_nor_erase;
 	mtd->_read = spi_nor_read;
@@ -3123,7 +3123,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	 * We need the bounce buffer early to read/write registers when going
 	 * through the spi-mem layer (buffers have to be DMA-able).
 	 * For spi-mem drivers, we'll reallocate a new buffer if
-	 * nor->page_size turns out to be greater than PAGE_SIZE (which
+	 * nor->params->page_size turns out to be greater than PAGE_SIZE (which
 	 * shouldn't happen before long since NOR pages are usually less
 	 * than 1KB) after spi_nor_scan() returns.
 	 */
@@ -3180,8 +3180,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 			nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
 	}
 
-	nor->page_size = nor->params->page_size;
-
 	if (of_property_read_bool(np, "broken-flash-reset"))
 		nor->flags |= SNOR_F_BROKEN_RESET;
 
@@ -3346,8 +3344,8 @@ static int spi_nor_probe(struct spi_mem *spimem)
 	 * and add this logic so that if anyone ever adds support for such
 	 * a NOR we don't end up with buffer overflows.
 	 */
-	if (nor->page_size > PAGE_SIZE) {
-		nor->bouncebuf_size = nor->page_size;
+	if (nor->params->page_size > PAGE_SIZE) {
+		nor->bouncebuf_size = nor->params->page_size;
 		devm_kfree(nor->dev, nor->bouncebuf);
 		nor->bouncebuf = devm_kmalloc(nor->dev,
 					      nor->bouncebuf_size,
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index 1138bdbf4199..0658e47564ba 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -28,11 +28,12 @@ static const struct flash_info xilinx_parts[] = {
  */
 static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
 {
+	u32 page_size = nor->params->page_size;
 	u32 offset, page;
 
-	offset = addr % nor->page_size;
-	page = addr / nor->page_size;
-	page <<= (nor->page_size > 512) ? 10 : 9;
+	offset = addr % page_size;
+	page = addr / page_size;
+	page <<= (page_size > 512) ? 10 : 9;
 
 	return page | offset;
 }
@@ -40,6 +41,7 @@ static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
 static int xilinx_nor_setup(struct spi_nor *nor,
 			    const struct spi_nor_hwcaps *hwcaps)
 {
+	u32 page_size;
 	int ret;
 
 	ret = spi_nor_xread_sr(nor, nor->bouncebuf);
@@ -64,10 +66,11 @@ static int xilinx_nor_setup(struct spi_nor *nor,
 	 */
 	if (nor->bouncebuf[0] & XSR_PAGESIZE) {
 		/* Flash in Power of 2 mode */
-		nor->page_size = (nor->page_size == 264) ? 256 : 512;
-		nor->mtd.writebufsize = nor->page_size;
-		nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
-		nor->mtd.erasesize = 8 * nor->page_size;
+		page_size = (nor->params->page_size == 264) ? 256 : 512;
+		nor->params->page_size = page_size;
+		nor->mtd.writebufsize = page_size;
+		nor->mtd.size = 8 * page_size * nor->info->n_sectors;
+		nor->mtd.erasesize = 8 * page_size;
 	} else {
 		/* Flash in Default addressing mode */
 		nor->params->convert_addr = s3an_convert_addr;
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index f67457748ed8..fc90fce26e33 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -371,7 +371,6 @@ struct spi_nor_flash_parameter;
  * @bouncebuf_size:	size of the bounce buffer
  * @info:		SPI NOR part JEDEC MFR ID and other info
  * @manufacturer:	SPI NOR manufacturer
- * @page_size:		the page size of the SPI NOR
  * @addr_width:		number of address bytes
  * @erase_opcode:	the opcode for erasing a sector
  * @read_opcode:	the read opcode
@@ -401,7 +400,6 @@ struct spi_nor {
 	size_t			bouncebuf_size;
 	const struct flash_info	*info;
 	const struct spi_nor_manufacturer *manufacturer;
-	u32			page_size;
 	u8			addr_width;
 	u8			erase_opcode;
 	u8			read_opcode;
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:11 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:11 +0300
Subject: [PATCH v3 03/25] mtd: spi-nor: Introduce spi_nor_set_mtd_info()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-4-tudor.ambarus@microchip.com>

Used to init all the mtd_info fields. Move the mtd_info init
the last thing in the spi_nor_scan(), so that we avoid superfluous
initialization of the mtd_info fields in case of errors.

While here use common naming scheme for functions that are setting
mtd_info fields:
s/spi_nor_register_locking_ops/spi_nor_set_mtd_locking_ops
s/spi_nor_otp_init/spi_nor_set_mtd_otp_ops
The functions names are self explanatory, get rid of the comment
for the OTP function.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 54 +++++++++++++++++++++-----------------
 drivers/mtd/spi-nor/core.h |  4 +--
 drivers/mtd/spi-nor/otp.c  |  2 +-
 drivers/mtd/spi-nor/swp.c  |  2 +-
 4 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 277d1fde84c8..ae971c773334 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3071,6 +3071,35 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	return info;
 }
 
+static void spi_nor_set_mtd_info(struct spi_nor *nor)
+{
+	struct mtd_info *mtd = &nor->mtd;
+	struct device *dev = nor->dev;
+
+	spi_nor_set_mtd_locking_ops(nor);
+	spi_nor_set_mtd_otp_ops(nor);
+
+	mtd->dev.parent = dev;
+	if (!mtd->name)
+		mtd->name = dev_name(dev);
+	mtd->type = MTD_NORFLASH;
+	mtd->flags = MTD_CAP_NORFLASH;
+	if (nor->info->flags & SPI_NOR_NO_ERASE)
+		mtd->flags |= MTD_NO_ERASE;
+	mtd->writesize = nor->params->writesize;
+	mtd->writebufsize = nor->page_size;
+	mtd->size = nor->params->size;
+	mtd->_erase = spi_nor_erase;
+	mtd->_read = spi_nor_read;
+	/* Might be already set by some SST flashes. */
+	if (!mtd->_write)
+		mtd->_write = spi_nor_write;
+	mtd->_suspend = spi_nor_suspend;
+	mtd->_resume = spi_nor_resume;
+	mtd->_get_device = spi_nor_get_device;
+	mtd->_put_device = spi_nor_put_device;
+}
+
 int spi_nor_scan(struct spi_nor *nor, const char *name,
 		 const struct spi_nor_hwcaps *hwcaps)
 {
@@ -3125,26 +3154,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	if (info->flags & SPI_NOR_HAS_LOCK)
 		nor->flags |= SNOR_F_HAS_LOCK;
 
-	mtd->_write = spi_nor_write;
-
 	/* Init flash parameters based on flash_info struct and SFDP */
 	ret = spi_nor_init_params(nor);
 	if (ret)
 		return ret;
 
-	if (!mtd->name)
-		mtd->name = dev_name(dev);
-	mtd->type = MTD_NORFLASH;
-	mtd->writesize = nor->params->writesize;
-	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->size = nor->params->size;
-	mtd->_erase = spi_nor_erase;
-	mtd->_read = spi_nor_read;
-	mtd->_suspend = spi_nor_suspend;
-	mtd->_resume = spi_nor_resume;
-	mtd->_get_device = spi_nor_get_device;
-	mtd->_put_device = spi_nor_put_device;
-
 	if (info->flags & USE_FSR)
 		nor->flags |= SNOR_F_USE_FSR;
 	if (info->flags & SPI_NOR_HAS_TB) {
@@ -3166,12 +3180,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 			nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
 	}
 
-	if (info->flags & SPI_NOR_NO_ERASE)
-		mtd->flags |= MTD_NO_ERASE;
-
-	mtd->dev.parent = dev;
 	nor->page_size = nor->params->page_size;
-	mtd->writebufsize = nor->page_size;
 
 	if (of_property_read_bool(np, "broken-flash-reset"))
 		nor->flags |= SNOR_F_BROKEN_RESET;
@@ -3196,15 +3205,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	if (ret)
 		return ret;
 
-	spi_nor_register_locking_ops(nor);
-
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
 		return ret;
 
-	/* Configure OTP parameters and ops */
-	spi_nor_otp_init(nor);
+	spi_nor_set_mtd_info(nor);
 
 	dev_info(dev, "%s (%lld Kbytes)\n", info->name,
 			(long long)mtd->size >> 10);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 223a03769950..48f26d3f1b3c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -548,8 +548,8 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 
 void spi_nor_init_default_locking_ops(struct spi_nor *nor);
 void spi_nor_try_unlock_all(struct spi_nor *nor);
-void spi_nor_register_locking_ops(struct spi_nor *nor);
-void spi_nor_otp_init(struct spi_nor *nor);
+void spi_nor_set_mtd_locking_ops(struct spi_nor *nor);
+void spi_nor_set_mtd_otp_ops(struct spi_nor *nor);
 
 static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
 {
diff --git a/drivers/mtd/spi-nor/otp.c b/drivers/mtd/spi-nor/otp.c
index 983e40b19134..fa63d8571218 100644
--- a/drivers/mtd/spi-nor/otp.c
+++ b/drivers/mtd/spi-nor/otp.c
@@ -480,7 +480,7 @@ static int spi_nor_mtd_otp_lock(struct mtd_info *mtd, loff_t from, size_t len)
 	return ret;
 }
 
-void spi_nor_otp_init(struct spi_nor *nor)
+void spi_nor_set_mtd_otp_ops(struct spi_nor *nor)
 {
 	struct mtd_info *mtd = &nor->mtd;
 
diff --git a/drivers/mtd/spi-nor/swp.c b/drivers/mtd/spi-nor/swp.c
index 8594bcbb7dbe..1f178313ba8f 100644
--- a/drivers/mtd/spi-nor/swp.c
+++ b/drivers/mtd/spi-nor/swp.c
@@ -414,7 +414,7 @@ void spi_nor_try_unlock_all(struct spi_nor *nor)
 		dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n");
 }
 
-void spi_nor_register_locking_ops(struct spi_nor *nor)
+void spi_nor_set_mtd_locking_ops(struct spi_nor *nor)
 {
 	struct mtd_info *mtd = &nor->mtd;
 
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:13 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:13 +0300
Subject: [PATCH v3 05/25] mtd: spi-nor: core: Introduce the late_init() hook
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-6-tudor.ambarus@microchip.com>

Flash parameters init is done in a spaghetti way right now.
There is the init based on the flash_info data, then there is the
default_init() hook, then SFDP init, an intermediary post_bft(),
then post_sfdp() and a spi_nor_late_init_params(). Each method can
overwrite previuosly initialized parameters.

We want to separate what is SFDP and non-SFDP specific. late_init()
will replace the default_init() hook and will be used only to initialize
flash parameters that are not declared in the JESD216 SFDP standard, or
where SFDP tables are not defined at all.
We cut a member in the chain of initializing parameters by getting rid
of the default_init() hook, and we make it clear that everything that is
in late_init() is not covered by the SFDP tables defined by the flash.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 17 +++++++++++++----
 drivers/mtd/spi-nor/core.h |  4 ++++
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 13515ad12bf1..4679298c5301 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2666,11 +2666,19 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
  * spi_nor_late_init_params() - Late initialization of default flash parameters.
  * @nor:	pointer to a 'struct spi_nor'
  *
- * Used to set default flash parameters and settings when the ->default_init()
- * hook or the SFDP parser let voids.
+ * Used to initialize flash parameters that are not declared in the JESD216
+ * SFDP standard, or where SFDP tables are not defined at all.
+ * Will replace the spi_nor_manufacturer_init_params() method.
  */
 static void spi_nor_late_init_params(struct spi_nor *nor)
 {
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->late_init)
+		nor->manufacturer->fixups->late_init(nor);
+
+	if (nor->info->fixups && nor->info->fixups->late_init)
+		nor->info->fixups->late_init(nor);
+
 	/*
 	 * NOR protection support. When locking_ops are not provided, we pick
 	 * the default ones.
@@ -2712,8 +2720,9 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
  *    wrong).
  *		spi_nor_post_sfdp_fixups()
  *
- * 5/ Late default flash parameters initialization, used when the
- * ->default_init() hook or the SFDP parser do not set specific params.
+ * 5/ Late flash parameters initialization, used to initialize flash
+ * parameters that are not declared in the JESD216 SFDP standard, or where SFDP
+ * tables are not defined at all.
  *		spi_nor_late_init_params()
  */
 static int spi_nor_init_params(struct spi_nor *nor)
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 48f26d3f1b3c..f6c4b6f4743b 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -297,6 +297,9 @@ struct spi_nor_flash_parameter {
  *             parameters that could not be extracted by other means (i.e.
  *             when information provided by the SFDP/flash_info tables are
  *             incomplete or wrong).
+ * @late_init: used to initialize flash parameters that are not declared in the
+ *             JESD216 SFDP standard, or where SFDP tables not defined at all.
+ *             Will replace the default_init() hook.
  *
  * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
  * table is broken or not available.
@@ -307,6 +310,7 @@ struct spi_nor_fixups {
 			 const struct sfdp_parameter_header *bfpt_header,
 			 const struct sfdp_bfpt *bfpt);
 	void (*post_sfdp)(struct spi_nor *nor);
+	void (*late_init)(struct spi_nor *nor);
 };
 
 struct flash_info {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:14 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:14 +0300
Subject: [PATCH v3 06/25] mtd: spi-nor: atmel: Use flash late_init() for
 locking
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-7-tudor.ambarus@microchip.com>

Locking is not described in JESD216 SFDP standard, place the
locking init in late_init().

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/atmel.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
index 1fea5cab492c..d0e7883b38e3 100644
--- a/drivers/mtd/spi-nor/atmel.c
+++ b/drivers/mtd/spi-nor/atmel.c
@@ -48,13 +48,13 @@ static const struct spi_nor_locking_ops atmel_at25fs_locking_ops = {
 	.is_locked = atmel_at25fs_is_locked,
 };
 
-static void atmel_at25fs_default_init(struct spi_nor *nor)
+static void atmel_at25fs_late_init(struct spi_nor *nor)
 {
 	nor->params->locking_ops = &atmel_at25fs_locking_ops;
 }
 
 static const struct spi_nor_fixups atmel_at25fs_fixups = {
-	.default_init = atmel_at25fs_default_init,
+	.late_init = atmel_at25fs_late_init,
 };
 
 /**
@@ -146,13 +146,13 @@ static const struct spi_nor_locking_ops atmel_global_protection_ops = {
 	.is_locked = atmel_is_global_protected,
 };
 
-static void atmel_global_protection_default_init(struct spi_nor *nor)
+static void atmel_global_protection_late_init(struct spi_nor *nor)
 {
 	nor->params->locking_ops = &atmel_global_protection_ops;
 }
 
 static const struct spi_nor_fixups atmel_global_protection_fixups = {
-	.default_init = atmel_global_protection_default_init,
+	.late_init = atmel_global_protection_late_init,
 };
 
 static const struct flash_info atmel_parts[] = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:16 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:16 +0300
Subject: [PATCH v3 08/25] mtd: spi-nor: winbond: Use manufacturer late_init()
 for OTP ops
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-9-tudor.ambarus@microchip.com>

OTP is not described in the JESD216 SFDP standard, place the
OTP ops init in late_init().

We can't get rid of the default_init() hook for winbond, as the
4byte_addr_mode is SFDP specific and will require to have all
flashes at hand, in order to check which has the SFDP tables defined,
in which case there's nothing to do if the SFDP tables are corect,
and which of the flashes do not define the SFDP tables in which case
each flash should declare a late_init() fixup.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/winbond.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 96573f61caf5..dd4be0f78e67 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -147,12 +147,17 @@ static const struct spi_nor_otp_ops winbond_otp_ops = {
 static void winbond_default_init(struct spi_nor *nor)
 {
 	nor->params->set_4byte_addr_mode = winbond_set_4byte_addr_mode;
+}
+
+static void winbond_late_init(struct spi_nor *nor)
+{
 	if (nor->params->otp.org->n_regions)
 		nor->params->otp.ops = &winbond_otp_ops;
 }
 
 static const struct spi_nor_fixups winbond_fixups = {
 	.default_init = winbond_default_init,
+	.late_init = winbond_late_init,
 };
 
 const struct spi_nor_manufacturer spi_nor_winbond = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:15 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:15 +0300
Subject: [PATCH v3 07/25] mtd: spi-nor: sst: Use flash late_init() for locking
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-8-tudor.ambarus@microchip.com>

Locking is not described in JESD216 SFDP standard, place the
locking init in late_init().

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/sst.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 980f4c09c91d..660aabde477a 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -46,13 +46,13 @@ static const struct spi_nor_locking_ops sst26vf_locking_ops = {
 	.is_locked = sst26vf_is_locked,
 };
 
-static void sst26vf_default_init(struct spi_nor *nor)
+static void sst26vf_late_init(struct spi_nor *nor)
 {
 	nor->params->locking_ops = &sst26vf_locking_ops;
 }
 
 static const struct spi_nor_fixups sst26vf_fixups = {
-	.default_init = sst26vf_default_init,
+	.late_init = sst26vf_late_init,
 };
 
 static const struct flash_info sst_parts[] = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:17 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:17 +0300
Subject: [PATCH v3 09/25] mtd: spi-nor: xilinx: Use manufacturer late_init()
 to set setup method
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-10-tudor.ambarus@microchip.com>

post_sfdp was misleading in this case, as SFDP is not supported by
xilinx. Plus, there's no fixup here, just setting the correct
setup method, as required by xilinx parts.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/xilinx.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index 0658e47564ba..7e970ccf7903 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -80,13 +80,13 @@ static int xilinx_nor_setup(struct spi_nor *nor,
 	return 0;
 }
 
-static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
+static void xilinx_late_init(struct spi_nor *nor)
 {
 	nor->params->setup = xilinx_nor_setup;
 }
 
 static const struct spi_nor_fixups xilinx_fixups = {
-	.post_sfdp = xilinx_post_sfdp_fixups,
+	.late_init = xilinx_late_init,
 };
 
 const struct spi_nor_manufacturer spi_nor_xilinx = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:18 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:18 +0300
Subject: [PATCH v3 10/25] mtd: spi-nor: sst: Use manufacturer late_init() to
 set _write()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-11-tudor.ambarus@microchip.com>

Setting the correct nor->mtd._write in a fixup hook was misleading,
since this is not a fixup, just a specific setting for SST, that differs
from the SPI NOR core default init.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/sst.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 660aabde477a..3593aae0920f 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -177,14 +177,14 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
 	return ret;
 }
 
-static void sst_post_sfdp_fixups(struct spi_nor *nor)
+static void sst_late_init(struct spi_nor *nor)
 {
 	if (nor->info->flags & SST_WRITE)
 		nor->mtd._write = sst_write;
 }
 
 static const struct spi_nor_fixups sst_fixups = {
-	.post_sfdp = sst_post_sfdp_fixups,
+	.late_init = sst_late_init,
 };
 
 const struct spi_nor_manufacturer spi_nor_sst = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:19 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:19 +0300
Subject: [PATCH v3 11/25] mtd: spi-nor: spansion: Use manufacturer late_init()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-12-tudor.ambarus@microchip.com>

spansion_post_sfdp_fixups() was called regardless if the flash defined
SFDP tables or not. A better place for this kind of parameters init is
in manufacturer's late_init() hook. post_sfdp() should be called only
when SFDP is defined. No functional change in this patch.

Instead of doing the 4b opcodes settings at manufacturer level, thus
also for every flash that will be introduced, this should be done
just where it is needed, per flash. I'll let this for other patch.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/spansion.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index ee82dcd75310..a3ea0135f7b1 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -276,7 +276,7 @@ static const struct flash_info spansion_parts[] = {
 	},
 };
 
-static void spansion_post_sfdp_fixups(struct spi_nor *nor)
+static void spansion_late_init(struct spi_nor *nor)
 {
 	if (nor->params->size <= SZ_16M)
 		return;
@@ -288,7 +288,7 @@ static void spansion_post_sfdp_fixups(struct spi_nor *nor)
 }
 
 static const struct spi_nor_fixups spansion_fixups = {
-	.post_sfdp = spansion_post_sfdp_fixups,
+	.late_init = spansion_late_init,
 };
 
 const struct spi_nor_manufacturer spi_nor_spansion = {
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:20 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:20 +0300
Subject: [PATCH v3 12/25] mtd: spi-nor: core: Call spi_nor_post_sfdp_fixups()
 only when SFDP is defined
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-13-tudor.ambarus@microchip.com>

spi_nor_post_sfdp_fixups() was called even when there were no SFDP
tables defined. late_init() should be instead used for flashes that
do not define SFDP tables.

Use spi_nor_post_sfdp_fixups() just to fix SFDP data. post_sfdp()
hook is as of now used just by s28hs512t, mt35xu512aba, and both
support SFDP, there's no functional change with this patch.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 56 ++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 30 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 4679298c5301..82cc56c9d09e 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2508,6 +2508,25 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 		nor->info->fixups->default_init(nor);
 }
 
+/**
+ * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
+ * after SFDP has been parsed. Called only for flashes that define JESD216 SFDP
+ * tables.
+ * @nor:	pointer to a 'struct spi_nor'
+ *
+ * Used to tweak various flash parameters when information provided by the SFDP
+ * tables are wrong.
+ */
+static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
+{
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->post_sfdp)
+		nor->manufacturer->fixups->post_sfdp(nor);
+
+	if (nor->info->fixups && nor->info->fixups->post_sfdp)
+		nor->info->fixups->post_sfdp(nor);
+}
+
 /**
  * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
  * based on JESD216 SFDP standard.
@@ -2522,7 +2541,9 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
 
 	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
 
-	if (spi_nor_parse_sfdp(nor)) {
+	if (!spi_nor_parse_sfdp(nor)) {
+		spi_nor_post_sfdp_fixups(nor);
+	} else {
 		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
 		nor->addr_width = 0;
 		nor->flags &= ~SNOR_F_4B_OPCODES;
@@ -2642,26 +2663,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 }
 
-/**
- * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
- * after SFDP has been parsed (is also called for SPI NORs that do not
- * support RDSFDP).
- * @nor:	pointer to a 'struct spi_nor'
- *
- * Typically used to tweak various parameters that could not be extracted by
- * other means (i.e. when information provided by the SFDP/flash_info tables
- * are incomplete or wrong).
- */
-static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
-{
-	if (nor->manufacturer && nor->manufacturer->fixups &&
-	    nor->manufacturer->fixups->post_sfdp)
-		nor->manufacturer->fixups->post_sfdp(nor);
-
-	if (nor->info->fixups && nor->info->fixups->post_sfdp)
-		nor->info->fixups->post_sfdp(nor);
-}
-
 /**
  * spi_nor_late_init_params() - Late initialization of default flash parameters.
  * @nor:	pointer to a 'struct spi_nor'
@@ -2712,15 +2713,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
  *    Please note that there is a ->post_bfpt() fixup hook that can overwrite
  *    the flash parameters and settings immediately after parsing the Basic
  *    Flash Parameter Table.
+ *    spi_nor_post_sfdp_fixups() is called after the SFDP tables are parsed.
+ *    It is used to tweak various flash parameters when information provided
+ *    by the SFDP tables are wrong.
  *
  * which can be overwritten by:
- * 4/ Post SFDP flash parameters initialization. Used to tweak various
- *    parameters that could not be extracted by other means (i.e. when
- *    information provided by the SFDP/flash_info tables are incomplete or
- *    wrong).
- *		spi_nor_post_sfdp_fixups()
- *
- * 5/ Late flash parameters initialization, used to initialize flash
+ * 4/ Late flash parameters initialization, used to initialize flash
  * parameters that are not declared in the JESD216 SFDP standard, or where SFDP
  * tables are not defined at all.
  *		spi_nor_late_init_params()
@@ -2740,8 +2738,6 @@ static int spi_nor_init_params(struct spi_nor *nor)
 	    !(nor->info->flags & SPI_NOR_SKIP_SFDP))
 		spi_nor_sfdp_init_params(nor);
 
-	spi_nor_post_sfdp_fixups(nor);
-
 	spi_nor_late_init_params(nor);
 
 	return 0;
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:21 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:21 +0300
Subject: [PATCH v3 13/25] mtd: spi-nor: sst: Get rid of SST_WRITE flash_info
 flag
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-14-tudor.ambarus@microchip.com>

The flash_info flags should be generic and not manufacturer specific.
Get rid of the manufacturer specific flag and use the late_init() fixup
hook instead.
Please note that sst_write is now set at flash level and not globally,
per manufacturer. Manufacturer hooks are generally a bad idea, because
it affects settings for all the flashes and we might end up with fixups
for "manufacturer settings".

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.h |   1 -
 drivers/mtd/spi-nor/sst.c  | 100 +++++++++++++++++++++----------------
 2 files changed, 58 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index f6c4b6f4743b..6fc63ef4267b 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -336,7 +336,6 @@ struct flash_info {
 	u32		flags;
 #define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */
 #define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */
-#define SST_WRITE		BIT(2)	/* use SST byte programming */
 #define SPI_NOR_NO_FR		BIT(3)	/* Can't do fastread */
 #define SECT_4K_PMC		BIT(4)	/* SPINOR_OP_BE_4K_PMC works uniformly */
 #define SPI_NOR_DUAL_READ	BIT(5)	/* Flash supports Dual Read */
diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 3593aae0920f..40e55b531edb 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -55,42 +55,6 @@ static const struct spi_nor_fixups sst26vf_fixups = {
 	.late_init = sst26vf_late_init,
 };
 
-static const struct flash_info sst_parts[] = {
-	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
-	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128,
-			      SECT_4K | SPI_NOR_4BIT_BP | SPI_NOR_HAS_LOCK |
-			      SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024,  4, SECT_4K | SPI_NOR_HAS_LOCK) },
-	{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024,  8, SECT_4K | SPI_NOR_HAS_LOCK) },
-	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16,
-			      SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE) },
-	{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
-			      SECT_4K | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ) },
-	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
-			      SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
-			      SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			      SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
-		.fixups = &sst26vf_fixups },
-};
-
 static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
 		     size_t *retlen, const u_char *buf)
 {
@@ -177,19 +141,71 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
 	return ret;
 }
 
-static void sst_late_init(struct spi_nor *nor)
+static void sst_write_late_init(struct spi_nor *nor)
 {
-	if (nor->info->flags & SST_WRITE)
-		nor->mtd._write = sst_write;
+	nor->mtd._write = sst_write;
 }
 
-static const struct spi_nor_fixups sst_fixups = {
-	.late_init = sst_late_init,
+static const struct spi_nor_fixups sst_write_fixup = {
+	.late_init = sst_write_late_init,
+};
+
+static const struct flash_info sst_parts[] = {
+	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
+	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128,
+			      SECT_4K | SPI_NOR_4BIT_BP | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE) },
+	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024,  4, SECT_4K | SPI_NOR_HAS_LOCK) },
+	{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024,  8, SECT_4K | SPI_NOR_HAS_LOCK) },
+	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16,
+			      SECT_4K | SPI_NOR_HAS_LOCK |
+			      SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst_write_fixup },
+	{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
+			      SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
+			      SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
+		.fixups = &sst26vf_fixups },
 };
 
 const struct spi_nor_manufacturer spi_nor_sst = {
 	.name = "sst",
 	.parts = sst_parts,
 	.nparts = ARRAY_SIZE(sst_parts),
-	.fixups = &sst_fixups,
 };
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:22 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:22 +0300
Subject: [PATCH v3 14/25] mtd: spi-nor: Introduce flash_info flags masks
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-15-tudor.ambarus@microchip.com>

Clarify for what the flash_info flags are used for. Split them in
three categories:
1/ NON_SFDP_FLAGS: flags that indicate support that is not defined
   by the JESD216 standard in its SFDP tables.
2/ SFDP_FLAGS: flags that indicate support that can be discovered
   via SFDP. These flags are used when the flash does not define the
   SFDP tables. Used together with SPI_NOR_SKIP_SFDP flag.
3/ FIXUP_FLAGS: flags that indicate support that can be discovered
   via SFDP ideally, but can not be discovered for this particular flash
   because the SFDP table that indicates this support is not defined by
   the flash. In case the table for this support is defined but has wrong
   values, one should instead use a post_sfdp() hook to set the SNOR_F
   equivalent flag.

Manufacturer specific flags like USE_CLSR, USE_FSR, SPI_NOR_XSR_RDY,
will be removed in a future series.

BIT(0) was kept for SPI_NOR_PARSE_SFDP (will be introduced in a
further patch).

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.h | 89 ++++++++++++++++++++++++--------------
 1 file changed, 57 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 6fc63ef4267b..1fadd0e74103 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -334,56 +334,81 @@ struct flash_info {
 	u16		addr_width;
 
 	u32		flags;
-#define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */
-#define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */
-#define SPI_NOR_NO_FR		BIT(3)	/* Can't do fastread */
-#define SECT_4K_PMC		BIT(4)	/* SPINOR_OP_BE_4K_PMC works uniformly */
-#define SPI_NOR_DUAL_READ	BIT(5)	/* Flash supports Dual Read */
-#define SPI_NOR_QUAD_READ	BIT(6)	/* Flash supports Quad Read */
-#define USE_FSR			BIT(7)	/* use flag status register */
-#define SPI_NOR_HAS_LOCK	BIT(8)	/* Flash supports lock/unlock via SR */
-#define SPI_NOR_HAS_TB		BIT(9)	/*
+#define SPI_NOR_SKIP_SFDP	BIT(1)	/* Skip parsing of SFDP tables */
+
+/*
+ * Flags that indicate support that is not defined by the JESD216 standard in
+ * its SFDP tables.
+ */
+#define NON_SFDP_FLAGS_MASK	GENMASK(15, 2)
+#define NON_SFDP_FLAGS(x)	((x) & NON_SFDP_FLAGS_MASK)
+#define SPI_NOR_HAS_LOCK	BIT(2)	/* Flash supports lock/unlock via SR */
+#define SPI_NOR_HAS_TB		BIT(3)	/*
 					 * Flash SR has Top/Bottom (TB) protect
 					 * bit. Must be used with
 					 * SPI_NOR_HAS_LOCK.
 					 */
-#define SPI_NOR_XSR_RDY		BIT(10)	/*
-					 * S3AN flashes have specific opcode to
-					 * read the status register.
-					 */
-#define SPI_NOR_4B_OPCODES	BIT(11)	/*
-					 * Use dedicated 4byte address op codes
-					 * to support memory size above 128Mib.
-					 */
-#define NO_CHIP_ERASE		BIT(12) /* Chip does not support chip erase */
-#define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */
-#define USE_CLSR		BIT(14)	/* use CLSR command */
-#define SPI_NOR_OCTAL_READ	BIT(15)	/* Flash supports Octal Read */
-#define SPI_NOR_TB_SR_BIT6	BIT(16)	/*
+#define SPI_NOR_TB_SR_BIT6	BIT(4)	/*
 					 * Top/Bottom (TB) is bit 6 of
 					 * status register. Must be used with
 					 * SPI_NOR_HAS_TB.
 					 */
-#define SPI_NOR_4BIT_BP		BIT(17) /*
+#define SPI_NOR_4BIT_BP		BIT(5) /*
 					 * Flash SR has 4 bit fields (BP0-3)
 					 * for block protection.
 					 */
-#define SPI_NOR_BP3_SR_BIT6	BIT(18) /*
+#define SPI_NOR_BP3_SR_BIT6	BIT(6) /*
 					 * BP3 is bit 6 of status register.
 					 * Must be used with SPI_NOR_4BIT_BP.
 					 */
-#define SPI_NOR_OCTAL_DTR_READ	BIT(19) /* Flash supports octal DTR Read. */
-#define SPI_NOR_OCTAL_DTR_PP	BIT(20) /* Flash supports Octal DTR Page Program */
-#define SPI_NOR_IO_MODE_EN_VOLATILE	BIT(21) /*
-						 * Flash enables the best
-						 * available I/O mode via a
-						 * volatile bit.
-						 */
-#define SPI_NOR_SWP_IS_VOLATILE	BIT(22)	/*
+#define SPI_NOR_SWP_IS_VOLATILE	BIT(7)	/*
 					 * Flash has volatile software write
 					 * protection bits. Usually these will
 					 * power-up in a write-protected state.
 					 */
+#define SPI_NOR_NO_ERASE	BIT(8)	/* No erase command needed */
+#define NO_CHIP_ERASE		BIT(9) /* Chip does not support chip erase */
+#define SPI_NOR_NO_FR		BIT(10)	/* Can't do fastread */
+#define USE_CLSR		BIT(11)	/* use CLSR command */
+#define USE_FSR			BIT(12)	/* use flag status register */
+#define SPI_NOR_XSR_RDY		BIT(13)	/*
+					 * S3AN flashes have specific opcode to
+					 * read the status register.
+					 */
+
+/*
+ * Flags that indicate support that can be discovered via SFDP. Used when SFDP
+ * tables are not defined in the flash. These flags are used together with the
+ * SPI_NOR_SKIP_SFDP flag.
+ */
+#define SFDP_FLAGS_MASK		GENMASK(23, 16)
+#define SFDP_FLAGS(x)		((x) & SFDP_FLAGS_MASK)
+#define SECT_4K			BIT(16)	/* SPINOR_OP_BE_4K works uniformly */
+#define SECT_4K_PMC		BIT(17)	/* SPINOR_OP_BE_4K_PMC works uniformly */
+#define SPI_NOR_DUAL_READ	BIT(18)	/* Flash supports Dual Read */
+#define SPI_NOR_QUAD_READ	BIT(19)	/* Flash supports Quad Read */
+#define SPI_NOR_OCTAL_READ	BIT(20)	/* Flash supports Octal Read */
+#define SPI_NOR_OCTAL_DTR_READ	BIT(21) /* Flash supports octal DTR Read. */
+#define SPI_NOR_OCTAL_DTR_PP	BIT(22) /* Flash supports Octal DTR Page Program */
+
+/*
+ * Flags that indicate support that can be discovered via SFDP ideally, but can
+ * not be discovered for this particular flash because the SFDP table that
+ * indicates this support is not defined by the flash. In case the table for
+ * this support is defined but has wrong values, one should instead use a
+ * post_sfdp() hook to set the SNOR_F equivalent flag.
+ */
+#define FIXUP_FLAGS_MASK	GENMASK(31, 24)
+#define FIXUP_FLAGS(x)		((x) & FIXUP_FLAGS_MASK)
+#define SPI_NOR_4B_OPCODES	BIT(24)	/*
+					 * Use dedicated 4byte address op codes
+					 * to support memory size above 128Mib.
+					 */
+#define SPI_NOR_IO_MODE_EN_VOLATILE	BIT(25) /*
+						 * Flash enables the best
+						 * available I/O mode via a
+						 * volatile bit.
+						 */
 
 	const struct spi_nor_otp_organization otp_org;
 
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:23 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:23 +0300
Subject: [PATCH v3 15/25] mtd: spi-nor: Introduce spi_nor_nonsfdp_init_flags()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-16-tudor.ambarus@microchip.com>

Used to initialize the NOR flags for settings that are not defined
in the JESD216 SFDP standard, thus can not be retrieved when parsing
SFDP.
This moves the setting of SNOR_F_READY_XSR_RDY and SNOR_F_HAS_LOCK
late in the init call, without any functional change expected.
The rest of the flags were already set after the spi_nor_init_params().

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 88 ++++++++++++++++++++++----------------
 1 file changed, 52 insertions(+), 36 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 82cc56c9d09e..0e31f8a2457d 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2663,6 +2663,56 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 }
 
+/**
+ * spi_nor_nonsfdp_init_flags() - Initialize NOR flags for settings that are not
+ * defined in the JESD216 SFDP standard, thus can not be retrieved when parsing
+ * SFDP.
+ * @nor:	pointer to a 'struct spi_nor'
+ */
+static void spi_nor_nonsfdp_init_flags(struct spi_nor *nor)
+{
+	struct device_node *np = spi_nor_get_flash_node(nor);
+	const u32 info_flags = nor->info->flags & NON_SFDP_FLAGS_MASK;
+
+	if (of_property_read_bool(np, "broken-flash-reset"))
+		nor->flags |= SNOR_F_BROKEN_RESET;
+
+	if (info_flags & SPI_NOR_SWP_IS_VOLATILE)
+		nor->flags |= SNOR_F_SWP_IS_VOLATILE;
+
+	if (info_flags & SPI_NOR_HAS_LOCK)
+		nor->flags |= SNOR_F_HAS_LOCK;
+
+	if (info_flags & SPI_NOR_HAS_TB) {
+		nor->flags |= SNOR_F_HAS_SR_TB;
+		if (info_flags & SPI_NOR_TB_SR_BIT6)
+			nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
+	}
+
+	if (info_flags & SPI_NOR_4BIT_BP) {
+		nor->flags |= SNOR_F_HAS_4BIT_BP;
+		if (info_flags & SPI_NOR_BP3_SR_BIT6)
+			nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
+	}
+
+	if (info_flags & NO_CHIP_ERASE)
+		nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
+
+	if (info_flags & USE_CLSR)
+		nor->flags |= SNOR_F_USE_CLSR;
+
+	if (info_flags & USE_FSR)
+		nor->flags |= SNOR_F_USE_FSR;
+
+	/*
+	 * Make sure the XSR_RDY flag is set before calling
+	 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
+	 * with Atmel SPI NOR.
+	 */
+	if (info_flags & SPI_NOR_XSR_RDY)
+		nor->flags |=  SNOR_F_READY_XSR_RDY;
+}
+
 /**
  * spi_nor_late_init_params() - Late initialization of default flash parameters.
  * @nor:	pointer to a 'struct spi_nor'
@@ -2680,6 +2730,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 	if (nor->info->fixups && nor->info->fixups->late_init)
 		nor->info->fixups->late_init(nor);
 
+	spi_nor_nonsfdp_init_flags(nor);
+
 	/*
 	 * NOR protection support. When locking_ops are not provided, we pick
 	 * the default ones.
@@ -3111,7 +3163,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	const struct flash_info *info;
 	struct device *dev = nor->dev;
 	struct mtd_info *mtd = &nor->mtd;
-	struct device_node *np = spi_nor_get_flash_node(nor);
 	int ret;
 	int i;
 
@@ -3148,46 +3199,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 
 	mutex_init(&nor->lock);
 
-	/*
-	 * Make sure the XSR_RDY flag is set before calling
-	 * spi_nor_wait_till_ready(). Xilinx S3AN share MFR
-	 * with Atmel SPI NOR.
-	 */
-	if (info->flags & SPI_NOR_XSR_RDY)
-		nor->flags |=  SNOR_F_READY_XSR_RDY;
-
-	if (info->flags & SPI_NOR_HAS_LOCK)
-		nor->flags |= SNOR_F_HAS_LOCK;
-
 	/* Init flash parameters based on flash_info struct and SFDP */
 	ret = spi_nor_init_params(nor);
 	if (ret)
 		return ret;
 
-	if (info->flags & USE_FSR)
-		nor->flags |= SNOR_F_USE_FSR;
-	if (info->flags & SPI_NOR_HAS_TB) {
-		nor->flags |= SNOR_F_HAS_SR_TB;
-		if (info->flags & SPI_NOR_TB_SR_BIT6)
-			nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
-	}
-
-	if (info->flags & NO_CHIP_ERASE)
-		nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
-	if (info->flags & USE_CLSR)
-		nor->flags |= SNOR_F_USE_CLSR;
-	if (info->flags & SPI_NOR_SWP_IS_VOLATILE)
-		nor->flags |= SNOR_F_SWP_IS_VOLATILE;
-
-	if (info->flags & SPI_NOR_4BIT_BP) {
-		nor->flags |= SNOR_F_HAS_4BIT_BP;
-		if (info->flags & SPI_NOR_BP3_SR_BIT6)
-			nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
-	}
-
-	if (of_property_read_bool(np, "broken-flash-reset"))
-		nor->flags |= SNOR_F_BROKEN_RESET;
-
 	/*
 	 * Configure the SPI memory:
 	 * - select op codes for (Fast) Read, Page Program and Sector Erase.
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:24 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:24 +0300
Subject: [PATCH v3 16/25] mtd: spi-nor: Introduce spi_nor_init_fixup_flags()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-17-tudor.ambarus@microchip.com>

Initialize NOR flags for settings that can not be discovered by SFDP
for this particular flash because the SFDP table that indicates this
support is not defined in the flash. In case the table for his support
is defined but has wrong values, one should instead use a post_sfdp()
hook to set the SNOR_F equivalent flag.
Update all flash_info entries that use SPI_NOR_4B_OPCODES or
SPI_NOR_IO_MODE_EN_VOLATILE to also use the FIXUP_FLAGS() macro. This
should highlight to developers that those flags should be used only
as fixups, where flashes miss to define the SFDP tables that describe
those settings.
No functional change intended in this patch.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c       | 26 ++++++++++++++++++++------
 drivers/mtd/spi-nor/gigadevice.c |  5 +++--
 drivers/mtd/spi-nor/issi.c       |  4 ++--
 drivers/mtd/spi-nor/macronix.c   | 13 ++++++++-----
 drivers/mtd/spi-nor/micron-st.c  | 20 ++++++++++++--------
 drivers/mtd/spi-nor/spansion.c   |  6 +++---
 6 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 0e31f8a2457d..6f7978e7a46a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2713,6 +2713,25 @@ static void spi_nor_nonsfdp_init_flags(struct spi_nor *nor)
 		nor->flags |=  SNOR_F_READY_XSR_RDY;
 }
 
+/**
+ * spi_nor_init_fixup_flags() - Initialize NOR flags for settings that can not
+ * be discovered by SFDP for this particular flash because the SFDP table that
+ * indicates this support is not defined in the flash. In case the table for
+ * this support is defined but has wrong values, one should instead use a
+ * post_sfdp() hook to set the SNOR_F equivalent flag.
+ * @nor:	pointer to a 'struct spi_nor'
+ */
+static void spi_nor_init_fixup_flags(struct spi_nor *nor)
+{
+	const u32 info_flags = nor->info->flags & FIXUP_FLAGS_MASK;
+
+	if (info_flags & SPI_NOR_4B_OPCODES)
+		nor->flags |= SNOR_F_4B_OPCODES;
+
+	if (info_flags & SPI_NOR_IO_MODE_EN_VOLATILE)
+		nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
+}
+
 /**
  * spi_nor_late_init_params() - Late initialization of default flash parameters.
  * @nor:	pointer to a 'struct spi_nor'
@@ -2731,6 +2750,7 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 		nor->info->fixups->late_init(nor);
 
 	spi_nor_nonsfdp_init_flags(nor);
+	spi_nor_init_fixup_flags(nor);
 
 	/*
 	 * NOR protection support. When locking_ops are not provided, we pick
@@ -3214,12 +3234,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	if (ret)
 		return ret;
 
-	if (info->flags & SPI_NOR_4B_OPCODES)
-		nor->flags |= SNOR_F_4B_OPCODES;
-
-	if (info->flags & SPI_NOR_IO_MODE_EN_VOLATILE)
-		nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
-
 	ret = spi_nor_set_addr_width(nor);
 	if (ret)
 		return ret;
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index 447d84bb2128..59053f419642 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -47,8 +47,9 @@ static const struct flash_info gigadevice_parts[] = {
 			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
 	{ "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
 			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			   SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK |
-			   SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
+			   SPI_NOR_TB_SR_BIT6 |
+			   FIXUP_FLAGS(SPI_NOR_4B_OPCODES))
 		.fixups = &gd25q256_fixups },
 };
 
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 1e5bb5408b68..b2abe8202143 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -46,7 +46,7 @@ static const struct flash_info issi_parts[] = {
 			     SECT_4K | SPI_NOR_DUAL_READ) },
 	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			     SPI_NOR_4B_OPCODES)
+			     FIXUP_FLAGS(SPI_NOR_4B_OPCODES))
 		.fixups = &is25lp256_fixups },
 	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
@@ -56,7 +56,7 @@ static const struct flash_info issi_parts[] = {
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
 			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			    SPI_NOR_4B_OPCODES)
+			    FIXUP_FLAGS(SPI_NOR_4B_OPCODES))
 		.fixups = &is25lp256_fixups },
 
 	/* PMC */
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 27498ed0cc0d..d0285e60092e 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -65,20 +65,22 @@ static const struct flash_info macronix_parts[] = {
 			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
 		.fixups = &mx25l25635_fixups },
 	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
-			      SECT_4K | SPI_NOR_4B_OPCODES) },
+			      SECT_4K | FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "mx25u51245g", INFO(0xc2253a, 0, 64 * 1024, 1024,
 			      SECT_4K | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			      SPI_NOR_QUAD_READ |
+			      FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
 			      SECT_4K | SPI_NOR_DUAL_READ |
 			      SPI_NOR_QUAD_READ) },
 	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
 	{ "mx66l51235f", INFO(0xc2201a, 0, 64 * 1024, 1024,
 			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			      SPI_NOR_4B_OPCODES) },
+			      FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
 			      SECT_4K | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			      SPI_NOR_QUAD_READ |
+			      FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048,
 			      SECT_4K | SPI_NOR_DUAL_READ |
 			      SPI_NOR_QUAD_READ) },
@@ -86,7 +88,8 @@ static const struct flash_info macronix_parts[] = {
 			      SPI_NOR_QUAD_READ) },
 	{ "mx66u2g45g",	 INFO(0xc2253c, 0, 64 * 1024, 4096,
 			      SECT_4K | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			      SPI_NOR_QUAD_READ |
+			      FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 };
 
 static void macronix_default_init(struct spi_nor *nor)
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index f3d19b716b7b..c982458d5e31 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -121,13 +121,13 @@ static struct spi_nor_fixups mt35xu512aba_fixups = {
 static const struct flash_info micron_parts[] = {
 	{ "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
 			       SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			       SPI_NOR_4B_OPCODES | SPI_NOR_OCTAL_DTR_READ |
-			       SPI_NOR_OCTAL_DTR_PP |
-			       SPI_NOR_IO_MODE_EN_VOLATILE)
+			       SPI_NOR_OCTAL_DTR_READ | SPI_NOR_OCTAL_DTR_PP |
+			       FIXUP_FLAGS(SPI_NOR_4B_OPCODES |
+					   SPI_NOR_IO_MODE_EN_VOLATILE))
 	  .fixups = &mt35xu512aba_fixups},
 	{ "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
 			    SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			    SPI_NOR_4B_OPCODES) },
+			    FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 };
 
 static const struct flash_info st_parts[] = {
@@ -151,25 +151,29 @@ static const struct flash_info st_parts[] = {
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
 	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ |
+			       FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
 			      USE_FSR | SPI_NOR_DUAL_READ |
 			      SPI_NOR_QUAD_READ) },
 	{ "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ |
+			       FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
 	{ "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ |
+			       FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
 			      SPI_NOR_4BIT_BP | SPI_NOR_BP3_SR_BIT6) },
 	{ "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
 			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+			       SPI_NOR_QUAD_READ |
+			       FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024,
 			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
 			      SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index a3ea0135f7b1..3ee1cd3b8fb5 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -260,13 +260,13 @@ static const struct flash_info spansion_parts[] = {
 			     SECT_4K | SPI_NOR_DUAL_READ) },
 	{ "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			     SPI_NOR_4B_OPCODES) },
+			     FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			     SPI_NOR_4B_OPCODES) },
+			     FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			     SPI_NOR_4B_OPCODES) },
+			     FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
 	{ "cy15x104q",  INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1,
 			      SPI_NOR_NO_ERASE) },
 	{ "s28hs512t",   INFO(0x345b1a,      0, 256 * 1024, 256,
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:25 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:25 +0300
Subject: [PATCH v3 17/25] mtd: spi-nor: core: Introduce SPI_NOR_PARSE_SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-18-tudor.ambarus@microchip.com>

SPI NOR flashes that statically declare one of the
SPI_NOR_{DUAL, QUAD, OCTAL, OCTAL_DTR}_READ flags and do not support
the RDSFDP command are gratuiously receiving the RDSFDP command
in the attempt of parsing the SFDP tables. It is not desirable to issue
commands that are not supported, so introduce a flag to help on this
situation.

New flash additions that support the SFDP standard should be declared
using SPI_NOR_PARSE_SFDP. Support that can be discovered when parsing
SFDP should not be duplicated by explicit flags at flash declaration.
All the flash parameters will be discovered when parsing SFDP.
Sometimes manufacturers wrongly define some fields in the SFDP tables.
If that's the case, SFDP data can be amended with the fixups() hooks.
It is not common, but if the SFDP tables are entirely wrong, and it
does not worth the hassle to tweak the SFDP parameters by using the
fixups hooks, or if the flash does not define the SFDP tables at all,
then statically init the flash with the SPI_NOR_SKIP_SFDP flag and
specify the rest of flash capabilities with the flash info flags.

With time, we want to convert all flashes to SPI_NOR_PARSE_SFDP and
stop triggering the SFDP parsing with the
SPI_NOR_{DUAL, QUAD, OCTAL*}_READ flags. Getting rid of the
SPI_NOR_{OCTAL, OCTAL_DTR}_READ trigger is easily achievable, the rest
are a long term goal.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
Reviewed-by: Heiko Thiery <heiko.thiery at gmail.com>
Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
Reviewed-by: Michael Walle <michael at walle.cc>
---
 drivers/mtd/spi-nor/core.c | 3 ++-
 drivers/mtd/spi-nor/core.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 6f7978e7a46a..40d98ae300ca 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2805,7 +2805,8 @@ static int spi_nor_init_params(struct spi_nor *nor)
 
 	spi_nor_manufacturer_init_params(nor);
 
-	if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+	if ((nor->info->flags & (SPI_NOR_PARSE_SFDP |
+				 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 				 SPI_NOR_OCTAL_READ | SPI_NOR_OCTAL_DTR_READ)) &&
 	    !(nor->info->flags & SPI_NOR_SKIP_SFDP))
 		spi_nor_sfdp_init_params(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1fadd0e74103..9dd8ada65f0c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -334,6 +334,7 @@ struct flash_info {
 	u16		addr_width;
 
 	u32		flags;
+#define SPI_NOR_PARSE_SFDP	BIT(0)	/* Flash initialized based on SFDP. */
 #define SPI_NOR_SKIP_SFDP	BIT(1)	/* Skip parsing of SFDP tables */
 
 /*
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:26 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:26 +0300
Subject: [PATCH v3 18/25] mtd: spi-nor: core: Init flash params based on SFDP
 first for new flash additions
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-19-tudor.ambarus@microchip.com>

New flash additions that support SFDP should be declared with
SPI_NOR_PARSE_SFDP and with all the other flags that are not SFDP
discoverable.
Keep the old way of initializing the flash, until all the flashes
are converted to use either SPI_NOR_PARSE_SFDP or SPI_NOR_SKIP_SFDP.
Since we want to get rid of the default_init() hook, the rollback
mechanism for flashes that use SPI_NOR_PARSE_SFDP does not call
spi_nor_manufacturer_init_params().
Split spi_nor_info_init_params() in spi_nor_init_default_params()
and spi_nor_skip_sfdp_init_params(). spi_nor_init_default_params() is
called for all the flashes regardless if they support SFDP or not.
spi_nor_skip_sfdp_init_params() is called just for the flashes that
do not define SFDP and initializes parameters and setting solely based
on flash_info data.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/core.c | 187 +++++++++++++++++++++----------------
 1 file changed, 105 insertions(+), 82 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 40d98ae300ca..c509f257a6c3 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2493,6 +2493,56 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params->setup(nor, hwcaps);
 }
 
+/**
+ * spi_nor_init_default_params() - Default initialization of flash parameters
+ * and settings. Done for all flashes, regardless is they define SFDP tables
+ * or not.
+ * @nor:	pointer to a 'struct spi_nor'.
+ */
+static void spi_nor_init_default_params(struct spi_nor *nor)
+{
+	struct spi_nor_flash_parameter *params = nor->params;
+	const struct flash_info *info = nor->info;
+	struct device_node *np = spi_nor_get_flash_node(nor);
+
+	params->quad_enable = spi_nor_sr2_bit1_quad_enable;
+	params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
+	params->setup = spi_nor_default_setup;
+	params->otp.org = &info->otp_org;
+
+	/* Default to 16-bit Write Status (01h) Command */
+	nor->flags |= SNOR_F_HAS_16BIT_SR;
+
+	/* Set SPI NOR sizes. */
+	params->writesize = 1;
+	params->size = (u64)info->sector_size * info->n_sectors;
+	params->page_size = info->page_size;
+
+	if (!(info->flags & SPI_NOR_NO_FR)) {
+		/* Default to Fast Read for DT and non-DT platform devices. */
+		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
+
+		/* Mask out Fast Read if not requested at DT instantiation. */
+		if (np && !of_property_read_bool(np, "m25p,fast-read"))
+			params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
+	}
+
+	/* (Fast) Read settings. */
+	params->hwcaps.mask |= SNOR_HWCAPS_READ;
+	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
+				  0, 0, SPINOR_OP_READ,
+				  SNOR_PROTO_1_1_1);
+
+	if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
+		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
+					  0, 8, SPINOR_OP_READ_FAST,
+					  SNOR_PROTO_1_1_1);
+	/* Page Program settings. */
+	params->hwcaps.mask |= SNOR_HWCAPS_PP;
+	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
+				SPINOR_OP_PP, SNOR_PROTO_1_1_1);
+}
+
 /**
  * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
  * settings based on MFR register and ->default_init() hook.
@@ -2528,109 +2578,46 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
 }
 
 /**
- * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
- * based on JESD216 SFDP standard.
- * @nor:	pointer to a 'struct spi_nor'.
- *
- * The method has a roll-back mechanism: in case the SFDP parsing fails, the
- * legacy flash parameters and settings will be restored.
- */
-static void spi_nor_sfdp_init_params(struct spi_nor *nor)
-{
-	struct spi_nor_flash_parameter sfdp_params;
-
-	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
-
-	if (!spi_nor_parse_sfdp(nor)) {
-		spi_nor_post_sfdp_fixups(nor);
-	} else {
-		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
-		nor->addr_width = 0;
-		nor->flags &= ~SNOR_F_4B_OPCODES;
-	}
-}
-
-/**
- * spi_nor_info_init_params() - Initialize the flash's parameters and settings
- * based on nor->info data.
+ * spi_nor_skip_sfdp_init_params() - Initialize the flash's parameters and
+ * settings based on nor->info data.
  * @nor:	pointer to a 'struct spi_nor'.
  */
-static void spi_nor_info_init_params(struct spi_nor *nor)
+static void spi_nor_skip_sfdp_init_params(struct spi_nor *nor)
 {
 	struct spi_nor_flash_parameter *params = nor->params;
 	struct spi_nor_erase_map *map = &params->erase_map;
-	const struct flash_info *info = nor->info;
-	struct device_node *np = spi_nor_get_flash_node(nor);
+	const u32 info_flags = nor->info->flags & SFDP_FLAGS_MASK;
 	u8 i, erase_mask;
 
-	/* Initialize default flash parameters and settings. */
-	params->quad_enable = spi_nor_sr2_bit1_quad_enable;
-	params->set_4byte_addr_mode = spansion_set_4byte_addr_mode;
-	params->setup = spi_nor_default_setup;
-	params->otp.org = &info->otp_org;
-
-	/* Default to 16-bit Write Status (01h) Command */
-	nor->flags |= SNOR_F_HAS_16BIT_SR;
-
-	/* Set SPI NOR sizes. */
-	params->writesize = 1;
-	params->size = (u64)info->sector_size * info->n_sectors;
-	params->page_size = info->page_size;
-
-	if (!(info->flags & SPI_NOR_NO_FR)) {
-		/* Default to Fast Read for DT and non-DT platform devices. */
-		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
-
-		/* Mask out Fast Read if not requested at DT instantiation. */
-		if (np && !of_property_read_bool(np, "m25p,fast-read"))
-			params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
-	}
-
-	/* (Fast) Read settings. */
-	params->hwcaps.mask |= SNOR_HWCAPS_READ;
-	spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],
-				  0, 0, SPINOR_OP_READ,
-				  SNOR_PROTO_1_1_1);
-
-	if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
-		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],
-					  0, 8, SPINOR_OP_READ_FAST,
-					  SNOR_PROTO_1_1_1);
-
-	if (info->flags & SPI_NOR_DUAL_READ) {
+	if (info_flags & SPI_NOR_DUAL_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],
 					  0, 8, SPINOR_OP_READ_1_1_2,
 					  SNOR_PROTO_1_1_2);
 	}
 
-	if (info->flags & SPI_NOR_QUAD_READ) {
+	if (info_flags & SPI_NOR_QUAD_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_4],
 					  0, 8, SPINOR_OP_READ_1_1_4,
 					  SNOR_PROTO_1_1_4);
 	}
 
-	if (info->flags & SPI_NOR_OCTAL_READ) {
+	if (info_flags & SPI_NOR_OCTAL_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],
 					  0, 8, SPINOR_OP_READ_1_1_8,
 					  SNOR_PROTO_1_1_8);
 	}
 
-	if (info->flags & SPI_NOR_OCTAL_DTR_READ) {
+	if (info_flags & SPI_NOR_OCTAL_DTR_READ) {
 		params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
 		spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_8_8_8_DTR],
 					  0, 20, SPINOR_OP_READ_FAST,
 					  SNOR_PROTO_8_8_8_DTR);
 	}
 
-	/* Page Program settings. */
-	params->hwcaps.mask |= SNOR_HWCAPS_PP;
-	spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],
-				SPINOR_OP_PP, SNOR_PROTO_1_1_1);
-
-	if (info->flags & SPI_NOR_OCTAL_DTR_PP) {
+	if (info_flags & SPI_NOR_OCTAL_DTR_PP) {
 		params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
 		/*
 		 * Since xSPI Page Program opcode is backward compatible with
@@ -2646,23 +2633,49 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 	 */
 	erase_mask = 0;
 	i = 0;
-	if (info->flags & SECT_4K_PMC) {
+	if (info_flags & SECT_4K_PMC) {
 		erase_mask |= BIT(i);
 		spi_nor_set_erase_type(&map->erase_type[i], 4096u,
 				       SPINOR_OP_BE_4K_PMC);
 		i++;
-	} else if (info->flags & SECT_4K) {
+	} else if (info_flags & SECT_4K) {
 		erase_mask |= BIT(i);
 		spi_nor_set_erase_type(&map->erase_type[i], 4096u,
 				       SPINOR_OP_BE_4K);
 		i++;
 	}
 	erase_mask |= BIT(i);
-	spi_nor_set_erase_type(&map->erase_type[i], info->sector_size,
+	spi_nor_set_erase_type(&map->erase_type[i], nor->info->sector_size,
 			       SPINOR_OP_SE);
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 }
 
+/**
+ * spi_nor_sfdp_init_params() - Initialize the flash's parameters and settings
+ * based on JESD216 SFDP standard.
+ * @nor:	pointer to a 'struct spi_nor'.
+ *
+ * The method has a roll-back mechanism: in case the SFDP parsing fails, the
+ * legacy flash parameters and settings will be restored.
+ */
+static void spi_nor_sfdp_init_params(struct spi_nor *nor)
+{
+	struct spi_nor_flash_parameter sfdp_params;
+
+	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
+
+	if (!spi_nor_parse_sfdp(nor)) {
+		spi_nor_post_sfdp_fixups(nor);
+	} else {
+		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
+		nor->addr_width = 0;
+		nor->flags &= ~SNOR_F_4B_OPCODES;
+
+		if (nor->info->flags & SPI_NOR_PARSE_SFDP)
+			spi_nor_skip_sfdp_init_params(nor);
+	}
+}
+
 /**
  * spi_nor_nonsfdp_init_flags() - Initialize NOR flags for settings that are not
  * defined in the JESD216 SFDP standard, thus can not be retrieved when parsing
@@ -2760,6 +2773,19 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 		spi_nor_init_default_locking_ops(nor);
 }
 
+static void spi_nor_init_params_deprecated(struct spi_nor *nor)
+{
+	spi_nor_skip_sfdp_init_params(nor);
+
+	spi_nor_manufacturer_init_params(nor);
+
+	if ((nor->info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+				 SPI_NOR_OCTAL_READ |
+				 SPI_NOR_OCTAL_DTR_READ)) &&
+	    !(nor->info->flags & SPI_NOR_SKIP_SFDP))
+		spi_nor_sfdp_init_params(nor);
+}
+
 /**
  * spi_nor_init_params() - Initialize the flash's parameters and settings.
  * @nor:	pointer to a 'struct spi_nor'.
@@ -2801,15 +2827,12 @@ static int spi_nor_init_params(struct spi_nor *nor)
 	if (!nor->params)
 		return -ENOMEM;
 
-	spi_nor_info_init_params(nor);
+	spi_nor_init_default_params(nor);
 
-	spi_nor_manufacturer_init_params(nor);
-
-	if ((nor->info->flags & (SPI_NOR_PARSE_SFDP |
-				 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-				 SPI_NOR_OCTAL_READ | SPI_NOR_OCTAL_DTR_READ)) &&
-	    !(nor->info->flags & SPI_NOR_SKIP_SFDP))
+	if (nor->info->flags & SPI_NOR_PARSE_SFDP)
 		spi_nor_sfdp_init_params(nor);
+	else
+		spi_nor_init_params_deprecated(nor);
 
 	spi_nor_late_init_params(nor);
 
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:27 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:27 +0300
Subject: [PATCH v3 19/25] mtd: spi-nor: core: Move spi_nor_set_addr_width() in
 spi_nor_setup()
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-20-tudor.ambarus@microchip.com>

spi_nor_setup() configures the SPI NOR memory. Setting the addr width
is too a configuration, hence we can move the spi_nor_set_addr_width()
in spi_nor_setup().

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav at ti.com>
---
 drivers/mtd/spi-nor/core.c | 102 +++++++++++++++++++------------------
 1 file changed, 52 insertions(+), 50 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index c509f257a6c3..ea26f27a3229 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2484,13 +2484,61 @@ static int spi_nor_default_setup(struct spi_nor *nor,
 	return 0;
 }
 
+static int spi_nor_set_addr_width(struct spi_nor *nor)
+{
+	if (nor->addr_width) {
+		/* already configured from SFDP */
+	} else if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) {
+		/*
+		 * In 8D-8D-8D mode, one byte takes half a cycle to transfer. So
+		 * in this protocol an odd address width cannot be used because
+		 * then the address phase would only span a cycle and a half.
+		 * Half a cycle would be left over. We would then have to start
+		 * the dummy phase in the middle of a cycle and so too the data
+		 * phase, and we will end the transaction with half a cycle left
+		 * over.
+		 *
+		 * Force all 8D-8D-8D flashes to use an address width of 4 to
+		 * avoid this situation.
+		 */
+		nor->addr_width = 4;
+	} else if (nor->info->addr_width) {
+		nor->addr_width = nor->info->addr_width;
+	} else {
+		nor->addr_width = 3;
+	}
+
+	if (nor->addr_width == 3 && nor->mtd.size > 0x1000000) {
+		/* enable 4-byte addressing if the device exceeds 16MiB */
+		nor->addr_width = 4;
+	}
+
+	if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) {
+		dev_dbg(nor->dev, "address width is too large: %u\n",
+			nor->addr_width);
+		return -EINVAL;
+	}
+
+	/* Set 4byte opcodes when possible. */
+	if (nor->addr_width == 4 && nor->flags & SNOR_F_4B_OPCODES &&
+	    !(nor->flags & SNOR_F_HAS_4BAIT))
+		spi_nor_set_4byte_opcodes(nor);
+
+	return 0;
+}
+
 static int spi_nor_setup(struct spi_nor *nor,
 			 const struct spi_nor_hwcaps *hwcaps)
 {
-	if (!nor->params->setup)
-		return 0;
+	int ret;
 
-	return nor->params->setup(nor, hwcaps);
+	if (nor->params->setup) {
+		ret = nor->params->setup(nor, hwcaps);
+		if (ret)
+			return ret;
+	}
+
+	return spi_nor_set_addr_width(nor);
 }
 
 /**
@@ -3079,49 +3127,6 @@ static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
 	return NULL;
 }
 
-static int spi_nor_set_addr_width(struct spi_nor *nor)
-{
-	if (nor->addr_width) {
-		/* already configured from SFDP */
-	} else if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) {
-		/*
-		 * In 8D-8D-8D mode, one byte takes half a cycle to transfer. So
-		 * in this protocol an odd address width cannot be used because
-		 * then the address phase would only span a cycle and a half.
-		 * Half a cycle would be left over. We would then have to start
-		 * the dummy phase in the middle of a cycle and so too the data
-		 * phase, and we will end the transaction with half a cycle left
-		 * over.
-		 *
-		 * Force all 8D-8D-8D flashes to use an address width of 4 to
-		 * avoid this situation.
-		 */
-		nor->addr_width = 4;
-	} else if (nor->info->addr_width) {
-		nor->addr_width = nor->info->addr_width;
-	} else {
-		nor->addr_width = 3;
-	}
-
-	if (nor->addr_width == 3 && nor->mtd.size > 0x1000000) {
-		/* enable 4-byte addressing if the device exceeds 16MiB */
-		nor->addr_width = 4;
-	}
-
-	if (nor->addr_width > SPI_NOR_MAX_ADDR_WIDTH) {
-		dev_dbg(nor->dev, "address width is too large: %u\n",
-			nor->addr_width);
-		return -EINVAL;
-	}
-
-	/* Set 4byte opcodes when possible. */
-	if (nor->addr_width == 4 && nor->flags & SNOR_F_4B_OPCODES &&
-	    !(nor->flags & SNOR_F_HAS_4BAIT))
-		spi_nor_set_4byte_opcodes(nor);
-
-	return 0;
-}
-
 static void spi_nor_debugfs_init(struct spi_nor *nor,
 				 const struct flash_info *info)
 {
@@ -3253,15 +3258,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	 * - select op codes for (Fast) Read, Page Program and Sector Erase.
 	 * - set the number of dummy cycles (mode cycles + wait states).
 	 * - set the SPI protocols for register and memory accesses.
+	 * - set the address width.
 	 */
 	ret = spi_nor_setup(nor, hwcaps);
 	if (ret)
 		return ret;
 
-	ret = spi_nor_set_addr_width(nor);
-	if (ret)
-		return ret;
-
 	/* Send all the required SPI flash commands to initialize device */
 	ret = spi_nor_init(nor);
 	if (ret)
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:28 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:28 +0300
Subject: [PATCH v3 20/25] mtd: spi-nor: sst: sst26vf064b: Init flash based on
 SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-21-tudor.ambarus@microchip.com>

Get rid of the static initialization of the flash parameters and
init them when parsing SFDP.
Generated a 256 Kbyte random data and did an erase, write, read back
and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4 0xeb,
for erases SPINOR_OP_BE_4K 0x20, and for writes SPINOR_OP_PP 0x02.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/sst.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
index 40e55b531edb..b3fd54b24e25 100644
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -199,8 +199,9 @@ static const struct flash_info sst_parts[] = {
 	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
 			      SECT_4K | SPI_NOR_DUAL_READ) },
 	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
-			      SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			      SPI_NOR_HAS_LOCK | SPI_NOR_SWP_IS_VOLATILE)
+			      SPI_NOR_PARSE_SFDP |
+			      NON_SFDP_FLAGS(SPI_NOR_HAS_LOCK |
+					     SPI_NOR_SWP_IS_VOLATILE))
 		.fixups = &sst26vf_fixups },
 };
 
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:30 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:30 +0300
Subject: [PATCH v3 22/25] mtd: spi-nor: spansion: s25fl256s0: Skip SFDP parsing
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-23-tudor.ambarus@microchip.com>

s25fl256s0 does not define the SFDP tables nor implements the
RDSFDP 0x5a command. Skip the SFDP parsing in order to avoid
issuing an unsupported command to the flash.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/spansion.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 3ee1cd3b8fb5..463ddd0776ec 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -209,8 +209,9 @@ static const struct flash_info spansion_parts[] = {
 			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			      USE_CLSR) },
 	{ "s25fl256s0", INFO6(0x010219, 0x4d0080, 256 * 1024, 128,
-			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			      USE_CLSR) },
+			      SPI_NOR_SKIP_SFDP |
+			      SFDP_FLAGS(SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+					 USE_CLSR)) },
 	{ "s25fl256s1", INFO6(0x010219, 0x4d0180, 64 * 1024, 512,
 			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			      USE_CLSR) },
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:29 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:29 +0300
Subject: [PATCH v3 21/25] mtd: spi-nor: winbond: w25q256jvm: Init flash based
 on SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-22-tudor.ambarus@microchip.com>

Get rid of the static initialization of the flash parameters and
init them when parsing SFDP.
Generated a 256 Kbyte random data and did an erase, write, read back
and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4 0xeb,
for erases SPINOR_OP_BE_4K 0x20, and for writes SPINOR_OP_PP 0x02.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/winbond.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index dd4be0f78e67..fd65fa7a5d94 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -95,7 +95,7 @@ static const struct flash_info winbond_parts[] = {
 			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
 	  .fixups = &w25q256_fixups },
 	{ "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
-			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+			     SPI_NOR_PARSE_SFDP) },
 	{ "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
 			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:31 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:31 +0300
Subject: [PATCH v3 23/25] mtd: spi-nor: gigadevice: gd25q256: Init flash based
 on SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-24-tudor.ambarus@microchip.com>

Get rid of the static initialization of the flash parameters and
init them when parsing SFDP.
Generated a 256 Kbyte random data and did an erase, write, read back
and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_1_1_4_4B
0x34.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/gigadevice.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index 59053f419642..90573c59ad8b 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -46,9 +46,9 @@ static const struct flash_info gigadevice_parts[] = {
 			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
 			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
 	{ "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
-			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
-			   SPI_NOR_TB_SR_BIT6 |
+			   SPI_NOR_PARSE_SFDP |
+			   NON_SFDP_FLAGS(SPI_NOR_HAS_LOCK |
+					  SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6) |
 			   FIXUP_FLAGS(SPI_NOR_4B_OPCODES))
 		.fixups = &gd25q256_fixups },
 };
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:32 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:32 +0300
Subject: [PATCH v3 24/25] mtd: spi-nor: issi: is25lp256: Init flash based on
 SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-25-tudor.ambarus@microchip.com>

Get rid of the static initialization of the flash parameters and
init them when parsing SFDP.
Generated a 256 Kbyte random data and did an erase, write, read back
and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_4B 0x12.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/issi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index b2abe8202143..3c5ce2c2c646 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -45,7 +45,7 @@ static const struct flash_info issi_parts[] = {
 	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
 			     SECT_4K | SPI_NOR_DUAL_READ) },
 	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
-			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_PARSE_SFDP |
 			     FIXUP_FLAGS(SPI_NOR_4B_OPCODES))
 		.fixups = &is25lp256_fixups },
 	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
-- 
2.25.1



From tudor.ambarus at microchip.com  Fri Oct 29 10:26:33 2021
From: tudor.ambarus at microchip.com (Tudor Ambarus)
Date: Fri, 29 Oct 2021 20:26:33 +0300
Subject: [PATCH v3 25/25] mtd: spi-nor: macronix: mx25l25635e: Init flash
 based on SFDP
In-Reply-To: <20211029172633.886453-1-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
Message-ID: <20211029172633.886453-26-tudor.ambarus@microchip.com>

Get rid of the static initialization of the flash parameters and
init them when parsing SFDP.
Generated a 256 Kbyte random data and did an erase, write, read back
and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_1_4_4_4B
0x3e.

Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
---
 drivers/mtd/spi-nor/macronix.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index d0285e60092e..bd7b1d63783e 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -62,7 +62,7 @@ static const struct flash_info macronix_parts[] = {
 			      SECT_4K | SPI_NOR_DUAL_READ |
 			      SPI_NOR_QUAD_READ) },
 	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
-			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
+			      SPI_NOR_PARSE_SFDP)
 		.fixups = &mx25l25635_fixups },
 	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
 			      SECT_4K | FIXUP_FLAGS(SPI_NOR_4B_OPCODES)) },
-- 
2.25.1



From Tudor.Ambarus at microchip.com  Fri Oct 29 10:31:00 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 29 Oct 2021 17:31:00 +0000
Subject: [PATCH v3 20/25] mtd: spi-nor: sst: sst26vf064b: Init flash based
 on SFDP
In-Reply-To: <20211029172633.886453-21-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
 <20211029172633.886453-21-tudor.ambarus@microchip.com>
Message-ID: <11ac4016-94ad-39ce-e845-0324543065fa@microchip.com>

On 10/29/21 8:26 PM, Tudor Ambarus wrote:
> Get rid of the static initialization of the flash parameters and
> init them when parsing SFDP.
> Generated a 256 Kbyte random data and did an erase, write, read back
> and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4 0xeb,
> for erases SPINOR_OP_BE_4K 0x20, and for writes SPINOR_OP_PP 0x02.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---

root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
bf2643
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
sst
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname
sst26vf064b
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > sst26vf064b-sfdp
root at sama5d2-xplained:~# hexdump sst26vf064b-sfdp 
0000000 4653 5044 0106 ff02 0600 1001 0030 ff00
0000010 0081 0601 0100 ff00 00bf 1801 0200 0100
0000020 ffff ffff ffff ffff ffff ffff ffff ffff
0000030 20fd fff1 ffff 03ff eb44 6b08 3b08 bb80
0000040 fffe ffff ffff ff00 ffff 0b44 200c d80d
0000050 d80f d810 9120 2448 6f80 811d 0fed 3877
0000060 b030 b030 fff7 ffff c229 ff5c 30f0 80c0
0000070 ffff ffff ffff ffff ffff ffff ffff ffff
*
0000100 00ff ff04 7ff3 0000 7ff5 0000 fff9 007d
0000110 7ff5 0000 7ff3 0000 ffff ffff ffff ffff
0000120 ffff ffff ffff ffff ffff ffff ffff ffff
*
0000200 26bf ff43 5fb9 fffd f230 f360 ff32 120a
0000210 4623 0fff 3219 190f ff19 ffff ffff ffff
0000220 6600 3899 05ff 3501 0406 3202 30b0 4272
0000230 e88d 8898 85a5 9fc0 5aaf ffff ec06 0c06
0000240 0300 0b08 ffff ffff 07ff ffff 0202 06ff
0000250 0003 fdfd 0704 fc00 0003 fefe 0202 0e07
0000260

>  drivers/mtd/spi-nor/sst.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)


From Tudor.Ambarus at microchip.com  Fri Oct 29 10:31:42 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 29 Oct 2021 17:31:42 +0000
Subject: [PATCH v3 21/25] mtd: spi-nor: winbond: w25q256jvm: Init flash
 based on SFDP
In-Reply-To: <20211029172633.886453-22-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
 <20211029172633.886453-22-tudor.ambarus@microchip.com>
Message-ID: <0ea225ae-18ca-7cb8-1a15-7c70acb4d531@microchip.com>

On 10/29/21 8:26 PM, Tudor Ambarus wrote:
> Get rid of the static initialization of the flash parameters and
> init them when parsing SFDP.
> Generated a 256 Kbyte random data and did an erase, write, read back
> and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4 0xeb,
> for erases SPINOR_OP_BE_4K 0x20, and for writes SPINOR_OP_PP 0x02.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---

root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
ef7019
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
winbond
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname
w25q256jvm
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > sfdp-w25q256jvm
root at sama5d2-xplained:~# hexdump sfdp-w25q256jvm
0000000 4653 5044 0105 ff00 0500 1001 0080 ff00
0000010 ffff ffff ffff ffff ffff ffff ffff ffff
*
0000080 20e5 fffb ffff 0fff eb44 6b08 3b08 bb42
0000090 fffe ffff ffff 0000 ffff eb40 200c 520f
00000a0 d810 0000 0236 00a6 ea82 d314 63e9 3376
00000b0 757a 757a a2f7 5cd5 f719 ff4d 70e9 a5f9
00000c0

>  drivers/mtd/spi-nor/winbond.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)


From Tudor.Ambarus at microchip.com  Fri Oct 29 10:33:02 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 29 Oct 2021 17:33:02 +0000
Subject: [PATCH v3 23/25] mtd: spi-nor: gigadevice: gd25q256: Init flash
 based on SFDP
In-Reply-To: <20211029172633.886453-24-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
 <20211029172633.886453-24-tudor.ambarus@microchip.com>
Message-ID: <fa48e2f9-22ba-0326-d819-4ed50451f2b6@microchip.com>

On 10/29/21 8:26 PM, Tudor Ambarus wrote:
> Get rid of the static initialization of the flash parameters and
> init them when parsing SFDP.
> Generated a 256 Kbyte random data and did an erase, write, read back
> and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
> for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_1_1_4_4B
> 0x34.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---

root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
c84019
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
gigadevice
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname    
gd25q256
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > gd25q256-sfdp
root at sama5d2-xplained:~# hexdump gd25q256-sfdp 
0000000 4653 5044 0106 ff02 0600 1001 0030 ff00
0000010 00c8 0301 0090 ff00 0084 0201 00c0 ff00
0000020 ffff ffff ffff ffff ffff ffff ffff ffff
0000030 20e5 fff3 ffff 0fff eb44 6b08 3b08 bb42
0000040 ffee ffff ffff ff00 ffff ff00 200c 520f
0000050 d810 ff00 6242 fec9 e982 5814 60ec 3306
0000060 757a 757a bd04 5cd5 0600 0044 5008 0100
0000070 ffff ffff ffff ffff ffff ffff ffff ffff
*
0000090 3600 2700 f99e 6477 cbfc ffff ffff ffff
00000a0 ffff ffff ffff ffff ffff ffff ffff ffff
*
00000c0 0eff fff0 5c21 ffdc                    
00000c8

>  drivers/mtd/spi-nor/gigadevice.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)


From Tudor.Ambarus at microchip.com  Fri Oct 29 10:33:44 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 29 Oct 2021 17:33:44 +0000
Subject: [PATCH v3 24/25] mtd: spi-nor: issi: is25lp256: Init flash based
 on SFDP
In-Reply-To: <20211029172633.886453-25-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
 <20211029172633.886453-25-tudor.ambarus@microchip.com>
Message-ID: <ed3f2066-b4cd-1652-30ce-5032bfea1e88@microchip.com>

On 10/29/21 8:26 PM, Tudor Ambarus wrote:
> Get rid of the static initialization of the flash parameters and
> init them when parsing SFDP.
> Generated a 256 Kbyte random data and did an erase, write, read back
> and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
> for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_4B 0x12.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
9d6019
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
issi
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname
is25lp256
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > sfdp-issi
root at sama5d2-xplained:~# hexdump sfdp-issi 
0000000 4653 5044 0106 ff01 0600 1001 0030 ff00
0000010 059d 0301 0080 0200 ffff ffff ffff ffff
0000020 ffff ffff ffff ffff ffff ffff ffff ffff
0000030 20e5 fff9 ffff 0fff eb44 6b08 3b08 bb80
0000040 fffe ffff ffff ff00 ffff eb44 200c 520f
0000050 d810 ff00 4a23 00c9 d882 ce11 cdcc 4668
0000060 757a 757a aef7 5cd5 424a ff2c 30f0 a9f2
0000070 ffff ffff ffff ffff ffff ffff ffff ffff
0000080 3600 2300 f99e 64c0 ef8f ffff          
000008c
>  drivers/mtd/spi-nor/issi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

From Tudor.Ambarus at microchip.com  Fri Oct 29 10:34:35 2021
From: Tudor.Ambarus at microchip.com (Tudor.Ambarus at microchip.com)
Date: Fri, 29 Oct 2021 17:34:35 +0000
Subject: [PATCH v3 25/25] mtd: spi-nor: macronix: mx25l25635e: Init flash
 based on SFDP
In-Reply-To: <20211029172633.886453-26-tudor.ambarus@microchip.com>
References: <20211029172633.886453-1-tudor.ambarus@microchip.com>
 <20211029172633.886453-26-tudor.ambarus@microchip.com>
Message-ID: <85d1928d-d9d0-706f-d181-2ad530384f7d@microchip.com>

On 10/29/21 8:26 PM, Tudor Ambarus wrote:
> Get rid of the static initialization of the flash parameters and
> init them when parsing SFDP.
> Generated a 256 Kbyte random data and did an erase, write, read back
> and compare test. The flash uses for reads SPINOR_OP_READ_1_4_4_4B 0xec,
> for erases SPINOR_OP_BE_4K_4B 0x21, and for writes SPINOR_OP_PP_1_4_4_4B
> 0x3e.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus at microchip.com>
> ---
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/jedec_id
c22019
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/manufacturer
macronix
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/partname    
mx25l25635e
root at sama5d2-xplained:~# cat /sys/devices/platform/ahb/ahb:apb/f0020000.spi/spi_master/spi1/spi1.0/spi-nor/sfdp > mx25l25635e-sfdp
root at sama5d2-xplained:~# hexdump mx25l25635e-sfdp
0000000 4653 5044 0106 ff02 0600 1001 0030 ff00
0000010 00c2 0401 0110 ff00 0084 0201 00c0 ff00
0000020 ffff ffff ffff ffff ffff ffff ffff ffff
0000030 20e5 fffb ffff 0fff eb44 6b08 3b08 bb04
0000040 fffe ffff ffff ff00 ffff eb44 200c 520f
0000050 d810 ff00 59d6 00dd 9f82 db03 0344 3867
0000060 b030 b030 bdf7 5cd5 9e4a ff29 50f0 85f9
0000070 ffff ffff ffff ffff ffff ffff ffff ffff
*
00000c0 8f7f ffff 5c21 ffdc ffff ffff ffff ffff
00000d0 ffff ffff ffff ffff ffff ffff ffff ffff
*
0000110 3600 2700 f99d 64c0 cb85 ffff ffff ffff
0000120
>  drivers/mtd/spi-nor/macronix.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 

From p.yadav at ti.com  Fri Oct 29 11:11:57 2021
From: p.yadav at ti.com (Pratyush Yadav)
Date: Fri, 29 Oct 2021 23:41:57 +0530
Subject: [PATCH] MAINTAINERS: Add myself as the SPI NOR co-maintainer
Message-ID: <20211029181157.20623-1-p.yadav@ti.com>

I have been reviewing patches and contributing for over a year. I would
like to help maintain the subsystem as well.

Signed-off-by: Pratyush Yadav <p.yadav at ti.com>
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index afb997643b8f..b44e062f05d3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17907,8 +17907,8 @@ F:	drivers/pinctrl/spear/
 
 SPI NOR SUBSYSTEM
 M:	Tudor Ambarus <tudor.ambarus at microchip.com>
+M:	Pratyush Yadav <p.yadav at ti.com>
 R:	Michael Walle <michael at walle.cc>
-R:	Pratyush Yadav <p.yadav at ti.com>
 L:	linux-mtd at lists.infradead.org
 S:	Maintained
 W:	http://www.linux-mtd.infradead.org/
-- 
2.33.1.835.ge9e5ba39a7



From axboe at kernel.dk  Sat Oct 30 10:03:45 2021
From: axboe at kernel.dk (Jens Axboe)
Date: Sat, 30 Oct 2021 11:03:45 -0600
Subject: (subset) [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <163561342513.76453.10042066842818606438.b4-ty@kernel.dk>

On Fri, 15 Oct 2021 16:52:06 -0700, Luis Chamberlain wrote:
> This patch set consists of al the straggler drivers for which we have
> have no patch reviews done for yet. I'd like to ask for folks to please
> consider chiming in, specially if you're the maintainer for the driver.
> Additionally if you can specify if you'll take the patch in yourself or
> if you want Jens to take it, that'd be great too.
> 
> Luis Chamberlain (13):
>   block/brd: add error handling support for add_disk()
>   nvme-multipath: add error handling support for add_disk()
>   nvdimm/btt: do not call del_gendisk() if not needed
>   nvdimm/btt: use goto error labels on btt_blk_init()
>   nvdimm/btt: add error handling support for add_disk()
>   nvdimm/blk: avoid calling del_gendisk() on early failures
>   nvdimm/blk: add error handling support for add_disk()
>   zram: add error handling support for add_disk()
>   z2ram: add error handling support for add_disk()
>   ps3disk: add error handling support for add_disk()
>   ps3vram: add error handling support for add_disk()
>   block/sunvdc: add error handling support for add_disk()
>   mtd/ubi/block: add error handling support for add_disk()
> 
> [...]

Applied, thanks!

[08/13] zram: add error handling support for add_disk()
        commit: 5e2e1cc4131cf4d21629c94331f2351b7dc8b87c
[10/13] ps3disk: add error handling support for add_disk()
        commit: ff4cbe0fcf5d749f76040f782f0618656cd23e33
[11/13] ps3vram: add error handling support for add_disk()
        commit: 3c30883acab1d20ecbd3c48dc12b147b51548742

Best regards,
-- 
Jens Axboe




From axboe at kernel.dk  Sat Oct 30 10:07:46 2021
From: axboe at kernel.dk (Jens Axboe)
Date: Sat, 30 Oct 2021 11:07:46 -0600
Subject: (subset) [PATCH 00/13] block: add_disk() error handling stragglers
In-Reply-To: <20211015235219.2191207-1-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
Message-ID: <163561366669.77445.6593243934116934390.b4-ty@kernel.dk>

On Fri, 15 Oct 2021 16:52:06 -0700, Luis Chamberlain wrote:
> This patch set consists of al the straggler drivers for which we have
> have no patch reviews done for yet. I'd like to ask for folks to please
> consider chiming in, specially if you're the maintainer for the driver.
> Additionally if you can specify if you'll take the patch in yourself or
> if you want Jens to take it, that'd be great too.
> 
> Luis Chamberlain (13):
>   block/brd: add error handling support for add_disk()
>   nvme-multipath: add error handling support for add_disk()
>   nvdimm/btt: do not call del_gendisk() if not needed
>   nvdimm/btt: use goto error labels on btt_blk_init()
>   nvdimm/btt: add error handling support for add_disk()
>   nvdimm/blk: avoid calling del_gendisk() on early failures
>   nvdimm/blk: add error handling support for add_disk()
>   zram: add error handling support for add_disk()
>   z2ram: add error handling support for add_disk()
>   ps3disk: add error handling support for add_disk()
>   ps3vram: add error handling support for add_disk()
>   block/sunvdc: add error handling support for add_disk()
>   mtd/ubi/block: add error handling support for add_disk()
> 
> [...]

Applied, thanks!

[01/13] block/brd: add error handling support for add_disk()
        commit: e1528830bd4ebf435d91c154e309e6e028336210

Best regards,
-- 
Jens Axboe




From info at ts3card.com  Sat Oct 30 11:03:32 2021
From: info at ts3card.com (=?utf-8?B?44OI44Oo44K/44OV44Kh44Kk44OK44Oz44K55qCq5byP5Lya56S+?=)
Date: Sun, 31 Oct 2021 01:03:32 +0700
Subject: =?utf-8?B?VFMzIFRTIENVQklDQ0FSROOCq+ODvOODieOAkA==?=
 =?utf-8?B?6YeN6KaBOuW/heOBmuOBiuiqreOBv+OBj+OBoOOBleOBhOOAkQ==?=
Message-ID: <20211031010339486042@ts3card.com>

????????????????????????????????????????

??.:*:TS CUBIC CARD???????????.:*:

????????????????????????????????????????


TS CUBIC CARD???

??????TS CUBIC CARDE??????????????????????????

???????????????????????????????????????
???????????TS CUBIC CARD????????????????????

?????TS CUBIC CARD?????????????????????24?????
????????????????????????????????? 

??????:https://my-ts3card-com.pkcibh.work

????????TS CUBIC CARD????????????????????????
????????????????????????

???????????????????????????????????????

????????????????????????????????????
??????????????????????
??????????????????????????
? ???????????????????????????????????

?================================================================

?????TS CUBIC CARD????????????????
????? https://tscubic.com/
??????????????????
??????451-6014?????????????6?1?

??????????????????
?TOYOTA, DAIHATSU, ?????, ???????? FDC?
??????TS CUBIC CARD, TS CUBIC VIEW CARD??????????
??????????????????
??????[ ?? ]?03?5617?2511
??????[???]?052?239?2511
(9:00?17:30 ???? ??????)
??????????????????????????????
???????????????????????????????
?????
???????????????????????????????????????

From dan.j.williams at intel.com  Sun Oct 31 10:47:22 2021
From: dan.j.williams at intel.com (Dan Williams)
Date: Sun, 31 Oct 2021 10:47:22 -0700
Subject: [PATCH 03/13] nvdimm/btt: do not call del_gendisk() if not needed
In-Reply-To: <20211015235219.2191207-4-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-4-mcgrof@kernel.org>
Message-ID: <CAPcyv4gU0q=UhDhGoDjK1mwS8WNcWYUXgEb7Rd8Amqr1XFs6ow@mail.gmail.com>

On Fri, Oct 15, 2021 at 4:53 PM Luis Chamberlain <mcgrof at kernel.org> wrote:
>
> We know we don't need del_gendisk() if we haven't added
> the disk, so just skip it. This should fix a bug on older
> kernels, as del_gendisk() became able to deal with
> disks not added only recently, after the patch titled
> "block: add flag for add_disk() completion notation".

Perhaps put this in:

    commit $abbrev_commit ("block: add flag for add_disk() completion notation")

...format, but I can't seem to find that commit?

If you're touching the changelog how about one that clarifies the
impact and drops "we"?

"del_gendisk() is not required if the disk has not been added. On
kernels prior to commit $abbrev_commit ("block: add flag for
add_disk() completion notation")
it is mandatory to not call del_gendisk() if the underlying device has
not been through device_add()."

Fixes: 41cd8b70c37a ("libnvdimm, btt: add support for blk integrity")

With that you can add:

Reviewed-by: Dan Williams <dan.j.williams at intel.com>


From dan.j.williams at intel.com  Sun Oct 31 10:51:08 2021
From: dan.j.williams at intel.com (Dan Williams)
Date: Sun, 31 Oct 2021 10:51:08 -0700
Subject: [PATCH 04/13] nvdimm/btt: use goto error labels on btt_blk_init()
In-Reply-To: <20211015235219.2191207-5-mcgrof@kernel.org>
References: <20211015235219.2191207-1-mcgrof@kernel.org>
 <20211015235219.2191207-5-mcgrof@kernel.org>
Message-ID: <CAPcyv4g98Dk4HFvgzEeCfCNjF-vjfpEhjGjsPDazGPg-BqMr8A@mail.gmail.com>

On Fri, Oct 15, 2021 at 4:53 PM Luis Chamberlain <mcgrof at kernel.org> wrote:
>
> This will make it easier to share common error paths.
>
> Signed-off-by: Luis Chamberlain <mcgrof at kernel.org>
> ---
>  drivers/nvdimm/btt.c | 19 ++++++++++++-------
>  1 file changed, 12 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
> index 29cc7325e890..23ee8c005db5 100644
> --- a/drivers/nvdimm/btt.c
> +++ b/drivers/nvdimm/btt.c
> @@ -1520,10 +1520,11 @@ static int btt_blk_init(struct btt *btt)
>  {
>         struct nd_btt *nd_btt = btt->nd_btt;
>         struct nd_namespace_common *ndns = nd_btt->ndns;
> +       int rc = -ENOMEM;
>
>         btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE);
>         if (!btt->btt_disk)
> -               return -ENOMEM;
> +               goto out;

I tend to not use a goto when there is nothing to unwind.

The rest looks good to me. After dropping "goto out;" you can add:

Reviewed-by: Dan Williams <dan.j.williams at intel.com>


From ebiggers at kernel.org  Sun Oct 31 16:15:02 2021
From: ebiggers at kernel.org (Eric Biggers)
Date: Sun, 31 Oct 2021 16:15:02 -0700
Subject: [GIT PULL] fscrypt updates for 5.16
Message-ID: <YX8jdp73zUDwlB5E@sol.localdomain>

The following changes since commit e4e737bb5c170df6135a127739a9e6148ee3da82:

  Linux 5.15-rc2 (2021-09-19 17:28:22 -0700)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/fs/fscrypt/fscrypt.git tags/fscrypt-for-linus

for you to fetch changes up to b7e072f9b77f4c516df96e0c22ec09f8b2e76ba1:

  fscrypt: improve a few comments (2021-10-25 19:11:50 -0700)

----------------------------------------------------------------

Some cleanups for fs/crypto/:

- Allow 256-bit master keys with AES-256-XTS

- Improve documentation and comments

- Remove unneeded field fscrypt_operations::max_namelen

----------------------------------------------------------------
Eric Biggers (5):
      fscrypt: remove fscrypt_operations::max_namelen
      fscrypt: clean up comments in bio.c
      fscrypt: improve documentation for inline encryption
      fscrypt: allow 256-bit master keys with AES-256-XTS
      fscrypt: improve a few comments

 Documentation/block/inline-encryption.rst |  2 +
 Documentation/filesystems/fscrypt.rst     | 83 +++++++++++++++++++++++--------
 fs/crypto/bio.c                           | 32 ++++++------
 fs/crypto/fname.c                         |  3 +-
 fs/crypto/fscrypt_private.h               | 16 ++++--
 fs/crypto/hkdf.c                          | 11 ++--
 fs/crypto/keysetup.c                      | 62 +++++++++++++++++------
 fs/ext4/super.c                           |  1 -
 fs/f2fs/super.c                           |  1 -
 fs/ubifs/crypto.c                         |  1 -
 include/linux/fscrypt.h                   |  3 --
 11 files changed, 150 insertions(+), 65 deletions(-)


From libaokun1 at huawei.com  Sun Oct 31 18:37:39 2021
From: libaokun1 at huawei.com (Baokun Li)
Date: Mon, 1 Nov 2021 09:37:39 +0800
Subject: [PATCH -next] ubi: fix race between ctrl_cdev_ioctl and ubi_cdev_ioctl
Message-ID: <20211101013739.236430-1-libaokun1@huawei.com>

Hulk Robot reported a KASAN report about use-after-free:
 ==================================================================
 BUG: KASAN: use-after-free in __list_del_entry_valid+0x13d/0x160
 Read of size 8 at addr ffff888035e37d98 by task ubiattach/1385
 [...]
 Call Trace:
  klist_dec_and_del+0xa7/0x4a0
  klist_put+0xc7/0x1a0
  device_del+0x4d4/0xed0
  cdev_device_del+0x1a/0x80
  ubi_attach_mtd_dev+0x2951/0x34b0 [ubi]
  ctrl_cdev_ioctl+0x286/0x2f0 [ubi]

 Allocated by task 1414:
  device_add+0x60a/0x18b0
  cdev_device_add+0x103/0x170
  ubi_create_volume+0x1118/0x1a10 [ubi]
  ubi_cdev_ioctl+0xb7f/0x1ba0 [ubi]

 Freed by task 1385:
  cdev_device_del+0x1a/0x80
  ubi_remove_volume+0x438/0x6c0 [ubi]
  ubi_cdev_ioctl+0xbf4/0x1ba0 [ubi]
 [...]
 ==================================================================

The following race could cause the use-after-free problem:
           cpu1                   cpu2                  cpu3
_______________________|________________________|______________________
ctrl_cdev_ioctl
 ubi_attach_mtd_dev
  uif_init
                           ubi_cdev_ioctl
                            ubi_create_volume
                             cdev_device_add
   ubi_add_volume
   // sysfs exist
   kill_volumes
                                                    ubi_cdev_ioctl
                                                     ubi_remove_volume
                                                      cdev_device_del
                                                       // first free
    ubi_free_volume
     cdev_del
     // double free
   cdev_device_del

The lock held by ctrl_cdev_ioctl is ubi_devices_mutex, but the lock held by
ubi cdev_ioctl is ubi->device_mutex. Therefore, the two locks can be
concurrent. However, volume addition and deletion operations are performed
in both ctrl_cdev_ioctl and ubi_cdev_ioctl. When these operations are
performed concurrently in both ioctl, a race condition may be triggered.The
UAF stack above is one such case.

To solve this problem, add spin_lock(&ubi->volumes_lock) to ctrl_cdev_ioctl
where volumes are added and deleted.

Reported-by: Hulk Robot <hulkci at huawei.com>
Signed-off-by: Baokun Li <libaokun1 at huawei.com>
---
 drivers/mtd/ubi/build.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index a7e3eb9befb6..708b1b96de01 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -467,6 +467,7 @@ static int uif_init(struct ubi_device *ubi)
 	if (err)
 		goto out_unreg;
 
+	spin_lock(&ubi->volumes_lock);
 	for (i = 0; i < ubi->vtbl_slots; i++)
 		if (ubi->volumes[i]) {
 			err = ubi_add_volume(ubi, ubi->volumes[i]);
@@ -475,11 +476,13 @@ static int uif_init(struct ubi_device *ubi)
 				goto out_volumes;
 			}
 		}
+	spin_unlock(&ubi->volumes_lock);
 
 	return 0;
 
 out_volumes:
 	kill_volumes(ubi);
+	spin_unlock(&ubi->volumes_lock);
 	cdev_device_del(&ubi->cdev, &ubi->dev);
 out_unreg:
 	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
-- 
2.31.1



From han.xu at nxp.com  Sun Oct 31 21:01:09 2021
From: han.xu at nxp.com (han.xu at nxp.com)
Date: Sun, 31 Oct 2021 23:01:09 -0500
Subject: [RFC PATCH 2/2] gpmi-nand: Add ERR007117 protection for
 nfc_apply_timings
In-Reply-To: <3c7415036ad62278e144da43198490c3c57d5721.camel@phytec.de>
References: <20211011084607.27a840e0@xps13>
 <20211012090224.4101984-1-s.riedmueller@phytec.de>
 <20211012090224.4101984-2-s.riedmueller@phytec.de>
 <20211013050148.2w373kpbfaeuxbwm@umbrella>
 <92d463460324d4501523f8a1da1f07c12fd6490f.camel@phytec.de>
 <20211022143514.lplk6jaxklq3rxry@umbrella>
 <3c7415036ad62278e144da43198490c3c57d5721.camel@phytec.de>
Message-ID: <20211101040109.glroscaybeso4alo@umbrella>

On 21/10/28 09:28AM, Stefan Riedm?ller wrote:
> Hi Han,
> 
> On Fri, 2021-10-22 at 09:35 -0500, han.xu at nxp.com wrote:
> > On 21/10/22 08:45AM, Stefan Riedm?ller wrote:
> > > Hi Han,
> > > 
> > > sorry it took me some time to get back to you.
> > > 
> > > On Wed, 2021-10-13 at 00:01 -0500, Han Xu wrote:
> > > > On 21/10/12 11:02AM, Stefan Riedmueller wrote:
> > > > > According to i.MX 6 erratum ERR007117 gpmi clocks need to be gated off
> > > > > when doing a gpmi_io clk rate change. So gate the clocks off before
> > > > > the rate change in nfc_apply_timings and ungate them again after the
> > > > > change.
> > > > > 
> > > > > Otherwise this rate change can lead to an unresponsive GPMI core which
> > > > > results in DMA timeouts and failed driver probe:
> > > > > 
> > > > > [    4.072318] gpmi-nand 112000.gpmi-nand: DMA timeout, last DMA
> > > > > ...
> > > > > [    4.370355] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -110
> > > > > ...
> > > > > [    4.375988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > > [    4.381524] gpmi-nand 112000.gpmi-nand: Error in ECC-based read:
> > > > > -22
> > > > > [    4.387988] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > > [    4.393535] gpmi-nand 112000.gpmi-nand: Chip: 0, Error -22
> > > > > ...
> > > > > 
> > > > > Signed-off-by: Stefan Riedmueller <s.riedmueller at phytec.de>
> > > > > ---
> > > > > Hi,
> > > > > 
> > > > > I'm not sure about the error handling here, if it is actually
> > > > > neccessary.
> > > > > So some feedback would be nice here.
> > > > > 
> > > > > Thanks,
> > > > > Stefan
> > > > > ---
> > > > >  drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c | 21 +++++++++++++++++++--
> > > > >  1 file changed, 19 insertions(+), 2 deletions(-)
> > > > > 
> > > > > diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > > b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > > index a1f7000f033e..326c8a895f1f 100644
> > > > > --- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > > +++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
> > > > > @@ -713,15 +713,28 @@ static void gpmi_nfc_compute_timings(struct
> > > > > gpmi_nand_data *this,
> > > > >  			      (use_half_period ?
> > > > > BM_GPMI_CTRL1_HALF_PERIOD :
> > > > > 0);
> > > > >  }
> > > > >  
> > > > > -static void gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > > +static int gpmi_nfc_apply_timings(struct gpmi_nand_data *this)
> > > > >  {
> > > > >  	struct gpmi_nfc_hardware_timing *hw = &this->hw;
> > > > >  	struct resources *r = &this->resources;
> > > > >  	void __iomem *gpmi_regs = r->gpmi_regs;
> > > > >  	unsigned int dll_wait_time_us;
> > > > > +	int ret;
> > > > > +
> > > > > +	if (GPMI_IS_MX6Q(this)) {
> > > > 
> > > > Not only for 6Q but for GPMI_IS_MX6
> > > 
> > > Can you confirm that i.MX 6SX and i.MX 7 are affected by the ERR007117
> > > erratum
> > > as well? Because the i.MX 6UL/ULL are included by the GPMI_IS_MX6Q
> > > already.
> > 
> > i.MX6SX has the glitch issue for sure, but I can double check if it's due to
> > the
> > same errata. I will also go check if the errata will affect i.MX7
> 
> Any updates yet?
> 
> Thanks,
> Stefan

Sorry Stefan, I didn't get useful info so I involved more people for this
question. Hopefully can get an answer soon.

Or you can just add 6Q and 6UL/ULL first.

> 
> > 
> > > Or do we need another macro for i.MX 6UL/ULL as Christian has suggested
> > > earlier?
> > > 
> > > Thanks,
> > > Stefan
> > > 
> > > > > +		ret = __gpmi_enable_clk(this, false);
> > > > > +		if (ret)
> > > > > +			return ret;
> > > > > +	}
> > > > >  
> > > > >  	clk_set_rate(r->clock[0], hw->clk_rate);
> > > > >  
> > > > > +	if (GPMI_IS_MX6Q(this)) {
> > > > > +		ret = __gpmi_enable_clk(this, true);
> > > > > +		if (ret)
> > > > > +			return ret;
> > > > > +	}
> > > > > +
> > > > >  	writel(hw->timing0, gpmi_regs + HW_GPMI_TIMING0);
> > > > >  	writel(hw->timing1, gpmi_regs + HW_GPMI_TIMING1);
> > > > >  
> > > > > @@ -739,6 +752,8 @@ static void gpmi_nfc_apply_timings(struct
> > > > > gpmi_nand_data *this)
> > > > >  
> > > > >  	/* Wait for the DLL to settle. */
> > > > >  	udelay(dll_wait_time_us);
> > > > > +
> > > > > +	return 0;
> > > > >  }
> > > > >  
> > > > >  static int gpmi_setup_interface(struct nand_chip *chip, int chipnr,
> > > > > @@ -2271,7 +2286,9 @@ static int gpmi_nfc_exec_op(struct nand_chip
> > > > > *chip,
> > > > >  	 */
> > > > >  	if (this->hw.must_apply_timings) {
> > > > >  		this->hw.must_apply_timings = false;
> > > > > -		gpmi_nfc_apply_timings(this);
> > > > > +		ret = gpmi_nfc_apply_timings(this);
> > > > > +		if (ret)
> > > > > +			return ret;
> > > > >  	}
> > > > >  
> > > > >  	dev_dbg(this->dev, "%s: %d instructions\n", __func__, op-
> > > > > >ninstrs);
> > > > > -- 
> > > > > 2.25.1
> > > > > 


