All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mtd: spi-nor: fix selection of uniform erase type in flexible conf
@ 2018-11-16 11:17 Tudor.Ambarus
  2018-11-16 17:36 ` Tudor.Ambarus
  0 siblings, 1 reply; 4+ messages in thread
From: Tudor.Ambarus @ 2018-11-16 11:17 UTC (permalink / raw)
  To: marek.vasut, dwmw2, computersforpeace, boris.brezillon, richard,
	linux-mtd, linux-kernel
  Cc: Tudor.Ambarus

There are uniform, non-uniform and flexible erase flash configurations.

The non-uniform erase types, are the erase types that can _not_ erase
the entire flash by their own.

As the code was, in case flashes had flexible erase capabilities
(support both uniform and non-uniform erase types in the same flash
configuration) and supported multiple uniform erase type sizes, the
code did not sort the uniform erase types, and could select the wrong
erase type size.

Sort the uniform erase mask in case of flexible erase flash
configurations, in order to select the best uniform erase type size.

Uniform, non-uniform, and flexible configurations with just a valid
uniform erase type, are not affected by this change.

Uniform erase tested on mx25l3273fm2i-08g and sst26vf064B-104i/sn.
Non uniform erase tested on sst26vf064B-104i/sn.

Fixes: 5390a8df769e ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories")
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 52 +++++++++++++++++++++++++++++++------------
 1 file changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 69784b3b8ca1..4c595cf686e2 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2529,6 +2529,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
 }
 
 /**
+ * spi_nor_sort_erase_mask() - sort erase mask
+ * @map:	the erase map of the SPI NOR
+ * @erase_mask:	the erase type mask to be sorted
+ *
+ * Replicate the sort done for the map's erase types in BFPT: sort the erase
+ * mask in ascending order with the smallest erase type size starting from
+ * BIT(0) in the sorted erase mask.
+ *
+ * Return: sorted erase mask.
+ */
+static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
+{
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	int i;
+	u8 sorted_erase_mask = 0;
+
+	if (!erase_mask)
+		return 0;
+
+	/* Replicate the sort done for the map's erase types. */
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+		if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
+			sorted_erase_mask |= BIT(i);
+
+	return sorted_erase_mask;
+}
+
+/**
  * spi_nor_regions_sort_erase_types() - sort erase types in each region
  * @map:	the erase map of the SPI NOR
  *
@@ -2543,19 +2571,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
 static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
 {
 	struct spi_nor_erase_region *region = map->regions;
-	struct spi_nor_erase_type *erase_type = map->erase_type;
-	int i;
 	u8 region_erase_mask, sorted_erase_mask;
 
 	while (region) {
 		region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
 
-		/* Replicate the sort done for the map's erase types. */
-		sorted_erase_mask = 0;
-		for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
-			if (erase_type[i].size &&
-			    region_erase_mask & BIT(erase_type[i].idx))
-				sorted_erase_mask |= BIT(i);
+		sorted_erase_mask = spi_nor_sort_erase_mask(map,
+							    region_erase_mask);
 
 		/* Overwrite erase mask. */
 		region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
@@ -2729,9 +2751,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 	 * uniform_erase_type bitmask. The bitmask will be used later on when
 	 * selecting the uniform erase.
 	 */
-	spi_nor_regions_sort_erase_types(map);
-	map->uniform_erase_type = map->uniform_region.offset &
-				  SNOR_ERASE_TYPE_MASK;
+	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
+						map->uniform_erase_type);
 
 	/* Stop here if not JESD216 rev A or later. */
 	if (bfpt_header->length < BFPT_DWORD_MAX)
@@ -2985,7 +3006,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 	u64 offset;
 	u32 region_count;
 	int i, j;
-	u8 erase_type;
+	u8 erase_type, uniform_erase_type;
 
 	region_count = SMPT_MAP_REGION_COUNT(*smpt);
 	/*
@@ -2998,7 +3019,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 		return -ENOMEM;
 	map->regions = region;
 
-	map->uniform_erase_type = 0xff;
+	uniform_erase_type = 0xff;
 	offset = 0;
 	/* Populate regions. */
 	for (i = 0; i < region_count; i++) {
@@ -3013,12 +3034,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 		 * Save the erase types that are supported in all regions and
 		 * can erase the entire flash memory.
 		 */
-		map->uniform_erase_type &= erase_type;
+		uniform_erase_type &= erase_type;
 
 		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
 			 region[i].size;
 	}
 
+	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
+							  uniform_erase_type);
+
 	spi_nor_region_mark_end(&region[i - 1]);
 
 	return 0;
-- 
2.9.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] mtd: spi-nor: fix selection of uniform erase type in flexible conf
  2018-11-16 11:17 [PATCH] mtd: spi-nor: fix selection of uniform erase type in flexible conf Tudor.Ambarus
@ 2018-11-16 17:36 ` Tudor.Ambarus
  2018-11-16 17:46   ` [PATCH v2] " Tudor.Ambarus
  0 siblings, 1 reply; 4+ messages in thread
From: Tudor.Ambarus @ 2018-11-16 17:36 UTC (permalink / raw)
  To: marek.vasut, dwmw2, computersforpeace, boris.brezillon, richard,
	linux-mtd, linux-kernel



On 11/16/2018 01:17 PM, Tudor Ambarus - M18064 wrote:

[cut]
> @@ -2729,9 +2751,8 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
>  	 * uniform_erase_type bitmask. The bitmask will be used later on when
>  	 * selecting the uniform erase.
>  	 */
> -	spi_nor_regions_sort_erase_types(map);
> -	map->uniform_erase_type = map->uniform_region.offset &
> -				  SNOR_ERASE_TYPE_MASK;
> +	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
> +						map->uniform_erase_type);

Even if this particular change does not affect how erase works in uniform case,
it is not quite good because map->uniform_erase_type will not reflect what is in
map->uniform_region.offset & SNOR_ERASE_TYPE_MASK.

This change will be removed in v2.

Cheers,
ta

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v2] mtd: spi-nor: fix selection of uniform erase type in flexible conf
  2018-11-16 17:36 ` Tudor.Ambarus
