[PATCH] media: i2c: cvs: register subdev nodes when the remote sensor binds

From: Pierre Pinon

Date: Thu Sep 03 2026 - 09:17:01 EST


The CVS bridge picks up the remote sensor through a v4l2 subdev notifier
of its own, but nothing in that path creates the sensor's device node.
The IPU7 ISYS driver calls v4l2_device_register_subdev_nodes() from its
own .bound -- which runs for the CVS subdev itself, before the sensor
behind it is bound -- and from .complete. The sensor's node therefore
depends entirely on .complete being reached.

That does not happen when another sensor on the same notifier has no
driver. On a Panther Lake laptop ipu-bridge instantiates two camera
endpoints, OVTI08F4 (ov08x40) and HIMX1092; there is no driver for the
latter, so it stays in the notifier's waiting list forever:

# cat /sys/kernel/debug/v4l2-async/pending_async_subdevices
ipu7:
[fwnode] dev=i2c-HIMX1092:00, node=HIMX1092-2/port@0/endpoint@0
ov08x40 17-0036:
Intel CVS:

The ov08x40 subdev is registered with the v4l2_device and shows up in
the media graph, but never gets a /dev/v4l-subdevN, so userspace cannot
open it. libcamera fails with:

Failed to open V4L2 device '': No such file or directory
No valid pipeline for sensor 'ov08x40 17-0036', skipping

Register the subdev nodes from the CVS notifier's .bound instead. By the
time it runs, v4l2_async_match_notify() has already called
__v4l2_device_register_subdev() for the sensor, so sd->v4l2_dev is
valid. When .complete is reached as well, the extra call is a no-op:
__v4l2_device_register_subdev_nodes() skips subdevs that already have a
devnode.

With this the sensor gets its node even though HIMX1092 is still
pending, and the camera streams.

Fixes: 8e2b43d2c10b ("media: i2c: cvs: Add driver of Intel Computer Vision Sensing Controller(CVS)")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Pierre Pinon <pierre@xxxxxxxxx>
---

Notes:
I am not certain this is the right layer. The same gap would affect any
sensor sitting behind a sub-notifier, so the fix could equally live in
ipu7-isys.c or in the v4l2-async core; I put it in the CVS driver because
that is where the sub-notifier is created. Happy to redo it either way.

Tested on a Panther Lake laptop (Intel Graphics [8086:b090], IPU7 + Intel
CVS + ov08x40) on top of 7.3.0-rc1: with the patch the sensor gets its
/dev/v4l-subdev node and libcamera streams at 3848x2176, while HIMX1092
is still sitting in the notifier's waiting list.

drivers/media/i2c/cvs/v4l2.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/media/i2c/cvs/v4l2.c b/drivers/media/i2c/cvs/v4l2.c
index 9fadca7a3..0a42f91c0 100644
--- a/drivers/media/i2c/cvs/v4l2.c
+++ b/drivers/media/i2c/cvs/v4l2.c
@@ -13,6 +13,7 @@
#include <media/v4l2-async.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mc.h>
@@ -400,7 +401,7 @@ static int cvs_csi_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_async_connection *asc)
{
struct icvs *ctx = notifier_to_csi(notifier);
- int pad;
+ int pad, ret;

pad = media_entity_get_fwnode_pad(&sd->entity, asc->match.fwnode,
MEDIA_PAD_FL_SOURCE);
@@ -409,9 +410,21 @@ static int cvs_csi_notify_bound(struct v4l2_async_notifier *notifier,

ctx->remote = &sd->entity.pads[pad];

- return media_create_pad_link(&sd->entity, pad, &ctx->subdev.entity,
- ICVS_CSI_PAD_SINK, MEDIA_LNK_FL_ENABLED |
- MEDIA_LNK_FL_IMMUTABLE);
+ ret = media_create_pad_link(&sd->entity, pad, &ctx->subdev.entity,
+ ICVS_CSI_PAD_SINK, MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+ if (ret)
+ return ret;
+
+ /*
+ * v4l2_async_match_notify() has already registered the sensor with
+ * the v4l2_device, but only the bridge driver creates subdev nodes,
+ * and it does so from its own .bound and .complete callbacks. The
+ * former ran for this subdev, before the sensor was bound; the latter
+ * is never reached if another sensor on the same notifier has no
+ * driver. Create the nodes here so the sensor is reachable either way.
+ */
+ return v4l2_device_register_subdev_nodes(sd->v4l2_dev);
}

/**

base-commit: 940de590b839f71d6dc846160534bf202401b8b7
--
2.55.0