1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * V4L2 asynchronous subdevice registration API
4 *
5 * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
6 */
7
8 #include <linux/debugfs.h>
9 #include <linux/device.h>
10 #include <linux/err.h>
11 #include <linux/i2c.h>
12 #include <linux/list.h>
13 #include <linux/mm.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/of.h>
17 #include <linux/platform_device.h>
18 #include <linux/seq_file.h>
19 #include <linux/slab.h>
20 #include <linux/types.h>
21
22 #include <media/v4l2-async.h>
23 #include <media/v4l2-device.h>
24 #include <media/v4l2-fwnode.h>
25 #include <media/v4l2-subdev.h>
26
27 #include "v4l2-subdev-priv.h"
28
v4l2_async_nf_call_bound(struct v4l2_async_notifier * n,struct v4l2_subdev * subdev,struct v4l2_async_connection * asc)29 static int v4l2_async_nf_call_bound(struct v4l2_async_notifier *n,
30 struct v4l2_subdev *subdev,
31 struct v4l2_async_connection *asc)
32 {
33 if (!n->ops || !n->ops->bound)
34 return 0;
35
36 return n->ops->bound(n, subdev, asc);
37 }
38
v4l2_async_nf_call_unbind(struct v4l2_async_notifier * n,struct v4l2_subdev * subdev,struct v4l2_async_connection * asc)39 static void v4l2_async_nf_call_unbind(struct v4l2_async_notifier *n,
40 struct v4l2_subdev *subdev,
41 struct v4l2_async_connection *asc)
42 {
43 if (!n->ops || !n->ops->unbind)
44 return;
45
46 n->ops->unbind(n, subdev, asc);
47 }
48
v4l2_async_nf_call_complete(struct v4l2_async_notifier * n)49 static int v4l2_async_nf_call_complete(struct v4l2_async_notifier *n)
50 {
51 if (!n->ops || !n->ops->complete)
52 return 0;
53
54 return n->ops->complete(n);
55 }
56
v4l2_async_nf_call_destroy(struct v4l2_async_notifier * n,struct v4l2_async_connection * asc)57 static void v4l2_async_nf_call_destroy(struct v4l2_async_notifier *n,
58 struct v4l2_async_connection *asc)
59 {
60 if (!n->ops || !n->ops->destroy)
61 return;
62
63 n->ops->destroy(asc);
64 }
65
match_i2c(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_match_desc * match)66 static bool match_i2c(struct v4l2_async_notifier *notifier,
67 struct v4l2_subdev *sd,
68 struct v4l2_async_match_desc *match)
69 {
70 #if IS_ENABLED(CONFIG_I2C)
71 struct i2c_client *client = i2c_verify_client(sd->dev);
72
73 return client &&
74 match->i2c.adapter_id == client->adapter->nr &&
75 match->i2c.address == client->addr;
76 #else
77 return false;
78 #endif
79 }
80
notifier_dev(struct v4l2_async_notifier * notifier)81 static struct device *notifier_dev(struct v4l2_async_notifier *notifier)
82 {
83 if (notifier->sd)
84 return notifier->sd->dev;
85
86 if (notifier->v4l2_dev)
87 return notifier->v4l2_dev->dev;
88
89 return NULL;
90 }
91
92 static bool
match_fwnode_one(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct fwnode_handle * sd_fwnode,struct v4l2_async_match_desc * match)93 match_fwnode_one(struct v4l2_async_notifier *notifier,
94 struct v4l2_subdev *sd, struct fwnode_handle *sd_fwnode,
95 struct v4l2_async_match_desc *match)
96 {
97 struct fwnode_handle *asd_dev_fwnode;
98 bool ret;
99
100 dev_dbg(notifier_dev(notifier),
101 "v4l2-async: fwnode match: need %pfw, trying %pfw\n",
102 sd_fwnode, match->fwnode);
103
104 if (sd_fwnode == match->fwnode) {
105 dev_dbg(notifier_dev(notifier),
106 "v4l2-async: direct match found\n");
107 return true;
108 }
109
110 if (!fwnode_graph_is_endpoint(match->fwnode)) {
111 dev_dbg(notifier_dev(notifier),
112 "v4l2-async: direct match not found\n");
113 return false;
114 }
115
116 asd_dev_fwnode = fwnode_graph_get_port_parent(match->fwnode);
117
118 ret = sd_fwnode == asd_dev_fwnode;
119
120 fwnode_handle_put(asd_dev_fwnode);
121
122 dev_dbg(notifier_dev(notifier),
123 "v4l2-async: device--endpoint match %sfound\n",
124 ret ? "" : "not ");
125
126 return ret;
127 }
128
match_fwnode(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd,struct v4l2_async_match_desc * match)129 static bool match_fwnode(struct v4l2_async_notifier *notifier,
130 struct v4l2_subdev *sd,
131 struct v4l2_async_match_desc *match)
132 {
133 dev_dbg(notifier_dev(notifier),
134 "v4l2-async: matching for notifier %pfw, sd fwnode %pfw\n",
135 dev_fwnode(notifier_dev(notifier)), sd->fwnode);
136
137 if (!list_empty(&sd->async_subdev_endpoint_list)) {
138 struct v4l2_async_subdev_endpoint *ase;
139
140 dev_dbg(sd->dev,
141 "v4l2-async: endpoint fwnode list available, looking for %pfw\n",
142 match->fwnode);
143
144 list_for_each_entry(ase, &sd->async_subdev_endpoint_list,
145 async_subdev_endpoint_entry) {
146 bool matched = ase->endpoint == match->fwnode;
147
148 dev_dbg(sd->dev,
149 "v4l2-async: endpoint-endpoint match %sfound with %pfw\n",
150 matched ? "" : "not ", ase->endpoint);
151
152 if (matched)
153 return true;
154 }
155
156 dev_dbg(sd->dev, "async: no endpoint matched\n");
157
158 return false;
159 }
160
161 if (match_fwnode_one(notifier, sd, sd->fwnode, match))
162 return true;
163
164 /* Also check the secondary fwnode. */
165 if (IS_ERR_OR_NULL(sd->fwnode->secondary))
166 return false;
167
168 dev_dbg(notifier_dev(notifier),
169 "v4l2-async: trying secondary fwnode match\n");
170
171 return match_fwnode_one(notifier, sd, sd->fwnode->secondary, match);
172 }
173
174 static LIST_HEAD(subdev_list);
175 static LIST_HEAD(notifier_list);
176 static DEFINE_MUTEX(list_lock);
177
178 static struct v4l2_async_connection *
v4l2_async_find_match(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd)179 v4l2_async_find_match(struct v4l2_async_notifier *notifier,
180 struct v4l2_subdev *sd)
181 {
182 bool (*match)(struct v4l2_async_notifier *notifier,
183 struct v4l2_subdev *sd,
184 struct v4l2_async_match_desc *match);
185 struct v4l2_async_connection *asc;
186
187 list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) {
188 /* bus_type has been verified valid before */
189 switch (asc->match.type) {
190 case V4L2_ASYNC_MATCH_TYPE_I2C:
191 match = match_i2c;
192 break;
193 case V4L2_ASYNC_MATCH_TYPE_FWNODE:
194 match = match_fwnode;
195 break;
196 default:
197 /* Cannot happen, unless someone breaks us */
198 WARN_ON(true);
199 return NULL;
200 }
201
202 /* match cannot be NULL here */
203 if (match(notifier, sd, &asc->match))
204 return asc;
205 }
206
207 return NULL;
208 }
209
210 /* Compare two async match descriptors for equivalence */
v4l2_async_match_equal(struct v4l2_async_match_desc * match1,struct v4l2_async_match_desc * match2)211 static bool v4l2_async_match_equal(struct v4l2_async_match_desc *match1,
212 struct v4l2_async_match_desc *match2)
213 {
214 if (match1->type != match2->type)
215 return false;
216
217 switch (match1->type) {
218 case V4L2_ASYNC_MATCH_TYPE_I2C:
219 return match1->i2c.adapter_id == match2->i2c.adapter_id &&
220 match1->i2c.address == match2->i2c.address;
221 case V4L2_ASYNC_MATCH_TYPE_FWNODE:
222 return match1->fwnode == match2->fwnode;
223 default:
224 break;
225 }
226
227 return false;
228 }
229
230 /* Find the sub-device notifier registered by a sub-device driver. */
231 static struct v4l2_async_notifier *
v4l2_async_find_subdev_notifier(struct v4l2_subdev * sd)232 v4l2_async_find_subdev_notifier(struct v4l2_subdev *sd)
233 {
234 struct v4l2_async_notifier *n;
235
236 list_for_each_entry(n, ¬ifier_list, notifier_entry)
237 if (n->sd == sd)
238 return n;
239
240 return NULL;
241 }
242
243 /* Get v4l2_device related to the notifier if one can be found. */
244 static struct v4l2_device *
v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier * notifier)245 v4l2_async_nf_find_v4l2_dev(struct v4l2_async_notifier *notifier)
246 {
247 while (notifier->parent)
248 notifier = notifier->parent;
249
250 return notifier->v4l2_dev;
251 }
252
253 /*
254 * Return true if all child sub-device notifiers are complete, false otherwise.
255 */
256 static bool
v4l2_async_nf_can_complete(struct v4l2_async_notifier * notifier)257 v4l2_async_nf_can_complete(struct v4l2_async_notifier *notifier)
258 {
259 struct v4l2_async_connection *asc;
260
261 if (!list_empty(¬ifier->waiting_list))
262 return false;
263
264 list_for_each_entry(asc, ¬ifier->done_list, asc_entry) {
265 struct v4l2_async_notifier *subdev_notifier =
266 v4l2_async_find_subdev_notifier(asc->sd);
267
268 if (subdev_notifier &&
269 !v4l2_async_nf_can_complete(subdev_notifier))
270 return false;
271 }
272
273 return true;
274 }
275
276 /*
277 * Complete the master notifier if possible. This is done when all async
278 * sub-devices have been bound; v4l2_device is also available then.
279 */
280 static int
v4l2_async_nf_try_complete(struct v4l2_async_notifier * notifier)281 v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
282 {
283 struct v4l2_async_notifier *__notifier = notifier;
284
285 /* Quick check whether there are still more sub-devices here. */
286 if (!list_empty(¬ifier->waiting_list))
287 return 0;
288
289 if (notifier->sd)
290 dev_dbg(notifier_dev(notifier),
291 "v4l2-async: trying to complete\n");
292
293 /* Check the entire notifier tree; find the root notifier first. */
294 while (notifier->parent)
295 notifier = notifier->parent;
296
297 /* This is root if it has v4l2_dev. */
298 if (!notifier->v4l2_dev) {
299 dev_dbg(notifier_dev(__notifier),
300 "v4l2-async: V4L2 device not available\n");
301 return 0;
302 }
303
304 /* Is everything ready? */
305 if (!v4l2_async_nf_can_complete(notifier))
306 return 0;
307
308 dev_dbg(notifier_dev(__notifier), "v4l2-async: complete\n");
309
310 return v4l2_async_nf_call_complete(notifier);
311 }
312
313 static int
314 v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
315
v4l2_async_create_ancillary_links(struct v4l2_async_notifier * n,struct v4l2_subdev * sd)316 static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n,
317 struct v4l2_subdev *sd)
318 {
319 #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
320 struct media_link *link;
321
322 if (sd->entity.function != MEDIA_ENT_F_LENS &&
323 sd->entity.function != MEDIA_ENT_F_FLASH)
324 return 0;
325
326 if (!n->sd) {
327 dev_warn(notifier_dev(n),
328 "not a sub-device notifier, not creating an ancillary link for %s!\n",
329 dev_name(sd->dev));
330 return 0;
331 }
332
333 link = media_create_ancillary_link(&n->sd->entity, &sd->entity);
334
335 return IS_ERR(link) ? PTR_ERR(link) : 0;
336 #else
337 return 0;
338 #endif
339 }
340
v4l2_async_match_notify(struct v4l2_async_notifier * notifier,struct v4l2_device * v4l2_dev,struct v4l2_subdev * sd,struct v4l2_async_connection * asc)341 static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
342 struct v4l2_device *v4l2_dev,
343 struct v4l2_subdev *sd,
344 struct v4l2_async_connection *asc)
345 {
346 bool registered = false;
347 int ret;
348
349 if (list_empty(&sd->asc_list)) {
350 ret = __v4l2_device_register_subdev(v4l2_dev, sd, sd->owner);
351 if (ret < 0)
352 return ret;
353 registered = true;
354 }
355
356 ret = v4l2_async_nf_call_bound(notifier, sd, asc);
357 if (ret < 0) {
358 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
359 dev_dbg(notifier_dev(notifier),
360 "failed binding %pfw (%d)\n",
361 asc->match.fwnode, ret);
362 goto err_unregister_subdev;
363 }
364
365 if (registered) {
366 /*
367 * Depending of the function of the entities involved, we may
368 * want to create links between them (for example between a
369 * sensor and its lens or between a sensor's source pad and the
370 * connected device's sink pad).
371 */
372 ret = v4l2_async_create_ancillary_links(notifier, sd);
373 if (ret) {
374 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
375 dev_dbg(notifier_dev(notifier),
376 "failed creating links for %pfw (%d)\n",
377 asc->match.fwnode, ret);
378 goto err_call_unbind;
379 }
380 }
381
382 list_add(&asc->asc_subdev_entry, &sd->asc_list);
383 asc->sd = sd;
384
385 /* Move from the waiting list to notifier's done */
386 list_move(&asc->asc_entry, ¬ifier->done_list);
387
388 dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
389 dev_name(sd->dev), ret);
390
391 return 0;
392
393 err_call_unbind:
394 v4l2_async_nf_call_unbind(notifier, sd, asc);
395 list_del(&asc->asc_subdev_entry);
396
397 err_unregister_subdev:
398 if (registered)
399 v4l2_device_unregister_subdev(sd);
400
401 return ret;
402 }
403
404 static int
v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd)405 v4l2_async_nf_try_subdev_notifier(struct v4l2_async_notifier *notifier,
406 struct v4l2_subdev *sd)
407 {
408 struct v4l2_async_notifier *subdev_notifier;
409
410 /*
411 * See if the sub-device has a notifier. If not, return here.
412 */
413 subdev_notifier = v4l2_async_find_subdev_notifier(sd);
414 if (!subdev_notifier || subdev_notifier->parent)
415 return 0;
416
417 /*
418 * Proceed with checking for the sub-device notifier's async
419 * sub-devices, and return the result. The error will be handled by the
420 * caller.
421 */
422 subdev_notifier->parent = notifier;
423
424 return v4l2_async_nf_try_all_subdevs(subdev_notifier);
425 }
426
427 /* Test all async sub-devices in a notifier for a match. */
428 static int
v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier * notifier)429 v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
430 {
431 struct v4l2_device *v4l2_dev =
432 v4l2_async_nf_find_v4l2_dev(notifier);
433 struct v4l2_subdev *sd;
434
435 if (!v4l2_dev)
436 return 0;
437
438 dev_dbg(notifier_dev(notifier), "v4l2-async: trying all sub-devices\n");
439
440 again:
441 list_for_each_entry(sd, &subdev_list, async_list) {
442 struct v4l2_async_connection *asc;
443 int ret;
444
445 asc = v4l2_async_find_match(notifier, sd);
446 if (!asc)
447 continue;
448
449 dev_dbg(notifier_dev(notifier),
450 "v4l2-async: match found, subdev %s\n", sd->name);
451
452 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc);
453 if (ret < 0)
454 return ret;
455
456 ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
457 if (ret < 0)
458 return ret;
459
460 /*
461 * v4l2_async_match_notify() may lead to registering a
462 * new notifier and thus changing the async subdevs
463 * list. In order to proceed safely from here, restart
464 * parsing the list from the beginning.
465 */
466 goto again;
467 }
468
469 return 0;
470 }
471
v4l2_async_unbind_subdev_one(struct v4l2_async_notifier * notifier,struct v4l2_async_connection * asc)472 static void v4l2_async_unbind_subdev_one(struct v4l2_async_notifier *notifier,
473 struct v4l2_async_connection *asc)
474 {
475 list_move_tail(&asc->asc_entry, ¬ifier->waiting_list);
476 if (list_is_singular(&asc->asc_subdev_entry)) {
477 v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
478 v4l2_device_unregister_subdev(asc->sd);
479 asc->sd = NULL;
480 }
481 list_del(&asc->asc_subdev_entry);
482 }
483
484 /* Unbind all sub-devices in the notifier tree. */
485 static void
v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier * notifier)486 v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
487 {
488 struct v4l2_async_connection *asc, *asc_tmp;
489
490 list_for_each_entry_safe(asc, asc_tmp, ¬ifier->done_list,
491 asc_entry) {
492 struct v4l2_async_notifier *subdev_notifier =
493 v4l2_async_find_subdev_notifier(asc->sd);
494
495 if (subdev_notifier)
496 v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
497
498 v4l2_async_unbind_subdev_one(notifier, asc);
499 }
500
501 notifier->parent = NULL;
502 }
503
504 /* See if an async sub-device can be found in a notifier's lists. */
505 static bool
v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)506 v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
507 struct v4l2_async_match_desc *match)
508 {
509 struct v4l2_async_connection *asc;
510
511 list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry)
512 if (v4l2_async_match_equal(&asc->match, match))
513 return true;
514
515 list_for_each_entry(asc, ¬ifier->done_list, asc_entry)
516 if (v4l2_async_match_equal(&asc->match, match))
517 return true;
518
519 return false;
520 }
521
522 /*
523 * Find out whether an async sub-device was set up already or whether it exists
524 * in a given notifier.
525 */
526 static bool
v4l2_async_nf_has_async_match(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)527 v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
528 struct v4l2_async_match_desc *match)
529 {
530 struct list_head *heads[] = {
531 ¬ifier->waiting_list,
532 ¬ifier->done_list,
533 };
534 unsigned int i;
535
536 lockdep_assert_held(&list_lock);
537
538 /* Check that an asd is not being added more than once. */
539 for (i = 0; i < ARRAY_SIZE(heads); i++) {
540 struct v4l2_async_connection *asc;
541
542 list_for_each_entry(asc, heads[i], asc_entry) {
543 if (&asc->match == match)
544 continue;
545 if (v4l2_async_match_equal(&asc->match, match))
546 return true;
547 }
548 }
549
550 /* Check that an asc does not exist in other notifiers. */
551 list_for_each_entry(notifier, ¬ifier_list, notifier_entry)
552 if (v4l2_async_nf_has_async_match_entry(notifier, match))
553 return true;
554
555 return false;
556 }
557
v4l2_async_nf_match_valid(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)558 static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
559 struct v4l2_async_match_desc *match)
560 {
561 struct device *dev = notifier_dev(notifier);
562
563 switch (match->type) {
564 case V4L2_ASYNC_MATCH_TYPE_I2C:
565 case V4L2_ASYNC_MATCH_TYPE_FWNODE:
566 if (v4l2_async_nf_has_async_match(notifier, match)) {
567 dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
568 return -EEXIST;
569 }
570 break;
571 default:
572 dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
573 match->type, match);
574 return -EINVAL;
575 }
576
577 return 0;
578 }
579
v4l2_async_nf_init(struct v4l2_async_notifier * notifier,struct v4l2_device * v4l2_dev)580 void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
581 struct v4l2_device *v4l2_dev)
582 {
583 INIT_LIST_HEAD(¬ifier->waiting_list);
584 INIT_LIST_HEAD(¬ifier->done_list);
585 INIT_LIST_HEAD(¬ifier->notifier_entry);
586 notifier->v4l2_dev = v4l2_dev;
587 }
588 EXPORT_SYMBOL(v4l2_async_nf_init);
589
v4l2_async_subdev_nf_init(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd)590 void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
591 struct v4l2_subdev *sd)
592 {
593 INIT_LIST_HEAD(¬ifier->waiting_list);
594 INIT_LIST_HEAD(¬ifier->done_list);
595 INIT_LIST_HEAD(¬ifier->notifier_entry);
596 notifier->sd = sd;
597 }
598 EXPORT_SYMBOL_GPL(v4l2_async_subdev_nf_init);
599
__v4l2_async_nf_register(struct v4l2_async_notifier * notifier)600 static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
601 {
602 struct v4l2_async_connection *asc;
603 int ret;
604
605 mutex_lock(&list_lock);
606
607 list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) {
608 ret = v4l2_async_nf_match_valid(notifier, &asc->match);
609 if (ret)
610 goto err_unlock;
611 }
612
613 ret = v4l2_async_nf_try_all_subdevs(notifier);
614 if (ret < 0)
615 goto err_unbind;
616
617 ret = v4l2_async_nf_try_complete(notifier);
618 if (ret < 0)
619 goto err_unbind;
620
621 /* Keep also completed notifiers on the list */
622 list_add(¬ifier->notifier_entry, ¬ifier_list);
623
624 mutex_unlock(&list_lock);
625
626 return 0;
627
628 err_unbind:
629 /*
630 * On failure, unbind all sub-devices registered through this notifier.
631 */
632 v4l2_async_nf_unbind_all_subdevs(notifier);
633
634 err_unlock:
635 mutex_unlock(&list_lock);
636
637 return ret;
638 }
639
v4l2_async_nf_register(struct v4l2_async_notifier * notifier)640 int v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
641 {
642 if (WARN_ON(!notifier->v4l2_dev == !notifier->sd))
643 return -EINVAL;
644
645 return __v4l2_async_nf_register(notifier);
646 }
647 EXPORT_SYMBOL(v4l2_async_nf_register);
648
649 static void
__v4l2_async_nf_unregister(struct v4l2_async_notifier * notifier)650 __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
651 {
652 if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
653 return;
654
655 v4l2_async_nf_unbind_all_subdevs(notifier);
656
657 list_del_init(¬ifier->notifier_entry);
658 }
659
v4l2_async_nf_unregister(struct v4l2_async_notifier * notifier)660 void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
661 {
662 mutex_lock(&list_lock);
663
664 __v4l2_async_nf_unregister(notifier);
665
666 mutex_unlock(&list_lock);
667 }
668 EXPORT_SYMBOL(v4l2_async_nf_unregister);
669
__v4l2_async_nf_cleanup(struct v4l2_async_notifier * notifier)670 static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
671 {
672 struct v4l2_async_connection *asc, *tmp;
673
674 if (!notifier || !notifier->waiting_list.next)
675 return;
676
677 WARN_ON(!list_empty(¬ifier->done_list));
678
679 list_for_each_entry_safe(asc, tmp, ¬ifier->waiting_list, asc_entry) {
680 list_del(&asc->asc_entry);
681 v4l2_async_nf_call_destroy(notifier, asc);
682
683 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
684 fwnode_handle_put(asc->match.fwnode);
685
686 kfree(asc);
687 }
688
689 notifier->sd = NULL;
690 notifier->v4l2_dev = NULL;
691 }
692
v4l2_async_nf_cleanup(struct v4l2_async_notifier * notifier)693 void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
694 {
695 mutex_lock(&list_lock);
696
697 __v4l2_async_nf_cleanup(notifier);
698
699 mutex_unlock(&list_lock);
700 }
701 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
702
__v4l2_async_nf_add_connection(struct v4l2_async_notifier * notifier,struct v4l2_async_connection * asc)703 static void __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
704 struct v4l2_async_connection *asc)
705 {
706 mutex_lock(&list_lock);
707
708 list_add_tail(&asc->asc_entry, ¬ifier->waiting_list);
709
710 mutex_unlock(&list_lock);
711 }
712
713 struct v4l2_async_connection *
__v4l2_async_nf_add_fwnode(struct v4l2_async_notifier * notifier,struct fwnode_handle * fwnode,unsigned int asc_struct_size)714 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
715 struct fwnode_handle *fwnode,
716 unsigned int asc_struct_size)
717 {
718 struct v4l2_async_connection *asc;
719
720 asc = kzalloc(asc_struct_size, GFP_KERNEL);
721 if (!asc)
722 return ERR_PTR(-ENOMEM);
723
724 asc->notifier = notifier;
725 asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
726 asc->match.fwnode = fwnode_handle_get(fwnode);
727
728 __v4l2_async_nf_add_connection(notifier, asc);
729
730 return asc;
731 }
732 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode);
733
734 struct v4l2_async_connection *
__v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier * notif,struct fwnode_handle * endpoint,unsigned int asc_struct_size)735 __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
736 struct fwnode_handle *endpoint,
737 unsigned int asc_struct_size)
738 {
739 struct v4l2_async_connection *asc;
740 struct fwnode_handle *remote;
741
742 remote = fwnode_graph_get_remote_endpoint(endpoint);
743 if (!remote)
744 return ERR_PTR(-ENOTCONN);
745
746 asc = __v4l2_async_nf_add_fwnode(notif, remote, asc_struct_size);
747 /*
748 * Calling __v4l2_async_nf_add_fwnode grabs a refcount,
749 * so drop the one we got in fwnode_graph_get_remote_port_parent.
750 */
751 fwnode_handle_put(remote);
752 return asc;
753 }
754 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode_remote);
755
756 struct v4l2_async_connection *
__v4l2_async_nf_add_i2c(struct v4l2_async_notifier * notifier,int adapter_id,unsigned short address,unsigned int asc_struct_size)757 __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
758 unsigned short address, unsigned int asc_struct_size)
759 {
760 struct v4l2_async_connection *asc;
761
762 asc = kzalloc(asc_struct_size, GFP_KERNEL);
763 if (!asc)
764 return ERR_PTR(-ENOMEM);
765
766 asc->notifier = notifier;
767 asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
768 asc->match.i2c.adapter_id = adapter_id;
769 asc->match.i2c.address = address;
770
771 __v4l2_async_nf_add_connection(notifier, asc);
772
773 return asc;
774 }
775 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
776
v4l2_async_subdev_endpoint_add(struct v4l2_subdev * sd,struct fwnode_handle * fwnode)777 int v4l2_async_subdev_endpoint_add(struct v4l2_subdev *sd,
778 struct fwnode_handle *fwnode)
779 {
780 struct v4l2_async_subdev_endpoint *ase;
781
782 ase = kmalloc_obj(*ase);
783 if (!ase)
784 return -ENOMEM;
785
786 ase->endpoint = fwnode;
787 list_add(&ase->async_subdev_endpoint_entry,
788 &sd->async_subdev_endpoint_list);
789
790 return 0;
791 }
792 EXPORT_SYMBOL_GPL(v4l2_async_subdev_endpoint_add);
793
794 struct v4l2_async_connection *
v4l2_async_connection_unique(struct v4l2_subdev * sd)795 v4l2_async_connection_unique(struct v4l2_subdev *sd)
796 {
797 if (!list_is_singular(&sd->asc_list))
798 return NULL;
799
800 return list_first_entry(&sd->asc_list,
801 struct v4l2_async_connection, asc_subdev_entry);
802 }
803 EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
804
__v4l2_async_register_subdev(struct v4l2_subdev * sd,struct module * module)805 int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
806 {
807 struct v4l2_async_notifier *subdev_notifier;
808 struct v4l2_async_notifier *notifier;
809 struct v4l2_async_connection *asc;
810 int ret;
811
812 INIT_LIST_HEAD(&sd->asc_list);
813
814 /*
815 * No reference taken. The reference is held by the device (struct
816 * v4l2_subdev.dev), and async sub-device does not exist independently
817 * of the device at any point of time.
818 *
819 * The async sub-device shall always be registered for its device node,
820 * not the endpoint node.
821 */
822 if (!sd->fwnode && sd->dev) {
823 sd->fwnode = dev_fwnode(sd->dev);
824 } else if (fwnode_graph_is_endpoint(sd->fwnode)) {
825 dev_warn(sd->dev, "sub-device fwnode is an endpoint!\n");
826 return -EINVAL;
827 }
828
829 sd->owner = module;
830
831 mutex_lock(&list_lock);
832
833 list_for_each_entry(notifier, ¬ifier_list, notifier_entry) {
834 struct v4l2_device *v4l2_dev =
835 v4l2_async_nf_find_v4l2_dev(notifier);
836
837 if (!v4l2_dev)
838 continue;
839
840 while ((asc = v4l2_async_find_match(notifier, sd))) {
841 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd,
842 asc);
843 if (ret)
844 goto err_unlock;
845
846 ret = v4l2_async_nf_try_subdev_notifier(notifier, sd);
847 if (ret)
848 goto err_unbind_one;
849
850 ret = v4l2_async_nf_try_complete(notifier);
851 if (ret)
852 goto err_unbind;
853 }
854 }
855
856 /* None matched, wait for hot-plugging */
857 list_add(&sd->async_list, &subdev_list);
858
859 mutex_unlock(&list_lock);
860
861 return 0;
862
863 err_unbind:
864 /*
865 * Complete failed. Unbind the sub-devices bound through registering
866 * this async sub-device.
867 */
868 subdev_notifier = v4l2_async_find_subdev_notifier(sd);
869 if (subdev_notifier)
870 v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
871
872 err_unbind_one:
873 v4l2_async_unbind_subdev_one(notifier, asc);
874
875 err_unlock:
876 mutex_unlock(&list_lock);
877
878 sd->owner = NULL;
879
880 return ret;
881 }
882 EXPORT_SYMBOL(__v4l2_async_register_subdev);
883
v4l2_async_unregister_subdev(struct v4l2_subdev * sd)884 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
885 {
886 struct v4l2_async_connection *asc, *asc_tmp;
887
888 if (!sd->async_list.next)
889 return;
890
891 v4l2_subdev_put_privacy_led(sd);
892
893 mutex_lock(&list_lock);
894
895 __v4l2_async_nf_unregister(sd->subdev_notifier);
896 __v4l2_async_nf_cleanup(sd->subdev_notifier);
897 kfree(sd->subdev_notifier);
898 sd->subdev_notifier = NULL;
899
900 if (sd->asc_list.next) {
901 list_for_each_entry_safe(asc, asc_tmp, &sd->asc_list,
902 asc_subdev_entry) {
903 v4l2_async_unbind_subdev_one(asc->notifier, asc);
904 }
905 }
906
907 list_del(&sd->async_list);
908 sd->async_list.next = NULL;
909
910 mutex_unlock(&list_lock);
911 }
912 EXPORT_SYMBOL(v4l2_async_unregister_subdev);
913
print_waiting_match(struct seq_file * s,struct v4l2_async_match_desc * match)914 static void print_waiting_match(struct seq_file *s,
915 struct v4l2_async_match_desc *match)
916 {
917 switch (match->type) {
918 case V4L2_ASYNC_MATCH_TYPE_I2C:
919 seq_printf(s, " [i2c] dev=%d-%04x\n", match->i2c.adapter_id,
920 match->i2c.address);
921 break;
922 case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
923 struct fwnode_handle *devnode, *fwnode = match->fwnode;
924
925 devnode = fwnode_graph_is_endpoint(fwnode) ?
926 fwnode_graph_get_port_parent(fwnode) :
927 fwnode_handle_get(fwnode);
928
929 seq_printf(s, " [fwnode] dev=%s, node=%pfw\n",
930 devnode->dev ? dev_name(devnode->dev) : "nil",
931 fwnode);
932
933 fwnode_handle_put(devnode);
934 break;
935 }
936 }
937 }
938
939 static const char *
v4l2_async_nf_name(struct v4l2_async_notifier * notifier)940 v4l2_async_nf_name(struct v4l2_async_notifier *notifier)
941 {
942 if (notifier->v4l2_dev)
943 return notifier->v4l2_dev->name;
944 else if (notifier->sd)
945 return notifier->sd->name;
946 else
947 return "nil";
948 }
949
pending_subdevs_show(struct seq_file * s,void * data)950 static int pending_subdevs_show(struct seq_file *s, void *data)
951 {
952 struct v4l2_async_notifier *notif;
953 struct v4l2_async_connection *asc;
954
955 mutex_lock(&list_lock);
956
957 list_for_each_entry(notif, ¬ifier_list, notifier_entry) {
958 seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
959 list_for_each_entry(asc, ¬if->waiting_list, asc_entry)
960 print_waiting_match(s, &asc->match);
961 }
962
963 mutex_unlock(&list_lock);
964
965 return 0;
966 }
967 DEFINE_SHOW_ATTRIBUTE(pending_subdevs);
968
969 static struct dentry *v4l2_async_debugfs_dir;
970
v4l2_async_init(void)971 static int __init v4l2_async_init(void)
972 {
973 v4l2_async_debugfs_dir = debugfs_create_dir("v4l2-async", NULL);
974 debugfs_create_file("pending_async_subdevices", 0444,
975 v4l2_async_debugfs_dir, NULL,
976 &pending_subdevs_fops);
977
978 return 0;
979 }
980
v4l2_async_exit(void)981 static void __exit v4l2_async_exit(void)
982 {
983 debugfs_remove_recursive(v4l2_async_debugfs_dir);
984 }
985
986 subsys_initcall(v4l2_async_init);
987 module_exit(v4l2_async_exit);
988
989 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
990 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
991 MODULE_AUTHOR("Ezequiel Garcia <ezequiel@collabora.com>");
992 MODULE_DESCRIPTION("V4L2 asynchronous subdevice registration API");
993 MODULE_LICENSE("GPL");
994