* [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware @ 2026-05-11 17:59 Rong Zhang 2026-05-11 18:25 ` Greg Kroah-Hartman 0 siblings, 1 reply; 7+ messages in thread From: Rong Zhang @ 2026-05-11 17:59 UTC (permalink / raw) To: Heikki Krogerus, Greg Kroah-Hartman Cc: Hans de Goede, linux-usb, platform-driver-x86, linux-kernel, Rong Zhang Some Lenovo devices have broken firmware, which reads/writes half-valid- half-garbage values. While executing UCSI_DSM_FUNC_READ, the firmware repeatedly (> 20 times) calls a helper function, which reads and returns a byte from the EC, and then copies the return value from the helper function into the UCSI buffer. The helper function internally acquires a heavily shared mutex with a timeout. When the timeout is somehow reached, 0x00 will be returned. Unfortunately, the return value is copied into the buffer blindly, leaving a half-valid-half-garbage value in the buffer while the method still succeeds. Similar for UCSI_DSM_FUNC_WRITE, in which some bytes in the UCSI buffer may be silently left unwritten to the EC but the method still succeeds. What's worse, race condition could happen since the mutex only protects a single byte read/write instead of the whole method. All these issues lead to a lot of UCSI errors upon power events, e.g., ucsi_acpi USBC000:00: ucsi_handle_connector_change: GET_CONNECTOR_STATUS failed (-5) ucsi_acpi USBC000:00: ucsi_handle_connector_change: GET_CONNECTOR_STATUS failed (-5) ucsi_acpi USBC000:00: GET_CONNECTOR_STATUS failed (-5) ucsi_acpi USBC000:00: ucsi_handle_connector_change: GET_CONNECTOR_STATUS failed (-110) ucsi_acpi USBC000:00: ucsi_handle_connector_change entered without EVENT_PENDING ucsi_acpi USBC000:00: ucsi_handle_connector_change: GET_CONNECTOR_STATUS failed (-110) Given that everything is broken, disable ucsi_acpi on these devices. The impact of disabling it is minimal, as Lenovo laptops usually have most USCI commands more or less stubbed, and the EC can always handles USB-C events on its own. Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 Signed-off-by: Rong Zhang <i@rong.moe> --- drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 6b92f296e985..7632b441d401 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { { } }; +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { + /* Firmware reads/writes half-valid-half-garbage values. */ + + /* BIOS: P1CN??WW */ + { + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), + }, + }, + { + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), + }, + }, + + /* BIOS: R0CN??WW */ + { + .ident = "Lenovo IdeaPad Slim 5 14AKP10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), + }, + }, + { + .ident = "Lenovo IdeaPad Slim 5 14AKP10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), + }, + }, + { + .ident = "Lenovo IdeaPad Slim 5 16AKP10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), + }, + }, + + /* BIOS: QXCN??WW */ + { + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), + }, + }, + { + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), + }, + }, + + /* BIOS: LNCN??WW */ + { + .ident = "Lenovo Yoga Pro 7 14ARP8", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), + }, + }, + { + .ident = "Lenovo Slim Pro 7 14ARP8", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), + }, + }, + + /* BIOS: PSCN??WW */ + { + .ident = "Lenovo Yoga Pro 7 14ASP9", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), + }, + }, + { } +}; + static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) { struct ucsi_acpi *ua = data; @@ -181,6 +266,12 @@ static int ucsi_acpi_probe(struct platform_device *pdev) if (adev->dep_unmet) return -EPROBE_DEFER; + id = dmi_first_match(ucsi_acpi_broken_devices); + if (id) { + dev_warn(&pdev->dev, "broken UCSI ACPI implementation, disabling"); + return -ENODEV; + } + ua = devm_kzalloc(&pdev->dev, sizeof(*ua), GFP_KERNEL); if (!ua) return -ENOMEM; --- base-commit: 5d6919055dec134de3c40167a490f33c74c12581 change-id: 20260512-ucsi-acpi-broken-devices-c93a15b70600 Thanks, Rong ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-11 17:59 [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware Rong Zhang @ 2026-05-11 18:25 ` Greg Kroah-Hartman 2026-05-11 19:12 ` Rong Zhang 0 siblings, 1 reply; 7+ messages in thread From: Greg Kroah-Hartman @ 2026-05-11 18:25 UTC (permalink / raw) To: Rong Zhang Cc: Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86, linux-kernel On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: > Some Lenovo devices have broken firmware, which reads/writes half-valid- > half-garbage values. How does this work with this firmware on other operating systems? What is the odds of fixing the firmware? > Given that everything is broken, disable ucsi_acpi on these devices. The > impact of disabling it is minimal, as Lenovo laptops usually have most > USCI commands more or less stubbed, and the EC can always handles USB-C > events on its own. > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 > Signed-off-by: Rong Zhang <i@rong.moe> > --- > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 91 insertions(+) > > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c > index 6b92f296e985..7632b441d401 100644 > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { > { } > }; > > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { > + /* Firmware reads/writes half-valid-half-garbage values. */ > + > + /* BIOS: P1CN??WW */ > + { > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), > + }, > + }, > + { > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), > + }, > + }, > + > + /* BIOS: R0CN??WW */ > + { > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), > + }, > + }, > + { > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), > + }, > + }, > + { > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), > + }, > + }, > + > + /* BIOS: QXCN??WW */ > + { > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), > + }, > + }, > + { > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), > + }, > + }, > + > + /* BIOS: LNCN??WW */ > + { > + .ident = "Lenovo Yoga Pro 7 14ARP8", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), > + }, > + }, > + { > + .ident = "Lenovo Slim Pro 7 14ARP8", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), > + }, > + }, > + > + /* BIOS: PSCN??WW */ > + { > + .ident = "Lenovo Yoga Pro 7 14ASP9", > + .matches = { > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), > + }, > + }, > + { } > +}; That is a lot of devices to exclude, are you sure that none of them will ever work properly? thanks, greg k-h ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-11 18:25 ` Greg Kroah-Hartman @ 2026-05-11 19:12 ` Rong Zhang 2026-05-11 23:11 ` Mark Pearson 0 siblings, 1 reply; 7+ messages in thread From: Rong Zhang @ 2026-05-11 19:12 UTC (permalink / raw) To: Greg Kroah-Hartman Cc: Mark Pearson, Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86, linux-kernel (+CC Mark Pearson from Lenovo) Hi Greg, On Mon, 2026-05-11 at 20:25 +0200, Greg Kroah-Hartman wrote: > On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: > > Some Lenovo devices have broken firmware, which reads/writes half-valid- > > half-garbage values. > > How does this work with this firmware on other operating systems? > The timeout can hardly reached unless a bunch of events cause multiple drivers to compete for the same mutex simultaneously. If other operating systems' UCSI drivers don't send any command during power events, they won't suffer from the mutex acquisition timeout. Also, if other drivers on these operating systems don't touch the mutex on power events at all, their UCSI drivers should work well too. These operating systems' UCSI drivers are powered by undefined behavior (TM) in both cases. > What > is the odds of fixing the firmware? They are not Linux-certified devices, so Lenovo is very unlikely to fix the firmware unless it breaks Windows :( Quoting Mark Pearson's reply to the bugzilla thread: I can't promise anything - I don't have any official levers to pull for this platform I'm afraid (it is better to buy Linux supported/certified systems ;) ) https://bugzilla.kernel.org/show_bug.cgi?id=221065#c38 > > > Given that everything is broken, disable ucsi_acpi on these devices. The > > impact of disabling it is minimal, as Lenovo laptops usually have most > > USCI commands more or less stubbed, and the EC can always handles USB-C > > events on its own. > > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 > > Signed-off-by: Rong Zhang <i@rong.moe> > > --- > > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ > > 1 file changed, 91 insertions(+) > > > > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c > > index 6b92f296e985..7632b441d401 100644 > > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c > > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c > > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { > > { } > > }; > > > > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { > > + /* Firmware reads/writes half-valid-half-garbage values. */ > > + > > + /* BIOS: P1CN??WW */ > > + { > > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), > > + }, > > + }, > > + { > > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), > > + }, > > + }, > > + > > + /* BIOS: R0CN??WW */ > > + { > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), > > + }, > > + }, > > + { > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), > > + }, > > + }, > > + { > > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), > > + }, > > + }, > > + > > + /* BIOS: QXCN??WW */ > > + { > > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), > > + }, > > + }, > > + { > > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), > > + }, > > + }, > > + > > + /* BIOS: LNCN??WW */ > > + { > > + .ident = "Lenovo Yoga Pro 7 14ARP8", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), > > + }, > > + }, > > + { > > + .ident = "Lenovo Slim Pro 7 14ARP8", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), > > + }, > > + }, > > + > > + /* BIOS: PSCN??WW */ > > + { > > + .ident = "Lenovo Yoga Pro 7 14ASP9", > > + .matches = { > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), > > + }, > > + }, > > + { } > > +}; > > That is a lot of devices to exclude, are you sure that none of them will > ever work properly? Yes. I carefully checked all acpidumps for these devices provided by device owners who replied to the bugzilla thread, and confirmed that they all share the same UCSI-ACPI implementation. 83DR, 83HN, 83HY, 83AU, 83JR are owned by these device owners. Other devices share the same BIOS images (see comments in the match table), so I added them as well. Device owners also reported their dmesg dumps/snips with ucsi_acpi errors. As a reference, buggy ASL methods are shown as below. \_SB.PCI0.LPC0.EC0: Method (ECRD, 1, Serialized) { Local0 = Acquire (ECMT, 0x03E8) If ((Local0 == Zero)) { If (ECAV) { Local1 = DerefOf (Arg0) Release (ECMT) Return (Local1) } Else { Release (ECMT) } } Return (Zero) } Method (ECWT, 2, Serialized) { Local0 = Acquire (ECMT, 0x03E8) If ((Local0 == Zero)) { If (ECAV) { Arg1 = Arg0 } Release (ECMT) } } \_SB.UBTC: Method (ECWR, 0, Serialized) { IO80 = 0xD0 \_SB.PCI0.LPC0.EC0.ECWT (MGO0, RefOf (\_SB.PCI0.LPC0.EC0.MGO0)) \_SB.PCI0.LPC0.EC0.ECWT (MGO1, RefOf (\_SB.PCI0.LPC0.EC0.MGO1)) \_SB.PCI0.LPC0.EC0.ECWT (MGO2, RefOf (\_SB.PCI0.LPC0.EC0.MGO2)) \_SB.PCI0.LPC0.EC0.ECWT (MGO3, RefOf (\_SB.PCI0.LPC0.EC0.MGO3)) \_SB.PCI0.LPC0.EC0.ECWT (MGO4, RefOf (\_SB.PCI0.LPC0.EC0.MGO4)) \_SB.PCI0.LPC0.EC0.ECWT (MGO5, RefOf (\_SB.PCI0.LPC0.EC0.MGO5)) \_SB.PCI0.LPC0.EC0.ECWT (MGO6, RefOf (\_SB.PCI0.LPC0.EC0.MGO6)) \_SB.PCI0.LPC0.EC0.ECWT (MGO7, RefOf (\_SB.PCI0.LPC0.EC0.MGO7)) \_SB.PCI0.LPC0.EC0.ECWT (MGO8, RefOf (\_SB.PCI0.LPC0.EC0.MGO8)) \_SB.PCI0.LPC0.EC0.ECWT (MGO9, RefOf (\_SB.PCI0.LPC0.EC0.MGO9)) \_SB.PCI0.LPC0.EC0.ECWT (MGOA, RefOf (\_SB.PCI0.LPC0.EC0.MGOA)) \_SB.PCI0.LPC0.EC0.ECWT (MGOB, RefOf (\_SB.PCI0.LPC0.EC0.MGOB)) \_SB.PCI0.LPC0.EC0.ECWT (MGOC, RefOf (\_SB.PCI0.LPC0.EC0.MGOC)) \_SB.PCI0.LPC0.EC0.ECWT (MGOD, RefOf (\_SB.PCI0.LPC0.EC0.MGOD)) \_SB.PCI0.LPC0.EC0.ECWT (MGOE, RefOf (\_SB.PCI0.LPC0.EC0.MGOE)) \_SB.PCI0.LPC0.EC0.ECWT (MGOF, RefOf (\_SB.PCI0.LPC0.EC0.MGOF)) \_SB.PCI0.LPC0.EC0.ECWT (CTL0, RefOf (\_SB.PCI0.LPC0.EC0.CTL0)) \_SB.PCI0.LPC0.EC0.ECWT (CTL1, RefOf (\_SB.PCI0.LPC0.EC0.CTL1)) \_SB.PCI0.LPC0.EC0.ECWT (CTL2, RefOf (\_SB.PCI0.LPC0.EC0.CTL2)) \_SB.PCI0.LPC0.EC0.ECWT (CTL3, RefOf (\_SB.PCI0.LPC0.EC0.CTL3)) \_SB.PCI0.LPC0.EC0.ECWT (CTL4, RefOf (\_SB.PCI0.LPC0.EC0.CTL4)) \_SB.PCI0.LPC0.EC0.ECWT (CTL5, RefOf (\_SB.PCI0.LPC0.EC0.CTL5)) \_SB.PCI0.LPC0.EC0.ECWT (CTL6, RefOf (\_SB.PCI0.LPC0.EC0.CTL6)) \_SB.PCI0.LPC0.EC0.ECWT (CTL7, RefOf (\_SB.PCI0.LPC0.EC0.CTL7)) \_SB.PCI0.LPC0.EC0.ECWT (0xE0, RefOf (\_SB.PCI0.LPC0.EC0.USDC)) IO80 = 0xD1 } Method (ECRD, 0, Serialized) { IO80 = 0xD3 MGI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI0)) MGI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI1)) MGI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI2)) MGI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI3)) MGI4 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI4)) MGI5 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI5)) MGI6 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI6)) MGI7 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI7)) MGI8 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI8)) MGI9 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI9)) MGIA = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIA)) MGIB = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIB)) MGIC = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIC)) MGID = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGID)) MGIE = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIE)) MGIF = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIF)) VER1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER1)) VER2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER2)) RSV1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV1)) RSV2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV2)) CCI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI0)) CCI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI1)) CCI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI2)) CCI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI3)) \_SB.PCI0.LPC0.EC0.ECWT (0xE1, RefOf (\_SB.PCI0.LPC0.EC0.USGC)) IO80 = 0xD4 } Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { If ((Arg0 == ToUUID ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) { If ((ToInteger (Arg2) == Zero)) { Return (Buffer (One) { 0x0F // . }) } ElseIf ((ToInteger (Arg2) == One)) { ECWR () } ElseIf ((ToInteger (Arg2) == 0x02)) { ECRD () } Else { Return (Zero) } } Return (Zero) } } Thanks, Rong > > thanks, > > greg k-h ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-11 19:12 ` Rong Zhang @ 2026-05-11 23:11 ` Mark Pearson 2026-05-12 12:46 ` Rong Zhang 0 siblings, 1 reply; 7+ messages in thread From: Mark Pearson @ 2026-05-11 23:11 UTC (permalink / raw) To: Rong Zhang, Greg KH Cc: Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86@vger.kernel.org, linux-kernel On Mon, May 11, 2026, at 3:12 PM, Rong Zhang wrote: > (+CC Mark Pearson from Lenovo) > > Hi Greg, > > On Mon, 2026-05-11 at 20:25 +0200, Greg Kroah-Hartman wrote: >> On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: >> > Some Lenovo devices have broken firmware, which reads/writes half-valid- >> > half-garbage values. >> >> How does this work with this firmware on other operating systems? >> > > The timeout can hardly reached unless a bunch of events cause multiple > drivers to compete for the same mutex simultaneously. > > If other operating systems' UCSI drivers don't send any command during > power events, they won't suffer from the mutex acquisition timeout. > Also, if other drivers on these operating systems don't touch the mutex > on power events at all, their UCSI drivers should work well too. > > These operating systems' UCSI drivers are powered by undefined behavior > (TM) in both cases. > >> What >> is the odds of fixing the firmware? > > They are not Linux-certified devices, so Lenovo is very unlikely to fix > the firmware unless it breaks Windows :( > > Quoting Mark Pearson's reply to the bugzilla thread: > > I can't promise anything - I don't have any official levers to pull for > this platform I'm afraid (it is better to buy Linux supported/certified > systems ;) ) > > https://bugzilla.kernel.org/show_bug.cgi?id=221065#c38 > >> >> > Given that everything is broken, disable ucsi_acpi on these devices. The >> > impact of disabling it is minimal, as Lenovo laptops usually have most >> > USCI commands more or less stubbed, and the EC can always handles USB-C >> > events on its own. >> > >> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 >> > Signed-off-by: Rong Zhang <i@rong.moe> >> > --- >> > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ >> > 1 file changed, 91 insertions(+) >> > >> > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c >> > index 6b92f296e985..7632b441d401 100644 >> > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c >> > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c >> > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { >> > { } >> > }; >> > >> > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { >> > + /* Firmware reads/writes half-valid-half-garbage values. */ >> > + >> > + /* BIOS: P1CN??WW */ >> > + { >> > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), >> > + }, >> > + }, >> > + { >> > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), >> > + }, >> > + }, >> > + >> > + /* BIOS: R0CN??WW */ >> > + { >> > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), >> > + }, >> > + }, >> > + { >> > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), >> > + }, >> > + }, >> > + { >> > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), >> > + }, >> > + }, >> > + >> > + /* BIOS: QXCN??WW */ >> > + { >> > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), >> > + }, >> > + }, >> > + { >> > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), >> > + }, >> > + }, >> > + >> > + /* BIOS: LNCN??WW */ >> > + { >> > + .ident = "Lenovo Yoga Pro 7 14ARP8", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), >> > + }, >> > + }, >> > + { >> > + .ident = "Lenovo Slim Pro 7 14ARP8", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), >> > + }, >> > + }, >> > + >> > + /* BIOS: PSCN??WW */ >> > + { >> > + .ident = "Lenovo Yoga Pro 7 14ASP9", >> > + .matches = { >> > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), >> > + }, >> > + }, >> > + { } >> > +}; >> >> That is a lot of devices to exclude, are you sure that none of them will >> ever work properly? > > Yes. I carefully checked all acpidumps for these devices provided by > device owners who replied to the bugzilla thread, and confirmed that > they all share the same UCSI-ACPI implementation. > > 83DR, 83HN, 83HY, 83AU, 83JR are owned by these device owners. Other > devices share the same BIOS images (see comments in the match table), so > I added them as well. > > Device owners also reported their dmesg dumps/snips with ucsi_acpi > errors. > > As a reference, buggy ASL methods are shown as below. > > \_SB.PCI0.LPC0.EC0: > Method (ECRD, 1, Serialized) > { > Local0 = Acquire (ECMT, 0x03E8) > If ((Local0 == Zero)) > { > If (ECAV) > { > Local1 = DerefOf (Arg0) > Release (ECMT) > Return (Local1) > } > Else > { > Release (ECMT) > } > } > > Return (Zero) > } > > Method (ECWT, 2, Serialized) > { > Local0 = Acquire (ECMT, 0x03E8) > If ((Local0 == Zero)) > { > If (ECAV) > { > Arg1 = Arg0 > } > > Release (ECMT) > } > } > > \_SB.UBTC: > Method (ECWR, 0, Serialized) > { > IO80 = 0xD0 > \_SB.PCI0.LPC0.EC0.ECWT (MGO0, RefOf (\_SB.PCI0.LPC0.EC0.MGO0)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO1, RefOf (\_SB.PCI0.LPC0.EC0.MGO1)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO2, RefOf (\_SB.PCI0.LPC0.EC0.MGO2)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO3, RefOf (\_SB.PCI0.LPC0.EC0.MGO3)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO4, RefOf (\_SB.PCI0.LPC0.EC0.MGO4)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO5, RefOf (\_SB.PCI0.LPC0.EC0.MGO5)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO6, RefOf (\_SB.PCI0.LPC0.EC0.MGO6)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO7, RefOf (\_SB.PCI0.LPC0.EC0.MGO7)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO8, RefOf (\_SB.PCI0.LPC0.EC0.MGO8)) > \_SB.PCI0.LPC0.EC0.ECWT (MGO9, RefOf (\_SB.PCI0.LPC0.EC0.MGO9)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOA, RefOf (\_SB.PCI0.LPC0.EC0.MGOA)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOB, RefOf (\_SB.PCI0.LPC0.EC0.MGOB)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOC, RefOf (\_SB.PCI0.LPC0.EC0.MGOC)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOD, RefOf (\_SB.PCI0.LPC0.EC0.MGOD)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOE, RefOf (\_SB.PCI0.LPC0.EC0.MGOE)) > \_SB.PCI0.LPC0.EC0.ECWT (MGOF, RefOf (\_SB.PCI0.LPC0.EC0.MGOF)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL0, RefOf (\_SB.PCI0.LPC0.EC0.CTL0)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL1, RefOf (\_SB.PCI0.LPC0.EC0.CTL1)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL2, RefOf (\_SB.PCI0.LPC0.EC0.CTL2)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL3, RefOf (\_SB.PCI0.LPC0.EC0.CTL3)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL4, RefOf (\_SB.PCI0.LPC0.EC0.CTL4)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL5, RefOf (\_SB.PCI0.LPC0.EC0.CTL5)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL6, RefOf (\_SB.PCI0.LPC0.EC0.CTL6)) > \_SB.PCI0.LPC0.EC0.ECWT (CTL7, RefOf (\_SB.PCI0.LPC0.EC0.CTL7)) > \_SB.PCI0.LPC0.EC0.ECWT (0xE0, RefOf (\_SB.PCI0.LPC0.EC0.USDC)) > IO80 = 0xD1 > } > > Method (ECRD, 0, Serialized) > { > IO80 = 0xD3 > MGI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI0)) > MGI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI1)) > MGI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI2)) > MGI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI3)) > MGI4 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI4)) > MGI5 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI5)) > MGI6 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI6)) > MGI7 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI7)) > MGI8 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI8)) > MGI9 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI9)) > MGIA = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIA)) > MGIB = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIB)) > MGIC = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIC)) > MGID = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGID)) > MGIE = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIE)) > MGIF = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIF)) > VER1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER1)) > VER2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER2)) > RSV1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV1)) > RSV2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV2)) > CCI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI0)) > CCI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI1)) > CCI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI2)) > CCI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI3)) > \_SB.PCI0.LPC0.EC0.ECWT (0xE1, RefOf (\_SB.PCI0.LPC0.EC0.USGC)) > IO80 = 0xD4 > } > > Method (_DSM, 4, Serialized) // _DSM: Device-Specific > Method > { > If ((Arg0 == ToUUID > ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) > { > If ((ToInteger (Arg2) == Zero)) > { > Return (Buffer (One) > { > 0x0F > // . > }) > } > ElseIf ((ToInteger (Arg2) == One)) > { > ECWR () > } > ElseIf ((ToInteger (Arg2) == 0x02)) > { > ECRD () > } > Else > { > Return (Zero) > } > } > > Return (Zero) > } > } > > Thanks, > Rong > >> >> thanks, >> >> greg k-h My biggest concern with this patch is it stands a chance of growing rapidly and extensively. We've been having a ton of UCSI issues on this years Thinkpad systems. We'll get them fixed, though it's been slow going. I don't understand it yet (and your notes above might be useful for narrowing it down). The FW team says the FW passes all the UCSI tests under Windows, but on Linux it's really bad and I see the same on my HW. Hopefully once we figure out what is going on with the Thinkpads the other platforms will benefit? but flagging that this error is not uncommon. I'd be surprised if this is Lenovo only to be honest. I might be wrong, but there's really not a lot common between an Ideapad and Thinkpad - they're completely different FW teams. I would expect the chances that this shows up elsewhere to be reasonable, in which case your list will grow even more. Can we wait until a bit more investigation has been done on Thinkpad? Right now it's on a small list of gating issues on a few of our platforms - so it is getting a bit more attention. Once we have root cause it might be easier to find a better solution? Mark ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-11 23:11 ` Mark Pearson @ 2026-05-12 12:46 ` Rong Zhang 2026-05-12 18:28 ` Mark Pearson 0 siblings, 1 reply; 7+ messages in thread From: Rong Zhang @ 2026-05-12 12:46 UTC (permalink / raw) To: Mark Pearson, Greg KH Cc: Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86@vger.kernel.org, linux-kernel Hi Mark, On Mon, 2026-05-11 at 19:11 -0400, Mark Pearson wrote: > On Mon, May 11, 2026, at 3:12 PM, Rong Zhang wrote: > > (+CC Mark Pearson from Lenovo) > > > > Hi Greg, > > > > On Mon, 2026-05-11 at 20:25 +0200, Greg Kroah-Hartman wrote: > > > On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: > > > > Some Lenovo devices have broken firmware, which reads/writes half-valid- > > > > half-garbage values. > > > > > > How does this work with this firmware on other operating systems? > > > > > > > The timeout can hardly reached unless a bunch of events cause multiple > > drivers to compete for the same mutex simultaneously. > > > > If other operating systems' UCSI drivers don't send any command during > > power events, they won't suffer from the mutex acquisition timeout. > > Also, if other drivers on these operating systems don't touch the mutex > > on power events at all, their UCSI drivers should work well too. > > > > These operating systems' UCSI drivers are powered by undefined behavior > > (TM) in both cases. > > > > > What > > > is the odds of fixing the firmware? > > > > They are not Linux-certified devices, so Lenovo is very unlikely to fix > > the firmware unless it breaks Windows :( > > > > Quoting Mark Pearson's reply to the bugzilla thread: > > > > I can't promise anything - I don't have any official levers to pull for > > this platform I'm afraid (it is better to buy Linux supported/certified > > systems ;) ) > > > > https://bugzilla.kernel.org/show_bug.cgi?id=221065#c38 > > > > > > > > > Given that everything is broken, disable ucsi_acpi on these devices. The > > > > impact of disabling it is minimal, as Lenovo laptops usually have most > > > > USCI commands more or less stubbed, and the EC can always handles USB-C > > > > events on its own. > > > > > > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 > > > > Signed-off-by: Rong Zhang <i@rong.moe> > > > > --- > > > > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ > > > > 1 file changed, 91 insertions(+) > > > > > > > > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c > > > > index 6b92f296e985..7632b441d401 100644 > > > > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c > > > > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c > > > > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { > > > > { } > > > > }; > > > > > > > > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { > > > > + /* Firmware reads/writes half-valid-half-garbage values. */ > > > > + > > > > + /* BIOS: P1CN??WW */ > > > > + { > > > > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), > > > > + }, > > > > + }, > > > > + { > > > > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), > > > > + }, > > > > + }, > > > > + > > > > + /* BIOS: R0CN??WW */ > > > > + { > > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), > > > > + }, > > > > + }, > > > > + { > > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), > > > > + }, > > > > + }, > > > > + { > > > > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), > > > > + }, > > > > + }, > > > > + > > > > + /* BIOS: QXCN??WW */ > > > > + { > > > > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), > > > > + }, > > > > + }, > > > > + { > > > > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), > > > > + }, > > > > + }, > > > > + > > > > + /* BIOS: LNCN??WW */ > > > > + { > > > > + .ident = "Lenovo Yoga Pro 7 14ARP8", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), > > > > + }, > > > > + }, > > > > + { > > > > + .ident = "Lenovo Slim Pro 7 14ARP8", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), > > > > + }, > > > > + }, > > > > + > > > > + /* BIOS: PSCN??WW */ > > > > + { > > > > + .ident = "Lenovo Yoga Pro 7 14ASP9", > > > > + .matches = { > > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), > > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), > > > > + }, > > > > + }, > > > > + { } > > > > +}; > > > > > > That is a lot of devices to exclude, are you sure that none of them will > > > ever work properly? > > > > Yes. I carefully checked all acpidumps for these devices provided by > > device owners who replied to the bugzilla thread, and confirmed that > > they all share the same UCSI-ACPI implementation. > > > > 83DR, 83HN, 83HY, 83AU, 83JR are owned by these device owners. Other > > devices share the same BIOS images (see comments in the match table), so > > I added them as well. > > > > Device owners also reported their dmesg dumps/snips with ucsi_acpi > > errors. > > > > As a reference, buggy ASL methods are shown as below. > > > > \_SB.PCI0.LPC0.EC0: > > Method (ECRD, 1, Serialized) > > { > > Local0 = Acquire (ECMT, 0x03E8) > > If ((Local0 == Zero)) > > { > > If (ECAV) > > { > > Local1 = DerefOf (Arg0) > > Release (ECMT) > > Return (Local1) > > } > > Else > > { > > Release (ECMT) > > } > > } > > > > Return (Zero) > > } > > > > Method (ECWT, 2, Serialized) > > { > > Local0 = Acquire (ECMT, 0x03E8) > > If ((Local0 == Zero)) > > { > > If (ECAV) > > { > > Arg1 = Arg0 > > } > > > > Release (ECMT) > > } > > } > > > > \_SB.UBTC: > > Method (ECWR, 0, Serialized) > > { > > IO80 = 0xD0 > > \_SB.PCI0.LPC0.EC0.ECWT (MGO0, RefOf (\_SB.PCI0.LPC0.EC0.MGO0)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO1, RefOf (\_SB.PCI0.LPC0.EC0.MGO1)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO2, RefOf (\_SB.PCI0.LPC0.EC0.MGO2)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO3, RefOf (\_SB.PCI0.LPC0.EC0.MGO3)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO4, RefOf (\_SB.PCI0.LPC0.EC0.MGO4)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO5, RefOf (\_SB.PCI0.LPC0.EC0.MGO5)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO6, RefOf (\_SB.PCI0.LPC0.EC0.MGO6)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO7, RefOf (\_SB.PCI0.LPC0.EC0.MGO7)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO8, RefOf (\_SB.PCI0.LPC0.EC0.MGO8)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGO9, RefOf (\_SB.PCI0.LPC0.EC0.MGO9)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOA, RefOf (\_SB.PCI0.LPC0.EC0.MGOA)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOB, RefOf (\_SB.PCI0.LPC0.EC0.MGOB)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOC, RefOf (\_SB.PCI0.LPC0.EC0.MGOC)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOD, RefOf (\_SB.PCI0.LPC0.EC0.MGOD)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOE, RefOf (\_SB.PCI0.LPC0.EC0.MGOE)) > > \_SB.PCI0.LPC0.EC0.ECWT (MGOF, RefOf (\_SB.PCI0.LPC0.EC0.MGOF)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL0, RefOf (\_SB.PCI0.LPC0.EC0.CTL0)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL1, RefOf (\_SB.PCI0.LPC0.EC0.CTL1)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL2, RefOf (\_SB.PCI0.LPC0.EC0.CTL2)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL3, RefOf (\_SB.PCI0.LPC0.EC0.CTL3)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL4, RefOf (\_SB.PCI0.LPC0.EC0.CTL4)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL5, RefOf (\_SB.PCI0.LPC0.EC0.CTL5)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL6, RefOf (\_SB.PCI0.LPC0.EC0.CTL6)) > > \_SB.PCI0.LPC0.EC0.ECWT (CTL7, RefOf (\_SB.PCI0.LPC0.EC0.CTL7)) > > \_SB.PCI0.LPC0.EC0.ECWT (0xE0, RefOf (\_SB.PCI0.LPC0.EC0.USDC)) > > IO80 = 0xD1 > > } > > > > Method (ECRD, 0, Serialized) > > { > > IO80 = 0xD3 > > MGI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI0)) > > MGI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI1)) > > MGI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI2)) > > MGI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI3)) > > MGI4 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI4)) > > MGI5 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI5)) > > MGI6 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI6)) > > MGI7 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI7)) > > MGI8 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI8)) > > MGI9 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI9)) > > MGIA = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIA)) > > MGIB = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIB)) > > MGIC = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIC)) > > MGID = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGID)) > > MGIE = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIE)) > > MGIF = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIF)) > > VER1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER1)) > > VER2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER2)) > > RSV1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV1)) > > RSV2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV2)) > > CCI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI0)) > > CCI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI1)) > > CCI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI2)) > > CCI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI3)) > > \_SB.PCI0.LPC0.EC0.ECWT (0xE1, RefOf (\_SB.PCI0.LPC0.EC0.USGC)) > > IO80 = 0xD4 > > } > > > > Method (_DSM, 4, Serialized) // _DSM: Device-Specific > > Method > > { > > If ((Arg0 == ToUUID > > ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) > > { > > If ((ToInteger (Arg2) == Zero)) > > { > > Return (Buffer (One) > > { > > 0x0F > > // . > > }) > > } > > ElseIf ((ToInteger (Arg2) == One)) > > { > > ECWR () > > } > > ElseIf ((ToInteger (Arg2) == 0x02)) > > { > > ECRD () > > } > > Else > > { > > Return (Zero) > > } > > } > > > > Return (Zero) > > } > > } > > > > Thanks, > > Rong > > > > > > > > thanks, > > > > > > greg k-h > > My biggest concern with this patch is it stands a chance of growing rapidly and extensively. If the length of match table is a concern, we can turn this into an allow list, i.e., disable ucsi_acpi on all Ryzen-based (after Rembrandt- R) IdeaPad and Yoga devices by default if the allow list doesn't matches, as it seems that these devices heavily shares the same UCSI- ACPI implementation (probably developed by the same teams?). I don't have a strong preference on either, so it's up to you and Greg. > We've been having a ton of UCSI issues on this years Thinkpad systems. We'll get them fixed, though it's been slow going. I don't think ThinkPad devices have the same issue, as their USCI-ACPI implementations are completely different, which matches with my understanding to Lenovo firmware, i.e., ThinkPad firmware is generally developed by different teams compared to IdeaPad/Yoga teams. For example, ThinkPad Z16 Gen 1 (21D4/21D5) seems to implement the UCSI- ACPI DSM properly (my analysis attached at the end of the reply). Even if it is problematic, it must be caused by a different bug. > > I don't understand it yet (and your notes above might be useful for narrowing it down). The FW team says the FW passes all the UCSI tests under Windows, > It's just like you can safely use MT-unsafe libc functions in a single- threaded program -- this doesn't prove the MT-safety of these functions. As I've said, the timeout will only reach when a lot of ACPI methods compete for the ECMT mutex as the same time. If they tested it with little background noise, the mutex acquisition timeout was never reached so no test failed. > but on Linux it's really bad and I see the same on my HW. Well, I have another conjecture. Typical Windows users don't bother taking a look at Windows Event Viewer at all, so they never notices any error related to the ECMT mutex. In contrast, checking dmesg is much easier. > > Hopefully once we figure out what is going on with the Thinkpads the other platforms will benefit? but flagging that this error is not uncommon. See my analysis at the end of the reply. > > I'd be surprised if this is Lenovo only to be honest. > That's not surprising. This is not an issue of EC itself, but rather an issue of improper implementation of the UCSI-ACPI DSM method, as well as other EC-related ACPI methods. > I might be wrong, but there's really not a lot common between an Ideapad and Thinkpad - they're completely different FW teams. I would expect the chances that this shows up elsewhere to be reasonable, in which case your list will grow even more. That's why the best solution is BIOS update. It would be great if Lenovo provides BIOS updates to fix all these ECMT chaos. Meanwhile, some devices (namely, 83JR and 83JU) in the match table have, unfortunately, reached the "End of Development Support" as their BIOS download pages show: https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-14akp10/83jr/downloads/ds573496 https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-16akp10/83ju/downloads/ds573496 ... and PSREF says 83DR, 83AU and 83AX are "withdrawn," which means they are EOL according to the FAQs: https://psref.lenovo.com/WDProduct/IdeaPad/IdeaPad_5_2_in_1_14AHP9 https://psref.lenovo.com/WDProduct/Yoga/Yoga_Pro_7_14ARP8 https://psref.lenovo.com/WDProduct/lenovo_slim_pro_7_14arp8 > > Can we wait until a bit more investigation has been done on Thinkpad? > I originally decided to wait a few months before submitting this. Three months had passed and Hans suggested I should submit this: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c68 As my analysis will show, I don't think the issue on IdeaPad/Yoga has anything in common with ThinkPad. My speculation on the UCSI issues on ThinkPad is that they might be caused by the EC itself or the local mutex (so other ACPI methods may access EC simultaneously while ucsi_acpi accessing the EC). > Right now it's on a small list of gating issues on a few of our platforms - so it is getting a bit more attention. > Did you refer to "a ton of UCSI issues on this years Thinkpad systems," or the ECMT chaos on these IdeaPad/Yoga devices? > Once we have root cause it might be easier to find a better solution? > > Mark UCSI-ACPI DSM on ThinkPad Z16 Gen 1 (21D4/21D5): /* * This is an example of my comments. */ /* * ThinkPad: UBSY is a local mutex, so no other methods compete for it. * * IdeaPad/Yoga: ECMT is shared among a lot of ACPI methods: * * $ grep -rE 'Acquire \(.*ECMT' | wc -l * 21 * $ grep -orE 'Acquire \(.*ECMT[^)]+' | cut -d ',' -f2 | xargs -i bash -c 'echo $(( {} ))ms' | sort -n | uniq -c * 1 300ms * 2 1000ms * 4 2000ms * 4 8192ms * 10 40960ms */ Mutex (UBSY, 0x00) Method (SECM, 1, Serialized) { Local0 = 0x64 While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) { Sleep (0x01) Local0-- } \_SB.SCMD = Arg0 If ((Arg0 == 0x02)) { Local0 = 0x64 While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) { Sleep (0x01) Local0-- } } } /* * ThinkPad: the UBSY mutex protects the whole UCSI methods. * * IdeaPad/Yoga: the ECMT mutex protects a single byte read/write to the EC, * i.e., protects \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD. */ Method (ECWR, 0, Serialized) { /* * ThinkPad: the acquisition of UBSY has no timeout (0xFFFF means no timeout * according to the ACPI spec), so it will never fail. * * IdeaPad/Yoga: \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD silently * fail after the 1s timeout is reached while their callers never check for * failure. */ Acquire (UBSY, 0xFFFF) /* * ThinkPad: direct EC access, the UCSI buffer and the EC are synchronized. * * IdeaPad/Yoga: the helper functions fail silently when the timeout is reached, * leaving the UCSI buffer and the EC are out of sync. */ \_SB.MGO0 = MGO0 /* \_SB_.UBTC.MGO0 */ \_SB.MGO1 = MGO1 /* \_SB_.UBTC.MGO1 */ \_SB.MGO2 = MGO2 /* \_SB_.UBTC.MGO2 */ \_SB.MGO3 = MGO3 /* \_SB_.UBTC.MGO3 */ \_SB.MGO4 = MGO4 /* \_SB_.UBTC.MGO4 */ \_SB.MGO5 = MGO5 /* \_SB_.UBTC.MGO5 */ \_SB.MGO6 = MGO6 /* \_SB_.UBTC.MGO6 */ \_SB.MGO7 = MGO7 /* \_SB_.UBTC.MGO7 */ \_SB.MGO8 = MGO8 /* \_SB_.UBTC.MGO8 */ \_SB.MGO9 = MGO9 /* \_SB_.UBTC.MGO9 */ \_SB.MGOA = MGOA /* \_SB_.UBTC.MGOA */ \_SB.MGOB = MGOB /* \_SB_.UBTC.MGOB */ \_SB.MGOC = MGOC /* \_SB_.UBTC.MGOC */ \_SB.MGOD = MGOD /* \_SB_.UBTC.MGOD */ \_SB.MGOE = MGOE /* \_SB_.UBTC.MGOE */ \_SB.MGOF = MGOF /* \_SB_.UBTC.MGOF */ \_SB.CTL0 = CTL0 /* \_SB_.UBTC.CTL0 */ \_SB.CTL1 = CTL1 /* \_SB_.UBTC.CTL1 */ \_SB.CTL2 = CTL2 /* \_SB_.UBTC.CTL2 */ \_SB.CTL3 = CTL3 /* \_SB_.UBTC.CTL3 */ \_SB.CTL4 = CTL4 /* \_SB_.UBTC.CTL4 */ \_SB.CTL5 = CTL5 /* \_SB_.UBTC.CTL5 */ \_SB.CTL6 = CTL6 /* \_SB_.UBTC.CTL6 */ \_SB.CTL7 = CTL7 /* \_SB_.UBTC.CTL7 */ Sleep (0x19) SECM (0x01) Release (UBSY) } Method (ECRD, 0, Serialized) { /* * Same as above. */ Acquire (UBSY, 0xFFFF) SECM (0x02) Sleep (0x19) MGI0 = \_SB.MGI0 MGI1 = \_SB.MGI1 MGI2 = \_SB.MGI2 MGI3 = \_SB.MGI3 MGI4 = \_SB.MGI4 MGI5 = \_SB.MGI5 MGI6 = \_SB.MGI6 MGI7 = \_SB.MGI7 MGI8 = \_SB.MGI8 MGI9 = \_SB.MGI9 MGIA = \_SB.MGIA MGIB = \_SB.MGIB MGIC = \_SB.MGIC MGID = \_SB.MGID MGIE = \_SB.MGIE MGIF = \_SB.MGIF CCI0 = \_SB.CCI0 CCI1 = \_SB.CCI1 CCI2 = \_SB.CCI2 CCI3 = \_SB.CCI3 Release (UBSY) } [...] Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { If ((Arg0 == ToUUID ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) { If ((ToInteger (Arg2) == 0x00)) { Return (Buffer (0x01) { 0x0F // . }) } ElseIf ((ToInteger (Arg2) == 0x01)) { ECWR () } ElseIf ((ToInteger (Arg2) == 0x02)) { ECRD () } } Return (0x00) } The acpidump can be found at https://github.com/linuxhw/ACPI/blob/master/Notebook/Lenovo/ThinkPad/ThinkPad%20Z16%20Gen%201%2021D4S02A00/41C7BA241943.bin Thanks, Rong ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-12 12:46 ` Rong Zhang @ 2026-05-12 18:28 ` Mark Pearson 2026-05-12 19:16 ` Rong Zhang 0 siblings, 1 reply; 7+ messages in thread From: Mark Pearson @ 2026-05-12 18:28 UTC (permalink / raw) To: Rong Zhang, Greg KH Cc: Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86@vger.kernel.org, linux-kernel Hi Rong On Tue, May 12, 2026, at 8:46 AM, Rong Zhang wrote: > Hi Mark, > > On Mon, 2026-05-11 at 19:11 -0400, Mark Pearson wrote: >> On Mon, May 11, 2026, at 3:12 PM, Rong Zhang wrote: >> > (+CC Mark Pearson from Lenovo) >> > >> > Hi Greg, >> > >> > On Mon, 2026-05-11 at 20:25 +0200, Greg Kroah-Hartman wrote: >> > > On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: >> > > > Some Lenovo devices have broken firmware, which reads/writes half-valid- >> > > > half-garbage values. >> > > >> > > How does this work with this firmware on other operating systems? >> > > >> > >> > The timeout can hardly reached unless a bunch of events cause multiple >> > drivers to compete for the same mutex simultaneously. >> > >> > If other operating systems' UCSI drivers don't send any command during >> > power events, they won't suffer from the mutex acquisition timeout. >> > Also, if other drivers on these operating systems don't touch the mutex >> > on power events at all, their UCSI drivers should work well too. >> > >> > These operating systems' UCSI drivers are powered by undefined behavior >> > (TM) in both cases. >> > >> > > What >> > > is the odds of fixing the firmware? >> > >> > They are not Linux-certified devices, so Lenovo is very unlikely to fix >> > the firmware unless it breaks Windows :( >> > >> > Quoting Mark Pearson's reply to the bugzilla thread: >> > >> > I can't promise anything - I don't have any official levers to pull for >> > this platform I'm afraid (it is better to buy Linux supported/certified >> > systems ;) ) >> > >> > https://bugzilla.kernel.org/show_bug.cgi?id=221065#c38 >> > >> > > >> > > > Given that everything is broken, disable ucsi_acpi on these devices. The >> > > > impact of disabling it is minimal, as Lenovo laptops usually have most >> > > > USCI commands more or less stubbed, and the EC can always handles USB-C >> > > > events on its own. >> > > > >> > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 >> > > > Signed-off-by: Rong Zhang <i@rong.moe> >> > > > --- >> > > > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ >> > > > 1 file changed, 91 insertions(+) >> > > > >> > > > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c >> > > > index 6b92f296e985..7632b441d401 100644 >> > > > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c >> > > > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c >> > > > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { >> > > > { } >> > > > }; >> > > > >> > > > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { >> > > > + /* Firmware reads/writes half-valid-half-garbage values. */ >> > > > + >> > > > + /* BIOS: P1CN??WW */ >> > > > + { >> > > > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), >> > > > + }, >> > > > + }, >> > > > + { >> > > > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), >> > > > + }, >> > > > + }, >> > > > + >> > > > + /* BIOS: R0CN??WW */ >> > > > + { >> > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), >> > > > + }, >> > > > + }, >> > > > + { >> > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), >> > > > + }, >> > > > + }, >> > > > + { >> > > > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), >> > > > + }, >> > > > + }, >> > > > + >> > > > + /* BIOS: QXCN??WW */ >> > > > + { >> > > > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), >> > > > + }, >> > > > + }, >> > > > + { >> > > > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), >> > > > + }, >> > > > + }, >> > > > + >> > > > + /* BIOS: LNCN??WW */ >> > > > + { >> > > > + .ident = "Lenovo Yoga Pro 7 14ARP8", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), >> > > > + }, >> > > > + }, >> > > > + { >> > > > + .ident = "Lenovo Slim Pro 7 14ARP8", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), >> > > > + }, >> > > > + }, >> > > > + >> > > > + /* BIOS: PSCN??WW */ >> > > > + { >> > > > + .ident = "Lenovo Yoga Pro 7 14ASP9", >> > > > + .matches = { >> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), >> > > > + }, >> > > > + }, >> > > > + { } >> > > > +}; >> > > >> > > That is a lot of devices to exclude, are you sure that none of them will >> > > ever work properly? >> > >> > Yes. I carefully checked all acpidumps for these devices provided by >> > device owners who replied to the bugzilla thread, and confirmed that >> > they all share the same UCSI-ACPI implementation. >> > >> > 83DR, 83HN, 83HY, 83AU, 83JR are owned by these device owners. Other >> > devices share the same BIOS images (see comments in the match table), so >> > I added them as well. >> > >> > Device owners also reported their dmesg dumps/snips with ucsi_acpi >> > errors. >> > >> > As a reference, buggy ASL methods are shown as below. >> > >> > \_SB.PCI0.LPC0.EC0: >> > Method (ECRD, 1, Serialized) >> > { >> > Local0 = Acquire (ECMT, 0x03E8) >> > If ((Local0 == Zero)) >> > { >> > If (ECAV) >> > { >> > Local1 = DerefOf (Arg0) >> > Release (ECMT) >> > Return (Local1) >> > } >> > Else >> > { >> > Release (ECMT) >> > } >> > } >> > >> > Return (Zero) >> > } >> > >> > Method (ECWT, 2, Serialized) >> > { >> > Local0 = Acquire (ECMT, 0x03E8) >> > If ((Local0 == Zero)) >> > { >> > If (ECAV) >> > { >> > Arg1 = Arg0 >> > } >> > >> > Release (ECMT) >> > } >> > } >> > >> > \_SB.UBTC: >> > Method (ECWR, 0, Serialized) >> > { >> > IO80 = 0xD0 >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO0, RefOf (\_SB.PCI0.LPC0.EC0.MGO0)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO1, RefOf (\_SB.PCI0.LPC0.EC0.MGO1)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO2, RefOf (\_SB.PCI0.LPC0.EC0.MGO2)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO3, RefOf (\_SB.PCI0.LPC0.EC0.MGO3)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO4, RefOf (\_SB.PCI0.LPC0.EC0.MGO4)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO5, RefOf (\_SB.PCI0.LPC0.EC0.MGO5)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO6, RefOf (\_SB.PCI0.LPC0.EC0.MGO6)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO7, RefOf (\_SB.PCI0.LPC0.EC0.MGO7)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO8, RefOf (\_SB.PCI0.LPC0.EC0.MGO8)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGO9, RefOf (\_SB.PCI0.LPC0.EC0.MGO9)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOA, RefOf (\_SB.PCI0.LPC0.EC0.MGOA)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOB, RefOf (\_SB.PCI0.LPC0.EC0.MGOB)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOC, RefOf (\_SB.PCI0.LPC0.EC0.MGOC)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOD, RefOf (\_SB.PCI0.LPC0.EC0.MGOD)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOE, RefOf (\_SB.PCI0.LPC0.EC0.MGOE)) >> > \_SB.PCI0.LPC0.EC0.ECWT (MGOF, RefOf (\_SB.PCI0.LPC0.EC0.MGOF)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL0, RefOf (\_SB.PCI0.LPC0.EC0.CTL0)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL1, RefOf (\_SB.PCI0.LPC0.EC0.CTL1)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL2, RefOf (\_SB.PCI0.LPC0.EC0.CTL2)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL3, RefOf (\_SB.PCI0.LPC0.EC0.CTL3)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL4, RefOf (\_SB.PCI0.LPC0.EC0.CTL4)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL5, RefOf (\_SB.PCI0.LPC0.EC0.CTL5)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL6, RefOf (\_SB.PCI0.LPC0.EC0.CTL6)) >> > \_SB.PCI0.LPC0.EC0.ECWT (CTL7, RefOf (\_SB.PCI0.LPC0.EC0.CTL7)) >> > \_SB.PCI0.LPC0.EC0.ECWT (0xE0, RefOf (\_SB.PCI0.LPC0.EC0.USDC)) >> > IO80 = 0xD1 >> > } >> > >> > Method (ECRD, 0, Serialized) >> > { >> > IO80 = 0xD3 >> > MGI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI0)) >> > MGI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI1)) >> > MGI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI2)) >> > MGI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI3)) >> > MGI4 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI4)) >> > MGI5 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI5)) >> > MGI6 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI6)) >> > MGI7 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI7)) >> > MGI8 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI8)) >> > MGI9 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI9)) >> > MGIA = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIA)) >> > MGIB = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIB)) >> > MGIC = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIC)) >> > MGID = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGID)) >> > MGIE = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIE)) >> > MGIF = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIF)) >> > VER1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER1)) >> > VER2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER2)) >> > RSV1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV1)) >> > RSV2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV2)) >> > CCI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI0)) >> > CCI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI1)) >> > CCI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI2)) >> > CCI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI3)) >> > \_SB.PCI0.LPC0.EC0.ECWT (0xE1, RefOf (\_SB.PCI0.LPC0.EC0.USGC)) >> > IO80 = 0xD4 >> > } >> > >> > Method (_DSM, 4, Serialized) // _DSM: Device-Specific >> > Method >> > { >> > If ((Arg0 == ToUUID >> > ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) >> > { >> > If ((ToInteger (Arg2) == Zero)) >> > { >> > Return (Buffer (One) >> > { >> > 0x0F >> > // . >> > }) >> > } >> > ElseIf ((ToInteger (Arg2) == One)) >> > { >> > ECWR () >> > } >> > ElseIf ((ToInteger (Arg2) == 0x02)) >> > { >> > ECRD () >> > } >> > Else >> > { >> > Return (Zero) >> > } >> > } >> > >> > Return (Zero) >> > } >> > } >> > >> > Thanks, >> > Rong >> > >> > > >> > > thanks, >> > > >> > > greg k-h >> >> My biggest concern with this patch is it stands a chance of growing rapidly and extensively. > > If the length of match table is a concern, we can turn this into an > allow list, i.e., disable ucsi_acpi on all Ryzen-based (after Rembrandt- > R) IdeaPad and Yoga devices by default if the allow list doesn't > matches, as it seems that these devices heavily shares the same UCSI- > ACPI implementation (probably developed by the same teams?). > > I don't have a strong preference on either, so it's up to you and Greg. > An allow list would be worse from my (slightly selfish) perspective. >> We've been having a ton of UCSI issues on this years Thinkpad systems. We'll get them fixed, though it's been slow going. > > I don't think ThinkPad devices have the same issue, as their USCI-ACPI > implementations are completely different, which matches with my > understanding to Lenovo firmware, i.e., ThinkPad firmware is generally > developed by different teams compared to IdeaPad/Yoga teams. > > For example, ThinkPad Z16 Gen 1 (21D4/21D5) seems to implement the UCSI- > ACPI DSM properly (my analysis attached at the end of the reply). Even > if it is problematic, it must be caused by a different bug. > I'm testing on platforms that aren't released yet. Generally you're right - it's not a problem. But this years platforms have been bad (I don't think it's related to the CPU vendor) >> >> I don't understand it yet (and your notes above might be useful for narrowing it down). The FW team says the FW passes all the UCSI tests under Windows, >> > > It's just like you can safely use MT-unsafe libc functions in a single- > threaded program -- this doesn't prove the MT-safety of these functions. > > As I've said, the timeout will only reach when a lot of ACPI methods > compete for the ECMT mutex as the same time. If they tested it with > little background noise, the mutex acquisition timeout was never reached > so no test failed. > >> but on Linux it's really bad and I see the same on my HW. > > Well, I have another conjecture. Typical Windows users don't bother > taking a look at Windows Event Viewer at all, so they never notices any > error related to the ECMT mutex. In contrast, checking dmesg is much > easier. > You might be right. I'm told there is a bunch of qualification testing they do against Windows but I don't know the details and I've definitely previously seen garbage results previously with invalid connector numbers being returned (that we got fixed); so I'm personally dubious. Agreed that regular Windows users won't notice. I get this all the time - we fix stuff (usually ACPI errors) that Windows just covers up. Such is the penalty for being a superior OS ;) >> >> Hopefully once we figure out what is going on with the Thinkpads the other platforms will benefit? but flagging that this error is not uncommon. > > See my analysis at the end of the reply. > >> >> I'd be surprised if this is Lenovo only to be honest. >> > > That's not surprising. This is not an issue of EC itself, but rather an > issue of improper implementation of the UCSI-ACPI DSM method, as well as > other EC-related ACPI methods. > My concern is that you could end up seeing this on a lot of different HW. Maybe we just need to be more brutal when an error is detected and quit at that point with a pr_err "your UCSI FW is bad, report it to the vendor" and not retry? There's a huge number of different PCs being released every year, Linux usage is growing, any list approach feels doomed to me. >> I might be wrong, but there's really not a lot common between an Ideapad and Thinkpad - they're completely different FW teams. I would expect the chances that this shows up elsewhere to be reasonable, in which case your list will grow even more. > > That's why the best solution is BIOS update. It would be great if Lenovo > provides BIOS updates to fix all these ECMT chaos. > > Meanwhile, some devices (namely, 83JR and 83JU) in the match table have, > unfortunately, reached the "End of Development Support" as their BIOS > download pages show: > > https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-14akp10/83jr/downloads/ds573496 > https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-16akp10/83ju/downloads/ds573496 > > ... and PSREF says 83DR, 83AU and 83AX are "withdrawn," which means they > are EOL according to the FAQs: > > https://psref.lenovo.com/WDProduct/IdeaPad/IdeaPad_5_2_in_1_14AHP9 > https://psref.lenovo.com/WDProduct/Yoga/Yoga_Pro_7_14ARP8 > https://psref.lenovo.com/WDProduct/lenovo_slim_pro_7_14arp8 > Yeah, I know. And it sucks that we can't just have Linux on everything with vendor suport. One day we'll get there..... >> >> Can we wait until a bit more investigation has been done on Thinkpad? >> > > I originally decided to wait a few months before submitting this. Three > months had passed and Hans suggested I should submit this: > > https://bugzilla.kernel.org/show_bug.cgi?id=221065#c68 > > As my analysis will show, I don't think the issue on IdeaPad/Yoga has > anything in common with ThinkPad. > > My speculation on the UCSI issues on ThinkPad is that they might be > caused by the EC itself or the local mutex (so other ACPI methods may > access EC simultaneously while ucsi_acpi accessing the EC). > >> Right now it's on a small list of gating issues on a few of our platforms - so it is getting a bit more attention. >> > > Did you refer to "a ton of UCSI issues on this years Thinkpad systems," > or the ECMT chaos on these IdeaPad/Yoga devices? > >> Once we have root cause it might be easier to find a better solution? >> >> Mark > > UCSI-ACPI DSM on ThinkPad Z16 Gen 1 (21D4/21D5): > > /* > * This is an example of my comments. > */ > > /* > * ThinkPad: UBSY is a local mutex, so no other methods compete for it. > * > * IdeaPad/Yoga: ECMT is shared among a lot of ACPI methods: > * > * $ grep -rE 'Acquire \(.*ECMT' | wc -l > * 21 > * $ grep -orE 'Acquire \(.*ECMT[^)]+' | cut -d ',' -f2 | xargs -i > bash -c 'echo $(( {} ))ms' | sort -n | uniq -c > * 1 300ms > * 2 1000ms > * 4 2000ms > * 4 8192ms > * 10 40960ms > */ > Mutex (UBSY, 0x00) > Method (SECM, 1, Serialized) > { > Local0 = 0x64 > While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) > { > Sleep (0x01) > Local0-- > } > > \_SB.SCMD = Arg0 > If ((Arg0 == 0x02)) > { > Local0 = 0x64 > While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) > { > Sleep (0x01) > Local0-- > } > } > } > > /* > * ThinkPad: the UBSY mutex protects the whole UCSI methods. > * > * IdeaPad/Yoga: the ECMT mutex protects a single byte read/write to the EC, > * i.e., protects \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD. > */ > Method (ECWR, 0, Serialized) > { > /* > * ThinkPad: the acquisition of UBSY has no timeout (0xFFFF means no timeout > * according to the ACPI spec), so it will never fail. > * > * IdeaPad/Yoga: \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD silently > * fail after the 1s timeout is reached while their callers never check for > * failure. > */ > Acquire (UBSY, 0xFFFF) > /* > * ThinkPad: direct EC access, the UCSI buffer and the EC are synchronized. > * > * IdeaPad/Yoga: the helper functions fail silently when the timeout is reached, > * leaving the UCSI buffer and the EC are out of sync. > */ > \_SB.MGO0 = MGO0 /* \_SB_.UBTC.MGO0 */ > \_SB.MGO1 = MGO1 /* \_SB_.UBTC.MGO1 */ > \_SB.MGO2 = MGO2 /* \_SB_.UBTC.MGO2 */ > \_SB.MGO3 = MGO3 /* \_SB_.UBTC.MGO3 */ > \_SB.MGO4 = MGO4 /* \_SB_.UBTC.MGO4 */ > \_SB.MGO5 = MGO5 /* \_SB_.UBTC.MGO5 */ > \_SB.MGO6 = MGO6 /* \_SB_.UBTC.MGO6 */ > \_SB.MGO7 = MGO7 /* \_SB_.UBTC.MGO7 */ > \_SB.MGO8 = MGO8 /* \_SB_.UBTC.MGO8 */ > \_SB.MGO9 = MGO9 /* \_SB_.UBTC.MGO9 */ > \_SB.MGOA = MGOA /* \_SB_.UBTC.MGOA */ > \_SB.MGOB = MGOB /* \_SB_.UBTC.MGOB */ > \_SB.MGOC = MGOC /* \_SB_.UBTC.MGOC */ > \_SB.MGOD = MGOD /* \_SB_.UBTC.MGOD */ > \_SB.MGOE = MGOE /* \_SB_.UBTC.MGOE */ > \_SB.MGOF = MGOF /* \_SB_.UBTC.MGOF */ > \_SB.CTL0 = CTL0 /* \_SB_.UBTC.CTL0 */ > \_SB.CTL1 = CTL1 /* \_SB_.UBTC.CTL1 */ > \_SB.CTL2 = CTL2 /* \_SB_.UBTC.CTL2 */ > \_SB.CTL3 = CTL3 /* \_SB_.UBTC.CTL3 */ > \_SB.CTL4 = CTL4 /* \_SB_.UBTC.CTL4 */ > \_SB.CTL5 = CTL5 /* \_SB_.UBTC.CTL5 */ > \_SB.CTL6 = CTL6 /* \_SB_.UBTC.CTL6 */ > \_SB.CTL7 = CTL7 /* \_SB_.UBTC.CTL7 */ > Sleep (0x19) > SECM (0x01) > Release (UBSY) > } > > Method (ECRD, 0, Serialized) > { > /* > * Same as above. > */ > Acquire (UBSY, 0xFFFF) > SECM (0x02) > Sleep (0x19) > MGI0 = \_SB.MGI0 > MGI1 = \_SB.MGI1 > MGI2 = \_SB.MGI2 > MGI3 = \_SB.MGI3 > MGI4 = \_SB.MGI4 > MGI5 = \_SB.MGI5 > MGI6 = \_SB.MGI6 > MGI7 = \_SB.MGI7 > MGI8 = \_SB.MGI8 > MGI9 = \_SB.MGI9 > MGIA = \_SB.MGIA > MGIB = \_SB.MGIB > MGIC = \_SB.MGIC > MGID = \_SB.MGID > MGIE = \_SB.MGIE > MGIF = \_SB.MGIF > CCI0 = \_SB.CCI0 > CCI1 = \_SB.CCI1 > CCI2 = \_SB.CCI2 > CCI3 = \_SB.CCI3 > Release (UBSY) > } > > [...] > > Method (_DSM, 4, Serialized) // _DSM: Device-Specific > Method > { > If ((Arg0 == ToUUID > ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) > { > If ((ToInteger (Arg2) == 0x00)) > { > Return (Buffer (0x01) > { > 0x0F > // . > }) > } > ElseIf ((ToInteger (Arg2) == 0x01)) > { > ECWR () > } > ElseIf ((ToInteger (Arg2) == 0x02)) > { > ECRD () > } > } > > Return (0x00) > } > > The acpidump can be found at > https://github.com/linuxhw/ACPI/blob/master/Notebook/Lenovo/ThinkPad/ThinkPad%20Z16%20Gen%201%2021D4S02A00/41C7BA241943.bin > Been tied up in meetings today, but I do plan on seeing if this matches what I'm seeing. On my todo list... Mark ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware 2026-05-12 18:28 ` Mark Pearson @ 2026-05-12 19:16 ` Rong Zhang 0 siblings, 0 replies; 7+ messages in thread From: Rong Zhang @ 2026-05-12 19:16 UTC (permalink / raw) To: Mark Pearson, Greg KH Cc: Heikki Krogerus, Hans de Goede, linux-usb, platform-driver-x86@vger.kernel.org, linux-kernel Hi Mark, 于 2026年5月13日 GMT+08:00 02:28:56,Mark Pearson <mpearson-lenovo@squebb.ca> 写道: >Hi Rong > >On Tue, May 12, 2026, at 8:46 AM, Rong Zhang wrote: >> Hi Mark, >> >> On Mon, 2026-05-11 at 19:11 -0400, Mark Pearson wrote: >>> On Mon, May 11, 2026, at 3:12 PM, Rong Zhang wrote: >>> > (+CC Mark Pearson from Lenovo) >>> > >>> > Hi Greg, >>> > >>> > On Mon, 2026-05-11 at 20:25 +0200, Greg Kroah-Hartman wrote: >>> > > On Tue, May 12, 2026 at 01:59:34AM +0800, Rong Zhang wrote: >>> > > > Some Lenovo devices have broken firmware, which reads/writes half-valid- >>> > > > half-garbage values. >>> > > >>> > > How does this work with this firmware on other operating systems? >>> > > >>> > >>> > The timeout can hardly reached unless a bunch of events cause multiple >>> > drivers to compete for the same mutex simultaneously. >>> > >>> > If other operating systems' UCSI drivers don't send any command during >>> > power events, they won't suffer from the mutex acquisition timeout. >>> > Also, if other drivers on these operating systems don't touch the mutex >>> > on power events at all, their UCSI drivers should work well too. >>> > >>> > These operating systems' UCSI drivers are powered by undefined behavior >>> > (TM) in both cases. >>> > >>> > > What >>> > > is the odds of fixing the firmware? >>> > >>> > They are not Linux-certified devices, so Lenovo is very unlikely to fix >>> > the firmware unless it breaks Windows :( >>> > >>> > Quoting Mark Pearson's reply to the bugzilla thread: >>> > >>> > I can't promise anything - I don't have any official levers to pull for >>> > this platform I'm afraid (it is better to buy Linux supported/certified >>> > systems ;) ) >>> > >>> > https://bugzilla.kernel.org/show_bug.cgi?id=221065#c38 >>> > >>> > > >>> > > > Given that everything is broken, disable ucsi_acpi on these devices. The >>> > > > impact of disabling it is minimal, as Lenovo laptops usually have most >>> > > > USCI commands more or less stubbed, and the EC can always handles USB-C >>> > > > events on its own. >>> > > > >>> > > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=221065#c33 >>> > > > Signed-off-by: Rong Zhang <i@rong.moe> >>> > > > --- >>> > > > drivers/usb/typec/ucsi/ucsi_acpi.c | 91 ++++++++++++++++++++++++++++++++++++++ >>> > > > 1 file changed, 91 insertions(+) >>> > > > >>> > > > diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c >>> > > > index 6b92f296e985..7632b441d401 100644 >>> > > > --- a/drivers/usb/typec/ucsi/ucsi_acpi.c >>> > > > +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c >>> > > > @@ -155,6 +155,91 @@ static const struct dmi_system_id ucsi_acpi_quirks[] = { >>> > > > { } >>> > > > }; >>> > > > >>> > > > +static const struct dmi_system_id ucsi_acpi_broken_devices[] = { >>> > > > + /* Firmware reads/writes half-valid-half-garbage values. */ >>> > > > + >>> > > > + /* BIOS: P1CN??WW */ >>> > > > + { >>> > > > + .ident = "Lenovo IdeaPad 5 2-in-1 14AHP9", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DR"), >>> > > > + }, >>> > > > + }, >>> > > > + { >>> > > > + .ident = "Lenovo IdeaPad 5 2-in-1 16AHP9", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83DS"), >>> > > > + }, >>> > > > + }, >>> > > > + >>> > > > + /* BIOS: R0CN??WW */ >>> > > > + { >>> > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83NJ"), >>> > > > + }, >>> > > > + }, >>> > > > + { >>> > > > + .ident = "Lenovo IdeaPad Slim 5 14AKP10", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HX"), >>> > > > + }, >>> > > > + }, >>> > > > + { >>> > > > + .ident = "Lenovo IdeaPad Slim 5 16AKP10", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HY"), >>> > > > + }, >>> > > > + }, >>> > > > + >>> > > > + /* BIOS: QXCN??WW */ >>> > > > + { >>> > > > + .ident = "Lenovo Yoga 7 2-in-1 14AKP10", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JR"), >>> > > > + }, >>> > > > + }, >>> > > > + { >>> > > > + .ident = "Lenovo Yoga 7 2-in-1 16AKP10", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83JU"), >>> > > > + }, >>> > > > + }, >>> > > > + >>> > > > + /* BIOS: LNCN??WW */ >>> > > > + { >>> > > > + .ident = "Lenovo Yoga Pro 7 14ARP8", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AU"), >>> > > > + }, >>> > > > + }, >>> > > > + { >>> > > > + .ident = "Lenovo Slim Pro 7 14ARP8", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83AX"), >>> > > > + }, >>> > > > + }, >>> > > > + >>> > > > + /* BIOS: PSCN??WW */ >>> > > > + { >>> > > > + .ident = "Lenovo Yoga Pro 7 14ASP9", >>> > > > + .matches = { >>> > > > + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), >>> > > > + DMI_MATCH(DMI_PRODUCT_NAME, "83HN"), >>> > > > + }, >>> > > > + }, >>> > > > + { } >>> > > > +}; >>> > > >>> > > That is a lot of devices to exclude, are you sure that none of them will >>> > > ever work properly? >>> > >>> > Yes. I carefully checked all acpidumps for these devices provided by >>> > device owners who replied to the bugzilla thread, and confirmed that >>> > they all share the same UCSI-ACPI implementation. >>> > >>> > 83DR, 83HN, 83HY, 83AU, 83JR are owned by these device owners. Other >>> > devices share the same BIOS images (see comments in the match table), so >>> > I added them as well. >>> > >>> > Device owners also reported their dmesg dumps/snips with ucsi_acpi >>> > errors. >>> > >>> > As a reference, buggy ASL methods are shown as below. >>> > >>> > \_SB.PCI0.LPC0.EC0: >>> > Method (ECRD, 1, Serialized) >>> > { >>> > Local0 = Acquire (ECMT, 0x03E8) >>> > If ((Local0 == Zero)) >>> > { >>> > If (ECAV) >>> > { >>> > Local1 = DerefOf (Arg0) >>> > Release (ECMT) >>> > Return (Local1) >>> > } >>> > Else >>> > { >>> > Release (ECMT) >>> > } >>> > } >>> > >>> > Return (Zero) >>> > } >>> > >>> > Method (ECWT, 2, Serialized) >>> > { >>> > Local0 = Acquire (ECMT, 0x03E8) >>> > If ((Local0 == Zero)) >>> > { >>> > If (ECAV) >>> > { >>> > Arg1 = Arg0 >>> > } >>> > >>> > Release (ECMT) >>> > } >>> > } >>> > >>> > \_SB.UBTC: >>> > Method (ECWR, 0, Serialized) >>> > { >>> > IO80 = 0xD0 >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO0, RefOf (\_SB.PCI0.LPC0.EC0.MGO0)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO1, RefOf (\_SB.PCI0.LPC0.EC0.MGO1)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO2, RefOf (\_SB.PCI0.LPC0.EC0.MGO2)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO3, RefOf (\_SB.PCI0.LPC0.EC0.MGO3)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO4, RefOf (\_SB.PCI0.LPC0.EC0.MGO4)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO5, RefOf (\_SB.PCI0.LPC0.EC0.MGO5)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO6, RefOf (\_SB.PCI0.LPC0.EC0.MGO6)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO7, RefOf (\_SB.PCI0.LPC0.EC0.MGO7)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO8, RefOf (\_SB.PCI0.LPC0.EC0.MGO8)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGO9, RefOf (\_SB.PCI0.LPC0.EC0.MGO9)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOA, RefOf (\_SB.PCI0.LPC0.EC0.MGOA)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOB, RefOf (\_SB.PCI0.LPC0.EC0.MGOB)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOC, RefOf (\_SB.PCI0.LPC0.EC0.MGOC)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOD, RefOf (\_SB.PCI0.LPC0.EC0.MGOD)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOE, RefOf (\_SB.PCI0.LPC0.EC0.MGOE)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (MGOF, RefOf (\_SB.PCI0.LPC0.EC0.MGOF)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL0, RefOf (\_SB.PCI0.LPC0.EC0.CTL0)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL1, RefOf (\_SB.PCI0.LPC0.EC0.CTL1)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL2, RefOf (\_SB.PCI0.LPC0.EC0.CTL2)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL3, RefOf (\_SB.PCI0.LPC0.EC0.CTL3)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL4, RefOf (\_SB.PCI0.LPC0.EC0.CTL4)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL5, RefOf (\_SB.PCI0.LPC0.EC0.CTL5)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL6, RefOf (\_SB.PCI0.LPC0.EC0.CTL6)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (CTL7, RefOf (\_SB.PCI0.LPC0.EC0.CTL7)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (0xE0, RefOf (\_SB.PCI0.LPC0.EC0.USDC)) >>> > IO80 = 0xD1 >>> > } >>> > >>> > Method (ECRD, 0, Serialized) >>> > { >>> > IO80 = 0xD3 >>> > MGI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI0)) >>> > MGI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI1)) >>> > MGI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI2)) >>> > MGI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI3)) >>> > MGI4 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI4)) >>> > MGI5 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI5)) >>> > MGI6 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI6)) >>> > MGI7 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI7)) >>> > MGI8 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI8)) >>> > MGI9 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGI9)) >>> > MGIA = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIA)) >>> > MGIB = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIB)) >>> > MGIC = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIC)) >>> > MGID = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGID)) >>> > MGIE = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIE)) >>> > MGIF = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.MGIF)) >>> > VER1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER1)) >>> > VER2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.VER2)) >>> > RSV1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV1)) >>> > RSV2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.RSV2)) >>> > CCI0 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI0)) >>> > CCI1 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI1)) >>> > CCI2 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI2)) >>> > CCI3 = \_SB.PCI0.LPC0.EC0.ECRD (RefOf (\_SB.PCI0.LPC0.EC0.CCI3)) >>> > \_SB.PCI0.LPC0.EC0.ECWT (0xE1, RefOf (\_SB.PCI0.LPC0.EC0.USGC)) >>> > IO80 = 0xD4 >>> > } >>> > >>> > Method (_DSM, 4, Serialized) // _DSM: Device-Specific >>> > Method >>> > { >>> > If ((Arg0 == ToUUID >>> > ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) >>> > { >>> > If ((ToInteger (Arg2) == Zero)) >>> > { >>> > Return (Buffer (One) >>> > { >>> > 0x0F >>> > // . >>> > }) >>> > } >>> > ElseIf ((ToInteger (Arg2) == One)) >>> > { >>> > ECWR () >>> > } >>> > ElseIf ((ToInteger (Arg2) == 0x02)) >>> > { >>> > ECRD () >>> > } >>> > Else >>> > { >>> > Return (Zero) >>> > } >>> > } >>> > >>> > Return (Zero) >>> > } >>> > } >>> > >>> > Thanks, >>> > Rong >>> > >>> > > >>> > > thanks, >>> > > >>> > > greg k-h >>> >>> My biggest concern with this patch is it stands a chance of growing rapidly and extensively. >> >> If the length of match table is a concern, we can turn this into an >> allow list, i.e., disable ucsi_acpi on all Ryzen-based (after Rembrandt- >> R) IdeaPad and Yoga devices by default if the allow list doesn't >> matches, as it seems that these devices heavily shares the same UCSI- >> ACPI implementation (probably developed by the same teams?). >> >> I don't have a strong preference on either, so it's up to you and Greg. >> > >An allow list would be worse from my (slightly selfish) perspective. > >>> We've been having a ton of UCSI issues on this years Thinkpad systems. We'll get them fixed, though it's been slow going. >> >> I don't think ThinkPad devices have the same issue, as their USCI-ACPI >> implementations are completely different, which matches with my >> understanding to Lenovo firmware, i.e., ThinkPad firmware is generally >> developed by different teams compared to IdeaPad/Yoga teams. >> >> For example, ThinkPad Z16 Gen 1 (21D4/21D5) seems to implement the UCSI- >> ACPI DSM properly (my analysis attached at the end of the reply). Even >> if it is problematic, it must be caused by a different bug. >> > >I'm testing on platforms that aren't released yet. Generally you're right - it's not a problem. But this years platforms have been bad (I don't think it's related to the CPU vendor) Well, while the bug itself has nothing to do with the CPU vendor, platforms with the same CPU vendor are more likely to share most ACPI implementations. I guess that's why the bug here is only seen on AMD-based ones. > >>> >>> I don't understand it yet (and your notes above might be useful for narrowing it down). The FW team says the FW passes all the UCSI tests under Windows, >>> >> >> It's just like you can safely use MT-unsafe libc functions in a single- >> threaded program -- this doesn't prove the MT-safety of these functions. >> >> As I've said, the timeout will only reach when a lot of ACPI methods >> compete for the ECMT mutex as the same time. If they tested it with >> little background noise, the mutex acquisition timeout was never reached >> so no test failed. >> >>> but on Linux it's really bad and I see the same on my HW. >> >> Well, I have another conjecture. Typical Windows users don't bother >> taking a look at Windows Event Viewer at all, so they never notices any >> error related to the ECMT mutex. In contrast, checking dmesg is much >> easier. >> > >You might be right. I'm told there is a bunch of qualification testing they do against Windows but I don't know the details and I've definitely previously seen garbage results previously with invalid connector numbers being returned (that we got fixed); so I'm personally dubious. > >Agreed that regular Windows users won't notice. I get this all the time - we fix stuff (usually ACPI errors) that Windows just covers up. Such is the penalty for being a superior OS ;) > >>> >>> Hopefully once we figure out what is going on with the Thinkpads the other platforms will benefit? but flagging that this error is not uncommon. >> >> See my analysis at the end of the reply. >> >>> >>> I'd be surprised if this is Lenovo only to be honest. >>> >> >> That's not surprising. This is not an issue of EC itself, but rather an >> issue of improper implementation of the UCSI-ACPI DSM method, as well as >> other EC-related ACPI methods. >> > >My concern is that you could end up seeing this on a lot of different HW. > >Maybe we just need to be more brutal when an error is detected and quit at that point with a pr_err "your UCSI FW is bad, report it to the vendor" and not retry? This can hardly be detected. The usci_acpi driver know few UCSI things because it's just a transport driver. It don't really understand what's in the buffer. Should we detect it, we would have to do so in the typec_ucsi driver, which is non-optimal. Moreover, a half-valid-half-garbage value could happen to be interpreted as a completely valid value (but *different* from the real value), as long as the garbage bytes are lucky enough. So the detection itself will be unreliable. That's why I said "everything is broken" in the commit message -- we can't trust the buffer any more. If you really want some sorts of detection, the only things we can detect are ACPI object names. I don't think overfitting to them is a good idea and it will definitely lead to a mess if someday a BIOS update fixes the bug. > >There's a huge number of different PCs being released every year, Linux usage is growing, any list approach feels doomed to me. TBH, using a device match table is the least invasive and the most common approach. > >>> I might be wrong, but there's really not a lot common between an Ideapad and Thinkpad - they're completely different FW teams. I would expect the chances that this shows up elsewhere to be reasonable, in which case your list will grow even more. >> >> That's why the best solution is BIOS update. It would be great if Lenovo >> provides BIOS updates to fix all these ECMT chaos. >> >> Meanwhile, some devices (namely, 83JR and 83JU) in the match table have, >> unfortunately, reached the "End of Development Support" as their BIOS >> download pages show: >> >> https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-14akp10/83jr/downloads/ds573496 >> https://pcsupport.lenovo.com/us/en/products/laptops-and-netbooks/yoga-series/yoga-7-2-in-1-16akp10/83ju/downloads/ds573496 >> >> ... and PSREF says 83DR, 83AU and 83AX are "withdrawn," which means they >> are EOL according to the FAQs: >> >> https://psref.lenovo.com/WDProduct/IdeaPad/IdeaPad_5_2_in_1_14AHP9 >> https://psref.lenovo.com/WDProduct/Yoga/Yoga_Pro_7_14ARP8 >> https://psref.lenovo.com/WDProduct/lenovo_slim_pro_7_14arp8 >> > >Yeah, I know. And it sucks that we can't just have Linux on everything with vendor suport. One day we'll get there..... Well, that's why we've already seen a lot of quirk table entries in various drivers and will see more in the future. Using a match table in such a case isn't that horrible from my perspective. > >>> >>> Can we wait until a bit more investigation has been done on Thinkpad? >>> >> >> I originally decided to wait a few months before submitting this. Three >> months had passed and Hans suggested I should submit this: >> >> https://bugzilla.kernel.org/show_bug.cgi?id=221065#c68 >> >> As my analysis will show, I don't think the issue on IdeaPad/Yoga has >> anything in common with ThinkPad. >> >> My speculation on the UCSI issues on ThinkPad is that they might be >> caused by the EC itself or the local mutex (so other ACPI methods may >> access EC simultaneously while ucsi_acpi accessing the EC). >> >>> Right now it's on a small list of gating issues on a few of our platforms - so it is getting a bit more attention. >>> >> >> Did you refer to "a ton of UCSI issues on this years Thinkpad systems," >> or the ECMT chaos on these IdeaPad/Yoga devices? >> >>> Once we have root cause it might be easier to find a better solution? >>> >>> Mark >> >> UCSI-ACPI DSM on ThinkPad Z16 Gen 1 (21D4/21D5): >> >> /* >> * This is an example of my comments. >> */ >> >> /* >> * ThinkPad: UBSY is a local mutex, so no other methods compete for it. >> * >> * IdeaPad/Yoga: ECMT is shared among a lot of ACPI methods: >> * >> * $ grep -rE 'Acquire \(.*ECMT' | wc -l >> * 21 >> * $ grep -orE 'Acquire \(.*ECMT[^)]+' | cut -d ',' -f2 | xargs -i >> bash -c 'echo $(( {} ))ms' | sort -n | uniq -c >> * 1 300ms >> * 2 1000ms >> * 4 2000ms >> * 4 8192ms >> * 10 40960ms >> */ >> Mutex (UBSY, 0x00) >> Method (SECM, 1, Serialized) >> { >> Local0 = 0x64 >> While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) >> { >> Sleep (0x01) >> Local0-- >> } >> >> \_SB.SCMD = Arg0 >> If ((Arg0 == 0x02)) >> { >> Local0 = 0x64 >> While (((\_SB.SCMD != 0x00) && (Local0 != 0x00))) >> { >> Sleep (0x01) >> Local0-- >> } >> } >> } >> >> /* >> * ThinkPad: the UBSY mutex protects the whole UCSI methods. >> * >> * IdeaPad/Yoga: the ECMT mutex protects a single byte read/write to the EC, >> * i.e., protects \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD. >> */ >> Method (ECWR, 0, Serialized) >> { >> /* >> * ThinkPad: the acquisition of UBSY has no timeout (0xFFFF means no timeout >> * according to the ACPI spec), so it will never fail. >> * >> * IdeaPad/Yoga: \_SB.PCI0.LPC0.EC0.ECWT and \_SB.PCI0.LPC0.EC0.ECRD silently >> * fail after the 1s timeout is reached while their callers never check for >> * failure. >> */ >> Acquire (UBSY, 0xFFFF) >> /* >> * ThinkPad: direct EC access, the UCSI buffer and the EC are synchronized. >> * >> * IdeaPad/Yoga: the helper functions fail silently when the timeout is reached, >> * leaving the UCSI buffer and the EC are out of sync. >> */ >> \_SB.MGO0 = MGO0 /* \_SB_.UBTC.MGO0 */ >> \_SB.MGO1 = MGO1 /* \_SB_.UBTC.MGO1 */ >> \_SB.MGO2 = MGO2 /* \_SB_.UBTC.MGO2 */ >> \_SB.MGO3 = MGO3 /* \_SB_.UBTC.MGO3 */ >> \_SB.MGO4 = MGO4 /* \_SB_.UBTC.MGO4 */ >> \_SB.MGO5 = MGO5 /* \_SB_.UBTC.MGO5 */ >> \_SB.MGO6 = MGO6 /* \_SB_.UBTC.MGO6 */ >> \_SB.MGO7 = MGO7 /* \_SB_.UBTC.MGO7 */ >> \_SB.MGO8 = MGO8 /* \_SB_.UBTC.MGO8 */ >> \_SB.MGO9 = MGO9 /* \_SB_.UBTC.MGO9 */ >> \_SB.MGOA = MGOA /* \_SB_.UBTC.MGOA */ >> \_SB.MGOB = MGOB /* \_SB_.UBTC.MGOB */ >> \_SB.MGOC = MGOC /* \_SB_.UBTC.MGOC */ >> \_SB.MGOD = MGOD /* \_SB_.UBTC.MGOD */ >> \_SB.MGOE = MGOE /* \_SB_.UBTC.MGOE */ >> \_SB.MGOF = MGOF /* \_SB_.UBTC.MGOF */ >> \_SB.CTL0 = CTL0 /* \_SB_.UBTC.CTL0 */ >> \_SB.CTL1 = CTL1 /* \_SB_.UBTC.CTL1 */ >> \_SB.CTL2 = CTL2 /* \_SB_.UBTC.CTL2 */ >> \_SB.CTL3 = CTL3 /* \_SB_.UBTC.CTL3 */ >> \_SB.CTL4 = CTL4 /* \_SB_.UBTC.CTL4 */ >> \_SB.CTL5 = CTL5 /* \_SB_.UBTC.CTL5 */ >> \_SB.CTL6 = CTL6 /* \_SB_.UBTC.CTL6 */ >> \_SB.CTL7 = CTL7 /* \_SB_.UBTC.CTL7 */ >> Sleep (0x19) >> SECM (0x01) >> Release (UBSY) >> } >> >> Method (ECRD, 0, Serialized) >> { >> /* >> * Same as above. >> */ >> Acquire (UBSY, 0xFFFF) >> SECM (0x02) >> Sleep (0x19) >> MGI0 = \_SB.MGI0 >> MGI1 = \_SB.MGI1 >> MGI2 = \_SB.MGI2 >> MGI3 = \_SB.MGI3 >> MGI4 = \_SB.MGI4 >> MGI5 = \_SB.MGI5 >> MGI6 = \_SB.MGI6 >> MGI7 = \_SB.MGI7 >> MGI8 = \_SB.MGI8 >> MGI9 = \_SB.MGI9 >> MGIA = \_SB.MGIA >> MGIB = \_SB.MGIB >> MGIC = \_SB.MGIC >> MGID = \_SB.MGID >> MGIE = \_SB.MGIE >> MGIF = \_SB.MGIF >> CCI0 = \_SB.CCI0 >> CCI1 = \_SB.CCI1 >> CCI2 = \_SB.CCI2 >> CCI3 = \_SB.CCI3 >> Release (UBSY) >> } >> >> [...] >> >> Method (_DSM, 4, Serialized) // _DSM: Device-Specific >> Method >> { >> If ((Arg0 == ToUUID >> ("6f8398c2-7ca4-11e4-ad36-631042b5008f") /* Unknown UUID */)) >> { >> If ((ToInteger (Arg2) == 0x00)) >> { >> Return (Buffer (0x01) >> { >> 0x0F >> // . >> }) >> } >> ElseIf ((ToInteger (Arg2) == 0x01)) >> { >> ECWR () >> } >> ElseIf ((ToInteger (Arg2) == 0x02)) >> { >> ECRD () >> } >> } >> >> Return (0x00) >> } >> >> The acpidump can be found at >> https://github.com/linuxhw/ACPI/blob/master/Notebook/Lenovo/ThinkPad/ThinkPad%20Z16%20Gen%201%2021D4S02A00/41C7BA241943.bin >> >Been tied up in meetings today, but I do plan on seeing if this matches what I'm seeing. On my todo list... Thanks a lot for your efforts in pushing Lenovo's Linux support so far. I've used Lenovo laptops for years and your efforts definitely make my life easier :) Thanks, Rong > >Mark ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-12 19:17 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-11 17:59 [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware Rong Zhang 2026-05-11 18:25 ` Greg Kroah-Hartman 2026-05-11 19:12 ` Rong Zhang 2026-05-11 23:11 ` Mark Pearson 2026-05-12 12:46 ` Rong Zhang 2026-05-12 18:28 ` Mark Pearson 2026-05-12 19:16 ` Rong Zhang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox