kernel: 5.10: drop broken-flash-reset patch
Flash accessing instruction templates are determined during probe since
v5.6 for spimem-dirmap support in spi-nor driver in upstream commit:
df5c21002cf4 ("mtd: spi-nor: use spi-mem dirmap API")
As a result, changing bus_width on the fly doesn't work anymore and this
patch will cause executing spi-mem ops with 3-byte address on 16-32M
flash area.
We can't easily revert that behavioral change upstream so drop the patch
to prevent u-boot and eeprom from being erased.
Fixes: b10d604459("kernel: add linux 5.10 support")
Reported-by: Frank Di Matteo <dimatto@foxmail.com>
Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
			
			
This commit is contained in:
		| @@ -1,180 +0,0 @@ | |||||||
| From ea92cbb50a78404e29de2cc3999a240615ffb1c8 Mon Sep 17 00:00:00 2001 |  | ||||||
| From: Chuanhong Guo <gch981213@gmail.com> |  | ||||||
| Date: Mon, 6 Apr 2020 17:58:48 +0800 |  | ||||||
| Subject: [PATCH] mtd: spi-nor: rework broken-flash-reset support |  | ||||||
|  |  | ||||||
| Instead of resetting flash to 3B address on remove hook, this |  | ||||||
| implementation only enters 4B mode when needed, which prevents |  | ||||||
| more unexpected reboot stuck. This implementation makes it only |  | ||||||
| break when a kernel panic happens during flash operation on 16M+ |  | ||||||
| areas. |  | ||||||
| *OpenWrt only*: silent broken-flash-reset warning. We are not dealing |  | ||||||
| with vendors and it's unpleasant for users to se that unnecessary |  | ||||||
| and long WARN_ON print. |  | ||||||
|  |  | ||||||
| Signed-off-by: Chuanhong Guo <gch981213@gmail.com> |  | ||||||
| --- |  | ||||||
|  drivers/mtd/spi-nor/spi-nor.c | 52 +++++++++++++++++++++++++++++++++-- |  | ||||||
|  1 file changed, 49 insertions(+), 3 deletions(-) |  | ||||||
|  |  | ||||||
| --- a/drivers/mtd/spi-nor/core.c |  | ||||||
| +++ b/drivers/mtd/spi-nor/core.c |  | ||||||
| @@ -1449,6 +1449,23 @@ destroy_erase_cmd_list: |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
|   |  | ||||||
| +int spi_nor_check_set_addr_width(struct spi_nor *nor, loff_t addr) |  | ||||||
| +{ |  | ||||||
| +	u8 addr_width; |  | ||||||
| + |  | ||||||
| +	if ((nor->flags & (SNOR_F_4B_OPCODES | SNOR_F_BROKEN_RESET)) != |  | ||||||
| +	    SNOR_F_BROKEN_RESET) |  | ||||||
| +		return 0; |  | ||||||
| + |  | ||||||
| +	addr_width = addr & 0xff000000 ? 4 : 3; |  | ||||||
| +	if (nor->addr_width == addr_width) |  | ||||||
| +		return 0; |  | ||||||
| + |  | ||||||
| +	nor->addr_width = addr_width; |  | ||||||
| + |  | ||||||
| +	return nor->params->set_4byte_addr_mode(nor, addr_width == 4); |  | ||||||
| +} |  | ||||||
| + |  | ||||||
|  /* |  | ||||||
|   * Erase an address range on the nor chip.  The address range may extend |  | ||||||
|   * one or more erase sectors.  Return an error is there is a problem erasing. |  | ||||||
| @@ -1476,6 +1493,10 @@ static int spi_nor_erase(struct mtd_info |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	ret = spi_nor_check_set_addr_width(nor, instr->addr + instr->len); |  | ||||||
| +	if (ret < 0) |  | ||||||
| +		return ret; |  | ||||||
| + |  | ||||||
|  	/* whole-chip erase? */ |  | ||||||
|  	if (len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) { |  | ||||||
|  		unsigned long timeout; |  | ||||||
| @@ -1535,6 +1556,7 @@ static int spi_nor_erase(struct mtd_info |  | ||||||
|  	ret = spi_nor_write_disable(nor); |  | ||||||
|   |  | ||||||
|  erase_err: |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|   |  | ||||||
|  	return ret; |  | ||||||
| @@ -1874,7 +1896,9 @@ static int spi_nor_lock(struct mtd_info |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	spi_nor_check_set_addr_width(nor, ofs + len); |  | ||||||
|  	ret = nor->params->locking_ops->lock(nor, ofs, len); |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|   |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
| @@ -1889,7 +1913,9 @@ static int spi_nor_unlock(struct mtd_inf |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	spi_nor_check_set_addr_width(nor, ofs + len); |  | ||||||
|  	ret = nor->params->locking_ops->unlock(nor, ofs, len); |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|   |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
| @@ -1904,7 +1930,9 @@ static int spi_nor_is_locked(struct mtd_ |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	spi_nor_check_set_addr_width(nor, ofs + len); |  | ||||||
|  	ret = nor->params->locking_ops->is_locked(nor, ofs, len); |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|   |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
| @@ -2097,6 +2125,10 @@ static int spi_nor_read(struct mtd_info |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	ret = spi_nor_check_set_addr_width(nor, from + len); |  | ||||||
| +	if (ret < 0) |  | ||||||
| +		return ret; |  | ||||||
| + |  | ||||||
|  	while (len) { |  | ||||||
|  		loff_t addr = from; |  | ||||||
|   |  | ||||||
| @@ -2120,6 +2152,7 @@ static int spi_nor_read(struct mtd_info |  | ||||||
|  	ret = 0; |  | ||||||
|   |  | ||||||
|  read_err: |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| @@ -2142,6 +2175,10 @@ static int spi_nor_write(struct mtd_info |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	ret = spi_nor_check_set_addr_width(nor, to + len); |  | ||||||
| +	if (ret < 0) |  | ||||||
| +		return ret; |  | ||||||
| + |  | ||||||
|  	for (i = 0; i < len; ) { |  | ||||||
|  		ssize_t written; |  | ||||||
|  		loff_t addr = to + i; |  | ||||||
| @@ -2184,6 +2221,7 @@ static int spi_nor_write(struct mtd_info |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  write_err: |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| @@ -2983,9 +3021,13 @@ static int spi_nor_init(struct spi_nor * |  | ||||||
|  		 * reboots (e.g., crashes). Warn the user (or hopefully, system |  | ||||||
|  		 * designer) that this is bad. |  | ||||||
|  		 */ |  | ||||||
| -		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET, |  | ||||||
| -			  "enabling reset hack; may not recover from unexpected reboots\n"); |  | ||||||
| -		nor->params->set_4byte_addr_mode(nor, true); |  | ||||||
| +		if (nor->flags & SNOR_F_BROKEN_RESET) { |  | ||||||
| +			dev_warn(nor->dev, |  | ||||||
| +				"enabling reset hack; may not recover from unexpected reboots\n"); |  | ||||||
| +			nor->addr_width = 3; |  | ||||||
| +		} else { |  | ||||||
| +			nor->params->set_4byte_addr_mode(nor, true); |  | ||||||
| +		} |  | ||||||
|  	} |  | ||||||
|   |  | ||||||
|  	return 0; |  | ||||||
| --- a/drivers/mtd/spi-nor/core.h |  | ||||||
| +++ b/drivers/mtd/spi-nor/core.h |  | ||||||
| @@ -400,6 +400,7 @@ extern const struct spi_nor_manufacturer |  | ||||||
|  extern const struct spi_nor_manufacturer spi_nor_xmc; |  | ||||||
|  extern const struct spi_nor_manufacturer spi_nor_xtx; |  | ||||||
|   |  | ||||||
| +int spi_nor_check_set_addr_width(struct spi_nor *nor, loff_t addr); |  | ||||||
|  int spi_nor_write_enable(struct spi_nor *nor); |  | ||||||
|  int spi_nor_write_disable(struct spi_nor *nor); |  | ||||||
|  int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable); |  | ||||||
| --- a/drivers/mtd/spi-nor/sst.c |  | ||||||
| +++ b/drivers/mtd/spi-nor/sst.c |  | ||||||
| @@ -55,6 +55,10 @@ static int sst_write(struct mtd_info *mt |  | ||||||
|  	if (ret) |  | ||||||
|  		return ret; |  | ||||||
|   |  | ||||||
| +	ret = spi_nor_check_set_addr_width(nor, to + len); |  | ||||||
| +	if (ret < 0) |  | ||||||
| +		return ret; |  | ||||||
| + |  | ||||||
|  	ret = spi_nor_write_enable(nor); |  | ||||||
|  	if (ret) |  | ||||||
|  		goto out; |  | ||||||
| @@ -124,6 +128,7 @@ static int sst_write(struct mtd_info *mt |  | ||||||
|  	} |  | ||||||
|  out: |  | ||||||
|  	*retlen += actual; |  | ||||||
| +	spi_nor_check_set_addr_width(nor, 0); |  | ||||||
|  	spi_nor_unlock_and_unprep(nor); |  | ||||||
|  	return ret; |  | ||||||
|  } |  | ||||||
| @@ -55,7 +55,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net> | |||||||
| +}; | +}; | ||||||
| --- a/drivers/mtd/spi-nor/core.c | --- a/drivers/mtd/spi-nor/core.c | ||||||
| +++ b/drivers/mtd/spi-nor/core.c | +++ b/drivers/mtd/spi-nor/core.c | ||||||
| @@ -2040,6 +2040,7 @@ int spi_nor_sr2_bit7_quad_enable(struct | @@ -2012,6 +2012,7 @@ int spi_nor_sr2_bit7_quad_enable(struct | ||||||
|   |   | ||||||
|  static const struct spi_nor_manufacturer *manufacturers[] = { |  static const struct spi_nor_manufacturer *manufacturers[] = { | ||||||
|  	&spi_nor_atmel, |  	&spi_nor_atmel, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Chuanhong Guo
					Chuanhong Guo