Commit 1e56c88a authored by Mika Westerberg's avatar Mika Westerberg

thunderbolt: Runtime resume USB4 port when retimers are scanned

Sometimes when plugging in a USB4 device we might see following error:

  thunderbolt 1-0:3.1: runtime PM trying to activate child device 1-0:3.1 but parent (usb4_port3) is not active

This happens because the parent USB4 port was still runtime suspended.
Fix this by runtime resuming the USB4 port before scanning the retimers
below it.
Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 43bddb26
...@@ -324,15 +324,10 @@ struct device_type tb_retimer_type = { ...@@ -324,15 +324,10 @@ struct device_type tb_retimer_type = {
static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
{ {
struct usb4_port *usb4;
struct tb_retimer *rt; struct tb_retimer *rt;
u32 vendor, device; u32 vendor, device;
int ret; int ret;
usb4 = port->usb4;
if (!usb4)
return -EINVAL;
ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor, ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor,
sizeof(vendor)); sizeof(vendor));
if (ret) { if (ret) {
...@@ -374,7 +369,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) ...@@ -374,7 +369,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
rt->port = port; rt->port = port;
rt->tb = port->sw->tb; rt->tb = port->sw->tb;
rt->dev.parent = &usb4->dev; rt->dev.parent = &port->usb4->dev;
rt->dev.bus = &tb_bus_type; rt->dev.bus = &tb_bus_type;
rt->dev.type = &tb_retimer_type; rt->dev.type = &tb_retimer_type;
dev_set_name(&rt->dev, "%s:%u.%u", dev_name(&port->sw->dev), dev_set_name(&rt->dev, "%s:%u.%u", dev_name(&port->sw->dev),
...@@ -453,6 +448,13 @@ int tb_retimer_scan(struct tb_port *port, bool add) ...@@ -453,6 +448,13 @@ int tb_retimer_scan(struct tb_port *port, bool add)
{ {
u32 status[TB_MAX_RETIMER_INDEX + 1] = {}; u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
int ret, i, last_idx = 0; int ret, i, last_idx = 0;
struct usb4_port *usb4;
usb4 = port->usb4;
if (!usb4)
return 0;
pm_runtime_get_sync(&usb4->dev);
/* /*
* Send broadcast RT to make sure retimer indices facing this * Send broadcast RT to make sure retimer indices facing this
...@@ -460,7 +462,7 @@ int tb_retimer_scan(struct tb_port *port, bool add) ...@@ -460,7 +462,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
*/ */
ret = usb4_port_enumerate_retimers(port); ret = usb4_port_enumerate_retimers(port);
if (ret) if (ret)
return ret; goto out;
/* /*
* Enable sideband channel for each retimer. We can do this * Enable sideband channel for each retimer. We can do this
...@@ -490,8 +492,10 @@ int tb_retimer_scan(struct tb_port *port, bool add) ...@@ -490,8 +492,10 @@ int tb_retimer_scan(struct tb_port *port, bool add)
break; break;
} }
if (!last_idx) if (!last_idx) {
return 0; ret = 0;
goto out;
}
/* Add on-board retimers if they do not exist already */ /* Add on-board retimers if they do not exist already */
for (i = 1; i <= last_idx; i++) { for (i = 1; i <= last_idx; i++) {
...@@ -507,7 +511,11 @@ int tb_retimer_scan(struct tb_port *port, bool add) ...@@ -507,7 +511,11 @@ int tb_retimer_scan(struct tb_port *port, bool add)
} }
} }
return 0; out:
pm_runtime_mark_last_busy(&usb4->dev);
pm_runtime_put_autosuspend(&usb4->dev);
return ret;
} }
static int remove_retimer(struct device *dev, void *data) static int remove_retimer(struct device *dev, void *data)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment