[PATCH v1 7/8] mtd: spi-nor: push the rollback mechanism into the sfdp module

Michael Walle mwalle at kernel.org
Fri Jul 3 07:29:18 PDT 2026


Right now, the core is handling the rollback of the parameters. But it
doesn't have the knowledge what has to be rolled back. And in fact,
havent rolled back everything. Push it down to the called function and
make it mandatory, that this function has no side effects if it fails.

Funny enough, there is a comment in the SFDP table handing code that
each table parser is responsible to roll back any changes. But none of
them did. So while add it, expand the logic to that and roll it back for
them. There is one simple rule though:

  SFDP parsing and fixups may only modify the spi_nor_flash_parameters.

Signed-off-by: Michael Walle <mwalle at kernel.org>
---
 drivers/mtd/spi-nor/core.c | 20 +-------------------
 drivers/mtd/spi-nor/sfdp.c | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8cbe44e12385..8446b7b39f55 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -3039,24 +3039,6 @@ static int spi_nor_late_init_params(struct spi_nor *nor)
 	return 0;
 }
 
-/**
- * spi_nor_sfdp_init_params_deprecated() - Deprecated way of initializing flash
- * parameters and settings based on JESD216 SFDP standard.
- * @nor:	pointer to a 'struct spi_nor'.
- *
- * The method has a roll-back mechanism: in case the SFDP parsing fails, the
- * legacy flash parameters and settings will be restored.
- */
-static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor)
-{
-	struct spi_nor_flash_parameter sfdp_params;
-
-	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
-
-	if (spi_nor_parse_sfdp(nor))
-		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
-}
-
 /**
  * spi_nor_init_params_deprecated() - Deprecated way of initializing flash
  * parameters and settings.
@@ -3076,7 +3058,7 @@ static void spi_nor_init_params_deprecated(struct spi_nor *nor)
 					SPI_NOR_QUAD_READ |
 					SPI_NOR_OCTAL_READ |
 					SPI_NOR_OCTAL_DTR_READ))
-		spi_nor_sfdp_init_params_deprecated(nor);
+		spi_nor_parse_sfdp(nor);
 }
 
 /**
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index 5ffd695d1e8b..a48bd74f3cef 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -1473,12 +1473,16 @@ int spi_nor_check_sfdp_signature(struct spi_nor *nor)
  * runtime the main parameters needed to perform basic SPI flash operations such
  * as Fast Read, Page Program or Sector Erase commands.
  *
+ * Because the parsing is optional, all the settings have to be reverted. IOW,
+ * nothing of struct spi_nor shall be changed.
+ *
  * Return: 0 on success, -errno otherwise.
  */
 int spi_nor_parse_sfdp(struct spi_nor *nor)
 {
 	const struct sfdp_parameter_header *param_header, *bfpt_header;
 	struct sfdp_parameter_header *param_headers = NULL;
+	struct spi_nor_flash_parameter params;
 	struct sfdp_header header;
 	struct device *dev = nor->dev;
 	struct sfdp *sfdp;
@@ -1486,6 +1490,12 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 	size_t psize;
 	int i, err;
 
+	/*
+	 * Get a backup of all the parameter to roll back to in case of an
+	 * error.
+	 */
+	memcpy(&params, nor->params, sizeof(params));
+
 	/* Get the SFDP header. */
 	err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
 	if (err < 0)
@@ -1607,6 +1617,7 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 
 	/* Parse optional parameter tables. */
 	for (i = 0; i < header.nph; i++) {
+		memcpy(&params, nor->params, sizeof(params));
 		param_header = &param_headers[i];
 
 		switch (SFDP_PARAM_HEADER_ID(param_header)) {
@@ -1640,15 +1651,19 @@ int spi_nor_parse_sfdp(struct spi_nor *nor)
 			/*
 			 * Let's not drop all information we extracted so far
 			 * if optional table parsers fail. In case of failing,
-			 * each optional parser is responsible to roll back to
-			 * the previously known spi_nor data.
+			 * roll back to the previously known
+			 * spi_nor_flash_parameter data.
 			 */
 			err = 0;
+			memcpy(nor->params, &params, sizeof(*nor->params));
 		}
 	}
 
 	err = spi_nor_post_sfdp_fixups(nor);
 exit:
 	kfree(param_headers);
+	if (err)
+		memcpy(nor->params, &params, sizeof(*nor->params));
+
 	return err;
 }
-- 
2.47.3




More information about the linux-mtd mailing list