Skip to content

Commit 8cd25f1

Browse files
Gil Finegregkh
Gil Fine
authored andcommitted
thunderbolt: Honor TMU requirements in the domain when setting TMU mode
commit 3cea8af 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>
1 parent 9523a02 commit 8cd25f1

File tree

1 file changed

+42
-6
lines changed
  • drivers/thunderbolt

1 file changed

+42
-6
lines changed

drivers/thunderbolt/tb.c

+42-6
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,24 @@ static void tb_increase_tmu_accuracy(struct tb_tunnel *tunnel)
383383
device_for_each_child(&sw->dev, NULL, tb_increase_switch_tmu_accuracy);
384384
}
385385

386+
static int tb_switch_tmu_hifi_uni_required(struct device *dev, void *not_used)
387+
{
388+
struct tb_switch *sw = tb_to_switch(dev);
389+
390+
if (sw && tb_switch_tmu_is_enabled(sw) &&
391+
tb_switch_tmu_is_configured(sw, TB_SWITCH_TMU_MODE_HIFI_UNI))
392+
return 1;
393+
394+
return device_for_each_child(dev, NULL,
395+
tb_switch_tmu_hifi_uni_required);
396+
}
397+
398+
static bool tb_tmu_hifi_uni_required(struct tb *tb)
399+
{
400+
return device_for_each_child(&tb->dev, NULL,
401+
tb_switch_tmu_hifi_uni_required) == 1;
402+
}
403+
386404
static int tb_enable_tmu(struct tb_switch *sw)
387405
{
388406
int ret;
@@ -397,12 +415,30 @@ static int tb_enable_tmu(struct tb_switch *sw)
397415
ret = tb_switch_tmu_configure(sw,
398416
TB_SWITCH_TMU_MODE_MEDRES_ENHANCED_UNI);
399417
if (ret == -EOPNOTSUPP) {
400-
if (tb_switch_clx_is_enabled(sw, TB_CL1))
401-
ret = tb_switch_tmu_configure(sw,
402-
TB_SWITCH_TMU_MODE_LOWRES);
403-
else
404-
ret = tb_switch_tmu_configure(sw,
405-
TB_SWITCH_TMU_MODE_HIFI_BI);
418+
if (tb_switch_clx_is_enabled(sw, TB_CL1)) {
419+
/*
420+
* Figure out uni-directional HiFi TMU requirements
421+
* currently in the domain. If there are no
422+
* uni-directional HiFi requirements we can put the TMU
423+
* into LowRes mode.
424+
*
425+
* Deliberately skip bi-directional HiFi links
426+
* as these work independently of other links
427+
* (and they do not allow any CL states anyway).
428+
*/
429+
if (tb_tmu_hifi_uni_required(sw->tb))
430+
ret = tb_switch_tmu_configure(sw,
431+
TB_SWITCH_TMU_MODE_HIFI_UNI);
432+
else
433+
ret = tb_switch_tmu_configure(sw,
434+
TB_SWITCH_TMU_MODE_LOWRES);
435+
} else {
436+
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
437+
}
438+
439+
/* If not supported, fallback to bi-directional HiFi */
440+
if (ret == -EOPNOTSUPP)
441+
ret = tb_switch_tmu_configure(sw, TB_SWITCH_TMU_MODE_HIFI_BI);
406442
}
407443
if (ret)
408444
return ret;

0 commit comments

Comments
 (0)