2020-10-12 18:09:24

by Pratyush Yadav

[permalink] [raw]
Subject: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it

Hi,

The Cypress Semper S28 flash family uses 2-bit ECC by default. Under
this ECC scheme, multi-pass page programs result in a program error.
This means that unlike many other SPI NOR flashes, bit-walking cannot be
done. In other words, once a page is programmed, its bits cannot then be
flipped to 0 without an erase in between.

This causes problems with UBIFS because it uses bit-walking to clear EC
and VID magic numbers from a PEB before issuing an erase to preserve the
file system correctness in case of power cuts.

This series fixes that problem by introducing a flag
MTD_NO_MULTI_PASS_WRITE that tells the file system layer that it can't
do multi-pass writes. It also sets the writesize to the page size for
such flashes to make sure file systems know that they should write the
entire page in one go.

It is based on the xSPI/8D series that adds support for Cypress S28
flash [0]. The patches themselves are independent of that series in the
sense that they don't rely on 8D support. But since S28 flash is not
supported without that series, these patches don't make much sense
without it.

Tested on Cypress S28HS512T and MT35XU512ABA on J7200 and J721E
respectively.

[0] https://lore.kernel.org/linux-mtd/[email protected]/

Pratyush Yadav (3):
mtd: abi: Introduce MTD_NO_MULTI_PASS_WRITE
UBI: Do not zero out EC and VID when multi-pass writes are not
supported
mtd: spi-nor: core: Introduce SPI_NOR_NO_MULTI_PASS_PP

drivers/mtd/spi-nor/core.c | 5 +++++
drivers/mtd/spi-nor/core.h | 6 ++++++
drivers/mtd/spi-nor/spansion.c | 2 +-
drivers/mtd/ubi/io.c | 2 +-
include/uapi/mtd/mtd-abi.h | 1 +
5 files changed, 14 insertions(+), 2 deletions(-)

--
2.28.0


2020-10-13 08:15:13

by Pratyush Yadav

[permalink] [raw]
Subject: [PATCH 3/3] mtd: spi-nor: core: Introduce SPI_NOR_NO_MULTI_PASS_PP

The Cypress Semper S28 flash family uses 2-bit ECC by default. Under
this ECC scheme, multi-pass page programs result in a program error.
This means that unlike many other SPI NOR flashes, bit-walking cannot be
done. In other words, once a page is programmed, its bits cannot then be
flipped to 0 without an erase in between.

This causes problems with UBIFS because it uses bit-walking to clear EC
and VID magic numbers from a PEB before issuing an erase to preserve the
file system correctness in case of power cuts.

Use SPI_NOR_NO_MULTI_PASS_PP to set MTD_NO_MULTI_PASS_WRITE, telling
upper layers to avoid multi-pass page programming. In addition, update
mtd->writesize to match the page size to make sure upper layers make the
changes they need in one single go.

Signed-off-by: Pratyush Yadav <[email protected]>
---
drivers/mtd/spi-nor/core.c | 5 +++++
drivers/mtd/spi-nor/core.h | 6 ++++++
drivers/mtd/spi-nor/spansion.c | 2 +-
3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index ff592468cc15..16d4bcfe7b10 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3469,6 +3469,11 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
nor->page_size = nor->params->page_size;
mtd->writebufsize = nor->page_size;

+ if (info->flags & SPI_NOR_NO_MULTI_PASS_PP) {
+ mtd->flags |= MTD_NO_MULTI_PASS_WRITE;
+ mtd->writesize = nor->page_size;
+ }
+
if (of_property_read_bool(np, "broken-flash-reset"))
nor->flags |= SNOR_F_BROKEN_RESET;

diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 0a775a7b5606..3394b7474c08 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -329,6 +329,12 @@ struct flash_info {
* available I/O mode via a
* volatile bit.
*/
+#define SPI_NOR_NO_MULTI_PASS_PP BIT(22) /*
+ * Once a page is programmed it
+ * cannot be programmed again
+ * without an erase operation in
+ * between.
+ */

/* Part specific fixup hooks. */
const struct spi_nor_fixups *fixups;
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 2c5c0f69dc5c..72430cd4e6af 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -275,7 +275,7 @@ static const struct flash_info spansion_parts[] = {
SPI_NOR_NO_ERASE) },
{ "s28hs512t", INFO(0x345b1a, 0, 256 * 1024, 256,
SECT_4K | SPI_NOR_OCTAL_DTR_READ |
- SPI_NOR_OCTAL_DTR_PP)
+ SPI_NOR_OCTAL_DTR_PP | SPI_NOR_NO_MULTI_PASS_PP)
.fixups = &s28hs512t_fixups,
},
};
--
2.28.0

2020-10-28 07:08:33

by Pratyush Yadav

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it

On 12/10/20 11:34PM, Pratyush Yadav wrote:
> Hi,
>
> The Cypress Semper S28 flash family uses 2-bit ECC by default. Under
> this ECC scheme, multi-pass page programs result in a program error.
> This means that unlike many other SPI NOR flashes, bit-walking cannot be
> done. In other words, once a page is programmed, its bits cannot then be
> flipped to 0 without an erase in between.
>
> This causes problems with UBIFS because it uses bit-walking to clear EC
> and VID magic numbers from a PEB before issuing an erase to preserve the
> file system correctness in case of power cuts.
>
> This series fixes that problem by introducing a flag
> MTD_NO_MULTI_PASS_WRITE that tells the file system layer that it can't
> do multi-pass writes. It also sets the writesize to the page size for
> such flashes to make sure file systems know that they should write the
> entire page in one go.
>
> It is based on the xSPI/8D series that adds support for Cypress S28
> flash [0]. The patches themselves are independent of that series in the
> sense that they don't rely on 8D support. But since S28 flash is not
> supported without that series, these patches don't make much sense
> without it.
>
> Tested on Cypress S28HS512T and MT35XU512ABA on J7200 and J721E
> respectively.
>
> [0] https://lore.kernel.org/linux-mtd/[email protected]/

Ping. Any comments on the series?

> Pratyush Yadav (3):
> mtd: abi: Introduce MTD_NO_MULTI_PASS_WRITE
> UBI: Do not zero out EC and VID when multi-pass writes are not
> supported
> mtd: spi-nor: core: Introduce SPI_NOR_NO_MULTI_PASS_PP
>
> drivers/mtd/spi-nor/core.c | 5 +++++
> drivers/mtd/spi-nor/core.h | 6 ++++++
> drivers/mtd/spi-nor/spansion.c | 2 +-
> drivers/mtd/ubi/io.c | 2 +-
> include/uapi/mtd/mtd-abi.h | 1 +
> 5 files changed, 14 insertions(+), 2 deletions(-)
>

--
Regards,
Pratyush Yadav
Texas Instruments India

2020-10-31 21:48:55

by Richard Weinberger

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it

On Tue, Oct 27, 2020 at 12:24 PM Pratyush Yadav <[email protected]> wrote:
> > [0] https://lore.kernel.org/linux-mtd/[email protected]/
>
> Ping. Any comments on the series?

From the UBIFS point of view I'd like to avoid as many device specific
settings as possible.
We check already for NOR flash, checking for NOR *and* SPI_NOR_NO_MULTI_PASS_PP
feels a bit clumsy.

Tudor, what do you think about SPI_NOR_NO_MULTI_PASS_PP?
This kind of NOR seems to be a little NAND'ish. Maybe we can hide this detail
in the mtd framework?

--
Thanks,
//richard

2020-11-03 11:37:07

by Vignesh Raghavendra

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it



