Message ID | 5qc55gruhn4pmutiukohauki5dehba6n2k22jgvpt7i3hafkon@v2ng2a33o7vv (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [RFC] usb: typec: ucsi_acpi: Add LG Gram quirk | expand |
On Thu, May 09, 2024 at 12:50:36PM GMT, Diogo Ivo wrote: > Some LG Gram laptops report a bogus connector change event after a > GET_PDOS command for the partner's source PDOs, which disappears from > the CCI after acknowledging the command. However, the subsequent > GET_CONNECTOR_STATUS in ucsi_handle_connector_change() still reports > this bogus change in bits 5 and 6, leading to the UCSI core re-checking > the partner's source PDOs and thus to an infinite loop. > > Fix this by adding a quirk that signals when a potentially buggy GET_PDOS > command is used, checks the status change report and clears it if it is a > bogus event before sending it to the UCSI core. > > [Sending as RFC both to see if this is a good idea and so that more > users can test it to gather all the models affected by this bug.] > > Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt> > --- I just realized that I should be using the {set, test, clear}_bit() functions in the patch I sent, sorry for that. With this in mind it would still be good to hear what you think about it. Best regards, Diogo
On Thu, May 09, 2024 at 04:27:41PM +0100, Diogo Ivo wrote: > On Thu, May 09, 2024 at 12:50:36PM GMT, Diogo Ivo wrote: > > Some LG Gram laptops report a bogus connector change event after a > > GET_PDOS command for the partner's source PDOs, which disappears from > > the CCI after acknowledging the command. However, the subsequent > > GET_CONNECTOR_STATUS in ucsi_handle_connector_change() still reports > > this bogus change in bits 5 and 6, leading to the UCSI core re-checking > > the partner's source PDOs and thus to an infinite loop. > > > > Fix this by adding a quirk that signals when a potentially buggy GET_PDOS > > command is used, checks the status change report and clears it if it is a > > bogus event before sending it to the UCSI core. > > > > [Sending as RFC both to see if this is a good idea and so that more > > users can test it to gather all the models affected by this bug.] > > > > Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt> > > --- > > I just realized that I should be using the {set, test, clear}_bit() > functions in the patch I sent, sorry for that. With this in mind it > would still be good to hear what you think about it. The quirk looks reasonable to me. thanks,
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 8d112c3edae5..c67607f68b44 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -25,6 +25,7 @@ struct ucsi_acpi { unsigned long flags; #define UCSI_ACPI_COMMAND_PENDING 1 #define UCSI_ACPI_ACK_PENDING 2 +#define UCSI_ACPI_CHECK_BOGUS_EVENT 4 guid_t guid; u64 cmd; }; @@ -128,6 +129,58 @@ static const struct ucsi_operations ucsi_zenbook_ops = { .async_write = ucsi_acpi_async_write }; +static int ucsi_gram_read(struct ucsi *ucsi, unsigned int offset, + void *val, size_t val_len) +{ + u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE | + UCSI_CONSTAT_PDOS_CHANGE; + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + struct ucsi_connector_status *status; + int ret; + + ret = ucsi_acpi_read(ucsi, offset, val, val_len); + if (ret < 0) + return ret; + + if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS && + ua->flags & UCSI_ACPI_CHECK_BOGUS_EVENT && + offset == UCSI_MESSAGE_IN) { + status = (struct ucsi_connector_status *)val; + + /* Clear the bogus change */ + if (status->change == bogus_change) + status->change = 0; + + ua->flags &= ~UCSI_ACPI_CHECK_BOGUS_EVENT; + } + + return ret; +} + +static int ucsi_gram_sync_write(struct ucsi *ucsi, unsigned int offset, + const void *val, size_t val_len) +{ + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); + int ret; + + ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); + if (ret < 0) + return ret; + + if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS && + ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) && + ua->cmd & UCSI_GET_PDOS_SRC_PDOS) + ua->flags |= UCSI_ACPI_CHECK_BOGUS_EVENT; + + return ret; +} + +static const struct ucsi_operations ucsi_gram_ops = { + .read = ucsi_gram_read, + .sync_write = ucsi_gram_sync_write, + .async_write = ucsi_acpi_async_write +}; + static const struct dmi_system_id ucsi_acpi_quirks[] = { { .matches = { @@ -136,6 +189,13 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { }, .driver_data = (void *)&ucsi_zenbook_ops, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_PRODUCT_NAME, "Z90Q"), + }, + .driver_data = (void *)&ucsi_gram_ops, + }, { } };
Some LG Gram laptops report a bogus connector change event after a GET_PDOS command for the partner's source PDOs, which disappears from the CCI after acknowledging the command. However, the subsequent GET_CONNECTOR_STATUS in ucsi_handle_connector_change() still reports this bogus change in bits 5 and 6, leading to the UCSI core re-checking the partner's source PDOs and thus to an infinite loop. Fix this by adding a quirk that signals when a potentially buggy GET_PDOS command is used, checks the status change report and clears it if it is a bogus event before sending it to the UCSI core. [Sending as RFC both to see if this is a good idea and so that more users can test it to gather all the models affected by this bug.] Signed-off-by: Diogo Ivo <diogo.ivo@tecnico.ulisboa.pt> --- drivers/usb/typec/ucsi/ucsi_acpi.c | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)