Skip to content

Commit 375ab23

Browse files
miquelraynalgregkh
authored andcommitted
mtd: rawnand: Bypass a couple of sanity checks during NAND identification
commit 8754d98 upstream. Early during NAND identification, mtd_info fields have not yet been initialized (namely, writesize and oobsize) and thus cannot be used for sanity checks yet. Of course if there is a misuse of nand_change_read_column_op() so early we won't be warned, but there is anyway no actual check to perform at this stage as we do not yet know the NAND geometry. So, if the fields are empty, especially mtd->writesize which is *always* set quite rapidly after identification, let's skip the sanity checks. nand_change_read_column_op() is subject to be used early for ONFI/JEDEC identification in the very unlikely case of: - bitflips appearing in the parameter page, - the controller driver not supporting simple DATA_IN cycles. As nand_change_read_column_op() uses nand_fill_column_cycles() the logic explaind above also applies in this secondary helper. Fixes: c27842e ("mtd: rawnand: onfi: Adapt the parameter page read to constraint controllers") Fixes: daca317 ("mtd: rawnand: jedec: Adapt the parameter page read to constraint controllers") Cc: stable@vger.kernel.org Reported-by: Alexander Dahl <ada@thorsis.com> Closes: https://lore.kernel.org/linux-mtd/20240306-shaky-bunion-d28b65ea97d7@thorsis.com/ Reported-by: Steven Seeger <steven.seeger@flightsystems.net> Closes: https://lore.kernel.org/linux-mtd/DM6PR05MB4506554457CF95191A670BDEF7062@DM6PR05MB4506.namprd05.prod.outlook.com/ Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Tested-by: Sascha Hauer <s.hauer@pengutronix.de> Link: https://lore.kernel.org/linux-mtd/20240516131320.579822-3-miquel.raynal@bootlin.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b998a65 commit 375ab23

1 file changed

Lines changed: 31 additions & 24 deletions

File tree

drivers/mtd/nand/raw/nand_base.c

Lines changed: 31 additions & 24 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 =

0 commit comments

Comments
 (0)