Skip to content

platform/surface: aggregator: Defer probe while the wakeup GPIO is unavailable - #182

Closed
CmdrShepardsPie wants to merge 1 commit into
linux-surface:v7.2-surface-develfrom
CmdrShepardsPie:sam-probe-defer
Closed

CmdrShepardsPie wants to merge 1 commit into
linux-surface:v7.2-surface-develfrom
CmdrShepardsPie:sam-probe-defer

Conversation

@CmdrShepardsPie

Copy link
Copy Markdown

Fixes the permanent "surface_serial_hub serial0-0: error -EINVAL: failed to setup IRQ" probe failure when surface_aggregator loads before the Intel pinctrl module has bound the GPIO controller (linux-surface/linux-surface#2219, linux-surface/linux-surface#1645, linux-surface/linux-surface#2064, linux-surface/linux-surface#2039). Since b27622f (v6.12), ssam_irq_setup() turns gpiod_get()'s -EPROBE_DEFER into -EINVAL through the fwnode_irq_get() fallback; with gpiod_get_optional(), only "no GPIO described" falls back and the deferral reaches the probe, so the driver core retries once pinctrl is there.

Tested on a Surface Pro 9 (Fedora 43, 7.2.12 with the linux-surface patches, surface_aggregator loaded early from the initramfs): the unpatched kernel reproduces the -EINVAL, with no Type Cover, battery or tablet switch. Patched, the probe defers three times and completes about 0.2 s later, with Type Cover, battery and tablet switch present. Suspend/resume (s2idle) behaves as on an unpatched 7.2.11 kernel.

An earlier patch for the same problem is at https://lore.kernel.org/platform-driver-x86/20261003044844.63157-1-janussss@163.com/; this variant was offered in that thread on 2026-10-23.

Written with an AI coding assistant (Claude Code); reviewed and tested by me.

…available

Since commit b27622f ("platform/surface: Add OF support"),
ssam_irq_setup() treats every error from gpiod_get() as "no wakeup GPIO
described" and falls back to fwnode_irq_get(). On ACPI platforms the
wakeup interrupt is only described as a GpioInt resource, so the fallback
has nothing to find: on x86, acpi_irq_get() is a stub that returns
-EINVAL, and even where it is implemented it only parses Interrupt
resources.

Among the errors turned into -EINVAL this way is -EPROBE_DEFER, which
gpiod_get() returns when the GPIO controller providing the line has not
been registered yet. That is easy to hit on x86 Surface devices: the
Intel pinctrl driver (e.g. pinctrl_tigerlake for the INTC1055 controller
of the Surface Pro 9) is usually built as a module, and nothing orders
its loading before the Surface Serial Hub driver. When surface_aggregator
is loaded early from the initramfs, for example by a modules-load.d entry
or simply by udev coldplug ordering, the probe fails permanently, as
reported for several Surface generations since v6.12:

  surface_serial_hub serial0-0: SAM firmware version: 6.89.139
  surface_serial_hub serial0-0: error -EINVAL: failed to setup IRQ

and with it the whole Surface System Aggregator stack: no Type Cover,
no battery information, no tablet mode switch, until the device is
rebound by hand. Before b27622f the deferral was propagated and the
driver core retried the probe once the GPIO controller was there.

Use gpiod_get_optional(), which returns NULL only when no GPIO is
described (-ENOENT) and propagates every other error, including
-EPROBE_DEFER, to the probe. Fall back to fwnode_irq_get() only in the
NULL case, which is the device tree configuration the fallback was added
for. The probe already reports the error with dev_err_probe(), so a
deferral is logged at debug level only and shows up in the
deferred-probe debugfs list.

An earlier patch for the same problem [1] special-cased -EPROBE_DEFER
in the fallback; as suggested in its review, pass every error on
instead.

Fixes: b27622f ("platform/surface: Add OF support")
Cc: stable@vger.kernel.org # 6.12+
Closes: linux-surface/linux-surface#2219
Link: linux-surface/linux-surface#1645
Link: https://lore.kernel.org/platform-driver-x86/20261003044844.63157-1-janussss@163.com/ [1]
Signed-off-by: Chris Simpson <chris@nilk.net>
Patchset: surface-sam
@CmdrShepardsPie

Copy link
Copy Markdown
Author

Wu Enqiang has now posted a v2 of the original patch to
platform-driver-x86 that makes the same change as this PR
(gpiod_get_optional(), every error passed on, fwnode IRQ only when no
GPIO is described), with Fixes: b27622f and Cc: stable:

https://patchwork.kernel.org/project/platform-driver-x86/patch/20261024054921.48209-1-janussss@163.com/

I'd suggest carrying that one instead of this commit, so the author
and tags match what lands upstream. I'm closing this PR in favour of
it. The code is the same as the change I tested on the Surface Pro 9
above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant