diff options
author | Ladislav Michl <ladis@linux-mips.org> | 2019-01-12 13:58:28 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-01-15 07:56:50 +0100 |
commit | f9cbf973313de4d727d2b3237a5b40b791142429 (patch) | |
tree | 51a8af9c124aa853c1260be73bcf7338dfc5dd3c /drivers/mtd/core.c | |
parent | 8565d5d732123572517d6f53540f0e19e9249b67 (diff) | |
download | barebox-f9cbf973313de4d727d2b3237a5b40b791142429.tar.gz barebox-f9cbf973313de4d727d2b3237a5b40b791142429.tar.xz |
mtd: core: Fix erase area alignment for non power of 2 erasesize
On Thu, Jan 10, 2019 at 09:32:07AM +0100, Sascha Hauer wrote:
> On Wed, Jan 09, 2019 at 12:28:14PM +0100, Ladislav Michl wrote:
> > Devices as AT45DB161 DataFlash uses non power of two page size (528)
> > while present alignment algorithm relies on erasesize being power
> > of 2.
> > Fix that by introducing helper functions rounding to any multiply.
> > Note that logic is sligthly changed to be consistent as ending
> > address is moved forward to include also last byte meant to be
> > erased while previous implementation moved it backward.
> >
> > Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> > ---
> > drivers/mtd/core.c | 28 ++++++++++++++++++++++------
> > include/linux/kernel.h | 5 +++++
> > 2 files changed, 27 insertions(+), 6 deletions(-)
>
> Applied, thanks
Hi Sascha,
I was searching for paper bag, but was unable to find anything thick
enouh to cover behind :-/ This version is buggy and I noticed right
now when testing on another board. Corrected version follows, which
is also 192 bytes shorter for my ARM target. It seems next branch
at https://git.pengutronix.de/ is not yet updated, so perhaps my fault
won't affect anyone.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mtd/core.c')
-rw-r--r-- | drivers/mtd/core.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index d3cbe502fa..f44c6cfc69 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -141,15 +141,28 @@ static struct mtd_erase_region_info *mtd_find_erase_region(struct mtd_info *mtd, return NULL; } +static loff_t __mtd_erase_round(loff_t x, uint32_t esize, int up) +{ + uint64_t dividend = x; + uint32_t mod = do_div(dividend, esize); + if (mod == 0) + return x; + if (up) + x += esize; + return x - mod; +} +#define mtd_erase_round_up(x, esize) __mtd_erase_round(x, esize, 1) +#define mtd_erase_round_down(x, esize) __mtd_erase_round(x, esize, 0) + static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset) { struct mtd_erase_region_info *e; loff_t ofs; if (mtd->numeraseregions == 0) { - ofs = *offset & ~(loff_t)(mtd->erasesize - 1); - *count += (*offset - ofs); - *count = ALIGN(*count, mtd->erasesize); + ofs = mtd_erase_round_down(*offset, mtd->erasesize); + *count += *offset - ofs; + *count = mtd_erase_round_up(*count, mtd->erasesize); *offset = ofs; return 0; } @@ -158,14 +171,14 @@ static int mtd_erase_align(struct mtd_info *mtd, loff_t *count, loff_t *offset) if (!e) return -EINVAL; - ofs = *offset & ~(e->erasesize - 1); - *count += (*offset - ofs); + ofs = mtd_erase_round_down(*offset, e->erasesize); + *count += *offset - ofs; e = mtd_find_erase_region(mtd, *offset + *count); if (!e) return -EINVAL; - *count = ALIGN(*count, e->erasesize); + *count = mtd_erase_round_up(*count, e->erasesize); *offset = ofs; return 0; |