]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Mar 2026 09:29:19 +0000 (10:29 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Mar 2026 09:29:19 +0000 (10:29 +0100)
added patches:
mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch
mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch

queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch [new file with mode: 0644]
queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch [new file with mode: 0644]
queue-6.12/series

diff --git a/queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch b/queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch
new file mode 100644 (file)
index 0000000..4a48eca
--- /dev/null
@@ -0,0 +1,121 @@
+From f156b23df6a84efb2f6686156be94d4988568954 Mon Sep 17 00:00:00 2001
+From: Pratyush Yadav <p.yadav@ti.com>
+Date: Tue, 8 Jul 2025 17:16:45 +0800
+Subject: mtd: spi-nor: core: avoid odd length/address reads on 8D-8D-8D mode
+
+From: Pratyush Yadav <p.yadav@ti.com>
+
+commit f156b23df6a84efb2f6686156be94d4988568954 upstream.
+
+On Octal DTR capable flashes like Micron Xcella reads cannot start or
+end at an odd address in Octal DTR mode. Extra bytes need to be read at
+the start or end to make sure both the start address and length remain
+even.
+
+To avoid allocating too much extra memory, thereby putting unnecessary
+memory pressure on the system, the temporary buffer containing the extra
+padding bytes is capped at PAGE_SIZE bytes. The rest of the 2-byte
+aligned part should be read directly in the main buffer.
+
+Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
+Reviewed-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
+Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
+Link: https://lore.kernel.org/r/20250708091646.292-1-ziniu.wang_1@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mtd/spi-nor/core.c |   76 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 75 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/spi-nor/core.c
++++ b/drivers/mtd/spi-nor/core.c
+@@ -2037,6 +2037,76 @@ static const struct flash_info *spi_nor_
+       return info;
+ }
++/*
++ * On Octal DTR capable flashes, reads cannot start or end at an odd
++ * address in Octal DTR mode. Extra bytes need to be read at the start
++ * or end to make sure both the start address and length remain even.
++ */
++static int spi_nor_octal_dtr_read(struct spi_nor *nor, loff_t from, size_t len,
++                                u_char *buf)
++{
++      u_char *tmp_buf;
++      size_t tmp_len;
++      loff_t start, end;
++      int ret, bytes_read;
++
++      if (IS_ALIGNED(from, 2) && IS_ALIGNED(len, 2))
++              return spi_nor_read_data(nor, from, len, buf);
++      else if (IS_ALIGNED(from, 2) && len > PAGE_SIZE)
++              return spi_nor_read_data(nor, from, round_down(len, PAGE_SIZE),
++                                       buf);
++
++      tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
++      if (!tmp_buf)
++              return -ENOMEM;
++
++      start = round_down(from, 2);
++      end = round_up(from + len, 2);
++
++      /*
++       * Avoid allocating too much memory. The requested read length might be
++       * quite large. Allocating a buffer just as large (slightly bigger, in
++       * fact) would put unnecessary memory pressure on the system.
++       *
++       * For example if the read is from 3 to 1M, then this will read from 2
++       * to 4098. The reads from 4098 to 1M will then not need a temporary
++       * buffer so they can proceed as normal.
++       */
++      tmp_len = min_t(size_t, end - start, PAGE_SIZE);
++
++      ret = spi_nor_read_data(nor, start, tmp_len, tmp_buf);
++      if (ret == 0) {
++              ret = -EIO;
++              goto out;
++      }
++      if (ret < 0)
++              goto out;
++
++      /*
++       * More bytes are read than actually requested, but that number can't be
++       * reported to the calling function or it will confuse its calculations.
++       * Calculate how many of the _requested_ bytes were read.
++       */
++      bytes_read = ret;
++
++      if (from != start)
++              ret -= from - start;
++
++      /*
++       * Only account for extra bytes at the end if they were actually read.
++       * For example, if the total length was truncated because of temporary
++       * buffer size limit then the adjustment for the extra bytes at the end
++       * is not needed.
++       */
++      if (start + bytes_read == end)
++              ret -= end - (from + len);
++
++      memcpy(buf, tmp_buf + (from - start), ret);
++out:
++      kfree(tmp_buf);
++      return ret;
++}
++
+ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
+                       size_t *retlen, u_char *buf)
+ {
+@@ -2054,7 +2124,11 @@ static int spi_nor_read(struct mtd_info
+       while (len) {
+               loff_t addr = from;
+-              ret = spi_nor_read_data(nor, addr, len, buf);
++              if (nor->read_proto == SNOR_PROTO_8_8_8_DTR)
++                      ret = spi_nor_octal_dtr_read(nor, addr, len, buf);
++              else
++                      ret = spi_nor_read_data(nor, addr, len, buf);
++
+               if (ret == 0) {
+                       /* We shouldn't see 0-length reads */
+                       ret = -EIO;
diff --git a/queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch b/queue-6.12/mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch
new file mode 100644 (file)
index 0000000..79f78a1
--- /dev/null
@@ -0,0 +1,111 @@
+From 17926cd770ec837ed27d9856cf07f2da8dda4131 Mon Sep 17 00:00:00 2001
+From: Pratyush Yadav <p.yadav@ti.com>
+Date: Tue, 8 Jul 2025 17:16:46 +0800
+Subject: mtd: spi-nor: core: avoid odd length/address writes in 8D-8D-8D mode
+
+From: Pratyush Yadav <p.yadav@ti.com>
+
+commit 17926cd770ec837ed27d9856cf07f2da8dda4131 upstream.
+
+On Octal DTR capable flashes like Micron Xcella the writes cannot start
+or end at an odd address in Octal DTR mode. Extra 0xff bytes need to be
+appended or prepended to make sure the start address and end address are
+even. 0xff is used because on NOR flashes a program operation can only
+flip bits from 1 to 0, not the other way round. 0 to 1 flip needs to
+happen via erases.
+
+Signed-off-by: Pratyush Yadav <p.yadav@ti.com>
+Reviewed-by: Michael Walle <michael@walle.cc>
+Signed-off-by: Luke Wang <ziniu.wang_1@nxp.com>
+Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
+Link: https://lore.kernel.org/r/20250708091646.292-2-ziniu.wang_1@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/mtd/spi-nor/core.c |   69 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 68 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/spi-nor/core.c
++++ b/drivers/mtd/spi-nor/core.c
+@@ -2152,6 +2152,68 @@ read_err:
+ }
+ /*
++ * On Octal DTR capable flashes, writes cannot start or end at an odd address
++ * in Octal DTR mode. Extra 0xff bytes need to be appended or prepended to
++ * make sure the start address and end address are even. 0xff is used because
++ * on NOR flashes a program operation can only flip bits from 1 to 0, not the
++ * other way round. 0 to 1 flip needs to happen via erases.
++ */
++static int spi_nor_octal_dtr_write(struct spi_nor *nor, loff_t to, size_t len,
++                                 const u8 *buf)
++{
++      u8 *tmp_buf;
++      size_t bytes_written;
++      loff_t start, end;
++      int ret;
++
++      if (IS_ALIGNED(to, 2) && IS_ALIGNED(len, 2))
++              return spi_nor_write_data(nor, to, len, buf);
++
++      tmp_buf = kmalloc(nor->params->page_size, GFP_KERNEL);
++      if (!tmp_buf)
++              return -ENOMEM;
++
++      memset(tmp_buf, 0xff, nor->params->page_size);
++
++      start = round_down(to, 2);
++      end = round_up(to + len, 2);
++
++      memcpy(tmp_buf + (to - start), buf, len);
++
++      ret = spi_nor_write_data(nor, start, end - start, tmp_buf);
++      if (ret == 0) {
++              ret = -EIO;
++              goto out;
++      }
++      if (ret < 0)
++              goto out;
++
++      /*
++       * More bytes are written than actually requested, but that number can't
++       * be reported to the calling function or it will confuse its
++       * calculations. Calculate how many of the _requested_ bytes were
++       * written.
++       */
++      bytes_written = ret;
++
++      if (to != start)
++              ret -= to - start;
++
++      /*
++       * Only account for extra bytes at the end if they were actually
++       * written. For example, if for some reason the controller could only
++       * complete a partial write then the adjustment for the extra bytes at
++       * the end is not needed.
++       */
++      if (start + bytes_written == end)
++              ret -= end - (to + len);
++
++out:
++      kfree(tmp_buf);
++      return ret;
++}
++
++/*
+  * Write an address range to the nor chip.  Data must be written in
+  * FLASH_PAGESIZE chunks.  The address range may be any size provided
+  * it is within the physical boundaries.
+@@ -2187,7 +2249,12 @@ static int spi_nor_write(struct mtd_info
+                       goto write_err;
+               }
+-              ret = spi_nor_write_data(nor, addr, page_remain, buf + i);
++              if (nor->write_proto == SNOR_PROTO_8_8_8_DTR)
++                      ret = spi_nor_octal_dtr_write(nor, addr, page_remain,
++                                                    buf + i);
++              else
++                      ret = spi_nor_write_data(nor, addr, page_remain,
++                                               buf + i);
+               spi_nor_unlock_device(nor);
+               if (ret < 0)
+                       goto write_err;
index c1c1bd064e3d68ab70996b60ee682c6f727d38be..77291af3f281a655b7b58cec25266dfd13d50f5b 100644 (file)
@@ -440,3 +440,5 @@ i2c-fsi-fix-a-potential-leak-in-fsi_i2c_probe.patch
 i2c-pxa-defer-reset-on-armada-3700-when-recovery-is-used.patch
 ring-buffer-fix-to-update-per-subbuf-entries-of-persistent-ring-buffer.patch
 x86-platform-uv-handle-deconfigured-sockets.patch
+mtd-spi-nor-core-avoid-odd-length-address-reads-on-8d-8d-8d-mode.patch
+mtd-spi-nor-core-avoid-odd-length-address-writes-in-8d-8d-8d-mode.patch