Changelog: https://cdn.kernel.org/pub/linux/kernel/v5.x/ChangeLog-5.15.132
Removed upstreamed:
	bcm53xx/patches-5.15/037-v6.6-0006-ARM-dts-BCM53573-Add-cells-sizes-to-PCIe-node.patch[1]
	bcm53xx/patches-5.15/037-v6.6-0007-ARM-dts-BCM53573-Use-updated-spi-gpio-binding-proper.patch[2]
	bcm53xx/patches-5.15/037-v6.6-0008-ARM-dts-BCM5301X-Extend-RAM-to-full-256MB-for-Linksy.patch[3]
All other patches automatically rebased.
1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.132&id=b35f3ca1877e024887df205ede952863d65dad36
2. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.132&id=2840d9b9c8750be270fb1153ccd5b983cbb5d592
3. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.132&id=f086e859ddc252c32f0438edff241859c0f022ce
Build system: x86_64
Build-tested: ramips/tplink_archer-a6-v3
Run-tested: ramips/tplink_archer-a6-v3
Signed-off-by: John Audia <therealgraysky@proton.me>
(cherry picked from commit ac422c9788)
[Refresh on top of OpenWrt 23.05]
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
		
	
		
			
				
	
	
		
			246 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			246 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From acacdac272927ae1d96e0bca51eb82899671eaea Mon Sep 17 00:00:00 2001
 | 
						|
From: John Thomson <git@johnthomson.fastmail.com.au>
 | 
						|
Date: Fri, 25 Dec 2020 18:50:08 +1000
 | 
						|
Subject: [PATCH] mtd: spi-nor: write support for minor aligned partitions
 | 
						|
MIME-Version: 1.0
 | 
						|
Content-Type: text/plain; charset=UTF-8
 | 
						|
Content-Transfer-Encoding: 8bit
 | 
						|
 | 
						|
Do not prevent writing to mtd partitions where a partition boundary sits
 | 
						|
on a minor erasesize boundary.
 | 
						|
This addresses a FIXME that has been present since the start of the
 | 
						|
linux git history:
 | 
						|
/* Doesn't start on a boundary of major erase size */
 | 
						|
/* FIXME: Let it be writable if it is on a boundary of
 | 
						|
 * _minor_ erase size though */
 | 
						|
 | 
						|
Allow a uniform erase region spi-nor device to be configured
 | 
						|
to use the non-uniform erase regions code path for an erase with:
 | 
						|
CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE=y
 | 
						|
 | 
						|
On supporting hardware (SECT_4K: majority of current SPI-NOR device)
 | 
						|
provide the facility for an erase to use the least number
 | 
						|
of SPI-NOR operations, as well as access to 4K erase without
 | 
						|
requiring CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
 | 
						|
 | 
						|
Introduce erasesize_minor to the mtd struct,
 | 
						|
the smallest erasesize supported by the device
 | 
						|
 | 
						|
On existing devices, this is useful where write support is wanted
 | 
						|
for data on a 4K partition, such as some u-boot-env partitions,
 | 
						|
or RouterBoot soft_config, while still netting the performance
 | 
						|
benefits of using 64K sectors
 | 
						|
 | 
						|
Performance:
 | 
						|
time mtd erase firmware
 | 
						|
OpenWrt 5.10 ramips MT7621 w25q128jv 0xfc0000 partition length
 | 
						|
 | 
						|
Without this patch
 | 
						|
MTD_SPI_NOR_USE_4K_SECTORS=y	|n
 | 
						|
real    2m 11.66s		|0m 50.86s
 | 
						|
user    0m 0.00s		|0m 0.00s
 | 
						|
sys     1m 56.20s		|0m 50.80s
 | 
						|
 | 
						|
With this patch
 | 
						|
MTD_SPI_NOR_USE_VARIABLE_ERASE=n|y		|4K_SECTORS=y
 | 
						|
real    0m 51.68s		|0m 50.85s	|2m 12.89s
 | 
						|
user    0m 0.00s		|0m 0.00s	|0m 0.01s
 | 
						|
sys     0m 46.94s		|0m 50.38s	|2m 12.46s
 | 
						|
 | 
						|
Signed-off-by: John Thomson <git@johnthomson.fastmail.com.au>
 | 
						|
Signed-off-by: Thibaut VARÈNE <hacks+kernel@slashdirt.org>
 | 
						|
 | 
						|
---
 | 
						|
 | 
						|
