mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
media: v4l2-async: Fix error handling on steps after finding a match
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>
This commit is contained in:
parent
679f0b7b6a
commit
7345d6d356
|
|
@ -343,7 +343,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
|
|||
struct v4l2_subdev *sd,
|
||||
struct v4l2_async_connection *asc)
|
||||
{
|
||||
struct v4l2_async_notifier *subdev_notifier;
|
||||
bool registered = false;
|
||||
int ret;
|
||||
|
||||
|
|
@ -389,6 +388,25 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
|
|||
dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
|
||||
dev_name(sd->dev), ret);
|
||||
|
||||
return 0;
|
||||
|
||||
err_call_unbind:
|
||||
v4l2_async_nf_call_unbind(notifier, sd, asc);
|
||||
list_del(&asc->asc_subdev_entry);
|
||||
|
||||
err_unregister_subdev:
|
||||
if (registered)
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier *notifier,
|
||||
struct v4l2_subdev *sd)
|
||||
{
|
||||
struct v4l2_async_notifier *subdev_notifier;
|
||||
|
||||
/*
|
||||
* See if the sub-device has a notifier. If not, return here.
|
||||
*/
|
||||
|
|
@ -404,16 +422,6 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
|
|||
subdev_notifier->parent = notifier;
|
||||
|
||||
return v4l2_async_nf_try_all_subdevs(subdev_notifier);
|
||||
|
||||
err_call_unbind:
|
||||
v4l2_async_nf_call_unbind(notifier, sd, asc);
|
||||
list_del(&asc->asc_subdev_entry);
|
||||
|
||||
err_unregister_subdev:
|
||||
if (registered)
|
||||
v4l2_device_unregister_subdev(sd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Test all async sub-devices in a notifier for a match. */
|
||||
|
|
@ -445,6 +453,10 @@ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* v4l2_async_match_notify() may lead to registering a
|
||||
* new notifier and thus changing the async subdevs
|
||||
|
|
@ -829,7 +841,11 @@ int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
|
|||
ret = v4l2_async_match_notify(notifier, v4l2_dev, sd,
|
||||
asc);
|
||||
if (ret)
|
||||
goto err_unbind;
|
||||
goto err_unlock;
|
||||
|
||||
ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
|
||||
if (ret)
|
||||
goto err_unbind_one;
|
||||
|
||||
ret = v4l2_async_nf_try_complete(notifier);
|
||||
if (ret)
|
||||
|
|
@ -853,9 +869,10 @@ int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
|
|||
if (subdev_notifier)
|
||||
v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
|
||||
|
||||
if (asc)
|
||||
v4l2_async_unbind_subdev_one(notifier, asc);
|
||||
err_unbind_one:
|
||||
v4l2_async_unbind_subdev_one(notifier, asc);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&list_lock);
|
||||
|
||||
sd->owner = NULL;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user