diff options
author | Arseniy Krasnov <avkrasnov@sberdevices.ru> | 2023-03-13 10:32:44 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-04-05 11:23:46 +0200 |
commit | 4a81e2da7297f0518e27308f8fcc41db380d4fbc (patch) | |
tree | dea908761fcaa4d10f627f5844166ddefd3becf4 | |
parent | 47a449ec09b4479b89dcc6b27ec3829fc82ffafb (diff) | |
download | linux-stable-4a81e2da7297f0518e27308f8fcc41db380d4fbc.tar.gz linux-stable-4a81e2da7297f0518e27308f8fcc41db380d4fbc.tar.bz2 linux-stable-4a81e2da7297f0518e27308f8fcc41db380d4fbc.zip |
mtd: rawnand: meson: invalidate cache on polling ECC bit
[ Upstream commit e732e39ed9929c05fd219035bc9653ba4100d4fa ]
'info_buf' memory is cached and driver polls ECC bit in it. This bit
is set by the NAND controller. If 'usleep_range()' returns before device
sets this bit, 'info_buf' will be cached and driver won't see update of
this bit and will loop forever.
Fixes: 8fae856c5350 ("mtd: rawnand: meson: add support for Amlogic NAND flash controller")
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/d4ef0bd6-816e-f6fa-9385-f05f775f0ae2@sberdevices.ru
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/mtd/nand/raw/meson_nand.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 38f490088d76..dc631c514318 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -172,6 +172,7 @@ struct meson_nfc { dma_addr_t daddr; dma_addr_t iaddr; + u32 info_bytes; unsigned long assigned_cs; }; @@ -499,6 +500,7 @@ static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, void *databuf, nfc->daddr, datalen, dir); return ret; } + nfc->info_bytes = infolen; cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr); writel(cmd, nfc->reg_base + NFC_REG_CMD); @@ -516,8 +518,10 @@ static void meson_nfc_dma_buffer_release(struct nand_chip *nand, struct meson_nfc *nfc = nand_get_controller_data(nand); dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir); - if (infolen) + if (infolen) { dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir); + nfc->info_bytes = 0; + } } static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) @@ -706,6 +710,8 @@ static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc, usleep_range(10, 15); /* info is updated by nfc dma engine*/ smp_rmb(); + dma_sync_single_for_cpu(nfc->dev, nfc->iaddr, nfc->info_bytes, + DMA_FROM_DEVICE); ret = *info & ECC_COMPLETE; } while (!ret); } |