thunderbolt: CL1 support for USB4 and Titan Ridge
Subsystems (2)
v3 cover thunderbolt: CL1 support for USB4 and Titan Ridge
v1 can be found here:
https://lore.kernel.org/linux-usb/[email protected]/
v2 can be found here:
https://lore.kernel.org/linux-usb/[email protected]/
Changes in v3:
* Fix to support the case of enabling CL1 entry after resume from runtime PM (if CL1 suppported in the connected device)
Changes in v2:
* Handle CL1 and CL0s together since on the hardware level they are supported and enabled together
* Use device_for_each_child() to set TMU mode of host router's 1st children
* Use FIELD_x macros from include/linux/bitfield.h
* Split single patch into two for clarity
* Fix commit message
In this series of patches, first, we address several issues in the CL0s implementation.
Then, we add support for a second low power state of the
link: CL1. Low power states (called collectively CLx) are used to reduce transmitter and receiver power when a high-speed lane is idle. We enable it, if both sides of the link support it, and only for the first hop router (i.e. the first device that connected to the host router). This is needed for better thermal management. CL1 improves power management that was intoduced by CL0s. Also, we add support of dynamic change of TMU mode to HiFi uni-directional once DisplayPort tunnel is created.
This enables CL0s while DP tunnel exists.
Due to Intel hardware limitation, once we changed the TMU mode to HiFi uni-directional (when DP tunnel exists), we don't change TMU mode back to normal uni-directional, even if DP tunnel is torn down later. Though, after sleep or runtime PM resume, the TMU is changed to normal uni-directional (if CLx suppported in the connected device) to enable CL1 entry.
Gil Fine (6):
thunderbolt: Silently ignore CLx enabling in case CLx is not supported
thunderbolt: CLx disable before system suspend only if previously
enabled
thunderbolt: Fix typos in CLx enabling
thunderbolt: Change downstream router's TMU rate in both TMU uni/bidir
mode
thunderbolt: Add CL1 support for USB4 and Titan Ridge routers
thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort
tunneled
drivers/thunderbolt/switch.c | 91 ++++++++-------- drivers/thunderbolt/tb.c | 83 +++++++++++--- drivers/thunderbolt/tb.h | 51 +++++---- drivers/thunderbolt/tb_regs.h | 6 ++ drivers/thunderbolt/tmu.c | 198 ++++++++++++++++++++++++++++------ 5 files changed, 322 insertions(+), 107 deletions(-)
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 1/6 thunderbolt: Silently ignore CLx enabling in case CLx is not supported
We can't enable CLx if it is not supported either by the host or device, or by the USB4/TBT link (e.g. when an optical cable is used). We silently ignore CLx enabling in this case.
--- drivers/thunderbolt/tb.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/thunderbolt/tb.c +8 -2
@@ -581,6 +581,7 @@ static void tb_scan_port(struct tb_port *port)struct tb_cm *tcm =tb_priv (port->sw->tb);struct tb_port *upstream_port;struct tb_switch *sw; +int ret;if (tb_is_upstream_port (port))return ;
@@ -669,7 +670,9 @@ static void tb_scan_port(struct tb_port *port)tb_switch_lane_bonding_enable (sw);/* Set the link configured */ tb_switch_configure_link (sw); -if (tb_switch_enable_clx (sw,TB_CL0S )) +/* Silently ignore CLx enabling in case CLx is not supported */ + ret =tb_switch_enable_clx (sw,TB_CL0S ); +if (ret && ret != -EOPNOTSUPP )tb_sw_warn (sw,"failed to enable CLx on upstream port\n" ); tb_switch_tmu_configure(sw, TB_SWITCH_TMU_RATE_HIFI,
@@ -1452,12 +1455,15 @@ static int tb_suspend_noirq(struct tb *tb)static void tb_restore_children (struct tb_switch *sw) {struct tb_port *port; +int ret;/* No need to restore if the router is already unplugged */ if (sw->is_unplugged)return ; -if (tb_switch_enable_clx (sw,TB_CL0S )) +/* Silently ignore CLx re-enabling in case CLx is not supported */ + ret =tb_switch_enable_clx (sw,TB_CL0S ); +if (ret && ret != -EOPNOTSUPP )tb_sw_warn (sw,"failed to re-enable CLx on upstream port\n" );/*
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 2/6 thunderbolt: CLx disable before system suspend only if previously enabled
In reply to Gil FineDisable CLx before system suspended only if previously was enabled.
--- drivers/thunderbolt/switch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/thunderbolt/switch.c +4 -2
@@ -3063,8 +3063,10 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime)* Actually only needed for Titan Ridge but for simplicity can be * done for USB4 device too as CLx is re-enabled at resume. */ -if (tb_switch_disable_clx (sw,TB_CL0S )) -tb_sw_warn (sw,"failed to disable CLx on upstream port\n" ); +if (tb_switch_is_clx_enabled (sw)) { +if (tb_switch_disable_clx (sw,TB_CL0S )) +tb_sw_warn (sw,"failed to disable CLx on upstream port\n" ); + } err =tb_plug_events_active (sw, false);if (err)
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 3/6 thunderbolt: Fix typos in CLx enabling
In reply to Gil FineFix few typos in CLx enabling.
--- drivers/thunderbolt/switch.c | 2 +- drivers/thunderbolt/tmu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/thunderbolt/switch.c +1 -1
@@ -3485,7 +3485,7 @@ static int tb_switch_enable_cl0s(struct tb_switch *sw)* to improve performance. CLx is enabled only if both sides of the link * support CLx, and if both sides of the link are not configured as two * single lane links and only if the link is not inter-domain link. The -* complete set of conditions is descibed in CM Guide 1.0 section 8.1. +* complete set of conditions is described in CM Guide 1.0 section 8.1. * * Return: Returns 0 on success or an error code on failure. */
drivers/thunderbolt/tmu.c +1 -1
@@ -606,7 +606,7 @@ int tb_switch_tmu_enable(struct tb_switch *sw)/** * tb_switch_tmu_configure() - Configure the TMU rate and directionality * @sw: Router whose mode to change -* @rate: Rate to configure Off/LowRes/HiFi +* @rate: Rate to configure Off/Normal/HiFi * @unidirectional: If uni-directional (bi-directional otherwise) * * Selects the rate of the TMU and directionality (uni-directional or
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 4/6 thunderbolt: Change downstream router's TMU rate in both TMU uni/bidir mode
In reply to Gil FineIn case of uni-directional time sync, TMU handshake is initiated by upstream router. In case of bi-directional time sync, TMU handshake is initiated by downstream router. In order to handle correctly the case of uni-directional mode, we avoid changing the upstream router's rate to off, because it might have another downstream router plugged that is set to uni-directional mode (and we don't want to change its mode). Instead, we always change downstream router's rate.
--- drivers/thunderbolt/tmu.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/thunderbolt/tmu.c +7 -6
@@ -359,13 +359,14 @@ int tb_switch_tmu_disable(struct tb_switch *sw)* In case of uni-directional time sync, TMU handshake is * initiated by upstream router. In case of bi-directional * time sync, TMU handshake is initiated by downstream router. -* Therefore, we change the rate to off in the respective -* router. +* We change downstream router's rate to off for both uni/bidir +* cases although it is needed only for the bi-directional mode. +* We avoid changing upstream router's mode since it might +* have another downstream router plugged, that is set to +* uni-directional mode and we don't want to change it's TMU +* mode. */ -if (unidirectional) -tb_switch_tmu_rate_write (parent,TB_SWITCH_TMU_RATE_OFF ); -else -tb_switch_tmu_rate_write (sw,TB_SWITCH_TMU_RATE_OFF ); +tb_switch_tmu_rate_write (sw,TB_SWITCH_TMU_RATE_OFF );tb_port_tmu_time_sync_disable (up); ret =tb_port_tmu_time_sync_disable (down);
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 5/6 thunderbolt: Add CL1 support for USB4 and Titan Ridge routers
In reply to Gil FineIn this patch we add support for a second low power state of the link: CL1. Low power states (called collectively CLx) are used to reduce transmitter and receiver power when a high-speed lane is idle. We enable it, if both sides of the link support it,
and only for the first hop router (i.e. the first device that connected to the host router). This is needed for better thermal management.
--- drivers/thunderbolt/switch.c | 89 ++++++++--------- drivers/thunderbolt/tb.c | 55 ++++++++--- drivers/thunderbolt/tb.h | 46 ++++----- drivers/thunderbolt/tb_regs.h | 6 ++ drivers/thunderbolt/tmu.c | 177 ++++++++++++++++++++++++++++------ 5 files changed, 266 insertions(+), 107 deletions(-)
drivers/thunderbolt/switch.c +46 -43
@@ -3062,10 +3062,12 @@ void tb_switch_suspend(struct tb_switch *sw, bool runtime)/* * Actually only needed for Titan Ridge but for simplicity can be * done for USB4 device too as CLx is re-enabled at resume. +* CL0s and CL1 are enabled and supported together. */ -if (tb_switch_is_clx_enabled (sw)) { -if (tb_switch_disable_clx (sw,TB_CL0S )) -tb_sw_warn (sw,"failed to disable CLx on upstream port\n" ); +if (tb_switch_is_clx_enabled (sw,TB_CL1 )) { +if (tb_switch_disable_clx (sw,TB_CL1 )) +tb_sw_warn (sw,"failed to disable %s on upstream port\n" , +tb_switch_clx_name (TB_CL1 )); } err =tb_plug_events_active (sw, false);
@@ -3357,13 +3359,12 @@ static bool tb_port_clx_supported(struct tb_port *port, enum tb_clx clx) }switch (clx) { -case TB_CL0S : -/* CL0s support requires also CL1 support */ +case TB_CL1 : +/* CL0s and CL1 are enabled and supported together */ mask =LANE_ADP_CS_0_CL0S_SUPPORT |LANE_ADP_CS_0_CL1_SUPPORT ;break ; -/* For now we support only CL0s. Not CL1, CL2 */ -case TB_CL1 : +/* For now we support only CL0s and CL1. Not CL2 */ case TB_CL2 :default :return false;
@@ -3377,18 +3378,18 @@ static bool tb_port_clx_supported(struct tb_port *port, enum tb_clx clx)return !!(val & mask); } -static inline bool tb_port_cl0s_supported (struct tb_port *port) -{ -return tb_port_clx_supported (port,TB_CL0S ); -} - -static int __tb_port_cl0s_set (struct tb_port *port,bool enable) +static int __tb_port_clx_set (struct tb_port *port,enum tb_clx clx,bool enable) {u32 phy, mask;int ret; -/* To enable CL0s also required to enable CL1 */ - mask =LANE_ADP_CS_1_CL0S_ENABLE |LANE_ADP_CS_1_CL1_ENABLE ; +/* CL0s and CL1 are enabled and supported together */ +if (clx ==TB_CL1 ) + mask =LANE_ADP_CS_1_CL0S_ENABLE |LANE_ADP_CS_1_CL1_ENABLE ; +else +/* For now we support only CL0s and CL1. Not CL2 */ +return -EOPNOTSUPP ; + ret =tb_port_read (port, &phy,TB_CFG_PORT , port->cap_phy +LANE_ADP_CS_1 ,1 );if (ret)
@@ -3403,20 +3404,20 @@ static int __tb_port_cl0s_set(struct tb_port *port, bool enable) port->cap_phy + LANE_ADP_CS_1, 1); } -static int tb_port_cl0s_disable (struct tb_port *port) +static int tb_port_clx_disable (struct tb_port *port,enum tb_clx clx) { -return __tb_port_cl0s_set (port, false); +return __tb_port_clx_set (port, clx, false); } -static int tb_port_cl0s_enable (struct tb_port *port) +static int tb_port_clx_enable (struct tb_port *port,enum tb_clx clx) { -return __tb_port_cl0s_set (port, true); +return __tb_port_clx_set (port, clx, true); } -static int tb_switch_enable_cl0s (struct tb_switch *sw) +static int __tb_switch_enable_clx (struct tb_switch *sw,enum tb_clx clx) {struct tb_switch *parent =tb_switch_parent (sw); -bool up_cl0s_support, down_cl0s_support; +bool up_clx_support, down_clx_support;struct tb_port *up, *down;int ret;
@@ -3441,37 +3442,37 @@ static int tb_switch_enable_cl0s(struct tb_switch *sw) up =tb_upstream_port (sw); down =tb_port_at (tb_route (sw), parent); - up_cl0s_support =tb_port_cl0s_supported (up); - down_cl0s_support =tb_port_cl0s_supported (down); + up_clx_support =tb_port_clx_supported (up, clx); + down_clx_support =tb_port_clx_supported (down, clx); -tb_port_dbg (up,"CL0s %ssupported\n" , - up_cl0s_support ?"" :"not " ); -tb_port_dbg (down,"CL0s %ssupported\n" , - down_cl0s_support ?"" :"not " ); +tb_port_dbg (up,"%s %ssupported\n" ,tb_switch_clx_name (clx), + up_clx_support ?"" :"not " ); +tb_port_dbg (down,"%s %ssupported\n" ,tb_switch_clx_name (clx), + down_clx_support ?"" :"not " ); -if (!up_cl0s_support || !down_cl0s_support) +if (!up_clx_support || !down_clx_support)return -EOPNOTSUPP ; - ret =tb_port_cl0s_enable (up); + ret =tb_port_clx_enable (up, clx);if (ret)return ret; - ret =tb_port_cl0s_enable (down); + ret =tb_port_clx_enable (down, clx);if (ret) { -tb_port_cl0s_disable (up); +tb_port_clx_disable (up, clx);return ret; } ret =tb_switch_mask_clx_objections (sw);if (ret) { -tb_port_cl0s_disable (up); -tb_port_cl0s_disable (down); +tb_port_clx_disable (up, clx); +tb_port_clx_disable (down, clx);return ret; } - sw->clx =TB_CL0S ; + sw->clx = clx; -tb_port_dbg (up,"CL0s enabled\n" ); +tb_port_dbg (up,"%s enabled\n" ,tb_switch_clx_name (clx));return 0 ; }
@@ -3504,15 +3505,16 @@ int tb_switch_enable_clx(struct tb_switch *sw, enum tb_clx clx)return 0 ;switch (clx) { -case TB_CL0S : -return tb_switch_enable_cl0s (sw); +case TB_CL1 : +/* CL0s and CL1 are enabled and supported together */ +return __tb_switch_enable_clx (sw, clx);default :return -EOPNOTSUPP ; } } -static int tb_switch_disable_cl0s (struct tb_switch *sw) +static int __tb_switch_disable_clx (struct tb_switch *sw,enum tb_clx clx) {struct tb_switch *parent =tb_switch_parent (sw);struct tb_port *up, *down;
@@ -3534,17 +3536,17 @@ static int tb_switch_disable_cl0s(struct tb_switch *sw) up =tb_upstream_port (sw); down =tb_port_at (tb_route (sw), parent); - ret =tb_port_cl0s_disable (up); + ret =tb_port_clx_disable (up, clx);if (ret)return ret; - ret =tb_port_cl0s_disable (down); + ret =tb_port_clx_disable (down, clx);if (ret)return ret; sw->clx =TB_CLX_DISABLE ; -tb_port_dbg (up,"CL0s disabled\n" ); +tb_port_dbg (up,"%s disabled\n" ,tb_switch_clx_name (clx));return 0 ; }
@@ -3561,8 +3563,9 @@ int tb_switch_disable_clx(struct tb_switch *sw, enum tb_clx clx)return 0 ;switch (clx) { -case TB_CL0S : -return tb_switch_disable_cl0s (sw); +case TB_CL1 : +/* CL0s and CL1 are enabled and supported together */ +return __tb_switch_disable_clx (sw, clx);default :return -EOPNOTSUPP ;
drivers/thunderbolt/tb.c +40 -15
83 lines not on this page · raw message
drivers/thunderbolt/tb.h +24 -22
82 lines not on this page · raw message
drivers/thunderbolt/tb_regs.h +6 -0
@@ -234,6 +234,7 @@ enum usb4_switch_op {/* Router TMU configuration */ #define TMU_RTR_CS_0 0x00 +#define TMU_RTR_CS_0_FREQ_WIND_MASK GENMASK(26, 16)#define TMU_RTR_CS_0_TD BIT(27)#define TMU_RTR_CS_0_UCAP BIT(30)#define TMU_RTR_CS_1 0x01
@@ -244,6 +245,11 @@ enum usb4_switch_op {#define TMU_RTR_CS_3_LOCAL_TIME_NS_MASK GENMASK(15, 0)#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_MASK GENMASK(31, 16)#define TMU_RTR_CS_3_TS_PACKET_INTERVAL_SHIFT 16 +#define TMU_RTR_CS_15 0xf +#define TMU_RTR_CS_15_FREQ_AVG_MASK GENMASK(5, 0) +#define TMU_RTR_CS_15_DELAY_AVG_MASK GENMASK(11, 6) +#define TMU_RTR_CS_15_OFFSET_AVG_MASK GENMASK(17, 12) +#define TMU_RTR_CS_15_ERROR_AVG_MASK GENMASK(23, 18)#define TMU_RTR_CS_22 0x16#define TMU_RTR_CS_24 0x18#define TMU_RTR_CS_25 0x19
drivers/thunderbolt/tmu.c +150 -27
243 lines not on this page · raw message
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
PATCH v3 6/6 thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
In reply to Gil FineHere we configure TMU mode to HiFi uni-directional once DP tunnel is created. This is due to accuracy requirement for DP tunneling as appears in CM guide 1.0, section 7.3.2.
Due to Intel hardware limitation, once we changed the TMU mode to HiFi uni-directional (when DP tunnel exists), we don't change TMU mode back to normal uni-directional, even if DP tunnel is torn down later.
--- drivers/thunderbolt/tb.c | 28 ++++++++++++++++++++++++++++ drivers/thunderbolt/tb.h | 5 +++++ drivers/thunderbolt/tmu.c | 14 ++++++++++++++ 3 files changed, 47 insertions(+)
drivers/thunderbolt/tb.c +28 -0
@@ -50,6 +50,8 @@ struct tb_hotplug_event { };static void tb_handle_hotplug (struct work_struct *work); +static void tb_enable_tmu_1st_child (struct tb *tb, +enum tb_switch_tmu_rate rate);static void tb_queue_hotplug (struct tb *tb,u64 route,u8 port,bool unplug) {
@@ -118,6 +120,13 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw,switch (port->config.type) {case TB_TYPE_DP_HDMI_IN : tunnel =tb_tunnel_discover_dp (tb, port, alloc_hopids); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +if (tunnel) +tb_enable_tmu_1st_child (tb, +TB_SWITCH_TMU_RATE_HIFI );break ;case TB_TYPE_PCIE_DOWN :
@@ -235,6 +244,19 @@ static int tb_enable_tmu(struct tb_switch *sw)return tb_switch_tmu_enable (sw); } +/* +* Once a DP tunnel exists in the domain, we set the TMU mode so that +* it meets the accuracy requirements and also enables CLx entry (CL0s). +* We set the TMU mode of the first depth router(s) for CL0s to work. +*/ +static void tb_enable_tmu_1st_child (struct tb *tb,enum tb_switch_tmu_rate rate) +{ +struct tb_sw_tmu_config tmu = { .rate = rate }; + +device_for_each_child (&tb->root_switch->dev, &tmu, + tb_switch_tmu_config_enable); +} +/** * tb_find_unused_port() - return the first inactive port on @sw * @sw: Switch to find the port on
@@ -985,6 +1007,12 @@ static void tb_tunnel_dp(struct tb *tb)list_add_tail (&tunnel->list, &tcm->tunnel_list);tb_reclaim_usb3_bandwidth (tb, in, out); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +tb_enable_tmu_1st_child (tb,TB_SWITCH_TMU_RATE_HIFI ); +return ; err_free:
drivers/thunderbolt/tb.h +5 -0
@@ -110,6 +110,10 @@ struct tb_switch_tmu {enum tb_switch_tmu_rate rate_request; }; +struct tb_sw_tmu_config { +enum tb_switch_tmu_rate rate; +}; +enum tb_clx {TB_CLX_DISABLE ,/* CL0s and CL1 are enabled and supported together */
@@ -934,6 +938,7 @@ int tb_switch_tmu_enable(struct tb_switch *sw);void tb_switch_tmu_configure (struct tb_switch *sw,enum tb_switch_tmu_rate rate,bool unidirectional); +int tb_switch_tmu_config_enable (struct device *dev,void *data);/** * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled * @sw: Router whose TMU mode to check
drivers/thunderbolt/tmu.c +14 -0
@@ -727,6 +727,20 @@ int tb_switch_tmu_enable(struct tb_switch *sw)return tb_switch_tmu_set_time_disruption (sw, false); } +int tb_switch_tmu_config_enable (struct device *dev,void *data) +{ +if (tb_is_switch (dev)) { +struct tb_switch *sw =tb_to_switch (dev); +struct tb_sw_tmu_config *tmu = data; + +tb_switch_tmu_configure (sw, tmu->rate,tb_switch_is_clx_enabled (sw,TB_CL1 )); +if (tb_switch_tmu_enable (sw)) +tb_sw_dbg (sw,"Fail switching TMU to HiFi for 1st depth router\n" ); + } + +return 0 ; +} +/** * tb_switch_tmu_configure() - Configure the TMU rate and directionality * @sw: Router whose mode to change
Signature · 9 lines
2.17.1 --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Gil,
Quoted 19 lines · Gil Fine
Here we configure TMU mode to HiFi uni-directional once DP tunnel is created. This is due to accuracy requirement for DP tunneling as appears in CM guide 1.0, section 7.3.2.
Due to Intel hardware limitation, once we changed the TMU mode to HiFi uni-directional (when DP tunnel exists), we don't change TMU mode back to normal uni-directional, even if DP tunnel is torn down later.Signed-off-by Gil Fine <[email protected]>--- drivers/thunderbolt/tb.c | 28 ++++++++++++++++++++++++++++ drivers/thunderbolt/tb.h | 5 +++++ drivers/thunderbolt/tmu.c | 14 ++++++++++++++ 3 files changed, 47 insertions(+)drivers/thunderbolt/tb.c +0
-0
drivers/thunderbolt/tb.c struct tb_hotplug_event { · line 54
Quoted 5 lines
drivers/thunderbolt/tb.c +2
-0@@ -50,6 +50,8 @@ struct tb_hotplug_event { };static void tb_handle_hotplug (struct work_struct *work); +static void tb_enable_tmu_1st_child (struct tb *tb, +enum tb_switch_tmu_rate rate);
This forward declaration is not needed. You can just move the implementation before you call it first time.
Quoted 54 lines
drivers/thunderbolt/tb.c +26
-0static void tb_queue_hotplug (struct tb *tb,u64 route,u8 port,bool unplug) {@@ -118,6 +120,13 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw,switch (port->config.type) {case TB_TYPE_DP_HDMI_IN : tunnel =tb_tunnel_discover_dp (tb, port, alloc_hopids); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +if (tunnel) +tb_enable_tmu_1st_child (tb, +TB_SWITCH_TMU_RATE_HIFI );break ;case TB_TYPE_PCIE_DOWN :@@ -235,6 +244,19 @@ static int tb_enable_tmu(struct tb_switch *sw)return tb_switch_tmu_enable (sw); } +/* +* Once a DP tunnel exists in the domain, we set the TMU mode so that +* it meets the accuracy requirements and also enables CLx entry (CL0s). +* We set the TMU mode of the first depth router(s) for CL0s to work. +*/ +static void tb_enable_tmu_1st_child (struct tb *tb,enum tb_switch_tmu_rate rate) +{ +struct tb_sw_tmu_config tmu = { .rate = rate }; + +device_for_each_child (&tb->root_switch->dev, &tmu, + tb_switch_tmu_config_enable); +} +/** * tb_find_unused_port() - return the first inactive port on @sw * @sw: Switch to find the port on @@ -985,6 +1007,12 @@ static void tb_tunnel_dp(struct tb *tb)list_add_tail (&tunnel->list, &tcm->tunnel_list);tb_reclaim_usb3_bandwidth (tb, in, out); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +tb_enable_tmu_1st_child (tb,TB_SWITCH_TMU_RATE_HIFI ); +return ; err_free:drivers/thunderbolt/tb.h +0
-0
drivers/thunderbolt/tb.h struct tb_switch_tmu { · line 115
Quoted 6 lines
drivers/thunderbolt/tb.h +3
-0@@ -110,6 +110,10 @@ struct tb_switch_tmu {enum tb_switch_tmu_rate rate_request; }; +struct tb_sw_tmu_config { +enum tb_switch_tmu_rate rate; +};
Is this wrapper structure really needed?
Quoted 17 lines
drivers/thunderbolt/tb.h +2
-0+enum tb_clx {TB_CLX_DISABLE ,/* CL0s and CL1 are enabled and supported together */ @@ -934,6 +938,7 @@ int tb_switch_tmu_enable(struct tb_switch *sw);void tb_switch_tmu_configure (struct tb_switch *sw,enum tb_switch_tmu_rate rate,bool unidirectional); +int tb_switch_tmu_config_enable (struct device *dev,void *data);/** * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled * @sw: Router whose TMU mode to check drivers/thunderbolt/tmu.c +0
-0
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 728
Quoted 2 lines
drivers/thunderbolt/tmu.c +0
-0@@ -727,6 +727,20 @@ int tb_switch_tmu_enable(struct tb_switch *sw)return tb_switch_tmu_set_time_disruption (sw, false); }
You are missing kernel-doc for the non-static function.
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 730
Quoted 2 lines
drivers/thunderbolt/tmu.c +1
-0+int tb_switch_tmu_config_enable (struct device *dev,void *data)
Also can we please make it take some real type and not something arbitrary?
Can it be const too?
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 738
Quoted 8 lines
drivers/thunderbolt/tmu.c +8
-0+{ +if (tb_is_switch (dev)) { +struct tb_switch *sw =tb_to_switch (dev); +struct tb_sw_tmu_config *tmu = data; + +tb_switch_tmu_configure (sw, tmu->rate,tb_switch_is_clx_enabled (sw,TB_CL1 )); +if (tb_switch_tmu_enable (sw)) +tb_sw_dbg (sw,"Fail switching TMU to HiFi for 1st depth router\n" );
Be consistent with the messaging so don't start with capital letter here.
Quoted 10 lines
drivers/thunderbolt/tmu.c +5
-0+ } + +return 0 ; +} +/** * tb_switch_tmu_configure() - Configure the TMU rate and directionality * @sw: Router whose mode to change Signature · 1 line
2.17.1
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Mika,
Quoted 24 lines · Mika Westerberg
Hi Gil,
Quoted 21 lines · Gil Fine
Here we configure TMU mode to HiFi uni-directional once DP tunnel is created. This is due to accuracy requirement for DP tunneling as appears in CM guide 1.0, section 7.3.2.
Due to Intel hardware limitation, once we changed the TMU mode to HiFi uni-directional (when DP tunnel exists), we don't change TMU mode back to normal uni-directional, even if DP tunnel is torn down later.Signed-off-by Gil Fine <[email protected]>--- drivers/thunderbolt/tb.c | 28 ++++++++++++++++++++++++++++ drivers/thunderbolt/tb.h | 5 +++++ drivers/thunderbolt/tmu.c | 14 ++++++++++++++ 3 files changed, 47 insertions(+)drivers/thunderbolt/tb.c +0
-0@@ -50,6 +50,8 @@ struct tb_hotplug_event { };
Quoted 6 lines
drivers/thunderbolt/tb.c struct tb_hotplug_event { · line 54
Quoted 3 lines
drivers/thunderbolt/tb.c +2
-0static void tb_handle_hotplug (struct work_struct *work); +static void tb_enable_tmu_1st_child (struct tb *tb, +enum tb_switch_tmu_rate rate);This forward declaration is not needed. You can just move the implementation before you call it first time.
Sure, right.
Quoted 58 lines
Quoted 58 lines
drivers/thunderbolt/tb.c +26
-0static void tb_queue_hotplug (struct tb *tb,u64 route,u8 port,bool unplug) {@@ -118,6 +120,13 @@ static void tb_switch_discover_tunnels(struct tb_switch *sw,switch (port->config.type) {case TB_TYPE_DP_HDMI_IN : tunnel =tb_tunnel_discover_dp (tb, port, alloc_hopids); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +if (tunnel) +tb_enable_tmu_1st_child (tb, +TB_SWITCH_TMU_RATE_HIFI );break ;case TB_TYPE_PCIE_DOWN :@@ -235,6 +244,19 @@ static int tb_enable_tmu(struct tb_switch *sw)return tb_switch_tmu_enable (sw); } +/* +* Once a DP tunnel exists in the domain, we set the TMU mode so that +* it meets the accuracy requirements and also enables CLx entry (CL0s). +* We set the TMU mode of the first depth router(s) for CL0s to work. +*/ +static void tb_enable_tmu_1st_child (struct tb *tb,enum tb_switch_tmu_rate rate) +{ +struct tb_sw_tmu_config tmu = { .rate = rate }; + +device_for_each_child (&tb->root_switch->dev, &tmu, + tb_switch_tmu_config_enable); +} +/** * tb_find_unused_port() - return the first inactive port on @sw * @sw: Switch to find the port on @@ -985,6 +1007,12 @@ static void tb_tunnel_dp(struct tb *tb)list_add_tail (&tunnel->list, &tcm->tunnel_list);tb_reclaim_usb3_bandwidth (tb, in, out); +/* +* In case of DP tunnel exists, change TMU mode to +* HiFi for CL0s to work. +*/ +tb_enable_tmu_1st_child (tb,TB_SWITCH_TMU_RATE_HIFI ); +return ; err_free:drivers/thunderbolt/tb.h +0
-0@@ -110,6 +110,10 @@ struct tb_switch_tmu {enum tb_switch_tmu_rate rate_request; };
Quoted 5 lines
drivers/thunderbolt/tb.h struct tb_switch_tmu { · line 115
Quoted 3 lines
drivers/thunderbolt/tb.h +3
-0+struct tb_sw_tmu_config { +enum tb_switch_tmu_rate rate; +};Is this wrapper structure really needed?
Right, will fix
Quoted 14 lines
Quoted 14 lines
drivers/thunderbolt/tb.h +2
-0+enum tb_clx {TB_CLX_DISABLE ,/* CL0s and CL1 are enabled and supported together */ @@ -934,6 +938,7 @@ int tb_switch_tmu_enable(struct tb_switch *sw);void tb_switch_tmu_configure (struct tb_switch *sw,enum tb_switch_tmu_rate rate,bool unidirectional); +int tb_switch_tmu_config_enable (struct device *dev,void *data);/** * tb_switch_tmu_is_enabled() - Checks if the specified TMU mode is enabled * @sw: Router whose TMU mode to check drivers/thunderbolt/tmu.c +0
-0
Quoted 8 lines
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 728
Quoted 6 lines
index
e822ab90338b..b8ff9f64a71e100644drivers/thunderbolt/tmu.c +0
-0@@ -727,6 +727,20 @@ int tb_switch_tmu_enable(struct tb_switch *sw)return tb_switch_tmu_set_time_disruption (sw, false); }You are missing kernel-doc for the non-static function.
Right, will add
Quoted 6 lines
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 730
Quoted 3 lines
drivers/thunderbolt/tmu.c +1
-0+int tb_switch_tmu_config_enable (struct device *dev,void *data)Also can we please make it take some real type and not something arbitrary?
You mean the names, right?
Something like:
int tb_switch_tmu_config_enable(struct device *parent, void *rate) If so, yes, I will
Quoted 2 lines
Can it be const too?
IIUC, it shall be a function pointer with specified signature otherwise it will fail at compilation
Quoted 12 lines
drivers/thunderbolt/tmu.c int tb_switch_tmu_enable(struct tb_switch *sw) · line 738
Quoted 9 lines
drivers/thunderbolt/tmu.c +8
-0+{ +if (tb_is_switch (dev)) { +struct tb_switch *sw =tb_to_switch (dev); +struct tb_sw_tmu_config *tmu = data; + +tb_switch_tmu_configure (sw, tmu->rate,tb_switch_is_clx_enabled (sw,TB_CL1 )); +if (tb_switch_tmu_enable (sw)) +tb_sw_dbg (sw,"Fail switching TMU to HiFi for 1st depth router\n" );Be consistent with the messaging so don't start with capital letter here.
OK
Quoted 11 lines
Quoted 11 lines
drivers/thunderbolt/tmu.c +5
-0+ } + +return 0 ; +} +/** * tb_switch_tmu_configure() - Configure the TMU rate and directionality * @sw: Router whose mode to change Signature · 1 line
2.17.1
Signature · 9 lines
Thanks, Gil --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Gil,
Quoted 8 lines · Gil Fine
Quoted 4 lines
Quoted 1 line
+int
tb_switch_tmu_config_enable(struct device *dev, void *data)Also can we please make it take some real type and not something arbitrary?
You mean the names, right?
Something like:
inttb_switch_tmu_config_enable(struct device *parent, void *rate)If so, yes, I will
I mean use a real type, not void *.
Quoted 4 lines
Quoted 2 lines
Can it be const too?
IIUC, it shall be a function pointer with specified signature otherwise it will fail at compilation
Okay then I suggest to make a reasonable "API" function that handles all this internally that does not take arbitrary pointers. Remember to document it in kernel-doc too.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Mika,
Quoted 15 lines · Mika Westerberg
Hi Gil,
Quoted 8 lines · Gil Fine
Quoted 4 lines
Quoted 1 line
+int
tb_switch_tmu_config_enable(struct device *dev, void *data)Also can we please make it take some real type and not something arbitrary?
You mean the names, right?
Something like:
inttb_switch_tmu_config_enable(struct device *parent, void *rate)If so, yes, I willI mean use a real type, not void *.
Quoted 1 line
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Can it be const too?
IIUC, it shall be a function pointer with specified signature otherwise it will fail at compilation
Okay then I suggest to make a reasonable "API" function that handles all this internally that does not take arbitrary pointers. Remember to document it in kernel-doc too.
This is a function pointer that shall be passed to device_for_each_child() And it has to be defined as:
int (*fn)(struct device *dev, void *data)
Similar as here e.g.:
static int remove_retimer(struct device *dev, void *data) {
»·······struct tb_retimer *rt = tb_to_retimer(dev); »·······struct tb_port *port = data;
»·······if (rt && rt->port == port)
»·······»·······tb_retimer_remove(rt);
»·······return 0;
}
void tb_retimer_remove_all(struct tb_port *port)
{
»·······struct usb4_port *usb4;
»·······usb4 = port->usb4;
»·······if (usb4) »·······»·······device_for_each_child_reverse(&usb4->dev, port,
»·······»·······»·······»·······»······· remove_retimer);
}
So not sure I get you...
Signature · 9 lines
Thanks, Gil --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Quoted 47 lines · Gil Fine
Hi Mika,
Quoted 15 lines · Mika Westerberg
Hi Gil,
Quoted 8 lines · Gil Fine
Quoted 4 lines
Quoted 1 line
+int
tb_switch_tmu_config_enable(struct device *dev, void *data)Also can we please make it take some real type and not something arbitrary?
You mean the names, right?
Something like:
inttb_switch_tmu_config_enable(struct device *parent, void *rate)If so, yes, I willI mean use a real type, not void *.
Quoted 1 line
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Can it be const too?
IIUC, it shall be a function pointer with specified signature otherwise it will fail at compilation
Okay then I suggest to make a reasonable "API" function that handles all this internally that does not take arbitrary pointers. Remember to document it in kernel-doc too.
This is a function pointer that shall be passed to
device_for_each_child()And it has to be defined as:int (*fn)(struct device *dev, void *data)
Similar as here e.g.:
static int
remove_retimer(struct device *dev, void *data){
»·······structtb_retimer*rt =tb_to_retimer(dev); »·······structtb_port*port = data;»·······if (rt &&
rt->port== port)
»·······»·······tb_retimer_remove(rt);
»·······return 0;
}void
tb_retimer_remove_all(struct tb_port *port)
{
»·······structusb4_port*usb4;
Quoted 7 lines
»·······usb4 =
port->usb4;
»·······if (usb4) »·······»·······device_for_each_child_reverse(&usb4->dev, port,
»·······»·······»·······»·······»·······remove_retimer);
}So not sure I get you...
The difference is that above it is static function not exposed outside of that file and used directly below its implementation.
In your case you make it non-static "API" function exported from tmu.c and called from tb.c.
So instead I suggest to put the device_for_each_child() in tmu.c and then the tb_switch_tmu_config_enable() static right above it. Please also name the resulting API function consistently.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Mika,
Quoted 59 lines · Mika Westerberg
Quoted 47 lines · Gil Fine
Hi Mika,
Quoted 15 lines · Mika Westerberg
Hi Gil,
Quoted 8 lines · Gil Fine
Quoted 4 lines
Quoted 1 line
+int
tb_switch_tmu_config_enable(struct device *dev, void *data)Also can we please make it take some real type and not something arbitrary?
You mean the names, right?
Something like:
inttb_switch_tmu_config_enable(struct device *parent, void *rate)If so, yes, I willI mean use a real type, not void *.
Quoted 1 line
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Can it be const too?
IIUC, it shall be a function pointer with specified signature otherwise it will fail at compilation
Okay then I suggest to make a reasonable "API" function that handles all this internally that does not take arbitrary pointers. Remember to document it in kernel-doc too.
This is a function pointer that shall be passed to
device_for_each_child()And it has to be defined as:int (*fn)(struct device *dev, void *data)
Similar as here e.g.:
static int
remove_retimer(struct device *dev, void *data){
»·······structtb_retimer*rt =tb_to_retimer(dev); »·······structtb_port*port = data;»·······if (rt &&
rt->port== port)
»·······»·······tb_retimer_remove(rt);
»·······return 0;
}void
tb_retimer_remove_all(struct tb_port *port)
{
»·······structusb4_port*usb4;Quoted 7 lines
»·······usb4 =
port->usb4;
»·······if (usb4) »·······»·······device_for_each_child_reverse(&usb4->dev, port,
»·······»·······»·······»·······»·······remove_retimer);
}So not sure I get you...
The difference is that above it is static function not exposed outside of that file and used directly below its implementation.
Quoted 6 lines
In your case you make it non-static "API" function exported from
tmu.cand called fromtb.c.So instead I suggest to put the
device_for_each_child()intmu.cand then thetb_switch_tmu_config_enable()static right above it. Please also name the resulting API function consistently.
OK, got you and fixed that.
Please let me know when you think that I can send out the v4 series.
Signature · 9 lines
Thanks, Gil --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Hi Gil,
Quoted 6 lines · Gil Fine
Quoted 3 lines
So instead I suggest to put the
device_for_each_child()intmu.cand then thetb_switch_tmu_config_enable()static right above it. Please also name the resulting API function consistently.OK, got you and fixed that.
Please let me know when you think that I can send out the v4 series.
You can send it whenever you want but I think it can go to v5.20 and not v5.19 since I was planning to send out my pull request for Greg tomorrow. I can pick it up after v5.19-rc1 is released.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Quoted 7 lines · Mika Westerberg
Hi Gil,
Quoted 4 lines · Gil Fine
Quoted 3 lines
So instead I suggest to put the
device_for_each_child()intmu.cand then thetb_switch_tmu_config_enable()static right above it. Please also name the resulting API function consistently.
Quoted 6 lines
Quoted 2 lines
OK, got you and fixed that.
Please let me know when you think that I can send out the v4 series.You can send it whenever you want but I think it can go to v5.20 and not v5.19 since I was planning to send out my pull request for Greg tomorrow. I can pick it up after v5.19-rc1 is released.
Ohh I see, I was hoping to meet v5.19
Can't you send it also as part of your your pull request tomorrow? Or it is not mature enough yet...?
Signature · 9 lines
Thanks, Gil --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Greg KH
maintainerRe: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
Quoted 5 lines · Gil Fine
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies.
Now deleted. This footer is not compatible with kernel development, sorry.
Re: [PATCH v3 6/6] thunderbolt: Change TMU mode to HiFi uni-directional once DisplayPort tunneled
In reply to Gil FineQuoted 11 lines · Gil Fine
Quoted 10 lines · Mika Westerberg
Hi Gil,
Quoted 6 lines · Gil Fine
Quoted 3 lines
So instead I suggest to put the
device_for_each_child()intmu.cand then thetb_switch_tmu_config_enable()static right above it. Please also name the resulting API function consistently.OK, got you and fixed that.
Please let me know when you think that I can send out the v4 series.
Quoted 7 lines
Quoted 3 lines
You can send it whenever you want but I think it can go to v5.20 and not v5.19 since I was planning to send out my pull request for Greg tomorrow. I can pick it up after v5.19-rc1 is released.
Ohh I see, I was hoping to meet v5.19
Can't you send it also as part of your your pull request tomorrow? Or it is not mature enough yet...?
Well typically it is expected that patches have been sitting in linux-next for a while before going to the upstream maintainer (Greg in this case). This is to ensure they get at least some attention from the various build robots and also people running linux-next on their hardware.