[BUG] media: ipu-bridge: sensor fwnode graph not rebuilt on warm reload / hibernate-resume
From: Fernando Rimoli
Date: Tue Jul 14 2026 - 09:56:01 EST
Hi all,
Reporting a bug (not a patch) in the Intel IPU6 / ipu-bridge sensor
setup. On IPU6 platforms an IPU6 sensor (e.g. ov5693) that depends on
the ipu-bridge software_node graph for its link-frequencies property
fails to re-probe after the intel-ipu6 stack is unloaded and reloaded.
This includes hibernate-resume when a sleep hook reloads the stack. The
cause is two interacting issues: the bridge only builds the graph on
the first cold probe, and intel-ipu6's .remove leaks the bridge's
software_nodes, so a later probe cannot rebuild them.
Affected hardware / software
============================
- Microsoft Surface Pro 9 (Intel, IPU6), front sensor ov5693 (ACPI
OVTI5693).
- Rear sensor ov13858 is NOT affected. It reads link-frequencies from
its own ACPI _DSD, so it does not depend on the bridge-injected
property.
- Reproduced on linux-surface 6.19.8. Code paths below are quoted from
mainline v7.2-rc2 (drivers/media/pci/intel/ipu-bridge.c,
drivers/media/pci/intel/ipu6/ipu6.c, drivers/media/i2c/ov5693.c).
Line numbers are indicative of v7.2-rc2.
Symptom
=======
After unloading and reloading the IPU6 stack:
modprobe -r intel_ipu6_isys ov5693 intel_ipu6
modprobe intel_ipu6 ; sleep 2 ; modprobe ov5693 intel_ipu6_isys
or after a hibernate-resume where a sleep hook does the same, the front
sensor fails to bind:
ov5693 i2c-OVTI5693:00: supported link freq 419200000 not found
ov5693 i2c-OVTI5693:00: probe error -22
and, if the whole intel-ipu6 module is unloaded and reprobed (e.g. PCI
remove+rescan):
software_node_register: kobject_add_internal ... INT343E ... -EEXIST
intel-ipu6 0000:00:05.0: Failed to register the IPU HID node
intel-ipu6 0000:00:05.0: IPU6 bridge init failed (-17)
The sensors only recover on a full cold boot (empty software_node
registry).
Root cause
==========
(1) ipu_bridge_init() builds the swnode graph only once, and bails if
a graph already exists.
ipu_bridge_init() begins with:
if (!ipu_bridge_check_fwnode_graph(dev_fwnode(dev)))
return 0;
ipu_bridge_check_fwnode_graph() walks fwnode->secondary and returns 0
as soon as it finds any existing endpoint. So if a graph is already
present on the IPU device's fwnode chain, ipu_bridge_init() returns
immediately and builds nothing. The tell-tale "Connected %d cameras"
line is printed only on the cold path, never on a warm one. This is
correct for the intended lifecycle, but it means the graph is a
strictly cold-probe-time artifact.
(2) intel-ipu6's .remove does not tear the graph down, and the teardown
is not reachable.
ipu6_pci_remove() frees IRQ, MMU, firmware and bus devices, but never
unregisters the bridge's software_nodes (bridge->ipu_hid_node and the
per-sensor node groups). The only function that would do this,
ipu_bridge_unregister_sensors(), is static in ipu-bridge.c and is not
exported, so intel-ipu6 could not call it even if it tried.
set_secondary_fwnode(dev, ...) is likewise never undone.
Consequences:
- The INT343E / IPU-HID software_node and the sensor swnode groups leak
in the global software_node registry when intel-ipu6 is unloaded.
- On the next probe, software_node_register(&bridge->ipu_hid_node)
returns -EEXIST ("Failed to register the IPU HID node"), wedging the
IPU6 core until a reboot clears the registry.
- Where the module is not fully unloaded but the sensor driver is
reloaded, the stale graph is still attached, so (1) makes
ipu_bridge_init() a no-op and the sensor's link-frequencies are never
reinjected. ov5693 probe then fails with -EINVAL / -22.
Why hibernate makes this visible
================================
ov5693_check_hwcfg(), which reads link-frequencies from the fwnode,
runs only at probe time, not on the sensor's .resume. So a pure
resume-from-image (kernel state restored, no re-probe) is fine. The
failure is triggered by any path that re-probes the sensor against a
graph the bridge will not rebuild: a manual modprobe -r / modprobe, a
PCI remove+rescan, or a hibernate sleep hook that unloads and reloads
the IPU6 stack to work around other freeze-time issues on this platform
(the SP9 needs the IPU6 quiesced before the hibernate freeze; reloading
on resume then trips this).
Suggested fixes (for maintainer judgement; I am reporting, not
prescribing)
==============================================================
1. Make the bridge teardown reachable and call it on .remove. Export a
counterpart to ipu_bridge_init() (e.g. ipu_bridge_exit()) that
unregisters ipu_hid_node and the sensor node groups and clears the
device's secondary fwnode, and call it from ipu6_pci_remove(). This
fixes the -EEXIST leak and lets a warm reload rebuild the graph
cleanly.
2. Or make ipu_bridge_init() idempotent in a way that repopulates a
missing or partial graph rather than bailing on the mere presence of
a stale one.
3. Independently, harden the sensor so a transiently-missing
link-frequencies property is not fatal when the sensor supports
exactly one link frequency. This is defensive, not a substitute for
fixing the bridge.
Reproduce
=========
# with both IPU6 cameras working:
sudo modprobe -r intel_ipu6_isys ov5693 intel_ipu6
sudo modprobe intel_ipu6 ; sleep 2 ; sudo modprobe ov5693 intel_ipu6_isys
dmesg | grep -iE 'ov5693|Connected .* cameras|IPU HID|bridge init'
# front sensor fails ("supported link freq 419200000 not found"),
# and there is no "Connected N cameras" line.
---
Notes for reviewers (not part of the report body):
- I maintain a downstream DKMS ov5693 with the defensive fallback
(suggestion 3) which makes the SP9 front camera survive
hibernate-resume today. Happy to test any bridge-side fix on real SP9
hardware.
- Related prior contribution: the OVTI5693 ACPI HID plus
ipu_supported_sensors[] entry (Reviewed-by: Daniel Scally):
https://lore.kernel.org/linux-media/20260708213633.18392-1-fernandorimoli11@xxxxxxxxx/
Thanks,
Fernando Rimoli