@ 2018-11-16 17:46   ` Tudor.Ambarus
  2018-11-21 14:33     ` [v2] " Boris Brezillon
  0 siblings, 1 reply; 4+ messages in thread
From: Tudor.Ambarus @ 2018-11-16 17:46 UTC (permalink / raw)
  To: marek.vasut, dwmw2, computersforpeace, boris.brezillon, richard,
	linux-mtd, linux-kernel
  Cc: Tudor.Ambarus

There are uniform, non-uniform and flexible erase flash configurations.

The non-uniform erase types, are the erase types that can _not_ erase
the entire flash by their own.

As the code was, in case flashes had flexible erase capabilities
(support both uniform and non-uniform erase types in the same flash
configuration) and supported multiple uniform erase type sizes, the
code did not sort the uniform erase types, and could select a wrong
erase type size.

Sort the uniform erase mask in case of flexible erase flash
configurations, in order to select the best uniform erase type size.

Uniform, non-uniform, and flexible configurations with just a valid
uniform erase type, are not affected by this change.

Uniform erase tested on mx25l3273fm2i-08g and sst26vf064B-104i/sn.
Non uniform erase tested on sst26vf064B-104i/sn.

Fixes: 5390a8df769e ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories")
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v2: drop uneeded change

 drivers/mtd/spi-nor/spi-nor.c | 47 +++++++++++++++++++++++++++++++++----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 69784b3b8ca1..4c7e4dc25006 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -2529,6 +2529,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
 }
 
 /**
+ * spi_nor_sort_erase_mask() - sort erase mask
+ * @map:	the erase map of the SPI NOR
+ * @erase_mask:	the erase type mask to be sorted
+ *
+ * Replicate the sort done for the map's erase types in BFPT: sort the erase
+ * mask in ascending order with the smallest erase type size starting from
+ * BIT(0) in the sorted erase mask.
+ *
+ * Return: sorted erase mask.
+ */
+static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
+{
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	int i;
+	u8 sorted_erase_mask = 0;
+
+	if (!erase_mask)
+		return 0;
+
+	/* Replicate the sort done for the map's erase types. */
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+		if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
+			sorted_erase_mask |= BIT(i);
+
+	return sorted_erase_mask;
+}
+
+/**
  * spi_nor_regions_sort_erase_types() - sort erase types in each region
  * @map:	the erase map of the SPI NOR
  *
@@ -2543,19 +2571,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
 static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
 {
 	struct spi_nor_erase_region *region = map->regions;
-	struct spi_nor_erase_type *erase_type = map->erase_type;
-	int i;
 	u8 region_erase_mask, sorted_erase_mask;
 
 	while (region) {
 		region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
 
-		/* Replicate the sort done for the map's erase types. */
-		sorted_erase_mask = 0;
-		for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
-			if (erase_type[i].size &&
-			    region_erase_mask & BIT(erase_type[i].idx))
-				sorted_erase_mask |= BIT(i);
+		sorted_erase_mask = spi_nor_sort_erase_mask(map,
+							    region_erase_mask);
 
 		/* Overwrite erase mask. */
 		region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
