Skip to content

Commit 99f6d43

Browse files
Heikki Krogerusgregkh
authored andcommitted
usb: typec: ucsi: Check the connection on resume
Checking the connection status of every port on resume. This fixes an issue where the partner device is not unregistered properly after resume if it was unplugged while the system was suspended. The function ucsi_check_connection() is also modified so that it can be used also for registering the connection on top of unregistering it. Link: https://bugzilla.kernel.org/show_bug.cgi?id=210425 Fixes: a94ecde ("usb: typec: ucsi: ccg: enable runtime pm support") Cc: <[email protected]> Signed-off-by: Heikki Krogerus <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 48ed324 commit 99f6d43

File tree

1 file changed

+29
-13
lines changed

1 file changed

+29
-13
lines changed

drivers/usb/typec/ucsi/ucsi.c

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -183,16 +183,6 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command,
183183
}
184184
EXPORT_SYMBOL_GPL(ucsi_send_command);
185185

186-
int ucsi_resume(struct ucsi *ucsi)
187-
{
188-
u64 command;
189-
190-
/* Restore UCSI notification enable mask after system resume */
191-
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
192-
193-
return ucsi_send_command(ucsi, command, NULL, 0);
194-
}
195-
EXPORT_SYMBOL_GPL(ucsi_resume);
196186
/* -------------------------------------------------------------------------- */
197187

198188
struct ucsi_work {
@@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
744734

745735
static int ucsi_check_connection(struct ucsi_connector *con)
746736
{
737+
u8 prev_flags = con->status.flags;
747738
u64 command;
748739
int ret;
749740

@@ -754,10 +745,13 @@ static int ucsi_check_connection(struct ucsi_connector *con)
754745
return ret;
755746
}
756747

748+
if (con->status.flags == prev_flags)
749+
return 0;
750+
757751
if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
758-
if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
759-
UCSI_CONSTAT_PWR_OPMODE_PD)
760-
ucsi_partner_task(con, ucsi_check_altmodes, 30, 0);
752+
ucsi_register_partner(con);
753+
ucsi_pwr_opmode_change(con);
754+
ucsi_partner_change(con);
761755
} else {
762756
ucsi_partner_change(con);
763757
ucsi_port_psy_changed(con);
@@ -1276,6 +1270,28 @@ static int ucsi_init(struct ucsi *ucsi)
12761270
return ret;
12771271
}
12781272

1273+
int ucsi_resume(struct ucsi *ucsi)
1274+
{
1275+
struct ucsi_connector *con;
1276+
u64 command;
1277+
int ret;
1278+
1279+
/* Restore UCSI notification enable mask after system resume */
1280+
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
1281+
ret = ucsi_send_command(ucsi, command, NULL, 0);
1282+
if (ret < 0)
1283+
return ret;
1284+
1285+
for (con = ucsi->connector; con->port; con++) {
1286+
mutex_lock(&con->lock);
1287+
ucsi_check_connection(con);
1288+
mutex_unlock(&con->lock);
1289+
}
1290+
1291+
return 0;
1292+
}
1293+
EXPORT_SYMBOL_GPL(ucsi_resume);
1294+
12791295
static void ucsi_init_work(struct work_struct *work)
12801296
{
12811297
struct ucsi *ucsi = container_of(work, struct ucsi, work.work);

0 commit comments

Comments
 (0)