On 11/1/20 3:14 AM, Richard Weinberger wrote:
> On Tue, Oct 27, 2020 at 12:24 PM Pratyush Yadav <[email protected]> wrote:
>>> [0] https://lore.kernel.org/linux-mtd/[email protected]/
>>
>> Ping. Any comments on the series?
>
> From the UBIFS point of view I'd like to avoid as many device specific
> settings as possible.
> We check already for NOR flash, checking for NOR *and* SPI_NOR_NO_MULTI_PASS_PP
> feels a bit clumsy.
>
> Tudor, what do you think about SPI_NOR_NO_MULTI_PASS_PP?
> This kind of NOR seems to be a little NAND'ish. Maybe we can hide this detail
> in the mtd framework?
>

Agree with Richard. I don't see need for SPI_NOR_NO_MULTI_PASS_PP. From
MTD point of view setting mtd->writesize to be equal to pagesize should
be enough. Its upto clients of MTD devices to ensure there is no multi
pass programming within a "writesize" block.

If this is not clear in the current documentation of struct mtd, then
that can be updated.

Regards
Vignesh

2020-11-03 12:47:31

by Pratyush Yadav

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it

On 03/11/20 05:05PM, Vignesh Raghavendra wrote:
>
>
> On 11/1/20 3:14 AM, Richard Weinberger wrote:
> > On Tue, Oct 27, 2020 at 12:24 PM Pratyush Yadav <[email protected]> wrote:
> >>> [0] https://lore.kernel.org/linux-mtd/[email protected]/
> >>
> >> Ping. Any comments on the series?
> >
> > From the UBIFS point of view I'd like to avoid as many device specific
> > settings as possible.
> > We check already for NOR flash, checking for NOR *and* SPI_NOR_NO_MULTI_PASS_PP
> > feels a bit clumsy.
> >
> > Tudor, what do you think about SPI_NOR_NO_MULTI_PASS_PP?
> > This kind of NOR seems to be a little NAND'ish. Maybe we can hide this detail
> > in the mtd framework?
> >
>
> Agree with Richard. I don't see need for SPI_NOR_NO_MULTI_PASS_PP. From
> MTD point of view setting mtd->writesize to be equal to pagesize should
> be enough. Its upto clients of MTD devices to ensure there is no multi
> pass programming within a "writesize" block.

That is what I initially thought too but then I realized that multi-pass
programming is completely different from page-size programming. Instead
of writing 4 bytes twice, you can zero out the entire page in one single
operation. You would be compliant with the write size requirement but
you still do multi-pass programming because you did not erase the page
before this operation.

It is also not completely correct to say the Cypress S28 flash has a
write size of 256. You _can_ write one byte if you want. You just can't
write to that page again without erasing it first. For example, if a
file system only wants to write 128 bytes on a page, it can do so
without having to write the whole page. It just needs to make sure it
doesn't write to it again without erasing first.

nor_erase_prepare() was written to handle quirks of some specific
devices. Not every device starts filling zeroes from the end of a page.
So we have device-specific code in UBIFS already. You will obviously
need device-specific settings to have control over that code.

One might argue that we should move nor_erase_prepare() out of UBIFS.
But requiring a flash to start erasing from the start of the page is a
UBIFS-specific requirement. Other users of a flash might not care about
it at all.

And so we have ourselves a bit of a conundrum. Adding
SPI_NOR_NO_MULTI_PASS_PP is IMHO the least disruptive answer. If the
file system wants to do multi-pass page programming on NOR flashes, how
else do we tell it not to do it for this specific flash?

> If this is not clear in the current documentation of struct mtd, then
> that can be updated.

--
Regards,
Pratyush Yadav
Texas Instruments India

2020-11-05 12:23:17

by Vignesh Raghavendra

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it



