Commit eb5d7ff3 authored by Heikki Krogerus's avatar Heikki Krogerus Committed by Greg Kroah-Hartman
Browse files

usb: typec: ucsi: Fix role swapping

All attempts to swap the roles timed out because the
completion was done without releasing the port lock. Fixing
that by releasing the lock before starting to wait for the
completion.

Link: https://lore.kernel.org/linux-usb/037de7ac-e210-bdf5-ec7a-8c0c88a0be20@gmail.com/


Fixes: ad74b864 ("usb: typec: ucsi: Preliminary support for alternate modes")
Cc: stable@vger.kernel.org
Reported-and-tested-by: default avatarJia-Ju Bai <baijiaju1990@gmail.com>
Signed-off-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20220405134824.68067-3-heikki.krogerus@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e25adcca
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -958,14 +958,18 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
	if (ret < 0)
		goto out_unlock;

	mutex_unlock(&con->lock);

	if (!wait_for_completion_timeout(&con->complete,
					 msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
		ret = -ETIMEDOUT;
		return -ETIMEDOUT;

	return 0;

out_unlock:
	mutex_unlock(&con->lock);

	return ret < 0 ? ret : 0;
	return ret;
}

static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
@@ -996,11 +1000,13 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
	if (ret < 0)
		goto out_unlock;

	mutex_unlock(&con->lock);

	if (!wait_for_completion_timeout(&con->complete,
				msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) {
		ret = -ETIMEDOUT;
		goto out_unlock;
	}
					 msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS)))
		return -ETIMEDOUT;

	mutex_lock(&con->lock);

	/* Something has gone wrong while swapping the role */
	if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=