* [PATCH v2] usb: typec: ucsi: retry init when the PPM answers early commands incorrectly
@ 2026-08-24 17:35 Jacob Riff
2026-08-31 9:58 ` Heikki Krogerus
0 siblings, 1 reply; 2+ messages in thread
From: Jacob Riff @ 2026-08-24 17:35 UTC (permalink / raw)
To: Heikki Krogerus; +Cc: linux-usb, Greg Kroah-Hartman, Huang Wei
On some platforms the PPM is not ready to answer commands correctly
for a short window during boot. On the Lenovo ThinkPad X1 Carbon
Gen 14 (21V7, tested on BIOS 1.12 and 1.14) roughly half of all boots
fail ucsi_init() with either -ENODEV (GET_CAPABILITY completes but
reports zero connectors) or -EINVAL (a standard command is rejected,
logged as "possible UCSI driver bug"). The failure is not a timeout:
increasing the sync command completion wait does not change the rate.
Since ucsi_init_work() only requeues on -EPROBE_DEFER, a single bad
answer during that window leaves UCSI dead for the whole session, so
Type-C events are never handled again; most visibly, the machine
silently never resumes charging after the charger is replugged.
Manually reloading ucsi_acpi a few seconds later has succeeded on
every attempt observed, which suggests simply retrying is enough.
Retry -ENODEV and -EINVAL the same way as the role switch wait, log
the retries at debug level, keep the loud report for the case where
the retries are exhausted, and note when init only succeeded after
retrying.
Tested on the affected machine: across 8 consecutive boots with this
patch, 5 hit the failure (matching the historical ~50-60% rate) and
all 5 recovered on the first retry ("PPM init succeeded after 2
attempts"). 0 of 8 boots ended with UCSI unusable, where ~5 of 8
would have without the patch.
Signed-off-by: Jacob Riff <jacob@riff.dk>
---
v2: no functional change; resent without the RFC tag.
- Rebased on usb-next; applies unchanged.
- Discussion on v1: Huang Wei asked whether the -EINVAL retry should
distinguish a not-ready PPM from a genuine driver bug, since
ucsi_read_error() maps UCSI_ERROR_INVALID_CON_NUM /
UNREGONIZED_CMD / INVALID_CMD_ARGUMENT to -EINVAL. The two cases
are indistinguishable by error code here, so the patch relies on
context and persistence instead: the retry exists only in the
ucsi_init_work() path, it is bounded, and the dev_err() in
ucsi_read_error() is untouched and still fires on the first
occurrence. No code change resulted.
v1: https://lore.kernel.org/linux-usb/20260815005724.8741-1-jacob@riff.dk/
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -2212,18 +2212,36 @@
int ret;
ret = ucsi_init(ucsi);
- if (ret)
- dev_err_probe(ucsi->dev, ret, "PPM init failed\n");
+ if (!ret) {
+ if (ucsi->work_count)
+ dev_info(ucsi->dev,
+ "PPM init succeeded after %u attempts\n",
+ ucsi->work_count + 1);
+ return;
+ }
- if (ret == -EPROBE_DEFER) {
- if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT) {
- dev_err(ucsi->dev, "PPM init failed, stop trying\n");
+ /*
+ * On some platforms the PPM is not ready to answer commands
+ * correctly for a short window during boot: standard commands are
+ * rejected or GET_CAPABILITY reports zero connectors, seen as
+ * -EINVAL or -ENODEV from ucsi_init(), and a retry moments later
+ * succeeds (observed on Lenovo ThinkPad X1 Carbon Gen 14, where
+ * this affects roughly half of all boots). Retry those like the
+ * USB role switch wait instead of giving up on the first attempt.
+ */
+ if (ret == -EPROBE_DEFER || ret == -ENODEV || ret == -EINVAL) {
+ if (ucsi->work_count++ < UCSI_ROLE_SWITCH_WAIT_COUNT) {
+ dev_dbg(ucsi->dev, "PPM init failed (%pe), retrying\n",
+ ERR_PTR(ret));
+ queue_delayed_work(system_dfl_long_wq, &ucsi->work,
+ UCSI_ROLE_SWITCH_INTERVAL);
return;
}
-
- queue_delayed_work(system_dfl_long_wq, &ucsi->work,
- UCSI_ROLE_SWITCH_INTERVAL);
+ dev_err(ucsi->dev, "PPM init failed, stop trying\n");
+ return;
}
+
+ dev_err_probe(ucsi->dev, ret, "PPM init failed\n");
}
/**
base-commit: e1e6e541c5c9cf548e9fdc35fc26808c82074440
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH v2] usb: typec: ucsi: retry init when the PPM answers early commands incorrectly
2026-08-24 17:35 [PATCH v2] usb: typec: ucsi: retry init when the PPM answers early commands incorrectly Jacob Riff
@ 2026-08-31 9:58 ` Heikki Krogerus
0 siblings, 0 replies; 2+ messages in thread
From: Heikki Krogerus @ 2026-08-31 9:58 UTC (permalink / raw)
To: Jacob Riff; +Cc: linux-usb, Greg Kroah-Hartman, Huang Wei
On Mon, Aug 24, 2026 at 10:35:36AM -0700, Jacob Riff wrote:
> On some platforms the PPM is not ready to answer commands correctly
> for a short window during boot. On the Lenovo ThinkPad X1 Carbon
> Gen 14 (21V7, tested on BIOS 1.12 and 1.14) roughly half of all boots
> fail ucsi_init() with either -ENODEV (GET_CAPABILITY completes but
> reports zero connectors) or -EINVAL (a standard command is rejected,
> logged as "possible UCSI driver bug"). The failure is not a timeout:
> increasing the sync command completion wait does not change the rate.
>
> Since ucsi_init_work() only requeues on -EPROBE_DEFER, a single bad
> answer during that window leaves UCSI dead for the whole session, so
> Type-C events are never handled again; most visibly, the machine
> silently never resumes charging after the charger is replugged.
> Manually reloading ucsi_acpi a few seconds later has succeeded on
> every attempt observed, which suggests simply retrying is enough.
>
> Retry -ENODEV and -EINVAL the same way as the role switch wait, log
> the retries at debug level, keep the loud report for the case where
> the retries are exhausted, and note when init only succeeded after
> retrying.
>
> Tested on the affected machine: across 8 consecutive boots with this
> patch, 5 hit the failure (matching the historical ~50-60% rate) and
> all 5 recovered on the first retry ("PPM init succeeded after 2
> attempts"). 0 of 8 boots ended with UCSI unusable, where ~5 of 8
> would have without the patch.
>
> Signed-off-by: Jacob Riff <jacob@riff.dk>
Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> ---
> v2: no functional change; resent without the RFC tag.
> - Rebased on usb-next; applies unchanged.
> - Discussion on v1: Huang Wei asked whether the -EINVAL retry should
> distinguish a not-ready PPM from a genuine driver bug, since
> ucsi_read_error() maps UCSI_ERROR_INVALID_CON_NUM /
> UNREGONIZED_CMD / INVALID_CMD_ARGUMENT to -EINVAL. The two cases
> are indistinguishable by error code here, so the patch relies on
> context and persistence instead: the retry exists only in the
> ucsi_init_work() path, it is bounded, and the dev_err() in
> ucsi_read_error() is untouched and still fires on the first
> occurrence. No code change resulted.
>
> v1: https://lore.kernel.org/linux-usb/20260815005724.8741-1-jacob@riff.dk/
>
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -2212,18 +2212,36 @@
> int ret;
>
> ret = ucsi_init(ucsi);
> - if (ret)
> - dev_err_probe(ucsi->dev, ret, "PPM init failed\n");
> + if (!ret) {
> + if (ucsi->work_count)
> + dev_info(ucsi->dev,
> + "PPM init succeeded after %u attempts\n",
> + ucsi->work_count + 1);
> + return;
> + }
>
> - if (ret == -EPROBE_DEFER) {
> - if (ucsi->work_count++ > UCSI_ROLE_SWITCH_WAIT_COUNT) {
> - dev_err(ucsi->dev, "PPM init failed, stop trying\n");
> + /*
> + * On some platforms the PPM is not ready to answer commands
> + * correctly for a short window during boot: standard commands are
> + * rejected or GET_CAPABILITY reports zero connectors, seen as
> + * -EINVAL or -ENODEV from ucsi_init(), and a retry moments later
> + * succeeds (observed on Lenovo ThinkPad X1 Carbon Gen 14, where
> + * this affects roughly half of all boots). Retry those like the
> + * USB role switch wait instead of giving up on the first attempt.
> + */
> + if (ret == -EPROBE_DEFER || ret == -ENODEV || ret == -EINVAL) {
> + if (ucsi->work_count++ < UCSI_ROLE_SWITCH_WAIT_COUNT) {
> + dev_dbg(ucsi->dev, "PPM init failed (%pe), retrying\n",
> + ERR_PTR(ret));
> + queue_delayed_work(system_dfl_long_wq, &ucsi->work,
> + UCSI_ROLE_SWITCH_INTERVAL);
> return;
> }
> -
> - queue_delayed_work(system_dfl_long_wq, &ucsi->work,
> - UCSI_ROLE_SWITCH_INTERVAL);
> + dev_err(ucsi->dev, "PPM init failed, stop trying\n");
> + return;
> }
> +
> + dev_err_probe(ucsi->dev, ret, "PPM init failed\n");
> }
>
> /**
>
> base-commit: e1e6e541c5c9cf548e9fdc35fc26808c82074440
--
heikki
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-08-31 9:58 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-24 17:35 [PATCH v2] usb: typec: ucsi: retry init when the PPM answers early commands incorrectly Jacob Riff
2026-08-31 9:58 ` Heikki Krogerus
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox