Skip to content
/ linux Public

Commit 30aaed3

Browse files
Sakari AilusSasha Levin
authored andcommitted
media: v4l2-async: Fix error handling on steps after finding a match
[ Upstream commit 7345d6d ] Once an async connection is found to be matching with an fwnode, a sub-device may be registered (in case it wasn't already), its bound operation is called, ancillary links are created, the async connection is added to the sub-device's list of connections and removed from the global waiting connection list. Further on, the sub-device's possible own notifier is searched for possible additional matches. Fix these specific issues: - If v4l2_async_match_notify() failed before the sub-notifier handling, the async connection was unbound and its entry removed from the sub-device's async connection list. The latter part was also done in v4l2_async_match_notify(). - The async connection's sd field was only set after creating ancillary links in v4l2_async_match_notify(). It was however dereferenced in v4l2_async_unbind_subdev_one(), which was called on error path of v4l2_async_match_notify() failure. Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Tested-by: "Yew, Chang Ching" <chang.ching.yew@intel.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 4010e59 commit 30aaed3

File tree

1 file changed

+31
-14
lines changed

1 file changed

+31
-14
lines changed

drivers/media/v4l2-core/v4l2-async.c

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
339339
struct v4l2_subdev *sd,
340340
struct v4l2_async_connection *asc)
341341
{
342-
struct v4l2_async_notifier *subdev_notifier;
343342
bool registered = false;
344343
int ret;
345344

@@ -385,6 +384,25 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
385384
dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
386385
dev_name(sd->dev), ret);
387386

387+
return 0;
388+
389+
err_call_unbind:
390+
v4l2_async_nf_call_unbind(notifier, sd, asc);
391+
list_del(&asc->asc_subdev_entry);
392+
393+
err_unregister_subdev:
394+
if (registered)
395+
v4l2_device_unregister_subdev(sd);
396+
397+
return ret;
398+
}
399+
400+
static int
401+
v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier *notifier,
402+
struct v4l2_subdev *sd)
403+
{
404+
struct v4l2_async_notifier *subdev_notifier;
405+
388406
/*
389407
* See if the sub-device has a notifier. If not, return here.
390408
*/
@@ -400,16 +418,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
400418
subdev_notifier->parent = notifier;
401419

402420
return v4l2_async_nf_try_all_subdevs(subdev_notifier);
403-
404-
err_call_unbind:
405-
v4l2_async_nf_call_unbind(notifier, sd, asc);
406-
list_del(&asc->asc_subdev_entry);
407-
408-
err_unregister_subdev:
409-
if (registered)
410-
v4l2_device_unregister_subdev(sd);
411-
412-
return ret;
413421
}
414422

415423
/* Test all async sub-devices in a notifier for a match. */
@@ -441,6 +449,10 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
441449
if (ret < 0)
442450
return ret;
443451

452+
ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
453+
if (ret < 0)
454+
return ret;
455+
444456
/*
445457
* v4l2_async_match_notify() may lead to registering a
446458
* new notifier and thus changing the async subdevs
@@ -823,7 +835,11 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
823835
ret = v4l2_async_match_notify(notifier, v4l2_dev, sd,
824836
asc);
825837
if (ret)
826-
goto err_unbind;
838+
goto err_unlock;
839+
840+
ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
841+
if (ret)
842+
goto err_unbind_one;
827843

828844
ret = v4l2_async_nf_try_complete(notifier);
829845
if (ret)
@@ -847,9 +863,10 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
847863
if (subdev_notifier)
848864
v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
849865

850-
if (asc)
851-
v4l2_async_unbind_subdev_one(notifier, asc);
866+
err_unbind_one:
867+
v4l2_async_unbind_subdev_one(notifier, asc);
852868

869+
err_unlock:
853870
mutex_unlock(&list_lock);
854871

855872
return ret;

0 commit comments

Comments
 (0)