[PATCH v5 03/28] mtd: spi-nor: Garbage collection during sfdp parsing
Miquel Raynal
miquel.raynal at bootlin.com
Wed Aug 5 01:02:28 PDT 2026
SFDP parsing works as follows:
1- The header is read then parsed
2- If correct, the sfdp structure and the sfdp content table are
allocated then filled
3- The mandatory BFPT table is parsed
4- The optional tables are then parsed as well
Any failure in steps 1-3 leads to an error and an early return. The
failure is not always fatal though, since the deprecated will fallback
to the non SFDP definition (in the ID table, for legacy chips). In this
case, the devm_ memory allocations for the SFDP table structure and
table will remain in memory for the lifetime of the device but will
never ever be accessed anymore (since they are incorrect). In this case,
we shall free the memory manually since the device is not going out of
scope anytime soon.
The assignation of nor->sfdp is also cleared in case of failure, to
avoid carrying a dangling pointer upon partial failure. This is
particularly important since the presence of valid SFDP support is
checked using the following condition: `if (!nor->sfdp)`.
Signed-off-by: Miquel Raynal <miquel.raynal at bootlin.com>
---
This change is particularly useful for the next patches which generalize
the fact that SFDP parsing will be attempted on legacy chips not
manually advertizing dual/quad/octal capabilities. I don't think it is
relevant to backport it.
---
drivers/mtd/spi-nor/sfdp.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 6a571d8d822c..cf0e2dc7c120 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -1490,7 +1490,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
psize, param_headers);
if (err < 0) {
dev_dbg(dev, "failed to read SFDP parameter headers\n");
- goto exit;
+ goto free_param_headers;
}
}
@@ -1518,7 +1518,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
sfdp = devm_kzalloc(dev, sizeof(*sfdp), GFP_KERNEL);
if (!sfdp) {
err = -ENOMEM;
- goto exit;
+ goto free_param_headers;
}
/*
@@ -1532,16 +1532,13 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
sizeof(*sfdp->dwords), GFP_KERNEL);
if (!sfdp->dwords) {
err = -ENOMEM;
- devm_kfree(dev, sfdp);
- goto exit;
+ goto free_sfdp;
}
err = spi_nor_read_sfdp(nor, 0, sfdp_size, sfdp->dwords);
if (err < 0) {
dev_dbg(dev, "failed to read SFDP data\n");
- devm_kfree(dev, sfdp->dwords);
- devm_kfree(dev, sfdp);
- goto exit;
+ goto free_dwords;
}
nor->sfdp = sfdp;
@@ -1563,7 +1560,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
err = spi_nor_parse_bfpt(nor, bfpt_header);
if (err)
- goto exit;
+ goto clear_sfdp_ptr;
/* Parse optional parameter tables. */
for (i = 0; i < header.nph; i++) {
@@ -1608,7 +1605,20 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
}
err = spi_nor_post_sfdp_fixups(nor);
-exit:
+ if (err)
+ goto clear_sfdp_ptr;
+
+ kfree(param_headers);
+
+ return 0;
+
+clear_sfdp_ptr:
+ nor->sfdp = NULL;
+free_dwords:
+ devm_kfree(dev, sfdp->dwords);
+free_sfdp:
+ devm_kfree(dev, sfdp);
+free_param_headers:
kfree(param_headers);
return err;
}
--
2.54.0
More information about the linux-mtd
mailing list