usb: typec: ucsi: Resume in separate work
commitpull/1175/heade0dced9c7dupstream. It can take more than one second to check each connector when the system is resumed. So if you have, say, eight connectors, it may take eight seconds for ucsi_resume() to finish. That's a bit too much. This will modify ucsi_resume() so that it schedules a work where the interface is actually resumed instead of checking the connectors directly. The connections will also be checked in separate tasks which are queued for each connector separately. Link: https://bugzilla.kernel.org/show_bug.cgi?id=216706 Fixes:99f6d43611("usb: typec: ucsi: Check the connection on resume") Cc: <stable@vger.kernel.org> Reported-by: Todd Brandt <todd.e.brandt@intel.com> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20221123093021.25981-1-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
parent
c383c7c35c
commit
9222912924
|
|
@ -1270,8 +1270,9 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int ucsi_resume(struct ucsi *ucsi)
|
||||
static void ucsi_resume_work(struct work_struct *work)
|
||||
{
|
||||
struct ucsi *ucsi = container_of(work, struct ucsi, resume_work);
|
||||
struct ucsi_connector *con;
|
||||
u64 command;
|
||||
int ret;
|
||||
|
|
@ -1279,15 +1280,21 @@ int ucsi_resume(struct ucsi *ucsi)
|
|||
/* 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;
|
||||
if (ret < 0) {
|
||||
dev_err(ucsi->dev, "failed to re-enable notifications (%d)\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
for (con = ucsi->connector; con->port; con++) {
|
||||
mutex_lock(&con->lock);
|
||||
ucsi_check_connection(con);
|
||||
ucsi_partner_task(con, ucsi_check_connection, 1, 0);
|
||||
mutex_unlock(&con->lock);
|
||||
}
|
||||
}
|
||||
|
||||
int ucsi_resume(struct ucsi *ucsi)
|
||||
{
|
||||
queue_work(system_long_wq, &ucsi->resume_work);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ucsi_resume);
|
||||
|
|
@ -1347,6 +1354,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops)
|
|||
if (!ucsi)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
INIT_WORK(&ucsi->resume_work, ucsi_resume_work);
|
||||
INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work);
|
||||
mutex_init(&ucsi->ppm_lock);
|
||||
ucsi->dev = dev;
|
||||
|
|
@ -1401,6 +1409,7 @@ void ucsi_unregister(struct ucsi *ucsi)
|
|||
|
||||
/* Make sure that we are not in the middle of driver initialization */
|
||||
cancel_delayed_work_sync(&ucsi->work);
|
||||
cancel_work_sync(&ucsi->resume_work);
|
||||
|
||||
/* Disable notifications */
|
||||
ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ struct ucsi {
|
|||
struct ucsi_capability cap;
|
||||
struct ucsi_connector *connector;
|
||||
|
||||
struct work_struct resume_work;
|
||||
struct delayed_work work;
|
||||
int work_count;
|
||||
#define UCSI_ROLE_SWITCH_RETRY_PER_HZ 10
|
||||
|
|
|
|||
Loading…
Reference in New Issue