]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mtd: rawnand: meson: invalidate cache on polling ECC bit
authorArseniy Krasnov <avkrasnov@sberdevices.ru>
Mon, 13 Mar 2023 07:32:44 +0000 (10:32 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Apr 2023 09:16:43 +0000 (11:16 +0200)
[ 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: a8b6ef1f6111 ("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>
drivers/mtd/nand/raw/meson_nand.c

index a65aadb54af684b42b75172f4f59c5f536d18c1a..240b493abb86f8adc84c9410640713c076ff9abf 100644 (file)
@@ -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);
 }