Regression for NOR flash with multiple erase block regions

Mathias Thore Mathias.Thore at infinera.com
Mon Sep 25 01:05:03 PDT 2017


> -----Original Message-----
> From: Boris Brezillon [mailto:boris.brezillon at free-electrons.com]
> Sent: den 25 september 2017 09:30
> 
> On Mon, 25 Sep 2017 06:28:18 +0000
> Mathias Thore <Mathias.Thore at infinera.com> wrote:
> 
> > > From: Boris Brezillon [mailto:boris.brezillon at free-electrons.com]
> > > Sent: den 22 september 2017 22:05
> > >
> > > On Fri, 22 Sep 2017 18:27:42 +0000
> > > Chris Packham <Chris.Packham at alliedtelesis.co.nz> wrote:
> > >
> > > > Hi Mathias,
> > > >
> > > > On 23/09/17 01:12, Mathias Thore wrote:
> > > > > Hello,
> > > > >
> > > > > Commit 1eeef2d7483a7e3f8d2dd2a5b9939b3b814dc549 included in
> > > > > Linux
> > > 4.13 (
> > > > >
> > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/c
> > > ommit/d
> > >
> rivers/mtd/mtdpart.c?h=v4.13&id=1eeef2d7483a7e3f8d2dd2a5b9939b3b814
> > > dc549
> > > > > ) introduces a regression for NOR flash with multiple erase
> > > > > block regions of different sizes.
> > > > >
> > > > > Only the largest erase block size seems to be considered when
> > > > > determining if partitions are aligned. Partitions in smaller
> > > > > regions will be mounted as read-only. With Linux 4.12 and
> > > > > earlier, read/write access was available for these partitions.
> > >
> > > I don't understand how this could work before this patch? I mean, we
> > > were previously using mtd_mod_by_eb() to check part alignment and
> > > this functions is just returning the remainder of the off /
> > > erasesize division. So, assuming the erasesize of your NOR did not
> > > change between 4.12 and 4.13, I don't see how this commit could
> > > cause the regression you're describing here.
> >
> > Looking at the earlier code, in the call to mtd_mod_by_eb, the parameter
> is slave->mtd. The slave mtd struct holds the correct erase size. The new
> code uses wr_alignment for all alignment tests, which comes from
> master/parent, and seems to always hold the largest possible erase size.
> 
> Oh indeed! I didn't notice that the initial mtd_mod_by_eb() test was done
> against the slave dev and not the master one.
> 
> Can you test the following patch and let me know it it solves your problem?

The patch does not compile in my 4.13 tree. However,

	if (!(slave->mtd.flags & MTD_NO_ERASE))
		wr_alignment = slave->mtd.erasesize;
or
	if (!(master->flags & MTD_NO_ERASE))
		wr_alignment = slave->mtd.erasesize;

do, and both work equally well to solve my problem.

> 
> --->8---
> From cdc8a5078ee330a645d1076a8289b411cffc4257 Mon Sep 17 00:00:00
> 2001
> From: Boris Brezillon <boris.brezillon at free-electrons.com>
> Date: Mon, 25 Sep 2017 09:14:00 +0200
> Subject: [PATCH] mtd: Fix partition alignment check on multi-erasesize
> devices
> 
> Commit 1eeef2d7483a ("mtd: handle partitioning on devices with 0
> erasesize") introduced a regression on heterogeneous erase region devices.
> Alignment of the partition was tested against the master eraseblock size
> which can be bigger than the slave one, thus leading to some partitions being
> marked as read-only.
> 
> Update wr_alignment to match this slave erasesize after this erasesize has
> been determined by picking the biggest erasesize of all the regions
> embedded in the MTD partition.
> 
> Reported-by: Mathias Thore <Mathias.Thore at infinera.com>
> Fixes: 1eeef2d7483a ("mtd: handle partitioning on devices with 0 erasesize")
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Boris Brezillon <boris.brezillon at free-electrons.com>
> ---
>  drivers/mtd/mtdpart.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index
> 5736b0c90b33..8802185b7729 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -581,6 +581,14 @@ static struct mtd_part *allocate_partition(struct
> mtd_info *parent,
>  		slave->mtd.erasesize = parent->erasesize;
>  	}
> 
> +	/*
> +	 * Slave erasesize might differ from the master one if the
> master
> +	 * exposes several regions with different erasesize. Adjust
> +	 * wr_alignment accordingly.
> +	 */
> +	if (!(slave->flags & MTD_NO_ERASE))
> +		wr_alignment = slave->erasesize;
> +
>  	tmp = slave->offset;
>  	remainder = do_div(tmp, wr_alignment);
>  	if ((slave->mtd.flags & MTD_WRITEABLE) && remainder) {



More information about the linux-mtd mailing list