mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-01 10:43:43 +00:00
thunderbolt: Enable CL2 low power state
For USB4 v2 routers we can also enable CL2 which allows better power savings and thermal management than CL0s and CL1. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
This commit is contained in:
parent
d49b4f043d
commit
fd4d58d1fe
@ -17,17 +17,22 @@ MODULE_PARM_DESC(clx, "allow low power states on the high-speed lanes (default:
|
||||
|
||||
static const char *clx_name(unsigned int clx)
|
||||
{
|
||||
if (!clx)
|
||||
return "disabled";
|
||||
|
||||
if (clx & TB_CL2)
|
||||
switch (clx) {
|
||||
case TB_CL0S | TB_CL1 | TB_CL2:
|
||||
return "CL0s/CL1/CL2";
|
||||
if (clx & TB_CL1)
|
||||
case TB_CL1 | TB_CL2:
|
||||
return "CL1/CL2";
|
||||
case TB_CL0S | TB_CL2:
|
||||
return "CL0s/CL2";
|
||||
case TB_CL0S | TB_CL1:
|
||||
return "CL0s/CL1";
|
||||
if (clx & TB_CL0S)
|
||||
case TB_CL0S:
|
||||
return "CL0s";
|
||||
|
||||
return "unknown";
|
||||
case 0:
|
||||
return "disabled";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int tb_port_pm_secondary_set(struct tb_port *port, bool secondary)
|
||||
@ -104,6 +109,8 @@ static int tb_port_clx_set(struct tb_port *port, unsigned int clx, bool enable)
|
||||
mask |= LANE_ADP_CS_1_CL0S_ENABLE;
|
||||
if (clx & TB_CL1)
|
||||
mask |= LANE_ADP_CS_1_CL1_ENABLE;
|
||||
if (clx & TB_CL2)
|
||||
mask |= LANE_ADP_CS_1_CL2_ENABLE;
|
||||
|
||||
if (!mask)
|
||||
return -EOPNOTSUPP;
|
||||
@ -291,8 +298,6 @@ bool tb_switch_clx_is_supported(const struct tb_switch *sw)
|
||||
static bool validate_mask(unsigned int clx)
|
||||
{
|
||||
/* Previous states need to be enabled */
|
||||
if (clx & TB_CL2)
|
||||
return (clx & (TB_CL0S | TB_CL1)) == (TB_CL0S | TB_CL1);
|
||||
if (clx & TB_CL1)
|
||||
return (clx & TB_CL0S) == TB_CL0S;
|
||||
return true;
|
||||
@ -331,8 +336,10 @@ int tb_switch_clx_enable(struct tb_switch *sw, unsigned int clx)
|
||||
!tb_switch_clx_is_supported(sw))
|
||||
return 0;
|
||||
|
||||
/* CL2 is not yet supported */
|
||||
if (clx & TB_CL2)
|
||||
/* Only support CL2 for v2 routers */
|
||||
if ((clx & TB_CL2) &&
|
||||
(usb4_switch_version(parent_sw) < 2 ||
|
||||
usb4_switch_version(sw) < 2))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ret = tb_switch_pm_secondary_resolve(sw);
|
||||
|
@ -244,6 +244,7 @@ static void tb_discover_dp_resources(struct tb *tb)
|
||||
static int tb_enable_clx(struct tb_switch *sw)
|
||||
{
|
||||
struct tb_cm *tcm = tb_priv(sw->tb);
|
||||
unsigned int clx = TB_CL0S | TB_CL1;
|
||||
const struct tb_tunnel *tunnel;
|
||||
int ret;
|
||||
|
||||
@ -275,10 +276,12 @@ static int tb_enable_clx(struct tb_switch *sw)
|
||||
}
|
||||
|
||||
/*
|
||||
* CL0s and CL1 are enabled and supported together.
|
||||
* Silently ignore CLx enabling in case CLx is not supported.
|
||||
* Initially try with CL2. If that's not supported by the
|
||||
* topology try with CL0s and CL1 and then give up.
|
||||
*/
|
||||
ret = tb_switch_clx_enable(sw, TB_CL0S | TB_CL1);
|
||||
ret = tb_switch_clx_enable(sw, clx | TB_CL2);
|
||||
if (ret == -EOPNOTSUPP)
|
||||
ret = tb_switch_clx_enable(sw, clx);
|
||||
return ret == -EOPNOTSUPP ? 0 : ret;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user