Re: [PATCH RFC 2/2] usb: typec: ucsi: increase timeout for PPM reset operations

Fedor Pchelkin
2025-02-18T19:53:23Z

On Tue, 18. Feb 11:57, Mark Pearson wrote:
> Hi Fedor,
>
> On Thu, Feb 6, 2025, at 1:43 PM, Fedor Pchelkin wrote:
> > It is observed that on some systems an initial PPM reset during the boot
> > phase can trigger a timeout:
> >
> > [ 6.482546] ucsi_acpi USBC000:00: failed to reset PPM!
> > [ 6.482551] ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed
> >
> > Still, increasing the timeout value, albeit being the most straightforward
> > solution, eliminates the problem: the initial PPM reset may take up to
> > ~8000-10000ms on some Lenovo laptops. When it is reset after the above
> > period of time (or even if ucsi_reset_ppm() is not called overall), UCSI
> > works as expected.
> >
> > Moreover, if the ucsi_acpi module is loaded/unloaded manually after the
> > system has booted, reading the CCI values and resetting the PPM works
> > perfectly, without any timeout. Thus it's only a boot-time issue.
> >
> > The reason for this behavior is not clear but it may be the consequence
> > of some tricks that the firmware performs or be an actual firmware bug.
> > As a workaround, increase the timeout to avoid failing the UCSI
> > initialization prematurely.
> >
>
> Could you let me know which Lenovo platform(s) you see the issue on?
>
> I don't have any concerns with the patch below, but if the platform is in
> the Linux program I can reach out to the FW team and try to determine if
> there's an expected time needed (and how close we are to it).

Yep, here. (also at the bottom of the [PATCH RFC 0/2] mail)

Please let me know if there's more info needed.

Machine:
Type: Laptop System: LENOVO product: 21D0 v: ThinkBook 14 G4+ ARA
serial: <superuser required>
Mobo: LENOVO model: LNVNB161216 v: SDK0T76479 WIN
serial: <superuser required> UEFI: LENOVO v: J6CN50WW date: 09/27/2024

Relevant part of the ACPI dump.

Scope (\_SB)
{
Device (UBTC)
{
Name (_HID, EisaId ("USBC000")) // _HID: Hardware ID
Name (_CID, EisaId ("PNP0CA0")) // _CID: Compatible ID
Name (_UID, Zero) // _UID: Unique ID
Name (_DDN, "USB Type C") // _DDN: DOS Device Name
Name (_ADR, Zero) // _ADR: Address
Name (_DEP, Package (0x01) // _DEP: Dependencies
{
\_SB.PCI0.LPC0.EC0
})
Method (_STA, 0, NotSerialized) // _STA: Status
{
Return (0x0F)
}

Method (_PS0, 0, Serialized) // _PS0: Power State 0
{
Sleep (0x07D0)
}

Method (_PS3, 0, Serialized) // _PS3: Power State 3
{
Sleep (0x07D0)
}

Method (TPLD, 2, Serialized)
{
Name (PCKG, Package (0x01)
{
Buffer (0x10){}
})
CreateField (DerefOf (PCKG [Zero]), Zero, 0x07, REV)
REV = One
CreateField (DerefOf (PCKG [Zero]), 0x40, One, VISI)
VISI = Arg0
CreateField (DerefOf (PCKG [Zero]), 0x57, 0x08, GPOS)
GPOS = Arg1
CreateField (DerefOf (PCKG [Zero]), 0x4A, 0x04, SHAP)
SHAP = One
CreateField (DerefOf (PCKG [Zero]), 0x20, 0x10, WID)
WID = 0x08
CreateField (DerefOf (PCKG [Zero]), 0x30, 0x10, HGT)
HGT = 0x03
Return (PCKG) /* \_SB_.UBTC.TPLD.PCKG */
}

Method (_CRS, 0, NotSerialized) // _CRS: Current Resource Settings
{
Name (RBUF, ResourceTemplate ()
{
Memory32Fixed (ReadWrite,
0x7AF66000, // Address Base
0x00001000, // Address Length
)
})
Return (RBUF) /* \_SB_.UBTC._CRS.RBUF */
}

Device (HSP1)
{
Name (_ADR, One) // _ADR: Address
Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities
{
0xFF,
0x09,
Zero,
Zero
})
Method (_PLD, 0, NotSerialized) // _PLD: Physical Location of Device
{
Return (TPLD (One, 0x04))
}
}

Device (HSP2)
{
Name (_ADR, One) // _ADR: Address
Name (_UPC, Package (0x04) // _UPC: USB Port Capabilities
{
0xFF,
0x09,
Zero,
Zero
})
Method (_PLD, 0, NotSerialized) // _PLD: Physical Location of Device
{
Return (TPLD (One, 0x04))
}
}

OperationRegion (USBC, SystemMemory, 0x7AF66000, 0x30)
Field (USBC, ByteAcc, Lock, Preserve)
{
VER1, 8,
VER2, 8,
RSV1, 8,
RSV2, 8,
CCI0, 8,
CCI1, 8,
CCI2, 8,
CCI3, 8,
CTL0, 8,
CTL1, 8,
CTL2, 8,
CTL3, 8,
CTL4, 8,
CTL5, 8,
CTL6, 8,
CTL7, 8,
MGI0, 8,
MGI1, 8,
MGI2, 8,
MGI3, 8,
MGI4, 8,
MGI5, 8,
MGI6, 8,
MGI7, 8,
MGI8, 8,
MGI9, 8,
MGIA, 8,
MGIB, 8,
MGIC, 8,
MGID, 8,
MGIE, 8,
MGIF, 8,
MGO0, 8,
MGO1, 8,
MGO2, 8,
MGO3, 8,
MGO4, 8,
MGO5, 8,
MGO6, 8,
MGO7, 8,
MGO8, 8,
MGO9, 8,
MGOA, 8,
MGOB, 8,
MGOC, 8,
MGOD, 8,
MGOE, 8,
MGOF, 8
}

OperationRegion (DBG0, SystemIO, 0x80, One)
Field (DBG0, ByteAcc, NoLock, Preserve)
{
IO80, 8
}

Method (NTFY, 0, Serialized)
{
ECRD ()
Sleep (One)
Notify (\_SB.UBTC, 0x80) // Status Change
}

Method (ECWR, 0, Serialized)
{
IO80 = 0xA0
\_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 = 0xA1
}

Method (ECRD, 0, Serialized)
{
IO80 = 0xA3
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 = 0xA4
}

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)
}
}
}