media: platform: video-mux: Fix mutex locking
authorPaul Elder <paul.elder@ideasonboard.com>
Mon, 9 Sep 2024 15:48:28 +0000 (17:48 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Wed, 16 Oct 2024 07:32:41 +0000 (09:32 +0200)
The current order of locking between the driver mutex and the v4l2 subdev
state lock causes a circular locking dependency when trying to set up a
link. Fix this.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[Sakari Ailus: Fix spelling in commit message.]
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/media/platform/video-mux.c

index 5748aff8fc40b79a5b5da5e2b553f2364a7e609b..cba34893258a85f81b1e399da73e45f59f116f93 100644 (file)
@@ -52,6 +52,7 @@ static int video_mux_link_setup(struct media_entity *entity,
                                const struct media_pad *remote, u32 flags)
 {
        struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+       struct v4l2_subdev_state *sd_state;
        struct video_mux *vmux = v4l2_subdev_to_video_mux(sd);
        u16 source_pad = entity->num_pads - 1;
        int ret = 0;
@@ -67,10 +68,10 @@ static int video_mux_link_setup(struct media_entity *entity,
                remote->entity->name, remote->index, local->entity->name,
                local->index, flags & MEDIA_LNK_FL_ENABLED);
 
+       sd_state = v4l2_subdev_lock_and_get_active_state(sd);
        mutex_lock(&vmux->lock);
 
        if (flags & MEDIA_LNK_FL_ENABLED) {
-               struct v4l2_subdev_state *sd_state;
                struct v4l2_mbus_framefmt *source_mbusformat;
 
                if (vmux->active == local->index)
@@ -88,12 +89,10 @@ static int video_mux_link_setup(struct media_entity *entity,
                vmux->active = local->index;
 
                /* Propagate the active format to the source */
-               sd_state = v4l2_subdev_lock_and_get_active_state(sd);
                source_mbusformat = v4l2_subdev_state_get_format(sd_state,
                                                                 source_pad);
                *source_mbusformat = *v4l2_subdev_state_get_format(sd_state,
                                                                   vmux->active);
-               v4l2_subdev_unlock_state(sd_state);
        } else {
                if (vmux->active != local->index)
                        goto out;
@@ -105,6 +104,7 @@ static int video_mux_link_setup(struct media_entity *entity,
 
 out:
        mutex_unlock(&vmux->lock);
+       v4l2_subdev_unlock_state(sd_state);
        return ret;
 }