Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: ad74b8649bea ("usb: typec: ucsi: Preliminary support for alternate modes")
Cc: stable@vger.kernel.org
Reported-and-tested-by: Jia-Ju Bai <baijiaju1990@gmail.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20220405134824.68067-3-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
eb5d7ff3 e25adcca

+13 -7
+13 -7
drivers/usb/typec/ucsi/ucsi.c
··· 958 958 if (ret < 0) 959 959 goto out_unlock; 960 960 961 + mutex_unlock(&con->lock); 962 + 961 963 if (!wait_for_completion_timeout(&con->complete, 962 - msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) 963 - ret = -ETIMEDOUT; 964 + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) 965 + return -ETIMEDOUT; 966 + 967 + return 0; 964 968 965 969 out_unlock: 966 970 mutex_unlock(&con->lock); 967 971 968 - return ret < 0 ? ret : 0; 972 + return ret; 969 973 } 970 974 971 975 static int ucsi_pr_swap(struct typec_port *port, enum typec_role role) ··· 1000 996 if (ret < 0) 1001 997 goto out_unlock; 1002 998 999 + mutex_unlock(&con->lock); 1000 + 1003 1001 if (!wait_for_completion_timeout(&con->complete, 1004 - msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) { 1005 - ret = -ETIMEDOUT; 1006 - goto out_unlock; 1007 - } 1002 + msecs_to_jiffies(UCSI_SWAP_TIMEOUT_MS))) 1003 + return -ETIMEDOUT; 1004 + 1005 + mutex_lock(&con->lock); 1008 1006 1009 1007 /* Something has gone wrong while swapping the role */ 1010 1008 if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=