On 11/3/20 6:15 PM, Pratyush Yadav wrote:
> On 03/11/20 05:05PM, Vignesh Raghavendra wrote:
>>
>>
>> On 11/1/20 3:14 AM, Richard Weinberger wrote:
>>> On Tue, Oct 27, 2020 at 12:24 PM Pratyush Yadav <[email protected]> wrote:
>>>>> [0] https://lore.kernel.org/linux-mtd/[email protected]/
>>>>
>>>> Ping. Any comments on the series?
>>>
>>> From the UBIFS point of view I'd like to avoid as many device specific
>>> settings as possible.
>>> We check already for NOR flash, checking for NOR *and* SPI_NOR_NO_MULTI_PASS_PP
>>> feels a bit clumsy.
>>>
>>> Tudor, what do you think about SPI_NOR_NO_MULTI_PASS_PP?
>>> This kind of NOR seems to be a little NAND'ish. Maybe we can hide this detail
>>> in the mtd framework?
>>>
>>
>> Agree with Richard. I don't see need for SPI_NOR_NO_MULTI_PASS_PP. From
>> MTD point of view setting mtd->writesize to be equal to pagesize should
>> be enough. Its upto clients of MTD devices to ensure there is no multi
>> pass programming within a "writesize" block.
>
> That is what I initially thought too but then I realized that multi-pass
> programming is completely different from page-size programming. Instead
> of writing 4 bytes twice, you can zero out the entire page in one single
> operation. You would be compliant with the write size requirement but
> you still do multi-pass programming because you did not erase the page
> before this operation.
>

Right...

> It is also not completely correct to say the Cypress S28 flash has a
> write size of 256. You _can_ write one byte if you want. You just can't
> write to that page again without erasing it first. For example, if a
> file system only wants to write 128 bytes on a page, it can do so
> without having to write the whole page. It just needs to make sure it
> doesn't write to it again without erasing first.
>

As per documentation:
mtd_info::writesize: "In case of ECC-ed NOR it is of ECC block size"

This means, it is block on which ECC is calculated on ECC-ed NOR and
thus needs to be erased every time before being updated.

Looking at flash datasheet, this seems to be 16 bytes.

So mtd->writesize = 16 and not 256 (or pagesize)


Also, It does not imply length of data being written has to be multiple
of it. At least NAND subsystem does not seem to care that during writes
len < mtd->writesize[1].

> nor_erase_prepare() was written to handle quirks of some specific
> devices. Not every device starts filling zeroes from the end of a page.
> So we have device-specific code in UBIFS already. You will obviously
> need device-specific settings to have control over that code.
>

UBIFS intends to be robust against rogue power cuts and therefore would
need to ensure some consistency during erase which explains flash
specific quirk here.

> One might argue that we should move nor_erase_prepare() out of UBIFS.
> But requiring a flash to start erasing from the start of the page is a
> UBIFS-specific requirement. Other users of a flash might not care about
> it at all.
>

Yes. But I don't see much harm done.

> And so we have ourselves a bit of a conundrum. Adding
> SPI_NOR_NO_MULTI_PASS_PP is IMHO the least disruptive answer. If the
> file system wants to do multi-pass page programming on NOR flashes, how
> else do we tell it not to do it for this specific flash?
>

I see don't see need for SPI_NOR_NO_MULTI_PASS_PP as
SPI_NOR_NO_MULTI_PASS_PP is implied within a ECC block and writesize is
supposed to represent the same.

>> If this is not clear in the current documentation of struct mtd, then
>> that can be updated.
>

[1]
https://elixir.bootlin.com/linux/latest/source/drivers/mtd/nand/raw/nand_base.c#L4166

2020-11-05 13:23:26

by Pratyush Yadav

[permalink] [raw]
Subject: Re: [PATCH 0/3] mtd: Make sure UBIFS does not do multi-pass page programming on flashes that don't support it

