Re: [PATCH] usb: typec: ucsi: acpi: Disable on devices with broken firmware
From: Rong Zhang
Date: Tue May 12 2026 - 15:17:34 EST
Hi Mark,
于 2026年5月13日 GMT+08:00 02:28:56,Mark Pearson <mpearson-lenovo@xxxxxxxxx> 写道:
>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@xxxxxxxx>
>>> > > > ---
>>> > > > 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