--- /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
+@@ -383,6 +383,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;
+@@ -397,12 +415,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;