From 9ab8436baa8a0822a881555400958b76310e0476 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 30 Dec 2019 16:34:30 +0300 Subject: [PATCH] usb: typec: ucsi: Store the notification mask The driver needs to ignore any Connector Change Events before the Connector Change Indication notifications have actually been enabled. This adds a check to ucsi_connector_change() function to make sure the function does not try to process the event unless the Connector Change notifications have been enabled. It is quite common that the firmware representing the "PPM" (Platform Policy Manager) starts generating Connector Change notifications even when only the Command Completion notifications are enabled. Change-Id: I465c91247e70c34b74ede51bb89b103ed9f083c6 Signed-off-by: Heikki Krogerus Link: https://lore.kernel.org/r/20191230133431.63445-2-heikki.krogerus@linux.intel.com Signed-off-by: Greg Kroah-Hartman Git-commit: 71a1fa0df2a3728b8ccb97394be420d1f03df40e Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git Signed-off-by: Jack Pham --- drivers/usb/typec/ucsi/ucsi.c | 15 ++++++++++----- drivers/usb/typec/ucsi/ucsi.h | 3 +++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 4459bc68aa33..672cb61b737f 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -189,7 +189,7 @@ int ucsi_resume(struct ucsi *ucsi) u64 command; /* Restore UCSI notification enable mask after system resume */ - command = UCSI_SET_NOTIFICATION_ENABLE | UCSI_ENABLE_NTFY_ALL; + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; return ucsi_send_command(ucsi, command, NULL, 0); } @@ -589,6 +589,11 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num) { struct ucsi_connector *con = &ucsi->connector[num - 1]; + if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) { + dev_dbg(ucsi->dev, "Bogus connetor change event\n"); + return; + } + if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags)) schedule_work(&con->work); } @@ -656,7 +661,7 @@ static int ucsi_role_cmd(struct ucsi_connector *con, u64 command) ucsi_reset_ppm(con->ucsi); mutex_unlock(&con->ucsi->ppm_lock); - c = UCSI_SET_NOTIFICATION_ENABLE | UCSI_ENABLE_NTFY_ALL; + c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy; ucsi_send_command(con->ucsi, c, NULL, 0); ucsi_reset_connector(con, true); @@ -890,8 +895,8 @@ int ucsi_init(struct ucsi *ucsi) } /* Enable basic notifications */ - command = UCSI_SET_NOTIFICATION_ENABLE; - command |= UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; + ucsi->ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; ret = ucsi_run_command(ucsi, command, NULL, 0); if (ret < 0) goto err_reset; @@ -923,7 +928,7 @@ int ucsi_init(struct ucsi *ucsi) } /* Enable all notifications */ - command = UCSI_SET_NOTIFICATION_ENABLE | UCSI_ENABLE_NTFY_ALL; + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; ret = ucsi_run_command(ucsi, command, NULL, 0); if (ret < 0) goto err_unregister; diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 831c9470bdc1..cf3f48428bce 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -269,6 +269,9 @@ struct ucsi { /* PPM Communication lock */ struct mutex ppm_lock; + /* The latest "Notification Enable" bits (SET_NOTIFICATION_ENABLE) */ + u64 ntfy; + /* PPM communication flags */ unsigned long flags; #define EVENT_PENDING 0