diff mbox series

[RFC] mtd: spi nor: fix erase_map.regions after memcpy for uniform eraseregion

Message ID 20200922092135.167951-1-git@johnthomson.fastmail.com.au
State New
Delegated to: Vignesh R
Headers show
Series [RFC] mtd: spi nor: fix erase_map.regions after memcpy for uniform eraseregion | expand

Commit Message

John Thomson Sept. 22, 2020, 9:21 a.m. UTC
For a uniform erase regions device, erase_map.regions points to the
address of erase_map.uniform_region.
There is a memcpy of nor->params, which includes
erase_map.regions, and erase_map.uniform_region.
The memcpy destination erase_map.regions pointer needs to be updated to
the new address of uniform_region.

Without this change, when a uniform erase region spi-nor device used
the multiple erase regions code path,
e.g. spi_nor_has_uniform_erase forced to return false,
erase operations failed in find_erase_region.

This code path is not currently used for uniform eraseregion devices,
but is useful to allow use of minor (4K) erase while otherwise using 64K erase.

Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>

---

Only build tested on master,
what devices or approach is used to test master MTD SPI NOR?

Found and tested in kernel 5.4 on Openwrt on a MIPS access point,
while testing changes to mtdpart.c to allow writes for partitions
on 4K (minor) erase boundaries.
with:
- CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set
- spi_nor_has_uniform_erase forced to return false,
  so that a request for a 4K erase could use the multiple erase sectors
  code path on a uniform erase regions SPI NOR device.
---
 drivers/mtd/spi-nor/core.c | 8 ++++++++
 1 file changed, 8 insertions(+)
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 65eff4ce6ab..30f5db65781 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2716,12 +2716,20 @@  static void spi_nor_sfdp_init_params(struct spi_nor *nor)
 	struct spi_nor_flash_parameter sfdp_params;
 
 	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
+	if (nor->params->erase_map.regions ==
+	    &nor->params->erase_map.uniform_region)
+		sfdp_params.erase_map.regions = (
+			&sfdp_params.erase_map.uniform_region);
 
 	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
 		nor->addr_width = 0;
 		nor->flags &= ~SNOR_F_4B_OPCODES;
 	} else {
 		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
+		if (sfdp_params.erase_map.regions ==
+		    &sfdp_params.erase_map.uniform_region)
+			nor->params->erase_map.regions = (
+				&nor->params->erase_map.uniform_region);
 	}
 }