@@ -2985,7 +3007,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 	u64 offset;
 	u32 region_count;
 	int i, j;
-	u8 erase_type;
+	u8 erase_type, uniform_erase_type;
 
 	region_count = SMPT_MAP_REGION_COUNT(*smpt);
 	/*
@@ -2998,7 +3020,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 		return -ENOMEM;
 	map->regions = region;
 
-	map->uniform_erase_type = 0xff;
+	uniform_erase_type = 0xff;
 	offset = 0;
 	/* Populate regions. */
 	for (i = 0; i < region_count; i++) {
@@ -3013,12 +3035,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
 		 * Save the erase types that are supported in all regions and
 		 * can erase the entire flash memory.
 		 */
-		map->uniform_erase_type &= erase_type;
+		uniform_erase_type &= erase_type;
 
 		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
 			 region[i].size;
 	}
 
+	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
+							  uniform_erase_type);
+
 	spi_nor_region_mark_end(&region[i - 1]);
 
 	return 0;
-- 
2.9.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [v2] mtd: spi-nor: fix selection of uniform erase type in flexible conf
  2018-11-16 17:46   ` [PATCH v2] " Tudor.Ambarus
@ 2018-11-21 14:33     ` Boris Brezillon
  0 siblings, 0 replies; 4+ messages in thread
From: Boris Brezillon @ 2018-11-21 14:33 UTC (permalink / raw)
  To: Tudor.Ambarus, marek.vasut, dwmw2, computersforpeace,
	boris.brezillon, richard, linux-mtd, linux-kernel

On Fri, 2018-11-16 at 17:46:37 UTC,  wrote:
> There are uniform, non-uniform and flexible erase flash configurations.
> 
> The non-uniform erase types, are the erase types that can _not_ erase
> the entire flash by their own.
> 
> As the code was, in case flashes had flexible erase capabilities
> (support both uniform and non-uniform erase types in the same flash
> configuration) and supported multiple uniform erase type sizes, the
> code did not sort the uniform erase types, and could select a wrong
> erase type size.
> 
> Sort the uniform erase mask in case of flexible erase flash
> configurations, in order to select the best uniform erase type size.
> 
> Uniform, non-uniform, and flexible configurations with just a valid
> uniform erase type, are not affected by this change.
> 
> Uniform erase tested on mx25l3273fm2i-08g and sst26vf064B-104i/sn.
> Non uniform erase tested on sst26vf064B-104i/sn.
> 
> Fixes: 5390a8df769e ("mtd: spi-nor: add support to non-uniform SFDP SPI NOR flash memories")
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

Applied to http://git.infradead.org/linux-mtd.git master, thanks.

Boris

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-11-21 14:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-16 11:17 [PATCH] mtd: spi-nor: fix selection of uniform erase type in flexible conf Tudor.Ambarus
2018-11-16 17:36 ` Tudor.Ambarus
2018-11-16 17:46   ` [PATCH v2] " Tudor.Ambarus
2018-11-21 14:33     ` [v2] " Boris Brezillon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.