]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Nov 2024 16:46:11 +0000 (17:46 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 5 Nov 2024 16:46:11 +0000 (17:46 +0100)
added patches:
firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch
thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch
thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch

queue-6.11/firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch [new file with mode: 0644]
queue-6.11/series
queue-6.11/thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch [new file with mode: 0644]
queue-6.11/thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch [new file with mode: 0644]

diff --git a/queue-6.11/firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch b/queue-6.11/firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch
new file mode 100644 (file)
index 0000000..a3572c0
--- /dev/null
@@ -0,0 +1,126 @@
+From 83beece5aff75879bdfc6df8ba84ea88fd93050e Mon Sep 17 00:00:00 2001
+From: Conor Dooley <conor.dooley@microchip.com>
+Date: Wed, 16 Oct 2024 17:35:06 +0100
+Subject: firmware: microchip: auto-update: fix poll_complete() to not report spurious timeout errors
+
+From: Conor Dooley <conor.dooley@microchip.com>
+
+commit 83beece5aff75879bdfc6df8ba84ea88fd93050e upstream.
+
+fw_upload's poll_complete() is really intended for use with
+asynchronous write() implementations - or at least those where the
+write() loop may terminate without the kernel yet being aware of whether
+or not the firmware upload has succeeded. For auto-update, write() is
+only ever called once and will only return when uploading has completed,
+be that by passing or failing. The core fw_upload code only calls
+poll_complete() after the final call to write() has returned.
+
+However, the poll_complete() implementation in the auto-update driver
+was written to expect poll_complete() to be called from another context,
+and it waits for a completion signalled from write(). Since
+poll_complete() is actually called from the same context, after the
+write() loop has terminated, wait_for_completion() never sees the
+completion get signalled and always times out, causing programming to
+always report a failing.
+
+Since write() is full synchronous, and its return value will indicate
+whether or not programming passed or failed, poll_complete() serves no
+purpose and can be cut down to simply return FW_UPLOAD_ERR_NONE.
+
+Cc: stable@vger.kernel.org
+Fixes: ec5b0f1193ad4 ("firmware: microchip: add PolarFire SoC Auto Update support")
+Reported-by: Jamie Gibbons <jamie.gibbons@microchip.com>
+Tested-by: Jamie Gibbons <jamie.gibbons@microchip.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/firmware/microchip/mpfs-auto-update.c |   42 ++++----------------------
+ 1 file changed, 7 insertions(+), 35 deletions(-)
+
+--- a/drivers/firmware/microchip/mpfs-auto-update.c
++++ b/drivers/firmware/microchip/mpfs-auto-update.c
+@@ -76,14 +76,11 @@
+ #define AUTO_UPDATE_INFO_SIZE         SZ_1M
+ #define AUTO_UPDATE_BITSTREAM_BASE    (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
+-#define AUTO_UPDATE_TIMEOUT_MS                60000
+-
+ struct mpfs_auto_update_priv {
+       struct mpfs_sys_controller *sys_controller;
+       struct device *dev;
+       struct mtd_info *flash;
+       struct fw_upload *fw_uploader;
+-      struct completion programming_complete;
+       size_t size_per_bitstream;
+       bool cancel_request;
+ };
+@@ -156,19 +153,6 @@ static void mpfs_auto_update_cancel(stru
+ static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_uploader)
+ {
+-      struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
+-      int ret;
+-
+-      /*
+-       * There is no meaningful way to get the status of the programming while
+-       * it is in progress, so attempting anything other than waiting for it
+-       * to complete would be misplaced.
+-       */
+-      ret = wait_for_completion_timeout(&priv->programming_complete,
+-                                        msecs_to_jiffies(AUTO_UPDATE_TIMEOUT_MS));
+-      if (!ret)
+-              return FW_UPLOAD_ERR_TIMEOUT;
+-
+       return FW_UPLOAD_ERR_NONE;
+ }
+@@ -349,33 +333,23 @@ static enum fw_upload_err mpfs_auto_upda
+                                                u32 offset, u32 size, u32 *written)
+ {
+       struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
+-      enum fw_upload_err err = FW_UPLOAD_ERR_NONE;
+       int ret;
+-      reinit_completion(&priv->programming_complete);
+-
+       ret = mpfs_auto_update_write_bitstream(fw_uploader, data, offset, size, written);
+-      if (ret) {
+-              err = FW_UPLOAD_ERR_RW_ERROR;
+-              goto out;
+-      }
++      if (ret)
++              return FW_UPLOAD_ERR_RW_ERROR;
+-      if (priv->cancel_request) {
+-              err = FW_UPLOAD_ERR_CANCELED;
+-              goto out;
+-      }
++      if (priv->cancel_request)
++              return FW_UPLOAD_ERR_CANCELED;
+       if (mpfs_auto_update_is_bitstream_info(data, size))
+-              goto out;
++              return FW_UPLOAD_ERR_NONE;
+       ret = mpfs_auto_update_verify_image(fw_uploader);
+       if (ret)
+-              err = FW_UPLOAD_ERR_FW_INVALID;
++              return FW_UPLOAD_ERR_FW_INVALID;
+-out:
+-      complete(&priv->programming_complete);
+-
+-      return err;
++      return FW_UPLOAD_ERR_NONE;
+ }
+ static const struct fw_upload_ops mpfs_auto_update_ops = {
+@@ -461,8 +435,6 @@ static int mpfs_auto_update_probe(struct
+               return dev_err_probe(dev, ret,
+                                    "The current bitstream does not support auto-update\n");
+-      init_completion(&priv->programming_complete);
+-
+       fw_uploader = firmware_upload_register(THIS_MODULE, dev, "mpfs-auto-update",
+                                              &mpfs_auto_update_ops, priv);
+       if (IS_ERR(fw_uploader))
index 89d2d46e280fdc795058e36dcb77b6ec3e7b48eb..ab000d45903681844ae728932afca5be1d01051c 100644 (file)
@@ -136,3 +136,6 @@ risc-v-acpi-fix-early_ioremap-to-early_memremap.patch
 mm-shmem-fix-data-race-in-shmem_getattr.patch
 tools-mm-werror-fixes-in-page-types-slabinfo.patch
 mm-shrinker-avoid-memleak-in-alloc_shrinker_info.patch
+firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch
+thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch
+thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch
diff --git a/queue-6.11/thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch b/queue-6.11/thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch
new file mode 100644 (file)
index 0000000..73113dc
--- /dev/null
@@ -0,0 +1,68 @@
+From e9e1b20fae7de06ba36dd3f8dba858157bad233d Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Wed, 25 Sep 2024 12:59:20 +0300
+Subject: thunderbolt: Fix KASAN reported stack out-of-bounds read in tb_retimer_scan()
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+commit e9e1b20fae7de06ba36dd3f8dba858157bad233d upstream.
+
+KASAN reported following issue:
+
+ BUG: KASAN: stack-out-of-bounds in tb_retimer_scan+0xffe/0x1550 [thunderbolt]
+ Read of size 4 at addr ffff88810111fc1c by task kworker/u56:0/11
+ CPU: 0 UID: 0 PID: 11 Comm: kworker/u56:0 Tainted: G     U             6.11.0+ #1387
+ Tainted: [U]=USER
+ Workqueue: thunderbolt0 tb_handle_hotplug [thunderbolt]
+ Call Trace:
+  <TASK>
+  dump_stack_lvl+0x6c/0x90
+  print_report+0xd1/0x630
+  kasan_report+0xdb/0x110
+  __asan_report_load4_noabort+0x14/0x20
+  tb_retimer_scan+0xffe/0x1550 [thunderbolt]
+  tb_scan_port+0xa6f/0x2060 [thunderbolt]
+  tb_handle_hotplug+0x17b1/0x3080 [thunderbolt]
+  process_one_work+0x626/0x1100
+  worker_thread+0x6c8/0xfa0
+  kthread+0x2c8/0x3a0
+  ret_from_fork+0x3a/0x80
+  ret_from_fork_asm+0x1a/0x30
+
+This happens because the loop variable still gets incremented by one so
+max becomes 3 instead of 2, and this makes the second loop read past the
+the array declared on the stack.
+
+Fix this by assigning to max directly in the loop body.
+
+Fixes: ff6ab055e070 ("thunderbolt: Add receiver lane margining support for retimers")
+CC: stable@vger.kernel.org
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/retimer.c |    5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/thunderbolt/retimer.c
++++ b/drivers/thunderbolt/retimer.c
+@@ -516,7 +516,7 @@ int tb_retimer_scan(struct tb_port *port
+        */
+       tb_retimer_set_inbound_sbtx(port);
+-      for (i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
++      for (max = 1, i = 1; i <= TB_MAX_RETIMER_INDEX; i++) {
+               /*
+                * Last retimer is true only for the last on-board
+                * retimer (the one connected directly to the Type-C
+@@ -527,9 +527,10 @@ int tb_retimer_scan(struct tb_port *port
+                       last_idx = i;
+               else if (ret < 0)
+                       break;
++
++              max = i;
+       }
+-      max = i;
+       ret = 0;
+       /* Add retimers if they do not exist already */
diff --git a/queue-6.11/thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch b/queue-6.11/thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch
new file mode 100644 (file)
index 0000000..8fc774f
--- /dev/null
@@ -0,0 +1,117 @@
+From 3cea8af2d1a9ae5869b47c3dabe3b20f331f3bbd Mon Sep 17 00:00:00 2001
+From: Gil Fine <gil.fine@linux.intel.com>
+Date: Thu, 10 Oct 2024 17:29:42 +0300
+Subject: thunderbolt: Honor TMU requirements in the domain when setting TMU mode
+
+From: Gil Fine <gil.fine@linux.intel.com>
+
+commit 3cea8af2d1a9ae5869b47c3dabe3b20f331f3bbd upstream.
+
+Currently, when configuring TMU (Time Management Unit) mode of a given
+router, we take into account only its own TMU requirements ignoring
+other routers in the domain. This is problematic if the router we are
+configuring has lower TMU requirements than what is already configured
+in the domain.
+
+In the scenario below, we have a host router with two USB4 ports: A and
+B. Port A connected to device router #1 (which supports CL states) and
+existing DisplayPort tunnel, thus, the TMU mode is HiFi uni-directional.
+
+1. Initial topology
+
+          [Host]
+         A/
+         /
+ [Device #1]
+   /
+Monitor
+
+2. Plug in device #2 (that supports CL states) to downstream port B of
+   the host router
+
+         [Host]
+        A/    B\
+        /       \
+ [Device #1]    [Device #2]
+   /
+Monitor
+
+The TMU mode on port B and port A will be configured to LowRes which is
+not what we want and will cause monitor to start flickering.
+
+To address this we first scan the domain and search for any router
+configured to HiFi uni-directional mode, and if found, configure TMU
+mode of the given router to HiFi uni-directional as well.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Gil Fine <gil.fine@linux.intel.com>
+Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/thunderbolt/tb.c |   48 +++++++++++++++++++++++++++++++++++++++++------
+ 1 file changed, 42 insertions(+), 6 deletions(-)
+
+--- a/drivers/thunderbolt/tb.c
++++ b/drivers/thunderbolt/tb.c
+@@ -288,6 +288,24 @@ static void tb_increase_tmu_accuracy(str
+       device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy);
+ }
++static int tb_switch_tmu_hifi_uni_required(struct device *dev, void *not_used)
++{
++      struct tb_switch *sw = tb_to_switch(dev);
++
++      if (sw && tb_switch_tmu_is_enabled(sw) &&
++          tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_HIFI_UNI))
++              return 1;
++
++      return device_for_each_child(dev, NULL,
++                                   tb_switch_tmu_hifi_uni_required);
++}
++
++static bool tb_tmu_hifi_uni_required(struct tb *tb)
++{
++      return device_for_each_child(&tb->dev, NULL,
++                                   tb_switch_tmu_hifi_uni_required) == 1;
++}
++
+ static int tb_enable_tmu(struct tb_switch *sw)
+ {
+       int ret;
+@@ -302,12 +320,30 @@ static int tb_enable_tmu(struct tb_switc
+       ret = tb_switch_tmu_configure(sw,
+                       TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI);
+       if (ret == -EOPNOTSUPP) {
+-              if (tb_switch_clx_is_enabled(sw, TB_CL1))
+-                      ret = tb_switch_tmu_configure(sw,
+-                                      TB_SWITCH_TMU_MODE_LOWRES);
+-              else
+-                      ret = tb_switch_tmu_configure(sw,
+-                                      TB_SWITCH_TMU_MODE_HIFI_BI);
++              if (tb_switch_clx_is_enabled(sw, TB_CL1)) {
++                      /*
++                       * Figure out uni-directional HiFi TMU requirements
++                       * currently in the domain. If there are no
++                       * uni-directional HiFi requirements we can put the TMU
++                       * into LowRes mode.
++                       *
++                       * Deliberately skip bi-directional HiFi links
++                       * as these work independently of other links
++                       * (and they do not allow any CL states anyway).
++                       */
++                      if (tb_tmu_hifi_uni_required(sw->tb))
++                              ret = tb_switch_tmu_configure(sw,
++                                              TB_SWITCH_TMU_MODE_HIFI_UNI);
++                      else
++                              ret = tb_switch_tmu_configure(sw,
++                                              TB_SWITCH_TMU_MODE_LOWRES);
++              } else {
++                      ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
++              }
++
++              /* If not supported, fallback to bi-directional HiFi */
++              if (ret == -EOPNOTSUPP)
++                      ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
+       }
+       if (ret)
+               return ret;