checkpatch does not like the printk(KERN_WARNING
 | 
						|
these should be changed separately beforehand?
 | 
						|
 | 
						|
Changes v1 -> v2:
 | 
						|
Added mtdcore sysfs for erasesize_minor
 | 
						|
Removed finding minor erasesize for variable erase regions device,
 | 
						|
as untested and no responses regarding it.
 | 
						|
Moved IF_ENABLED for SPINOR variable erase to guard setting
 | 
						|
erasesize_minor in spi-nor/core.c
 | 
						|
Removed setting erasesize to minor where partition boundaries require
 | 
						|
minor erase to be writable
 | 
						|
Simplified minor boundary check by relying on minor being a factor of
 | 
						|
major
 | 
						|
 | 
						|
Changes RFC -> v1:
 | 
						|
Fix uninitialized variable smatch warning
 | 
						|
Reported-by: kernel test robot <lkp@intel.com>
 | 
						|
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
 | 
						|
---
 | 
						|
 drivers/mtd/mtdcore.c       | 10 ++++++++++
 | 
						|
 drivers/mtd/mtdpart.c       | 35 +++++++++++++++++++++++++----------
 | 
						|
 drivers/mtd/spi-nor/Kconfig | 10 ++++++++++
 | 
						|
 drivers/mtd/spi-nor/core.c  | 11 +++++++++--
 | 
						|
 include/linux/mtd/mtd.h     |  2 ++
 | 
						|
 5 files changed, 56 insertions(+), 12 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/mtd/mtdcore.c
 | 
						|
+++ b/drivers/mtd/mtdcore.c
 | 
						|
@@ -169,6 +169,15 @@ static ssize_t mtd_erasesize_show(struct
 | 
						|
 }
 | 
						|
 MTD_DEVICE_ATTR_RO(erasesize);
 | 
						|
 
 | 
						|
+static ssize_t mtd_erasesize_minor_show(struct device *dev,
 | 
						|
+		struct device_attribute *attr, char *buf)
 | 
						|
+{
 | 
						|
+	struct mtd_info *mtd = dev_get_drvdata(dev);
 | 
						|
+
 | 
						|
+	return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize_minor);
 | 
						|
+}
 | 
						|
+MTD_DEVICE_ATTR_RO(erasesize_minor);
 | 
						|
+
 | 
						|
 static ssize_t mtd_writesize_show(struct device *dev,
 | 
						|
 		struct device_attribute *attr, char *buf)
 | 
						|
 {
 | 
						|
@@ -314,6 +323,7 @@ static struct attribute *mtd_attrs[] = {
 | 
						|
 	&dev_attr_flags.attr,
 | 
						|
 	&dev_attr_size.attr,
 | 
						|
 	&dev_attr_erasesize.attr,
 | 
						|
+	&dev_attr_erasesize_minor.attr,
 | 
						|
 	&dev_attr_writesize.attr,
 | 
						|
 	&dev_attr_subpagesize.attr,
 | 
						|
 	&dev_attr_oobsize.attr,
 | 
						|
--- a/drivers/mtd/mtdpart.c
 | 
						|
+++ b/drivers/mtd/mtdpart.c
 | 
						|
@@ -41,6 +41,7 @@ static struct mtd_info *allocate_partiti
 | 
						|
 	struct mtd_info *master = mtd_get_master(parent);
 | 
						|
 	int wr_alignment = (parent->flags & MTD_NO_ERASE) ?
 | 
						|
 			   master->writesize : master->erasesize;
 | 
						|
+	int wr_alignment_minor = 0;
 | 
						|
 	u64 parent_size = mtd_is_partition(parent) ?
 | 
						|
 			  parent->part.size : parent->size;
 | 
						|
 	struct mtd_info *child;
 | 
						|
@@ -165,6 +166,7 @@ static struct mtd_info *allocate_partiti
 | 
						|
 	} else {
 | 
						|
 		/* Single erase size */
 | 
						|
 		child->erasesize = master->erasesize;
 | 
						|
+		child->erasesize_minor = master->erasesize_minor;
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	/*
 | 
						|
@@ -172,26 +174,39 @@ static struct mtd_info *allocate_partiti
 | 
						|
 	 * exposes several regions with different erasesize. Adjust
 | 
						|
 	 * wr_alignment accordingly.
 | 
						|
 	 */
 | 
						|
-	if (!(child->flags & MTD_NO_ERASE))
 | 
						|
+	if (!(child->flags & MTD_NO_ERASE)) {
 | 
						|
 		wr_alignment = child->erasesize;
 | 
						|
+		wr_alignment_minor = child->erasesize_minor;
 | 
						|
+	}
 | 
						|
 
 | 
						|
 	tmp = mtd_get_master_ofs(child, 0);
 | 
						|
 	remainder = do_div(tmp, wr_alignment);
 | 
						|
 	if ((child->flags & MTD_WRITEABLE) && remainder) {
 | 
						|
-		/* Doesn't start on a boundary of major erase size */
 | 
						|
-		/* FIXME: Let it be writable if it is on a boundary of
 | 
						|
-		 * _minor_ erase size though */
 | 
						|
-		child->flags &= ~MTD_WRITEABLE;
 | 
						|
-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
 | 
						|
-			part->name);
 | 
						|
+		if (wr_alignment_minor) {
 | 
						|
+			/* rely on minor being a factor of major erasesize */
 | 
						|
+			tmp = remainder;
 | 
						|
+			remainder = do_div(tmp, wr_alignment_minor);
 | 
						|
+		}
 | 
						|
+		if (remainder) {
 | 
						|
+			child->flags &= ~MTD_WRITEABLE;
 | 
						|
+			printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase/write block boundary -- force read-only\n",
 | 
						|
+				part->name);
 | 
						|
+		}
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	tmp = mtd_get_master_ofs(child, 0) + child->part.size;
 | 
						|
 	remainder = do_div(tmp, wr_alignment);
 | 
						|
 	if ((child->flags & MTD_WRITEABLE) && remainder) {
 | 
						|
-		child->flags &= ~MTD_WRITEABLE;
 | 
						|
-		printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
 | 
						|
-			part->name);
 | 
						|
+		if (wr_alignment_minor) {
 | 
						|
+			tmp = remainder;
 | 
						|
+			remainder = do_div(tmp, wr_alignment_minor);
 | 
						|
+		}
 | 
						|
+
 | 
						|
+		if (remainder) {
 | 
						|
+			child->flags &= ~MTD_WRITEABLE;
 | 
						|
+			printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
 | 
						|
+				part->name);
 | 
						|
+		}
 | 
						|
 	}
 | 
						|
 
 | 
						|
 	child->size = child->part.size;
 | 
						|
