1 // SPDX-License-Identifier: GPL-2.0-only
3 * V4L2 asynchronous subdevice registration API
5 * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
8 #include <linux/device.h>
10 #include <linux/i2c.h>
11 #include <linux/list.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
17 #include <linux/slab.h>
18 #include <linux/types.h>
20 #include <media/v4l2-async.h>
21 #include <media/v4l2-device.h>
22 #include <media/v4l2-fwnode.h>
23 #include <media/v4l2-subdev.h>
25 static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier
*n
,
26 struct v4l2_subdev
*subdev
,
27 struct v4l2_async_subdev
*asd
)
29 if (!n
->ops
|| !n
->ops
->bound
)
32 return n
->ops
->bound(n
, subdev
, asd
);
35 static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier
*n
,
36 struct v4l2_subdev
*subdev
,
37 struct v4l2_async_subdev
*asd
)
39 if (!n
->ops
|| !n
->ops
->unbind
)
42 n
->ops
->unbind(n
, subdev
, asd
);
45 static int v4l2_async_notifier_call_complete(struct v4l2_async_notifier
*n
)
47 if (!n
->ops
|| !n
->ops
->complete
)
50 return n
->ops
->complete(n
);
53 static bool match_i2c(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
55 #if IS_ENABLED(CONFIG_I2C)
56 struct i2c_client
*client
= i2c_verify_client(sd
->dev
);
59 asd
->match
.i2c
.adapter_id
== client
->adapter
->nr
&&
60 asd
->match
.i2c
.address
== client
->addr
;
66 static bool match_devname(struct v4l2_subdev
*sd
,
67 struct v4l2_async_subdev
*asd
)
69 return !strcmp(asd
->match
.device_name
, dev_name(sd
->dev
));
72 static bool match_fwnode(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
74 return sd
->fwnode
== asd
->match
.fwnode
;
77 static bool match_custom(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
79 if (!asd
->match
.custom
.match
)
83 return asd
->match
.custom
.match(sd
->dev
, asd
);
86 static LIST_HEAD(subdev_list
);
87 static LIST_HEAD(notifier_list
);
88 static DEFINE_MUTEX(list_lock
);
90 static struct v4l2_async_subdev
*
91 v4l2_async_find_match(struct v4l2_async_notifier
*notifier
,
92 struct v4l2_subdev
*sd
)
94 bool (*match
)(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
);
95 struct v4l2_async_subdev
*asd
;
97 list_for_each_entry(asd
, ¬ifier
->waiting
, list
) {
98 /* bus_type has been verified valid before */
99 switch (asd
->match_type
) {
100 case V4L2_ASYNC_MATCH_CUSTOM
:
101 match
= match_custom
;
103 case V4L2_ASYNC_MATCH_DEVNAME
:
104 match
= match_devname
;
106 case V4L2_ASYNC_MATCH_I2C
:
109 case V4L2_ASYNC_MATCH_FWNODE
:
110 match
= match_fwnode
;
113 /* Cannot happen, unless someone breaks us */
118 /* match cannot be NULL here */
126 /* Compare two async sub-device descriptors for equivalence */
127 static bool asd_equal(struct v4l2_async_subdev
*asd_x
,
128 struct v4l2_async_subdev
*asd_y
)
130 if (asd_x
->match_type
!= asd_y
->match_type
)
133 switch (asd_x
->match_type
) {
134 case V4L2_ASYNC_MATCH_DEVNAME
:
135 return strcmp(asd_x
->match
.device_name
,
136 asd_y
->match
.device_name
) == 0;
137 case V4L2_ASYNC_MATCH_I2C
:
138 return asd_x
->match
.i2c
.adapter_id
==
139 asd_y
->match
.i2c
.adapter_id
&&
140 asd_x
->match
.i2c
.address
==
141 asd_y
->match
.i2c
.address
;
142 case V4L2_ASYNC_MATCH_FWNODE
:
143 return asd_x
->match
.fwnode
== asd_y
->match
.fwnode
;
151 /* Find the sub-device notifier registered by a sub-device driver. */
152 static struct v4l2_async_notifier
*
153 v4l2_async_find_subdev_notifier(struct v4l2_subdev
*sd
)
155 struct v4l2_async_notifier
*n
;
157 list_for_each_entry(n
, ¬ifier_list
, list
)
164 /* Get v4l2_device related to the notifier if one can be found. */
165 static struct v4l2_device
*
166 v4l2_async_notifier_find_v4l2_dev(struct v4l2_async_notifier
*notifier
)
168 while (notifier
->parent
)
169 notifier
= notifier
->parent
;
171 return notifier
->v4l2_dev
;
175 * Return true if all child sub-device notifiers are complete, false otherwise.
178 v4l2_async_notifier_can_complete(struct v4l2_async_notifier
*notifier
)
180 struct v4l2_subdev
*sd
;
182 if (!list_empty(¬ifier
->waiting
))
185 list_for_each_entry(sd
, ¬ifier
->done
, async_list
) {
186 struct v4l2_async_notifier
*subdev_notifier
=
187 v4l2_async_find_subdev_notifier(sd
);
189 if (subdev_notifier
&&
190 !v4l2_async_notifier_can_complete(subdev_notifier
))
198 * Complete the master notifier if possible. This is done when all async
199 * sub-devices have been bound; v4l2_device is also available then.
202 v4l2_async_notifier_try_complete(struct v4l2_async_notifier
*notifier
)
204 /* Quick check whether there are still more sub-devices here. */
205 if (!list_empty(¬ifier
->waiting
))
208 /* Check the entire notifier tree; find the root notifier first. */
209 while (notifier
->parent
)
210 notifier
= notifier
->parent
;
212 /* This is root if it has v4l2_dev. */
213 if (!notifier
->v4l2_dev
)
216 /* Is everything ready? */
217 if (!v4l2_async_notifier_can_complete(notifier
))
220 return v4l2_async_notifier_call_complete(notifier
);
224 v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier
*notifier
);
226 static int v4l2_async_match_notify(struct v4l2_async_notifier
*notifier
,
227 struct v4l2_device
*v4l2_dev
,
228 struct v4l2_subdev
*sd
,
229 struct v4l2_async_subdev
*asd
)
231 struct v4l2_async_notifier
*subdev_notifier
;
234 ret
= v4l2_device_register_subdev(v4l2_dev
, sd
);
238 ret
= v4l2_async_notifier_call_bound(notifier
, sd
, asd
);
240 v4l2_device_unregister_subdev(sd
);
244 /* Remove from the waiting list */
245 list_del(&asd
->list
);
247 sd
->notifier
= notifier
;
249 /* Move from the global subdevice list to notifier's done */
250 list_move(&sd
->async_list
, ¬ifier
->done
);
253 * See if the sub-device has a notifier. If not, return here.
255 subdev_notifier
= v4l2_async_find_subdev_notifier(sd
);
256 if (!subdev_notifier
|| subdev_notifier
->parent
)
260 * Proceed with checking for the sub-device notifier's async
261 * sub-devices, and return the result. The error will be handled by the
264 subdev_notifier
->parent
= notifier
;
266 return v4l2_async_notifier_try_all_subdevs(subdev_notifier
);
269 /* Test all async sub-devices in a notifier for a match. */
271 v4l2_async_notifier_try_all_subdevs(struct v4l2_async_notifier
*notifier
)
273 struct v4l2_device
*v4l2_dev
=
274 v4l2_async_notifier_find_v4l2_dev(notifier
);
275 struct v4l2_subdev
*sd
;
281 list_for_each_entry(sd
, &subdev_list
, async_list
) {
282 struct v4l2_async_subdev
*asd
;
285 asd
= v4l2_async_find_match(notifier
, sd
);
289 ret
= v4l2_async_match_notify(notifier
, v4l2_dev
, sd
, asd
);
294 * v4l2_async_match_notify() may lead to registering a
295 * new notifier and thus changing the async subdevs
296 * list. In order to proceed safely from here, restart
297 * parsing the list from the beginning.
305 static void v4l2_async_cleanup(struct v4l2_subdev
*sd
)
307 v4l2_device_unregister_subdev(sd
);
309 * Subdevice driver will reprobe and put the subdev back
312 list_del_init(&sd
->async_list
);
316 /* Unbind all sub-devices in the notifier tree. */
318 v4l2_async_notifier_unbind_all_subdevs(struct v4l2_async_notifier
*notifier
)
320 struct v4l2_subdev
*sd
, *tmp
;
322 list_for_each_entry_safe(sd
, tmp
, ¬ifier
->done
, async_list
) {
323 struct v4l2_async_notifier
*subdev_notifier
=
324 v4l2_async_find_subdev_notifier(sd
);
327 v4l2_async_notifier_unbind_all_subdevs(subdev_notifier
);
329 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
330 v4l2_async_cleanup(sd
);
332 list_move(&sd
->async_list
, &subdev_list
);
335 notifier
->parent
= NULL
;
338 /* See if an async sub-device can be found in a notifier's lists. */
340 __v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier
*notifier
,
341 struct v4l2_async_subdev
*asd
)
343 struct v4l2_async_subdev
*asd_y
;
344 struct v4l2_subdev
*sd
;
346 list_for_each_entry(asd_y
, ¬ifier
->waiting
, list
)
347 if (asd_equal(asd
, asd_y
))
350 list_for_each_entry(sd
, ¬ifier
->done
, async_list
) {
351 if (WARN_ON(!sd
->asd
))
354 if (asd_equal(asd
, sd
->asd
))
362 * Find out whether an async sub-device was set up already or
363 * whether it exists in a given notifier before @this_index.
364 * If @this_index < 0, search the notifier's entire @asd_list.
367 v4l2_async_notifier_has_async_subdev(struct v4l2_async_notifier
*notifier
,
368 struct v4l2_async_subdev
*asd
,
371 struct v4l2_async_subdev
*asd_y
;
374 lockdep_assert_held(&list_lock
);
376 /* Check that an asd is not being added more than once. */
377 list_for_each_entry(asd_y
, ¬ifier
->asd_list
, asd_list
) {
378 if (this_index
>= 0 && j
++ >= this_index
)
380 if (asd_equal(asd
, asd_y
))
384 /* Check that an asd does not exist in other notifiers. */
385 list_for_each_entry(notifier
, ¬ifier_list
, list
)
386 if (__v4l2_async_notifier_has_async_subdev(notifier
, asd
))
392 static int v4l2_async_notifier_asd_valid(struct v4l2_async_notifier
*notifier
,
393 struct v4l2_async_subdev
*asd
,
397 notifier
->v4l2_dev
? notifier
->v4l2_dev
->dev
: NULL
;
402 switch (asd
->match_type
) {
403 case V4L2_ASYNC_MATCH_CUSTOM
:
404 case V4L2_ASYNC_MATCH_DEVNAME
:
405 case V4L2_ASYNC_MATCH_I2C
:
406 case V4L2_ASYNC_MATCH_FWNODE
:
407 if (v4l2_async_notifier_has_async_subdev(notifier
, asd
,
409 dev_dbg(dev
, "subdev descriptor already listed in this or other notifiers\n");
414 dev_err(dev
, "Invalid match type %u on %p\n",
415 asd
->match_type
, asd
);
422 void v4l2_async_notifier_init(struct v4l2_async_notifier
*notifier
)
424 INIT_LIST_HEAD(¬ifier
->asd_list
);
426 EXPORT_SYMBOL(v4l2_async_notifier_init
);
428 static int __v4l2_async_notifier_register(struct v4l2_async_notifier
*notifier
)
430 struct v4l2_async_subdev
*asd
;
433 INIT_LIST_HEAD(¬ifier
->waiting
);
434 INIT_LIST_HEAD(¬ifier
->done
);
436 mutex_lock(&list_lock
);
438 list_for_each_entry(asd
, ¬ifier
->asd_list
, asd_list
) {
439 ret
= v4l2_async_notifier_asd_valid(notifier
, asd
, i
++);
443 list_add_tail(&asd
->list
, ¬ifier
->waiting
);
446 ret
= v4l2_async_notifier_try_all_subdevs(notifier
);
450 ret
= v4l2_async_notifier_try_complete(notifier
);
454 /* Keep also completed notifiers on the list */
455 list_add(¬ifier
->list
, ¬ifier_list
);
457 mutex_unlock(&list_lock
);
463 * On failure, unbind all sub-devices registered through this notifier.
465 v4l2_async_notifier_unbind_all_subdevs(notifier
);
468 mutex_unlock(&list_lock
);
473 int v4l2_async_notifier_register(struct v4l2_device
*v4l2_dev
,
474 struct v4l2_async_notifier
*notifier
)
478 if (WARN_ON(!v4l2_dev
|| notifier
->sd
))
481 notifier
->v4l2_dev
= v4l2_dev
;
483 ret
= __v4l2_async_notifier_register(notifier
);
485 notifier
->v4l2_dev
= NULL
;
489 EXPORT_SYMBOL(v4l2_async_notifier_register
);
491 int v4l2_async_subdev_notifier_register(struct v4l2_subdev
*sd
,
492 struct v4l2_async_notifier
*notifier
)
496 if (WARN_ON(!sd
|| notifier
->v4l2_dev
))
501 ret
= __v4l2_async_notifier_register(notifier
);
507 EXPORT_SYMBOL(v4l2_async_subdev_notifier_register
);
510 __v4l2_async_notifier_unregister(struct v4l2_async_notifier
*notifier
)
512 if (!notifier
|| (!notifier
->v4l2_dev
&& !notifier
->sd
))
515 v4l2_async_notifier_unbind_all_subdevs(notifier
);
518 notifier
->v4l2_dev
= NULL
;
520 list_del(¬ifier
->list
);
523 void v4l2_async_notifier_unregister(struct v4l2_async_notifier
*notifier
)
525 mutex_lock(&list_lock
);
527 __v4l2_async_notifier_unregister(notifier
);
529 mutex_unlock(&list_lock
);
531 EXPORT_SYMBOL(v4l2_async_notifier_unregister
);
533 static void __v4l2_async_notifier_cleanup(struct v4l2_async_notifier
*notifier
)
535 struct v4l2_async_subdev
*asd
, *tmp
;
540 list_for_each_entry_safe(asd
, tmp
, ¬ifier
->asd_list
, asd_list
) {
541 switch (asd
->match_type
) {
542 case V4L2_ASYNC_MATCH_FWNODE
:
543 fwnode_handle_put(asd
->match
.fwnode
);
549 list_del(&asd
->asd_list
);
554 void v4l2_async_notifier_cleanup(struct v4l2_async_notifier
*notifier
)
556 mutex_lock(&list_lock
);
558 __v4l2_async_notifier_cleanup(notifier
);
560 mutex_unlock(&list_lock
);
562 EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup
);
564 int v4l2_async_notifier_add_subdev(struct v4l2_async_notifier
*notifier
,
565 struct v4l2_async_subdev
*asd
)
569 mutex_lock(&list_lock
);
571 ret
= v4l2_async_notifier_asd_valid(notifier
, asd
, -1);
575 list_add_tail(&asd
->asd_list
, ¬ifier
->asd_list
);
578 mutex_unlock(&list_lock
);
581 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_subdev
);
583 struct v4l2_async_subdev
*
584 v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier
*notifier
,
585 struct fwnode_handle
*fwnode
,
586 unsigned int asd_struct_size
)
588 struct v4l2_async_subdev
*asd
;
591 asd
= kzalloc(asd_struct_size
, GFP_KERNEL
);
593 return ERR_PTR(-ENOMEM
);
595 asd
->match_type
= V4L2_ASYNC_MATCH_FWNODE
;
596 asd
->match
.fwnode
= fwnode
;
598 ret
= v4l2_async_notifier_add_subdev(notifier
, asd
);
606 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev
);
608 struct v4l2_async_subdev
*
609 v4l2_async_notifier_add_i2c_subdev(struct v4l2_async_notifier
*notifier
,
610 int adapter_id
, unsigned short address
,
611 unsigned int asd_struct_size
)
613 struct v4l2_async_subdev
*asd
;
616 asd
= kzalloc(asd_struct_size
, GFP_KERNEL
);
618 return ERR_PTR(-ENOMEM
);
620 asd
->match_type
= V4L2_ASYNC_MATCH_I2C
;
621 asd
->match
.i2c
.adapter_id
= adapter_id
;
622 asd
->match
.i2c
.address
= address
;
624 ret
= v4l2_async_notifier_add_subdev(notifier
, asd
);
632 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_i2c_subdev
);
634 struct v4l2_async_subdev
*
635 v4l2_async_notifier_add_devname_subdev(struct v4l2_async_notifier
*notifier
,
636 const char *device_name
,
637 unsigned int asd_struct_size
)
639 struct v4l2_async_subdev
*asd
;
642 asd
= kzalloc(asd_struct_size
, GFP_KERNEL
);
644 return ERR_PTR(-ENOMEM
);
646 asd
->match_type
= V4L2_ASYNC_MATCH_DEVNAME
;
647 asd
->match
.device_name
= device_name
;
649 ret
= v4l2_async_notifier_add_subdev(notifier
, asd
);
657 EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev
);
659 int v4l2_async_register_subdev(struct v4l2_subdev
*sd
)
661 struct v4l2_async_notifier
*subdev_notifier
;
662 struct v4l2_async_notifier
*notifier
;
666 * No reference taken. The reference is held by the device
667 * (struct v4l2_subdev.dev), and async sub-device does not
668 * exist independently of the device at any point of time.
670 if (!sd
->fwnode
&& sd
->dev
)
671 sd
->fwnode
= dev_fwnode(sd
->dev
);
673 mutex_lock(&list_lock
);
675 INIT_LIST_HEAD(&sd
->async_list
);
677 list_for_each_entry(notifier
, ¬ifier_list
, list
) {
678 struct v4l2_device
*v4l2_dev
=
679 v4l2_async_notifier_find_v4l2_dev(notifier
);
680 struct v4l2_async_subdev
*asd
;
685 asd
= v4l2_async_find_match(notifier
, sd
);
689 ret
= v4l2_async_match_notify(notifier
, v4l2_dev
, sd
, asd
);
693 ret
= v4l2_async_notifier_try_complete(notifier
);
700 /* None matched, wait for hot-plugging */
701 list_add(&sd
->async_list
, &subdev_list
);
704 mutex_unlock(&list_lock
);
710 * Complete failed. Unbind the sub-devices bound through registering
711 * this async sub-device.
713 subdev_notifier
= v4l2_async_find_subdev_notifier(sd
);
715 v4l2_async_notifier_unbind_all_subdevs(subdev_notifier
);
718 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
719 v4l2_async_cleanup(sd
);
721 mutex_unlock(&list_lock
);
725 EXPORT_SYMBOL(v4l2_async_register_subdev
);
727 void v4l2_async_unregister_subdev(struct v4l2_subdev
*sd
)
729 mutex_lock(&list_lock
);
731 __v4l2_async_notifier_unregister(sd
->subdev_notifier
);
732 __v4l2_async_notifier_cleanup(sd
->subdev_notifier
);
733 kfree(sd
->subdev_notifier
);
734 sd
->subdev_notifier
= NULL
;
737 struct v4l2_async_notifier
*notifier
= sd
->notifier
;
739 list_add(&sd
->asd
->list
, ¬ifier
->waiting
);
741 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
744 v4l2_async_cleanup(sd
);
746 mutex_unlock(&list_lock
);
748 EXPORT_SYMBOL(v4l2_async_unregister_subdev
);