From: Greg Kroah-Hartman Date: Tue, 5 Nov 2024 16:46:11 +0000 (+0100) Subject: 6.11-stable patches X-Git-Tag: v4.19.323~66 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db54a4bdff92d1dac3b3b11819ea430acafedbd8;p=thirdparty%2Fkernel%2Fstable-queue.git 6.11-stable patches 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 --- 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 index 00000000000..a3572c05741 --- /dev/null +++ b/queue-6.11/firmware-microchip-auto-update-fix-poll_complete-to-not-report-spurious-timeout-errors.patch @@ -0,0 +1,126 @@ +From 83beece5aff75879bdfc6df8ba84ea88fd93050e Mon Sep 17 00:00:00 2001 +From: Conor Dooley +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 + +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 +Tested-by: Jamie Gibbons +Signed-off-by: Conor Dooley +Signed-off-by: Greg Kroah-Hartman +--- + 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)) diff --git a/queue-6.11/series b/queue-6.11/series index 89d2d46e280..ab000d45903 100644 --- a/queue-6.11/series +++ b/queue-6.11/series @@ -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 index 00000000000..73113dc052b --- /dev/null +++ b/queue-6.11/thunderbolt-fix-kasan-reported-stack-out-of-bounds-read-in-tb_retimer_scan.patch @@ -0,0 +1,68 @@ +From e9e1b20fae7de06ba36dd3f8dba858157bad233d Mon Sep 17 00:00:00 2001 +From: Mika Westerberg +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 + +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: + + 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..8fc774f8eb0 --- /dev/null +++ b/queue-6.11/thunderbolt-honor-tmu-requirements-in-the-domain-when-setting-tmu-mode.patch @@ -0,0 +1,117 @@ +From 3cea8af2d1a9ae5869b47c3dabe3b20f331f3bbd Mon Sep 17 00:00:00 2001 +From: Gil Fine +Date: Thu, 10 Oct 2024 17:29:42 +0300 +Subject: thunderbolt: Honor TMU requirements in the domain when setting TMU mode + +From: Gil Fine + +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 +Signed-off-by: Mika Westerberg +Signed-off-by: Greg Kroah-Hartman +--- + 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;