Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 317c07d3 authored by Arseniy Krasnov's avatar Arseniy Krasnov Committed by Greg Kroah-Hartman
Browse files

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: 8fae856c ("mtd: rawnand: meson: add support for Amlogic NAND flash controller")
Signed-off-by: default avatarArseniy Krasnov <AVKrasnov@sberdevices.ru>
Reviewed-by: default avatarNeil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/d4ef0bd6-816e-f6fa-9385-f05f775f0ae2@sberdevices.ru


Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent d65de5ee
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -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);
}