Skip to content

Commit 46c37b9

Browse files
Arseniy Krasnovmiquelraynal
authored andcommitted
mtd: rawnand: meson: check buffer length
Meson 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> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20230609112840.2325455-1-AVKrasnov@sberdevices.ru
1 parent 1a50947 commit 46c37b9

1 file changed

Lines changed: 43 additions & 3 deletions

File tree

drivers/mtd/nand/raw/meson_nand.c

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109

110110
#define PER_INFO_BYTE 8
111111

112+
#define NFC_CMD_RAW_LEN GENMASK(13, 0)
113+
112114
#define NFC_COLUMN_ADDR_0 0
113115
#define NFC_COLUMN_ADDR_1 0
114116

@@ -285,7 +287,7 @@ static void meson_nfc_cmd_access(struct nand_chip *nand, int raw, bool dir,
285287

286288
if (raw) {
287289
len = mtd->writesize + mtd->oobsize;
288-
cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir);
290+
cmd = len | scrambler | DMA_DIR(dir);
289291
writel(cmd, nfc->reg_base + NFC_REG_CMD);
290292
return;
291293
}
@@ -605,7 +607,7 @@ static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
605607
if (ret)
606608
goto out;
607609

608-
cmd = NFC_CMD_N2M | (len & GENMASK(13, 0));
610+
cmd = NFC_CMD_N2M | len;
609611
writel(cmd, nfc->reg_base + NFC_REG_CMD);
610612

611613
meson_nfc_drain_cmd(nfc);
@@ -629,7 +631,7 @@ static int meson_nfc_write_buf(struct nand_chip *nand, u8 *buf, int len)
629631
if (ret)
630632
return ret;
631633

632-
cmd = NFC_CMD_M2N | (len & GENMASK(13, 0));
634+
cmd = NFC_CMD_M2N | len;
633635
writel(cmd, nfc->reg_base + NFC_REG_CMD);
634636

635637
meson_nfc_drain_cmd(nfc);
@@ -960,6 +962,31 @@ meson_nand_op_put_dma_safe_output_buf(const struct nand_op_instr *instr,
960962
kfree(buf);
961963
}
962964

965+
static int meson_nfc_check_op(struct nand_chip *chip,
966+
const struct nand_operation *op)
967+
{
968+
int op_id;
969+
970+
for (op_id = 0; op_id < op->ninstrs; op_id++) {
971+
const struct nand_op_instr *instr;
972+
973+
instr = &op->instrs[op_id];
974+
975+
switch (instr->type) {
976+
case NAND_OP_DATA_IN_INSTR:
977+
case NAND_OP_DATA_OUT_INSTR:
978+
if (instr->ctx.data.len > NFC_CMD_RAW_LEN)
979+
return -ENOTSUPP;
980+
981+
break;
982+
default:
983+
break;
984+
}
985+
}
986+
987+
return 0;
988+
}
989+
963990
static int meson_nfc_exec_op(struct nand_chip *nand,
964991
const struct nand_operation *op, bool check_only)
965992
{
@@ -968,8 +995,13 @@ static int meson_nfc_exec_op(struct nand_chip *nand,
968995
const struct nand_op_instr *instr = NULL;
969996
void *buf;
970997
u32 op_id, delay_idle, cmd;
998+
int err;
971999
int i;
9721000

1001+
err = meson_nfc_check_op(nand, op);
1002+
if (err)
1003+
return err;
1004+
9731005
if (check_only)
9741006
return 0;
9751007

@@ -1243,6 +1275,7 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
12431275
struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand);
12441276
struct mtd_info *mtd = nand_to_mtd(nand);
12451277
int nsectors = mtd->writesize / 1024;
1278+
int raw_writesize;
12461279
int ret;
12471280

12481281
if (!mtd->name) {
@@ -1254,6 +1287,13 @@ static int meson_nand_attach_chip(struct nand_chip *nand)
12541287
return -ENOMEM;
12551288
}
12561289

1290+
raw_writesize = mtd->writesize + mtd->oobsize;
1291+
if (raw_writesize > NFC_CMD_RAW_LEN) {
1292+
dev_err(nfc->dev, "too big write size in raw mode: %d > %ld\n",
1293+
raw_writesize, NFC_CMD_RAW_LEN);
1294+
return -EINVAL;
1295+
}
1296+
12571297
if (nand->bbt_options & NAND_BBT_USE_FLASH)
12581298
nand->bbt_options |= NAND_BBT_NO_OOB;
12591299

0 commit comments

Comments
 (0)