--- /dev/null
+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))
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
--- /dev/null
+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 */
--- /dev/null
+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;