Commit c281d18d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'thunderbolt-for-v6.9-rc5' of...

Merge tag 'thunderbolt-for-v6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt into usb-linus

Mika writes:

thunderbolt: Fixes for v6.9-rc5

This includes following USB4/Thunderbolt fixes for v6.9-rc5:

  - Avoid creating DisplayPort tunnels for the adapters on the same router
  - Correct wake configurations after device router unplug
  - Fix immediate wake when "wakeup_count" is used to enter system sleep.

All these have been in linux-next with no reported issues.

* tag 'thunderbolt-for-v6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt:
  thunderbolt: Avoid notify PM core about runtime PM resume
  thunderbolt: Fix wake configurations after device unplug
  thunderbolt: Do not create DisplayPort tunnels on adapters of the same router
parents 34b990e9 dcd12aca
Loading
Loading
Loading
Loading
+39 −9
Original line number Diff line number Diff line
@@ -3180,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
{
	struct tb_port *up, *down;

	if (sw->is_unplugged)
		return;
	if (!tb_route(sw) || tb_switch_is_icm(sw))
		return;

	/*
	 * Unconfigure downstream port so that wake-on-connect can be
	 * configured after router unplug. No need to unconfigure upstream port
	 * since its router is unplugged.
	 */
	up = tb_upstream_port(sw);
	if (tb_switch_is_usb4(up->sw))
		usb4_port_unconfigure(up);
	else
		tb_lc_unconfigure_port(up);

	down = up->remote;
	if (tb_switch_is_usb4(down->sw))
		usb4_port_unconfigure(down);
	else
		tb_lc_unconfigure_port(down);

	if (sw->is_unplugged)
		return;

	up = tb_upstream_port(sw);
	if (tb_switch_is_usb4(up->sw))
		usb4_port_unconfigure(up);
	else
		tb_lc_unconfigure_port(up);
}

static void tb_switch_credits_init(struct tb_switch *sw)
@@ -3441,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
	return tb_lc_set_wake(sw, flags);
}

int tb_switch_resume(struct tb_switch *sw)
static void tb_switch_check_wakes(struct tb_switch *sw)
{
	if (device_may_wakeup(&sw->dev)) {
		if (tb_switch_is_usb4(sw))
			usb4_switch_check_wakes(sw);
	}
}

/**
 * tb_switch_resume() - Resume a switch after sleep
 * @sw: Switch to resume
 * @runtime: Is this resume from runtime suspend or system sleep
 *
 * Resumes and re-enumerates router (and all its children), if still plugged
 * after suspend. Don't enumerate device router whose UID was changed during
 * suspend. If this is resume from system sleep, notifies PM core about the
 * wakes occurred during suspend. Disables all wakes, except USB4 wake of
 * upstream port for USB4 routers that shall be always enabled.
 */
int tb_switch_resume(struct tb_switch *sw, bool runtime)
{
	struct tb_port *port;
	int err;
@@ -3490,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw)
	if (err)
		return err;

	if (!runtime)
		tb_switch_check_wakes(sw);

	/* Disable wakes */
	tb_switch_set_wake(sw, 0);

@@ -3519,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw)
			 */
			if (tb_port_unlock(port))
				tb_port_warn(port, "failed to unlock port\n");
			if (port->remote && tb_switch_resume(port->remote->sw)) {
			if (port->remote &&
			    tb_switch_resume(port->remote->sw, runtime)) {
				tb_port_warn(port,
					     "lost during suspend, disconnecting\n");
				tb_sw_set_unplugged(port->remote->sw);
+8 −2
Original line number Diff line number Diff line
@@ -1801,6 +1801,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
			continue;
		}

		/* Needs to be on different routers */
		if (in->sw == port->sw) {
			tb_port_dbg(port, "skipping DP OUT on same router\n");
			continue;
		}

		tb_port_dbg(port, "DP OUT available\n");

		/*
@@ -2936,7 +2942,7 @@ static int tb_resume_noirq(struct tb *tb)
	if (!tb_switch_is_usb4(tb->root_switch))
		tb_switch_reset(tb->root_switch);

	tb_switch_resume(tb->root_switch);
	tb_switch_resume(tb->root_switch, false);
	tb_free_invalid_tunnels(tb);
	tb_free_unplugged_children(tb->root_switch);
	tb_restore_children(tb->root_switch);
@@ -3062,7 +3068,7 @@ static int tb_runtime_resume(struct tb *tb)
	struct tb_tunnel *tunnel, *n;

	mutex_lock(&tb->lock);
	tb_switch_resume(tb->root_switch);
	tb_switch_resume(tb->root_switch, true);
	tb_free_invalid_tunnels(tb);
	tb_restore_children(tb->root_switch);
	list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
+2 −1
Original line number Diff line number Diff line
@@ -827,7 +827,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
int tb_switch_add(struct tb_switch *sw);
void tb_switch_remove(struct tb_switch *sw);
void tb_switch_suspend(struct tb_switch *sw, bool runtime);
int tb_switch_resume(struct tb_switch *sw);
int tb_switch_resume(struct tb_switch *sw, bool runtime);
int tb_switch_reset(struct tb_switch *sw);
int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
			   u32 value, int timeout_msec);
@@ -1288,6 +1288,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
	return usb4_switch_version(sw) > 0;
}

void usb4_switch_check_wakes(struct tb_switch *sw);
int usb4_switch_setup(struct tb_switch *sw);
int usb4_switch_configuration_valid(struct tb_switch *sw);
int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
+7 −6
Original line number Diff line number Diff line
@@ -155,7 +155,13 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
				tx_dwords, rx_data, rx_dwords);
}

static void usb4_switch_check_wakes(struct tb_switch *sw)
/**
 * usb4_switch_check_wakes() - Check for wakes and notify PM core about them
 * @sw: Router whose wakes to check
 *
 * Checks wakes occurred during suspend and notify the PM core about them.
 */
void usb4_switch_check_wakes(struct tb_switch *sw)
{
	bool wakeup_usb4 = false;
	struct usb4_port *usb4;
@@ -163,9 +169,6 @@ static void usb4_switch_check_wakes(struct tb_switch *sw)
	bool wakeup = false;
	u32 val;

	if (!device_may_wakeup(&sw->dev))
		return;

	if (tb_route(sw)) {
		if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
			return;
@@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
	u32 val = 0;
	int ret;

	usb4_switch_check_wakes(sw);

	if (!tb_route(sw))
		return 0;