On 05/11/20 05:51PM, Vignesh Raghavendra wrote:
>
>
> On 11/3/20 6:15 PM, Pratyush Yadav wrote:
> > On 03/11/20 05:05PM, Vignesh Raghavendra wrote:
> >>
> >>
> >> On 11/1/20 3:14 AM, Richard Weinberger wrote:
> >>> On Tue, Oct 27, 2020 at 12:24 PM Pratyush Yadav <[email protected]> wrote:
> >>>>> [0] https://lore.kernel.org/linux-mtd/[email protected]/
> >>>>
> >>>> Ping. Any comments on the series?
> >>>
> >>> From the UBIFS point of view I'd like to avoid as many device specific
> >>> settings as possible.
> >>> We check already for NOR flash, checking for NOR *and* SPI_NOR_NO_MULTI_PASS_PP
> >>> feels a bit clumsy.
> >>>
> >>> Tudor, what do you think about SPI_NOR_NO_MULTI_PASS_PP?
> >>> This kind of NOR seems to be a little NAND'ish. Maybe we can hide this detail
> >>> in the mtd framework?
> >>>
> >>
> >> Agree with Richard. I don't see need for SPI_NOR_NO_MULTI_PASS_PP. From
> >> MTD point of view setting mtd->writesize to be equal to pagesize should
> >> be enough. Its upto clients of MTD devices to ensure there is no multi
> >> pass programming within a "writesize" block.
> >
> > That is what I initially thought too but then I realized that multi-pass
> > programming is completely different from page-size programming. Instead
> > of writing 4 bytes twice, you can zero out the entire page in one single
> > operation. You would be compliant with the write size requirement but
> > you still do multi-pass programming because you did not erase the page
> > before this operation.
> >
>
> Right...
>
> > It is also not completely correct to say the Cypress S28 flash has a
> > write size of 256. You _can_ write one byte if you want. You just can't
> > write to that page again without erasing it first. For example, if a
> > file system only wants to write 128 bytes on a page, it can do so
> > without having to write the whole page. It just needs to make sure it
> > doesn't write to it again without erasing first.
> >
>
> As per documentation:
> mtd_info::writesize: "In case of ECC-ed NOR it is of ECC block size"
>
> This means, it is block on which ECC is calculated on ECC-ed NOR and
> thus needs to be erased every time before being updated.
>
> Looking at flash datasheet, this seems to be 16 bytes.
>
> So mtd->writesize = 16 and not 256 (or pagesize)

Ok.

> Also, It does not imply length of data being written has to be multiple
> of it. At least NAND subsystem does not seem to care that during writes
> len < mtd->writesize[1].

Ok.

> > nor_erase_prepare() was written to handle quirks of some specific
> > devices. Not every device starts filling zeroes from the end of a page.
> > So we have device-specific code in UBIFS already. You will obviously
> > need device-specific settings to have control over that code.
> >
>
> UBIFS intends to be robust against rogue power cuts and therefore would
> need to ensure some consistency during erase which explains flash
> specific quirk here.

Yes. There is no arguing if this is needed. The only question is how to
skip it on flashes that don't support doing this.

> > One might argue that we should move nor_erase_prepare() out of UBIFS.
> > But requiring a flash to start erasing from the start of the page is a
> > UBIFS-specific requirement. Other users of a flash might not care about
> > it at all.
> >
>
> Yes. But I don't see much harm done.
>
> > And so we have ourselves a bit of a conundrum. Adding
> > SPI_NOR_NO_MULTI_PASS_PP is IMHO the least disruptive answer. If the
> > file system wants to do multi-pass page programming on NOR flashes, how
> > else do we tell it not to do it for this specific flash?
> >
>
> I see don't see need for SPI_NOR_NO_MULTI_PASS_PP as
> SPI_NOR_NO_MULTI_PASS_PP is implied within a ECC block and writesize is
> supposed to represent the same.

Ok. So we can control the execution of nor_erase_prepare() with
mtd->writesize. Will re-roll. Thanks.

> >> If this is not clear in the current documentation of struct mtd, then
> >> that can be updated.
> >
>
> [1]
> https://elixir.bootlin.com/linux/latest/source/drivers/mtd/nand/raw/nand_base.c#L4166

--
Regards,
Pratyush Yadav
Texas Instruments India