--- a/drivers/mtd/spi-nor/Kconfig
 | 
						|
+++ b/drivers/mtd/spi-nor/Kconfig
 | 
						|
@@ -10,6 +10,16 @@ menuconfig MTD_SPI_NOR
 | 
						|
 
 | 
						|
 if MTD_SPI_NOR
 | 
						|
 
 | 
						|
+config MTD_SPI_NOR_USE_VARIABLE_ERASE
 | 
						|
+	bool "Disable uniform_erase to allow use of all hardware supported erasesizes"
 | 
						|
+	depends on !MTD_SPI_NOR_USE_4K_SECTORS
 | 
						|
+	default n
 | 
						|
+	help
 | 
						|
+	  Allow mixed use of all hardware supported erasesizes,
 | 
						|
+	  by forcing spi_nor to use the multiple eraseregions code path.
 | 
						|
+	  For example: A 68K erase will use one 64K erase, and one 4K erase
 | 
						|
+	  on supporting hardware.
 | 
						|
+
 | 
						|
 config MTD_SPI_NOR_USE_4K_SECTORS
 | 
						|
 	bool "Use small 4096 B erase sectors"
 | 
						|
 	default y
 | 
						|
--- a/drivers/mtd/spi-nor/core.c
 | 
						|
+++ b/drivers/mtd/spi-nor/core.c
 | 
						|
@@ -1272,6 +1272,8 @@ static u8 spi_nor_convert_3to4_erase(u8
 | 
						|
 
 | 
						|
 static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
 | 
						|
 {
 | 
						|
+	if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE))
 | 
						|
+		return false;
 | 
						|
 	return !!nor->params->erase_map.uniform_erase_type;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -2401,6 +2403,7 @@ static int spi_nor_select_erase(struct s
 | 
						|
 {
 | 
						|
 	struct spi_nor_erase_map *map = &nor->params->erase_map;
 | 
						|
 	const struct spi_nor_erase_type *erase = NULL;
 | 
						|
+	const struct spi_nor_erase_type *erase_minor = NULL;
 | 
						|
 	struct mtd_info *mtd = &nor->mtd;
 | 
						|
 	u32 wanted_size = nor->info->sector_size;
 | 
						|
 	int i;
 | 
						|
@@ -2433,8 +2436,9 @@ static int spi_nor_select_erase(struct s
 | 
						|
 	 */
 | 
						|
 	for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
 | 
						|
 		if (map->erase_type[i].size) {
 | 
						|
-			erase = &map->erase_type[i];
 | 
						|
-			break;
 | 
						|
+			if (!erase)
 | 
						|
+				erase = &map->erase_type[i];
 | 
						|
+			erase_minor = &map->erase_type[i];
 | 
						|
 		}
 | 
						|
 	}
 | 
						|
 
 | 
						|
@@ -2442,6 +2446,9 @@ static int spi_nor_select_erase(struct s
 | 
						|
 		return -EINVAL;
 | 
						|
 
 | 
						|
 	mtd->erasesize = erase->size;
 | 
						|
+	if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_VARIABLE_ERASE) &&
 | 
						|
+			erase_minor && erase_minor->size < erase->size)
 | 
						|
+		mtd->erasesize_minor = erase_minor->size;
 | 
						|
 	return 0;
 | 
						|
 }
 | 
						|
 
 | 
						|
--- a/include/linux/mtd/mtd.h
 | 
						|
+++ b/include/linux/mtd/mtd.h
 | 
						|
@@ -250,6 +250,8 @@ struct mtd_info {
 | 
						|
 	 * information below if they desire
 | 
						|
 	 */
 | 
						|
 	uint32_t erasesize;
 | 
						|
+	/* "Minor" (smallest) erase size supported by the whole device */
 | 
						|
+	uint32_t erasesize_minor;
 | 
						|
 	/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
 | 
						|
 	 * though individual bits can be cleared), in case of NAND flash it is
 | 
						|
 	 * one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
 |