Skip to content

Commit 90f4ad0

Browse files
committed
Merge tag 'mtd/fixes-for-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux
Pull mtd fixes from Miquel Raynal: - Rockchip NAND controller driver was not checking the timings properly and the introduction of NV-DDR support broke it. - The core was also misbehaving in some very specific cases: in case of (unlikely) bitflips in the parameter page, the fallback might have failed as well but for software reasons. - Finally, the chosen ECC configuration was no longer properly propagated to upper layers, mostly failing an info message at probe time. * tag 'mtd/fixes-for-6.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: mtd: rawnand: rockchip: ensure NVDDR timings are rejected mtd: rawnand: Bypass a couple of sanity checks during NAND identification mtd: rawnand: Fix the nand_read_data_op() early check mtd: rawnand: Ensure ECC configuration is propagated to upper layers
2 parents 9b458a2 + b27d894 commit 90f4ad0

2 files changed

Lines changed: 43 additions & 29 deletions

File tree

drivers/mtd/nand/raw/nand_base.c

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,28 +1093,32 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
10931093
unsigned int offset_in_page)
10941094
{
10951095
struct mtd_info *mtd = nand_to_mtd(chip);
1096+
bool ident_stage = !mtd->writesize;
10961097

1097-
/* Make sure the offset is less than the actual page size. */
1098-
if (offset_in_page > mtd->writesize + mtd->oobsize)
1099-
return -EINVAL;
1098+
/* Bypass all checks during NAND identification */
1099+
if (likely(!ident_stage)) {
1100+
/* Make sure the offset is less than the actual page size. */
1101+
if (offset_in_page > mtd->writesize + mtd->oobsize)
1102+
return -EINVAL;
11001103

1101-
/*
1102-
* On small page NANDs, there's a dedicated command to access the OOB
1103-
* area, and the column address is relative to the start of the OOB
1104-
* area, not the start of the page. Asjust the address accordingly.
1105-
*/
1106-
if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
1107-
offset_in_page -= mtd->writesize;
1104+
/*
1105+
* On small page NANDs, there's a dedicated command to access the OOB
1106+
* area, and the column address is relative to the start of the OOB
1107+
* area, not the start of the page. Asjust the address accordingly.
1108+
*/
1109+
if (mtd->writesize <= 512 && offset_in_page >= mtd->writesize)
1110+
offset_in_page -= mtd->writesize;
11081111

1109-
/*
1110-
* The offset in page is expressed in bytes, if the NAND bus is 16-bit
1111-
* wide, then it must be divided by 2.
1112-
*/
1113-
if (chip->options & NAND_BUSWIDTH_16) {
1114-
if (WARN_ON(offset_in_page % 2))
1115-
return -EINVAL;
1112+
/*
1113+
* The offset in page is expressed in bytes, if the NAND bus is 16-bit
1114+
* wide, then it must be divided by 2.
1115+
*/
1116+
if (chip->options & NAND_BUSWIDTH_16) {
1117+
if (WARN_ON(offset_in_page % 2))
1118+
return -EINVAL;
11161119

1117-
offset_in_page /= 2;
1120+
offset_in_page /= 2;
1121+
}
11181122
}
11191123

11201124
addrs[0] = offset_in_page;
@@ -1123,7 +1127,7 @@ static int nand_fill_column_cycles(struct nand_chip *chip, u8 *addrs,
11231127
* Small page NANDs use 1 cycle for the columns, while large page NANDs
11241128
* need 2
11251129
*/
1126-
if (mtd->writesize <= 512)
1130+
if (!ident_stage && mtd->writesize <= 512)
11271131
return 1;
11281132

11291133
addrs[1] = offset_in_page >> 8;
@@ -1436,16 +1440,19 @@ int nand_change_read_column_op(struct nand_chip *chip,
14361440
unsigned int len, bool force_8bit)
14371441
{
14381442
struct mtd_info *mtd = nand_to_mtd(chip);
1443+
bool ident_stage = !mtd->writesize;
14391444

14401445
if (len && !buf)
14411446
return -EINVAL;
14421447

1443-
if (offset_in_page + len > mtd->writesize + mtd->oobsize)
1444-
return -EINVAL;
1448+
if (!ident_stage) {
1449+
if (offset_in_page + len > mtd->writesize + mtd->oobsize)
1450+
return -EINVAL;
14451451

1446-
/* Small page NANDs do not support column change. */
1447-
if (mtd->writesize <= 512)
1448-
return -ENOTSUPP;
1452+
/* Small page NANDs do not support column change. */
1453+
if (mtd->writesize <= 512)
1454+
return -ENOTSUPP;
1455+
}
14491456

14501457
if (nand_has_exec_op(chip)) {
14511458
const struct nand_interface_config *conf =
@@ -2173,7 +2180,7 @@ EXPORT_SYMBOL_GPL(nand_reset_op);
21732180
int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
21742181
bool force_8bit, bool check_only)
21752182
{
2176-
if (!len || !buf)
2183+
if (!len || (!check_only && !buf))
21772184
return -EINVAL;
21782185

21792186
if (nand_has_exec_op(chip)) {
@@ -6301,6 +6308,7 @@ static const struct nand_ops rawnand_ops = {
63016308
static int nand_scan_tail(struct nand_chip *chip)
63026309
{
63036310
struct mtd_info *mtd = nand_to_mtd(chip);
6311+
struct nand_device *base = &chip->base;
63046312
struct nand_ecc_ctrl *ecc = &chip->ecc;
63056313
int ret, i;
63066314

@@ -6445,16 +6453,22 @@ static int nand_scan_tail(struct nand_chip *chip)
64456453
if (!ecc->write_oob_raw)
64466454
ecc->write_oob_raw = ecc->write_oob;
64476455

6448-
/* propagate ecc info to mtd_info */
6456+
/* Propagate ECC info to the generic NAND and MTD layers */
64496457
mtd->ecc_strength = ecc->strength;
6458+
if (!base->ecc.ctx.conf.strength)
6459+
base->ecc.ctx.conf.strength = ecc->strength;
64506460
mtd->ecc_step_size = ecc->size;
6461+
if (!base->ecc.ctx.conf.step_size)
6462+
base->ecc.ctx.conf.step_size = ecc->size;
64516463

64526464
/*
64536465
* Set the number of read / write steps for one page depending on ECC
64546466
* mode.
64556467
*/
64566468
if (!ecc->steps)
64576469
ecc->steps = mtd->writesize / ecc->size;
6470+
if (!base->ecc.ctx.nsteps)
6471+
base->ecc.ctx.nsteps = ecc->steps;
64586472
if (ecc->steps * ecc->size != mtd->writesize) {
64596473
WARN(1, "Invalid ECC parameters\n");
64606474
ret = -EINVAL;

drivers/mtd/nand/raw/rockchip-nand-controller.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,13 +420,13 @@ static int rk_nfc_setup_interface(struct nand_chip *chip, int target,
420420
u32 rate, tc2rw, trwpw, trw2c;
421421
u32 temp;
422422

423-
if (target < 0)
424-
return 0;
425-
426423
timings = nand_get_sdr_timings(conf);
427424
if (IS_ERR(timings))
428425
return -EOPNOTSUPP;
429426

427+
if (target < 0)
428+
return 0;
429+
430430
if (IS_ERR(nfc->nfc_clk))
431431
rate = clk_get_rate(nfc->ahb_clk);
432432
else

0 commit comments

Comments
 (0)