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

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
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -324,15 +324,10 @@ struct device_type tb_retimer_type = {

static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
{
	struct usb4_port *usb4;
	struct tb_retimer *rt;
	u32 vendor, device;
	int ret;

	usb4 = port->usb4;
	if (!usb4)
		return -EINVAL;

	ret = usb4_port_retimer_read(port, index, USB4_SB_VENDOR_ID, &vendor,
				     sizeof(vendor));
	if (ret) {
@@ -374,7 +369,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status)
	rt->port = port;
	rt->tb = port->sw->tb;

	rt->dev.parent = &usb4->dev;
	rt->dev.parent = &port->usb4->dev;
	rt->dev.bus = &tb_bus_type;
	rt->dev.type = &tb_retimer_type;
	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)
{
	u32 status[TB_MAX_RETIMER_INDEX + 1] = {};
	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
@@ -460,7 +462,7 @@ int tb_retimer_scan(struct tb_port *port, bool add)
	 */
	ret = usb4_port_enumerate_retimers(port);
	if (ret)
		return ret;
		goto out;

	/*
	 * Enable sideband channel for each retimer. We can do this
@@ -490,8 +492,10 @@ int tb_retimer_scan(struct tb_port *port, bool add)
			break;
	}

	if (!last_idx)
		return 0;
	if (!last_idx) {
		ret = 0;
		goto out;
	}

	/* Add on-board retimers if they do not exist already */
	for (i = 1; i <= last_idx; i++) {
@@ -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)