* [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP systems with empty _DSM func 2
@ 2026-04-20 16:05 Francesco Orro
2026-04-20 17:23 ` [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on " Francesco Orro
2026-04-27 8:39 ` [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP " Heikki Krogerus
0 siblings, 2 replies; 4+ messages in thread
From: Francesco Orro @ 2026-04-20 16:05 UTC (permalink / raw)
To: linux-usb@vger.kernel.org; +Cc: Heikki Krogerus, Greg KH
Hi,
The attached RFC patch lets ucsi_acpi probe successfully on HP ZBook
Fury G1i 16 inch (and likely other HP workstations shipping the same
"UcsiAcpi" SSDT), where _DSM func 2 (READ) is a stub and UCSI_VERSION
stays 0. Details in the commit message below.
Main open question for the list: is there a known-good pattern for
ucsi_acpi drivers to avoid disrupting alt-mode state already negotiated
by BIOS? On cold boot with a Thunderbolt dock attached, the PPM_RESET
issued by this patch - and later by Linux UCSI core in ucsi_init() -
tears down the TBT alt-mode the BIOS had set up, and the DP tunnel to
the dock dies until the user physically replugs. My local workaround
is to late-load ucsi_acpi via a systemd service after the thunderbolt
driver has adopted the tunnels, but that feels like papering over a
design assumption I am missing.
Tested on one machine only. Happy to refine the patch if the direction
is acceptable.
Regards,
Francesco Orro
---
From: Francesco Orro <ncesco@interstellar.eu>
Date: Mon, 20 Apr 2026 16:40:00 +0200
Subject: [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on systems with empty _DSM func 2
On HP ZBook Fury G1i 16 inch (BIOS X96 01.03.04) the SSDT16 "UcsiAcpi"
exposes a _DSM function 2 (READ) whose body is empty, so UCSI_VERSION
stays 0x0000 after the read. ucsi_init() treats VERSION=0 as firmware
absent and bails with -ENODEV, so /sys/class/typec is empty and no
alt-mode info reaches userspace.
The PPM is alive: writing UCSI_PPM_RESET through _DSM function 1 (WRITE)
drives RESET_COMPLETE in CCI. We can therefore bootstrap the PPM
explicitly on probe when necessary and, once RESET_COMPLETE is observed,
default VERSION to UCSI 1.2 - which matches the semantics advertised by
the SSDT tables on this platform.
The bootstrap checks CCI first and returns early if RESET_COMPLETE is
already set, to avoid resetting a PPM left in a stable state by
firmware. Note that this early-return path was not exercised on the
tested platform: on cold boot CCI did not have RESET_COMPLETE at probe
time and the PPM_RESET was issued. Consequently, alt-mode state
negotiated during BIOS POST (in this case a Thunderbolt dock's TBT
alt-mode) was disrupted at boot. Linux UCSI core later calls
ucsi_reset_ppm() in ucsi_init() regardless, so the PPM reset on probe
is arguably not the root cause of the disruption, but the patch leaves
the door open to avoid the early reset when firmware does leave the
flag set.
Bootstrap failure is non-fatal: we log a warning and continue. If the
PPM later reaches RESET_COMPLETE asynchronously, read_version() still
recovers via the UCSI_CCI_RESET_COMPLETE check gated by the
needs_bootstrap flag.
The behaviour is gated by DMI because unconditionally issuing a
PPM_RESET on systems whose firmware _does_ populate VERSION correctly
would be aggressive and unjustified. The DMI match starts with HP ZBook
Fury G1i 16 inch; other vendors/models can be added as they are
confirmed.
Tested on HP ZBook Fury G1i 16 inch Mobile Workstation PC with kernel
6.19.13. Before the patch ucsi_acpi probe returns -ENODEV; after the
patch /sys/class/typec/port{0,1,2} appear with partner altmodes
exposed when a USB4/TBT device is connected.
Signed-off-by: Francesco Orro <ncesco@interstellar.eu>
---
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c 2026-04-18 10:46:48.000000000 +0200
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c 2026-04-20 17:47:45.529559324 +0200
@@ -9,6 +9,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/acpi.h>
+#include <linux/delay.h>
#include <linux/dmi.h>
#include "ucsi.h"
@@ -17,11 +18,15 @@
#define UCSI_DSM_FUNC_WRITE 1
#define UCSI_DSM_FUNC_READ 2
+#define UCSI_ACPI_BOOTSTRAP_RETRIES 20
+#define UCSI_ACPI_BOOTSTRAP_DELAY_MS 50
+
struct ucsi_acpi {
struct device *dev;
struct ucsi *ucsi;
void *base;
bool check_bogus_event;
+ bool needs_bootstrap;
guid_t guid;
u64 cmd;
};
@@ -46,6 +51,7 @@
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
+ u32 cci;
ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
if (ret)
@@ -53,6 +59,21 @@
memcpy(version, ua->base + UCSI_VERSION, sizeof(*version));
+ /*
+ * Some firmwares (observed on HP ZBook Fury 16 G1i, SSDT16
+ * "UcsiAcpi") leave the VERSION field untouched by _DSM func 2.
+ * If the PPM has reached RESET_COMPLETE - typically because the
+ * firmware (or our bootstrap on probe) left it in that state -
+ * fall back to UCSI 1.2 which matches what those SSDTs advertise.
+ */
+ if (!*version && ua->needs_bootstrap) {
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE) {
+ dev_info(ua->dev, "VERSION unpopulated; defaulting to UCSI 1.2 after PPM RESET_COMPLETE\n");
+ *version = UCSI_VERSION_1_2;
+ }
+ }
+
return 0;
}
@@ -143,6 +164,56 @@
.async_control = ucsi_acpi_async_control
};
+/*
+ * DMI list of systems whose UCSI ACPI firmware does not populate VERSION
+ * from _DSM func 2 (READ). Entries here opt into ucsi_acpi_bootstrap_ppm()
+ * at probe time.
+ */
+static const struct dmi_system_id ucsi_acpi_bootstrap_quirk[] = {
+ {
+ .ident = "HP ZBook Fury G1i 16 inch",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME,
+ "HP ZBook Fury G1i 16 inch"),
+ },
+ },
+ { }
+};
+
+/*
+ * Drive PPM_RESET via _DSM WRITE and wait for RESET_COMPLETE, but only if
+ * the firmware hasn't already left the PPM in that state. Skipping the
+ * reset avoids disrupting alt mode state already negotiated by firmware
+ * (e.g. a Thunderbolt dock attached at boot whose TBT alt mode entry
+ * would otherwise be torn down by a fresh PPM reset).
+ */
+static int ucsi_acpi_bootstrap_ppm(struct ucsi_acpi *ua)
+{
+ u64 cmd = UCSI_PPM_RESET;
+ u32 cci;
+ int retries;
+
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE) {
+ dev_info(ua->dev, "PPM already in RESET_COMPLETE, skipping bootstrap\n");
+ return 0;
+ }
+
+ memcpy(ua->base + UCSI_CONTROL, &cmd, sizeof(cmd));
+ if (ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE))
+ return -EIO;
+
+ for (retries = UCSI_ACPI_BOOTSTRAP_RETRIES; retries > 0; retries--) {
+ msleep(UCSI_ACPI_BOOTSTRAP_DELAY_MS);
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE)
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
static const struct dmi_system_id ucsi_acpi_quirks[] = {
{
.matches = {
@@ -201,6 +272,15 @@
ua->dev = &pdev->dev;
+ if (dmi_check_system(ucsi_acpi_bootstrap_quirk)) {
+ ua->needs_bootstrap = true;
+ ret = ucsi_acpi_bootstrap_ppm(ua);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "PPM bootstrap did not complete (%d); continuing anyway\n",
+ ret);
+ }
+
id = dmi_first_match(ucsi_acpi_quirks);
if (id)
ops = id->driver_data;
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on systems with empty _DSM func 2
2026-04-20 16:05 [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP systems with empty _DSM func 2 Francesco Orro
@ 2026-04-20 17:23 ` Francesco Orro
2026-04-27 9:02 ` Heikki Krogerus
2026-04-27 8:39 ` [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP " Heikki Krogerus
1 sibling, 1 reply; 4+ messages in thread
From: Francesco Orro @ 2026-04-20 17:23 UTC (permalink / raw)
To: linux-usb; +Cc: Heikki Krogerus, Greg KH
On HP ZBook Fury G1i 16 inch (BIOS X96 01.03.04) the SSDT16 "UcsiAcpi"
exposes a _DSM function 2 (READ) whose body is empty, so UCSI_VERSION
stays 0x0000 after the read. ucsi_init() treats VERSION=0 as firmware
absent and bails with -ENODEV, so /sys/class/typec is empty and no
alt-mode info reaches userspace.
The PPM is alive: writing UCSI_PPM_RESET through _DSM function 1 (WRITE)
drives RESET_COMPLETE in CCI. We can therefore bootstrap the PPM
explicitly on probe when necessary and, once RESET_COMPLETE is observed,
default VERSION to UCSI 1.2 - which matches the semantics advertised by
the SSDT tables on this platform.
The bootstrap checks CCI first and returns early if RESET_COMPLETE is
already set, to avoid resetting a PPM left in a stable state by
firmware. Note that this early-return path was not exercised on the
tested platform: on cold boot CCI did not have RESET_COMPLETE at probe
time and the PPM_RESET was issued. Consequently, alt-mode state
negotiated during BIOS POST (in this case a Thunderbolt dock's TBT
alt-mode) was disrupted at boot. Linux UCSI core later calls
ucsi_reset_ppm() in ucsi_init() regardless, so the PPM reset on probe
is arguably not the root cause of the disruption, but the patch leaves
the door open to avoid the early reset when firmware does leave the
flag set.
Bootstrap failure is non-fatal: we log a warning and continue. If the
PPM later reaches RESET_COMPLETE asynchronously, read_version() still
recovers via the UCSI_CCI_RESET_COMPLETE check gated by the
needs_bootstrap flag.
The behaviour is gated by DMI because unconditionally issuing a
PPM_RESET on systems whose firmware _does_ populate VERSION correctly
would be aggressive and unjustified. The DMI match starts with HP ZBook
Fury G1i 16 inch; other vendors/models can be added as they are
confirmed.
Tested on HP ZBook Fury G1i 16 inch Mobile Workstation PC with kernel
6.19.13. Before the patch ucsi_acpi probe returns -ENODEV; after the
patch /sys/class/typec/port{0,1,2} appear with partner altmodes
exposed when a USB4/TBT device is connected.
Signed-off-by: Francesco Orro <ncesco@interstellar.eu>
---
Resending: previous send was mangled by quoted-printable encoding.
No content changes.
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c 2026-04-18 10:46:48.000000000 +0200
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c 2026-04-20 17:47:45.529559324 +0200
@@ -9,6 +9,7 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/acpi.h>
+#include <linux/delay.h>
#include <linux/dmi.h>
#include "ucsi.h"
@@ -17,11 +18,15 @@
#define UCSI_DSM_FUNC_WRITE 1
#define UCSI_DSM_FUNC_READ 2
+#define UCSI_ACPI_BOOTSTRAP_RETRIES 20
+#define UCSI_ACPI_BOOTSTRAP_DELAY_MS 50
+
struct ucsi_acpi {
struct device *dev;
struct ucsi *ucsi;
void *base;
bool check_bogus_event;
+ bool needs_bootstrap;
guid_t guid;
u64 cmd;
};
@@ -46,6 +51,7 @@
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
+ u32 cci;
ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
if (ret)
@@ -53,6 +59,21 @@
memcpy(version, ua->base + UCSI_VERSION, sizeof(*version));
+ /*
+ * Some firmwares (observed on HP ZBook Fury 16 G1i, SSDT16
+ * "UcsiAcpi") leave the VERSION field untouched by _DSM func 2.
+ * If the PPM has reached RESET_COMPLETE - typically because the
+ * firmware (or our bootstrap on probe) left it in that state -
+ * fall back to UCSI 1.2 which matches what those SSDTs advertise.
+ */
+ if (!*version && ua->needs_bootstrap) {
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE) {
+ dev_info(ua->dev, "VERSION unpopulated; defaulting to UCSI 1.2 after PPM RESET_COMPLETE\n");
+ *version = UCSI_VERSION_1_2;
+ }
+ }
+
return 0;
}
@@ -143,6 +164,56 @@
.async_control = ucsi_acpi_async_control
};
+/*
+ * DMI list of systems whose UCSI ACPI firmware does not populate VERSION
+ * from _DSM func 2 (READ). Entries here opt into ucsi_acpi_bootstrap_ppm()
+ * at probe time.
+ */
+static const struct dmi_system_id ucsi_acpi_bootstrap_quirk[] = {
+ {
+ .ident = "HP ZBook Fury G1i 16 inch",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME,
+ "HP ZBook Fury G1i 16 inch"),
+ },
+ },
+ { }
+};
+
+/*
+ * Drive PPM_RESET via _DSM WRITE and wait for RESET_COMPLETE, but only if
+ * the firmware hasn't already left the PPM in that state. Skipping the
+ * reset avoids disrupting alt mode state already negotiated by firmware
+ * (e.g. a Thunderbolt dock attached at boot whose TBT alt mode entry
+ * would otherwise be torn down by a fresh PPM reset).
+ */
+static int ucsi_acpi_bootstrap_ppm(struct ucsi_acpi *ua)
+{
+ u64 cmd = UCSI_PPM_RESET;
+ u32 cci;
+ int retries;
+
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE) {
+ dev_info(ua->dev, "PPM already in RESET_COMPLETE, skipping bootstrap\n");
+ return 0;
+ }
+
+ memcpy(ua->base + UCSI_CONTROL, &cmd, sizeof(cmd));
+ if (ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE))
+ return -EIO;
+
+ for (retries = UCSI_ACPI_BOOTSTRAP_RETRIES; retries > 0; retries--) {
+ msleep(UCSI_ACPI_BOOTSTRAP_DELAY_MS);
+ memcpy(&cci, ua->base + UCSI_CCI, sizeof(cci));
+ if (cci & UCSI_CCI_RESET_COMPLETE)
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+
static const struct dmi_system_id ucsi_acpi_quirks[] = {
{
.matches = {
@@ -201,6 +272,15 @@
ua->dev = &pdev->dev;
+ if (dmi_check_system(ucsi_acpi_bootstrap_quirk)) {
+ ua->needs_bootstrap = true;
+ ret = ucsi_acpi_bootstrap_ppm(ua);
+ if (ret)
+ dev_warn(&pdev->dev,
+ "PPM bootstrap did not complete (%d); continuing anyway\n",
+ ret);
+ }
+
id = dmi_first_match(ucsi_acpi_quirks);
if (id)
ops = id->driver_data;
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP systems with empty _DSM func 2
2026-04-20 16:05 [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP systems with empty _DSM func 2 Francesco Orro
2026-04-20 17:23 ` [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on " Francesco Orro
@ 2026-04-27 8:39 ` Heikki Krogerus
1 sibling, 0 replies; 4+ messages in thread
From: Heikki Krogerus @ 2026-04-27 8:39 UTC (permalink / raw)
To: Francesco Orro; +Cc: linux-usb@vger.kernel.org, Greg KH
Hi,
On Mon, Apr 20, 2026 at 04:05:47PM +0000, Francesco Orro wrote:
> Hi,
>
> The attached RFC patch lets ucsi_acpi probe successfully on HP ZBook
> Fury G1i 16 inch (and likely other HP workstations shipping the same
> "UcsiAcpi" SSDT), where _DSM func 2 (READ) is a stub and UCSI_VERSION
> stays 0. Details in the commit message below.
Please report this to HP. We really need to know which version they
support.
> Main open question for the list: is there a known-good pattern for
> ucsi_acpi drivers to avoid disrupting alt-mode state already negotiated
> by BIOS? On cold boot with a Thunderbolt dock attached, the PPM_RESET
> issued by this patch - and later by Linux UCSI core in ucsi_init() -
> tears down the TBT alt-mode the BIOS had set up, and the DP tunnel to
> the dock dies until the user physically replugs. My local workaround
> is to late-load ucsi_acpi via a systemd service after the thunderbolt
> driver has adopted the tunnels, but that feels like papering over a
> design assumption I am missing.
I'm surprised that PPM_RESET has that effect on your system, because
it does not reset the connectors. If you want to reset the connectors
you are expected to explicitly reset each of them before the executing
PPM_RESET. I'm not sure the PPM on this platform is behaving correctly,
so I think you need to contact HP about this too.
> Tested on one machine only. Happy to refine the patch if the direction
> is acceptable.
>
> Regards,
> Francesco Orro
>
> ---
>
> From: Francesco Orro <ncesco@interstellar.eu>
> Date: Mon, 20 Apr 2026 16:40:00 +0200
> Subject: [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on systems with empty _DSM func 2
Please avoid attaching the patch to the coverletter like this. It is
a bit confusing. Is this the same patch as the one you've sent
separately in this thread?
thanks,
--
heikki
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on systems with empty _DSM func 2
2026-04-20 17:23 ` [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on " Francesco Orro
@ 2026-04-27 9:02 ` Heikki Krogerus
0 siblings, 0 replies; 4+ messages in thread
From: Heikki Krogerus @ 2026-04-27 9:02 UTC (permalink / raw)
To: Francesco Orro; +Cc: linux-usb, Greg KH
Hi Francesco,
On Mon, Apr 20, 2026 at 07:23:41PM +0200, Francesco Orro wrote:
> On HP ZBook Fury G1i 16 inch (BIOS X96 01.03.04) the SSDT16 "UcsiAcpi"
> exposes a _DSM function 2 (READ) whose body is empty, so UCSI_VERSION
> stays 0x0000 after the read. ucsi_init() treats VERSION=0 as firmware
> absent and bails with -ENODEV, so /sys/class/typec is empty and no
> alt-mode info reaches userspace.
>
> The PPM is alive: writing UCSI_PPM_RESET through _DSM function 1 (WRITE)
> drives RESET_COMPLETE in CCI. We can therefore bootstrap the PPM
> explicitly on probe when necessary and, once RESET_COMPLETE is observed,
> default VERSION to UCSI 1.2 - which matches the semantics advertised by
> the SSDT tables on this platform.
>
> The bootstrap checks CCI first and returns early if RESET_COMPLETE is
> already set, to avoid resetting a PPM left in a stable state by
> firmware. Note that this early-return path was not exercised on the
> tested platform: on cold boot CCI did not have RESET_COMPLETE at probe
> time and the PPM_RESET was issued. Consequently, alt-mode state
> negotiated during BIOS POST (in this case a Thunderbolt dock's TBT
> alt-mode) was disrupted at boot. Linux UCSI core later calls
> ucsi_reset_ppm() in ucsi_init() regardless, so the PPM reset on probe
> is arguably not the root cause of the disruption, but the patch leaves
> the door open to avoid the early reset when firmware does leave the
> flag set.
>
> Bootstrap failure is non-fatal: we log a warning and continue. If the
> PPM later reaches RESET_COMPLETE asynchronously, read_version() still
> recovers via the UCSI_CCI_RESET_COMPLETE check gated by the
> needs_bootstrap flag.
>
> The behaviour is gated by DMI because unconditionally issuing a
> PPM_RESET on systems whose firmware _does_ populate VERSION correctly
> would be aggressive and unjustified. The DMI match starts with HP ZBook
> Fury G1i 16 inch; other vendors/models can be added as they are
> confirmed.
>
> Tested on HP ZBook Fury G1i 16 inch Mobile Workstation PC with kernel
> 6.19.13. Before the patch ucsi_acpi probe returns -ENODEV; after the
> patch /sys/class/typec/port{0,1,2} appear with partner altmodes
> exposed when a USB4/TBT device is connected.
>
> Signed-off-by: Francesco Orro <ncesco@interstellar.eu>
> ---
> Resending: previous send was mangled by quoted-printable encoding.
> No content changes.
Where did you send it? Or do you mean the patch you attached to the
cover-letter? I also can't find v1, v2, v3, v4, v5 or v6 anywhere, so
where did you send them?
In any case, you need to start by reporting these issues to HP.
The version field must return the actual ucsi version, so that really
needs to be fixed this platform. Guessing the version is a really
fragile solution.
In the UCSI specification the behaviour from PPM_RESET is a bit vague
in deed. However, the specification, starting from at least UCSI
1.2, does make a note that the connectors need to be reset separately.
So the connection states of the connectors should not be affected by
PPM_RESET.
thanks,
--
heikki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-04-27 9:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-20 16:05 [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP systems with empty _DSM func 2 Francesco Orro
2026-04-20 17:23 ` [PATCH v7] usb: typec: ucsi: acpi: bootstrap PPM on " Francesco Orro
2026-04-27 9:02 ` Heikki Krogerus
2026-04-27 8:39 ` [RFC PATCH] usb: typec: ucsi: acpi: bootstrap PPM on HP " Heikki Krogerus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox