[RFC,v5,5/6] mtd: rawnand: meson: check buffer length
Commit Message
This NAND controller has limited buffer length, so check it before
command execution to avoid length trim. Also check MTD write size on
chip attach.
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
---
Changelog v4->v5:
* Move length checks from functions 'meson_nfc_read/write_buf()' to
'meson_nfc_exec_op()'.
drivers/mtd/nand/raw/meson_nand.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)
@@ -111,6 +111,8 @@
#define NFC_USER_BYTES 2
#define NFC_OOB_PER_ECC(nand) ((nand)->ecc.bytes + NFC_USER_BYTES)
+#define NFC_CMD_RAW_LEN GENMASK(13, 0)
+
struct meson_nfc_nand_chip {
struct list_head node;
struct nand_chip nand;
@@ -284,7 +286,7 @@ static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir,
if (raw) {
len = mtd->writesize + mtd->oobsize;
- cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir);
+ cmd = len | scrambler | DMA_DIR(dir);
writel(cmd, nfc->reg_base + NFC_REG_CMD);
return;
}
@@ -573,7 +575,7 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
if (ret)
goto out;
- cmd = NFC_CMD_N2M | (len & GENMASK(13, 0));
+ cmd = NFC_CMD_N2M | len;
writel(cmd, nfc->reg_base + NFC_REG_CMD);
meson_nfc_drain_cmd(nfc);
@@ -597,7 +599,7 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
if (ret)
return ret;
- cmd = NFC_CMD_M2N | (len & GENMASK(13, 0));
+ cmd = NFC_CMD_M2N | len;
writel(cmd, nfc->reg_base + NFC_REG_CMD);
meson_nfc_drain_cmd(nfc);
@@ -1044,6 +1046,9 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
break;
case NAND_OP_DATA_IN_INSTR:
+ if (instr->ctx.data.len > NFC_CMD_RAW_LEN)
+ return -EINVAL;
+
buf = meson_nand_op_get_dma_safe_input_buf(instr);
if (!buf)
return -ENOMEM;
@@ -1052,6 +1057,9 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
break;
case NAND_OP_DATA_OUT_INSTR:
+ if (instr->ctx.data.len > NFC_CMD_RAW_LEN)
+ return -EINVAL;
+
buf = meson_nand_op_get_dma_safe_output_buf(instr);
if (!buf)
return -ENOMEM;
@@ -1293,6 +1301,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
struct mtd_info *mtd = nand_to_mtd(nand);
int nsectors = mtd->writesize / 1024;
+ int raw_writesize;
int ret;
if (!mtd->name) {
@@ -1304,6 +1313,13 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
return -ENOMEM;
}
+ raw_writesize = mtd->writesize + mtd->oobsize;
+ if (raw_writesize > NFC_CMD_RAW_LEN) {
+ dev_err(nfc->dev, "too big write size in raw mode: %d > %ld\n",
+ raw_writesize, NFC_CMD_RAW_LEN);
+ return -EINVAL;
+ }
+
if (nand->bbt_options & NAND_BBT_USE_FLASH)
nand->bbt_options |= NAND_BBT_NO_OOB;