2 * V4L2 asynchronous subdevice registration API
4 * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
11 #include <linux/device.h>
12 #include <linux/err.h>
13 #include <linux/i2c.h>
14 #include <linux/list.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
21 #include <linux/types.h>
23 #include <media/v4l2-async.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-fwnode.h>
26 #include <media/v4l2-subdev.h>
28 static int v4l2_async_notifier_call_bound(struct v4l2_async_notifier
*n
,
29 struct v4l2_subdev
*subdev
,
30 struct v4l2_async_subdev
*asd
)
32 if (!n
->ops
|| !n
->ops
->bound
)
35 return n
->ops
->bound(n
, subdev
, asd
);
38 static void v4l2_async_notifier_call_unbind(struct v4l2_async_notifier
*n
,
39 struct v4l2_subdev
*subdev
,
40 struct v4l2_async_subdev
*asd
)
42 if (!n
->ops
|| !n
->ops
->unbind
)
45 n
->ops
->unbind(n
, subdev
, asd
);
48 static int v4l2_async_notifier_call_complete(struct v4l2_async_notifier
*n
)
50 if (!n
->ops
|| !n
->ops
->complete
)
53 return n
->ops
->complete(n
);
56 static bool match_i2c(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
58 #if IS_ENABLED(CONFIG_I2C)
59 struct i2c_client
*client
= i2c_verify_client(sd
->dev
);
61 asd
->match
.i2c
.adapter_id
== client
->adapter
->nr
&&
62 asd
->match
.i2c
.address
== client
->addr
;
68 static bool match_devname(struct v4l2_subdev
*sd
,
69 struct v4l2_async_subdev
*asd
)
71 return !strcmp(asd
->match
.device_name
, dev_name(sd
->dev
));
74 static bool match_fwnode(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
76 return sd
->fwnode
== asd
->match
.fwnode
;
79 static bool match_custom(struct v4l2_subdev
*sd
, struct v4l2_async_subdev
*asd
)
81 if (!asd
->match
.custom
.match
)
85 return asd
->match
.custom
.match(sd
->dev
, asd
);
88 static LIST_HEAD(subdev_list
);
89 static LIST_HEAD(notifier_list
);
90 static DEFINE_MUTEX(list_lock
);
92 static struct v4l2_async_subdev
*v4l2_async_find_match(
93 struct v4l2_async_notifier
*notifier
, struct v4l2_subdev
*sd
)
95 bool (*match
)(struct v4l2_subdev
*, struct v4l2_async_subdev
*);
96 struct v4l2_async_subdev
*asd
;
98 list_for_each_entry(asd
, ¬ifier
->waiting
, list
) {
99 /* bus_type has been verified valid before */
100 switch (asd
->match_type
) {
101 case V4L2_ASYNC_MATCH_CUSTOM
:
102 match
= match_custom
;
104 case V4L2_ASYNC_MATCH_DEVNAME
:
105 match
= match_devname
;
107 case V4L2_ASYNC_MATCH_I2C
:
110 case V4L2_ASYNC_MATCH_FWNODE
:
111 match
= match_fwnode
;
114 /* Cannot happen, unless someone breaks us */
119 /* match cannot be NULL here */
127 /* Find the sub-device notifier registered by a sub-device driver. */
128 static struct v4l2_async_notifier
*v4l2_async_find_subdev_notifier(
129 struct v4l2_subdev
*sd
)
131 struct v4l2_async_notifier
*n
;
133 list_for_each_entry(n
, ¬ifier_list
, list
)
140 /* Get v4l2_device related to the notifier if one can be found. */
141 static struct v4l2_device
*v4l2_async_notifier_find_v4l2_dev(
142 struct v4l2_async_notifier
*notifier
)
144 while (notifier
->parent
)
145 notifier
= notifier
->parent
;
147 return notifier
->v4l2_dev
;
151 * Return true if all child sub-device notifiers are complete, false otherwise.
153 static bool v4l2_async_notifier_can_complete(
154 struct v4l2_async_notifier
*notifier
)
156 struct v4l2_subdev
*sd
;
158 if (!list_empty(¬ifier
->waiting
))
161 list_for_each_entry(sd
, ¬ifier
->done
, async_list
) {
162 struct v4l2_async_notifier
*subdev_notifier
=
163 v4l2_async_find_subdev_notifier(sd
);
165 if (subdev_notifier
&&
166 !v4l2_async_notifier_can_complete(subdev_notifier
))
174 * Complete the master notifier if possible. This is done when all async
175 * sub-devices have been bound; v4l2_device is also available then.
177 static int v4l2_async_notifier_try_complete(
178 struct v4l2_async_notifier
*notifier
)
180 /* Quick check whether there are still more sub-devices here. */
181 if (!list_empty(¬ifier
->waiting
))
184 /* Check the entire notifier tree; find the root notifier first. */
185 while (notifier
->parent
)
186 notifier
= notifier
->parent
;
188 /* This is root if it has v4l2_dev. */
189 if (!notifier
->v4l2_dev
)
192 /* Is everything ready? */
193 if (!v4l2_async_notifier_can_complete(notifier
))
196 return v4l2_async_notifier_call_complete(notifier
);
199 static int v4l2_async_notifier_try_all_subdevs(
200 struct v4l2_async_notifier
*notifier
);
202 static int v4l2_async_match_notify(struct v4l2_async_notifier
*notifier
,
203 struct v4l2_device
*v4l2_dev
,
204 struct v4l2_subdev
*sd
,
205 struct v4l2_async_subdev
*asd
)
207 struct v4l2_async_notifier
*subdev_notifier
;
210 ret
= v4l2_device_register_subdev(v4l2_dev
, sd
);
214 ret
= v4l2_async_notifier_call_bound(notifier
, sd
, asd
);
216 v4l2_device_unregister_subdev(sd
);
220 /* Remove from the waiting list */
221 list_del(&asd
->list
);
223 sd
->notifier
= notifier
;
225 /* Move from the global subdevice list to notifier's done */
226 list_move(&sd
->async_list
, ¬ifier
->done
);
229 * See if the sub-device has a notifier. If not, return here.
231 subdev_notifier
= v4l2_async_find_subdev_notifier(sd
);
232 if (!subdev_notifier
|| subdev_notifier
->parent
)
236 * Proceed with checking for the sub-device notifier's async
237 * sub-devices, and return the result. The error will be handled by the
240 subdev_notifier
->parent
= notifier
;
242 return v4l2_async_notifier_try_all_subdevs(subdev_notifier
);
245 /* Test all async sub-devices in a notifier for a match. */
246 static int v4l2_async_notifier_try_all_subdevs(
247 struct v4l2_async_notifier
*notifier
)
249 struct v4l2_device
*v4l2_dev
=
250 v4l2_async_notifier_find_v4l2_dev(notifier
);
251 struct v4l2_subdev
*sd
;
257 list_for_each_entry(sd
, &subdev_list
, async_list
) {
258 struct v4l2_async_subdev
*asd
;
261 asd
= v4l2_async_find_match(notifier
, sd
);
265 ret
= v4l2_async_match_notify(notifier
, v4l2_dev
, sd
, asd
);
270 * v4l2_async_match_notify() may lead to registering a
271 * new notifier and thus changing the async subdevs
272 * list. In order to proceed safely from here, restart
273 * parsing the list from the beginning.
281 static void v4l2_async_cleanup(struct v4l2_subdev
*sd
)
283 v4l2_device_unregister_subdev(sd
);
284 /* Subdevice driver will reprobe and put the subdev back onto the list */
285 list_del_init(&sd
->async_list
);
289 /* Unbind all sub-devices in the notifier tree. */
290 static void v4l2_async_notifier_unbind_all_subdevs(
291 struct v4l2_async_notifier
*notifier
)
293 struct v4l2_subdev
*sd
, *tmp
;
295 list_for_each_entry_safe(sd
, tmp
, ¬ifier
->done
, async_list
) {
296 struct v4l2_async_notifier
*subdev_notifier
=
297 v4l2_async_find_subdev_notifier(sd
);
300 v4l2_async_notifier_unbind_all_subdevs(subdev_notifier
);
302 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
303 v4l2_async_cleanup(sd
);
305 list_move(&sd
->async_list
, &subdev_list
);
308 notifier
->parent
= NULL
;
311 /* See if an fwnode can be found in a notifier's lists. */
312 static bool __v4l2_async_notifier_fwnode_has_async_subdev(
313 struct v4l2_async_notifier
*notifier
, struct fwnode_handle
*fwnode
)
315 struct v4l2_async_subdev
*asd
;
316 struct v4l2_subdev
*sd
;
318 list_for_each_entry(asd
, ¬ifier
->waiting
, list
) {
319 if (asd
->match_type
!= V4L2_ASYNC_MATCH_FWNODE
)
322 if (asd
->match
.fwnode
== fwnode
)
326 list_for_each_entry(sd
, ¬ifier
->done
, async_list
) {
327 if (WARN_ON(!sd
->asd
))
330 if (sd
->asd
->match_type
!= V4L2_ASYNC_MATCH_FWNODE
)
333 if (sd
->asd
->match
.fwnode
== fwnode
)
341 * Find out whether an async sub-device was set up for an fwnode already or
342 * whether it exists in a given notifier before @this_index.
344 static bool v4l2_async_notifier_fwnode_has_async_subdev(
345 struct v4l2_async_notifier
*notifier
, struct fwnode_handle
*fwnode
,
346 unsigned int this_index
)
350 lockdep_assert_held(&list_lock
);
352 /* Check that an fwnode is not being added more than once. */
353 for (j
= 0; j
< this_index
; j
++) {
354 struct v4l2_async_subdev
*asd
= notifier
->subdevs
[this_index
];
355 struct v4l2_async_subdev
*other_asd
= notifier
->subdevs
[j
];
357 if (other_asd
->match_type
== V4L2_ASYNC_MATCH_FWNODE
&&
359 other_asd
->match
.fwnode
)
363 /* Check than an fwnode did not exist in other notifiers. */
364 list_for_each_entry(notifier
, ¬ifier_list
, list
)
365 if (__v4l2_async_notifier_fwnode_has_async_subdev(
372 static int __v4l2_async_notifier_register(struct v4l2_async_notifier
*notifier
)
375 notifier
->v4l2_dev
? notifier
->v4l2_dev
->dev
: NULL
;
376 struct v4l2_async_subdev
*asd
;
380 if (notifier
->num_subdevs
> V4L2_MAX_SUBDEVS
)
383 INIT_LIST_HEAD(¬ifier
->waiting
);
384 INIT_LIST_HEAD(¬ifier
->done
);
386 mutex_lock(&list_lock
);
388 for (i
= 0; i
< notifier
->num_subdevs
; i
++) {
389 asd
= notifier
->subdevs
[i
];
391 switch (asd
->match_type
) {
392 case V4L2_ASYNC_MATCH_CUSTOM
:
393 case V4L2_ASYNC_MATCH_DEVNAME
:
394 case V4L2_ASYNC_MATCH_I2C
:
396 case V4L2_ASYNC_MATCH_FWNODE
:
397 if (v4l2_async_notifier_fwnode_has_async_subdev(
398 notifier
, asd
->match
.fwnode
, i
)) {
400 "fwnode has already been registered or in notifier's subdev list\n");
406 dev_err(dev
, "Invalid match type %u on %p\n",
407 asd
->match_type
, asd
);
411 list_add_tail(&asd
->list
, ¬ifier
->waiting
);
414 ret
= v4l2_async_notifier_try_all_subdevs(notifier
);
418 ret
= v4l2_async_notifier_try_complete(notifier
);
422 /* Keep also completed notifiers on the list */
423 list_add(¬ifier
->list
, ¬ifier_list
);
425 mutex_unlock(&list_lock
);
431 * On failure, unbind all sub-devices registered through this notifier.
433 v4l2_async_notifier_unbind_all_subdevs(notifier
);
436 mutex_unlock(&list_lock
);
441 int v4l2_async_notifier_register(struct v4l2_device
*v4l2_dev
,
442 struct v4l2_async_notifier
*notifier
)
446 if (WARN_ON(!v4l2_dev
|| notifier
->sd
))
449 notifier
->v4l2_dev
= v4l2_dev
;
451 ret
= __v4l2_async_notifier_register(notifier
);
453 notifier
->v4l2_dev
= NULL
;
457 EXPORT_SYMBOL(v4l2_async_notifier_register
);
459 int v4l2_async_subdev_notifier_register(struct v4l2_subdev
*sd
,
460 struct v4l2_async_notifier
*notifier
)
464 if (WARN_ON(!sd
|| notifier
->v4l2_dev
))
469 ret
= __v4l2_async_notifier_register(notifier
);
475 EXPORT_SYMBOL(v4l2_async_subdev_notifier_register
);
477 static void __v4l2_async_notifier_unregister(
478 struct v4l2_async_notifier
*notifier
)
480 if (!notifier
|| (!notifier
->v4l2_dev
&& !notifier
->sd
))
483 v4l2_async_notifier_unbind_all_subdevs(notifier
);
486 notifier
->v4l2_dev
= NULL
;
488 list_del(¬ifier
->list
);
491 void v4l2_async_notifier_unregister(struct v4l2_async_notifier
*notifier
)
493 mutex_lock(&list_lock
);
495 __v4l2_async_notifier_unregister(notifier
);
497 mutex_unlock(&list_lock
);
499 EXPORT_SYMBOL(v4l2_async_notifier_unregister
);
501 void v4l2_async_notifier_cleanup(struct v4l2_async_notifier
*notifier
)
505 if (!notifier
|| !notifier
->max_subdevs
)
508 for (i
= 0; i
< notifier
->num_subdevs
; i
++) {
509 struct v4l2_async_subdev
*asd
= notifier
->subdevs
[i
];
511 switch (asd
->match_type
) {
512 case V4L2_ASYNC_MATCH_FWNODE
:
513 fwnode_handle_put(asd
->match
.fwnode
);
523 notifier
->max_subdevs
= 0;
524 notifier
->num_subdevs
= 0;
526 kvfree(notifier
->subdevs
);
527 notifier
->subdevs
= NULL
;
529 EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup
);
531 int v4l2_async_register_subdev(struct v4l2_subdev
*sd
)
533 struct v4l2_async_notifier
*subdev_notifier
;
534 struct v4l2_async_notifier
*notifier
;
538 * No reference taken. The reference is held by the device
539 * (struct v4l2_subdev.dev), and async sub-device does not
540 * exist independently of the device at any point of time.
542 if (!sd
->fwnode
&& sd
->dev
)
543 sd
->fwnode
= dev_fwnode(sd
->dev
);
545 mutex_lock(&list_lock
);
547 INIT_LIST_HEAD(&sd
->async_list
);
549 list_for_each_entry(notifier
, ¬ifier_list
, list
) {
550 struct v4l2_device
*v4l2_dev
=
551 v4l2_async_notifier_find_v4l2_dev(notifier
);
552 struct v4l2_async_subdev
*asd
;
557 asd
= v4l2_async_find_match(notifier
, sd
);
561 ret
= v4l2_async_match_notify(notifier
, v4l2_dev
, sd
, asd
);
565 ret
= v4l2_async_notifier_try_complete(notifier
);
572 /* None matched, wait for hot-plugging */
573 list_add(&sd
->async_list
, &subdev_list
);
576 mutex_unlock(&list_lock
);
582 * Complete failed. Unbind the sub-devices bound through registering
583 * this async sub-device.
585 subdev_notifier
= v4l2_async_find_subdev_notifier(sd
);
587 v4l2_async_notifier_unbind_all_subdevs(subdev_notifier
);
590 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
591 v4l2_async_cleanup(sd
);
593 mutex_unlock(&list_lock
);
597 EXPORT_SYMBOL(v4l2_async_register_subdev
);
599 void v4l2_async_unregister_subdev(struct v4l2_subdev
*sd
)
601 mutex_lock(&list_lock
);
603 __v4l2_async_notifier_unregister(sd
->subdev_notifier
);
604 v4l2_async_notifier_cleanup(sd
->subdev_notifier
);
605 kfree(sd
->subdev_notifier
);
606 sd
->subdev_notifier
= NULL
;
609 struct v4l2_async_notifier
*notifier
= sd
->notifier
;
611 list_add(&sd
->asd
->list
, ¬ifier
->waiting
);
613 v4l2_async_notifier_call_unbind(notifier
, sd
, sd
->asd
);
616 v4l2_async_cleanup(sd
);
618 mutex_unlock(&list_lock
);
620 EXPORT_SYMBOL(v4l2_async_unregister_subdev
);