FROMLIST: v4l: async: Prepare for async sub-device notifiers

Refactor the V4L2 async framework a little in preparation for async
sub-device notifiers.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
(cherry picked from commit b0a3d090cf6c1f793758b5c900169f11e29669e1)
https://git.linuxtv.org/sailus/media_tree.git/log/?h=010f7f4393fd
http://www.spinics.net/lists/linux-media/msg122688.html
Signed-off-by: Marc Herbert <marc.herbert@intel.com>

BUG=b:64133998
TEST=media device topology shows subdevs registered successfully
TEST=no camera regression

Change-Id: Id6ea225545d16192ca8f6c10f99415b6bf4f22f0
Reviewed-on: https://chromium-review.googlesource.com/693694
Commit-Ready: Tomasz Figa <tfiga@chromium.org>
Tested-by: Hyungwoo Yang <hyungwoo.yang@intel.com>
Reviewed-by: Tomasz Figa <tfiga@chromium.org>
Signed-off-by: Jacob Chen <jacob2.chen@rock-chips.com>
This commit is contained in:
Sakari Ailus
2017-09-25 03:48:08 +03:00
committed by Tao Huang
parent 50130584d5
commit 8857e46897

View File

@@ -129,12 +129,13 @@ static struct v4l2_async_subdev *v4l2_async_find_match(
}
static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
struct v4l2_device *v4l2_dev,
struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd)
{
int ret;
ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd);
ret = v4l2_device_register_subdev(v4l2_dev, sd);
if (ret < 0)
return ret;
@@ -158,6 +159,31 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
return 0;
}
/* Test all async sub-devices in a notifier for a match. */
static int v4l2_async_notifier_try_all_subdevs(
struct v4l2_async_notifier *notifier)
{
struct v4l2_device *v4l2_dev = notifier->v4l2_dev;
struct v4l2_subdev *sd, *tmp;
list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) {
struct v4l2_async_subdev *asd;
int ret;
asd = v4l2_async_find_match(notifier, sd);
if (!asd)
continue;
ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
if (ret < 0) {
mutex_unlock(&list_lock);
return ret;
}
}
return 0;
}
static void v4l2_async_cleanup(struct v4l2_subdev *sd)
{
v4l2_device_unregister_subdev(sd);
@@ -167,17 +193,15 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
sd->dev = NULL;
}
int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
struct v4l2_async_notifier *notifier)
static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
{
struct v4l2_subdev *sd, *tmp;
struct v4l2_async_subdev *asd;
int ret;
int i;
if (!v4l2_dev || notifier->num_subdevs > V4L2_MAX_SUBDEVS)
if (notifier->num_subdevs > V4L2_MAX_SUBDEVS)
return -EINVAL;
notifier->v4l2_dev = v4l2_dev;
INIT_LIST_HEAD(&notifier->waiting);
INIT_LIST_HEAD(&notifier->done);
@@ -210,18 +234,10 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
mutex_lock(&list_lock);
list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) {
int ret;
asd = v4l2_async_find_match(notifier, sd);
if (!asd)
continue;
ret = v4l2_async_match_notify(notifier, sd, asd);
if (ret < 0) {
mutex_unlock(&list_lock);
return ret;
}
ret = v4l2_async_notifier_try_all_subdevs(notifier);
if (ret) {
mutex_unlock(&list_lock);
return ret;
}
/* Keep also completed notifiers on the list */
@@ -231,6 +247,17 @@ int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
return 0;
}
int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
struct v4l2_async_notifier *notifier)
{
if (WARN_ON(!v4l2_dev))
return -EINVAL;
notifier->v4l2_dev = v4l2_dev;
return __v4l2_async_notifier_register(notifier);
}
EXPORT_SYMBOL(v4l2_async_notifier_register);
void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
@@ -307,7 +334,8 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
struct v4l2_async_subdev *asd = v4l2_async_find_match(notifier,
sd);
if (asd) {
int ret = v4l2_async_match_notify(notifier, sd, asd);
int ret = v4l2_async_match_notify(
notifier, notifier->v4l2_dev, sd, asd);
mutex_unlock(&list_lock);
return ret;
}