Skip to content

Commit

Permalink
usb: typec: ucsi: Check the connection on resume
Browse files Browse the repository at this point in the history
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: <stable@vger.kernel.org>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20221007100951.43798-2-heikki.krogerus@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Heikki Krogerus authored and Greg Kroah-Hartman committed Oct 22, 2022
1 parent 48ed324 commit 99f6d43
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions drivers/usb/typec/ucsi/ucsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,6 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command,
}
EXPORT_SYMBOL_GPL(ucsi_send_command);

int ucsi_resume(struct ucsi *ucsi)
{
u64 command;

/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;

return ucsi_send_command(ucsi, command, NULL, 0);
}
EXPORT_SYMBOL_GPL(ucsi_resume);
/* -------------------------------------------------------------------------- */

struct ucsi_work {
Expand Down Expand Up @@ -744,6 +734,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)

static int ucsi_check_connection(struct ucsi_connector *con)
{
u8 prev_flags = con->status.flags;
u64 command;
int ret;

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

if (con->status.flags == prev_flags)
return 0;

if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
UCSI_CONSTAT_PWR_OPMODE_PD)
ucsi_partner_task(con, ucsi_check_altmodes, 30, 0);
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_partner_change(con);
} else {
ucsi_partner_change(con);
ucsi_port_psy_changed(con);
Expand Down Expand Up @@ -1276,6 +1270,28 @@ static int ucsi_init(struct ucsi *ucsi)
return ret;
}

int ucsi_resume(struct ucsi *ucsi)
{
struct ucsi_connector *con;
u64 command;
int ret;

/* Restore UCSI notification enable mask after system resume */
command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy;
ret = ucsi_send_command(ucsi, command, NULL, 0);
if (ret < 0)
return ret;

for (con = ucsi->connector; con->port; con++) {
mutex_lock(&con->lock);
ucsi_check_connection(con);
mutex_unlock(&con->lock);
}

return 0;
}
EXPORT_SYMBOL_GPL(ucsi_resume);

static void ucsi_init_work(struct work_struct *work)
{
struct ucsi *ucsi = container_of(work, struct ucsi, work.work);
Expand Down

0 comments on commit 99f6d43

Please sign in to comment.