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 struct media_link *link = NULL;
320
321 #if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
322
323 if (sd->entity.function != MEDIA_ENT_F_LENS &&
324 sd->entity.function != MEDIA_ENT_F_FLASH)
325 return 0;
326
327 if (!n->sd)
328 return 0;
329
330 link = media_create_ancillary_link(&n->sd->entity, &sd->entity);
331
332 #endif
333
334 return IS_ERR(link) ? PTR_ERR(link) : 0;
335 }
336
v4l2_async_match_notify(struct v4l2_async_notifier * notifier,struct v4l2_device * v4l2_dev,struct v4l2_subdev * sd,struct v4l2_async_connection * asc)337 static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
338 struct v4l2_device *v4l2_dev,
339 struct v4l2_subdev *sd,
340 struct v4l2_async_connection *asc)
341 {
342 struct v4l2_async_notifier *subdev_notifier;
343 bool registered = false;
344 int ret;
345
346 if (list_empty(&sd->asc_list)) {
347 ret = v4l2_device_register_subdev(v4l2_dev, sd);
348 if (ret < 0)
349 return ret;
350 registered = true;
351 }
352
353 ret = v4l2_async_nf_call_bound(notifier, sd, asc);
354 if (ret < 0) {
355 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
356 dev_dbg(notifier_dev(notifier),
357 "failed binding %pfw (%d)\n",
358 asc->match.fwnode, ret);
359 goto err_unregister_subdev;
360 }
361
362 if (registered) {
363 /*
364 * Depending of the function of the entities involved, we may
365 * want to create links between them (for example between a
366 * sensor and its lens or between a sensor's source pad and the
367 * connected device's sink pad).
368 */
369 ret = v4l2_async_create_ancillary_links(notifier, sd);
370 if (ret) {
371 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
372 dev_dbg(notifier_dev(notifier),
373 "failed creating links for %pfw (%d)\n",
374 asc->match.fwnode, ret);
375 goto err_call_unbind;
376 }
377 }
378
379 list_add(&asc->asc_subdev_entry, &sd->asc_list);
380 asc->sd = sd;
381
382 /* Move from the waiting list to notifier's done */
383 list_move(&asc->asc_entry, ¬ifier->done_list);
384
385 dev_dbg(notifier_dev(notifier), "v4l2-async: %s bound (ret %d)\n",
386 dev_name(sd->dev), ret);
387
388 /*
389 * See if the sub-device has a notifier. If not, return here.
390 */
391 subdev_notifier = v4l2_async_find_subdev_notifier(sd);
392 if (!subdev_notifier || subdev_notifier->parent)
393 return 0;
394
395 /*
396 * Proceed with checking for the sub-device notifier's async
397 * sub-devices, and return the result. The error will be handled by the
398 * caller.
399 */
400 subdev_notifier->parent = notifier;
401
402 return v4l2_async_nf_try_all_subdevs(subdev_notifier);
403
404 err_call_unbind:
405 v4l2_async_nf_call_unbind(notifier, sd, asc);
406 list_del(&asc->asc_subdev_entry);
407
408 err_unregister_subdev:
409 if (registered)
410 v4l2_device_unregister_subdev(sd);
411
412 return ret;
413 }
414
415 /* Test all async sub-devices in a notifier for a match. */
416 static int
v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier * notifier)417 v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier)
418 {
419 struct v4l2_device *v4l2_dev =
420 v4l2_async_nf_find_v4l2_dev(notifier);
421 struct v4l2_subdev *sd;
422
423 if (!v4l2_dev)
424 return 0;
425
426 dev_dbg(notifier_dev(notifier), "v4l2-async: trying all sub-devices\n");
427
428 again:
429 list_for_each_entry(sd, &subdev_list, async_list) {
430 struct v4l2_async_connection *asc;
431 int ret;
432
433 asc = v4l2_async_find_match(notifier, sd);
434 if (!asc)
435 continue;
436
437 dev_dbg(notifier_dev(notifier),
438 "v4l2-async: match found, subdev %s\n", sd->name);
439
440 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asc);
441 if (ret < 0)
442 return ret;
443
444 /*
445 * v4l2_async_match_notify() may lead to registering a
446 * new notifier and thus changing the async subdevs
447 * list. In order to proceed safely from here, restart
448 * parsing the list from the beginning.
449 */
450 goto again;
451 }
452
453 return 0;
454 }
455
v4l2_async_unbind_subdev_one(struct v4l2_async_notifier * notifier,struct v4l2_async_connection * asc)456 static void v4l2_async_unbind_subdev_one(struct v4l2_async_notifier *notifier,
457 struct v4l2_async_connection *asc)
458 {
459 list_move_tail(&asc->asc_entry, ¬ifier->waiting_list);
460 if (list_is_singular(&asc->asc_subdev_entry)) {
461 v4l2_async_nf_call_unbind(notifier, asc->sd, asc);
462 v4l2_device_unregister_subdev(asc->sd);
463 asc->sd = NULL;
464 }
465 list_del(&asc->asc_subdev_entry);
466 }
467
468 /* Unbind all sub-devices in the notifier tree. */
469 static void
v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier * notifier)470 v4l2_async_nf_unbind_all_subdevs(struct v4l2_async_notifier *notifier)
471 {
472 struct v4l2_async_connection *asc, *asc_tmp;
473
474 list_for_each_entry_safe(asc, asc_tmp, ¬ifier->done_list,
475 asc_entry) {
476 struct v4l2_async_notifier *subdev_notifier =
477 v4l2_async_find_subdev_notifier(asc->sd);
478
479 if (subdev_notifier)
480 v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
481
482 v4l2_async_unbind_subdev_one(notifier, asc);
483 }
484
485 notifier->parent = NULL;
486 }
487
488 /* See if an async sub-device can be found in a notifier's lists. */
489 static bool
v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)490 v4l2_async_nf_has_async_match_entry(struct v4l2_async_notifier *notifier,
491 struct v4l2_async_match_desc *match)
492 {
493 struct v4l2_async_connection *asc;
494
495 list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry)
496 if (v4l2_async_match_equal(&asc->match, match))
497 return true;
498
499 list_for_each_entry(asc, ¬ifier->done_list, asc_entry)
500 if (v4l2_async_match_equal(&asc->match, match))
501 return true;
502
503 return false;
504 }
505
506 /*
507 * Find out whether an async sub-device was set up already or whether it exists
508 * in a given notifier.
509 */
510 static bool
v4l2_async_nf_has_async_match(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)511 v4l2_async_nf_has_async_match(struct v4l2_async_notifier *notifier,
512 struct v4l2_async_match_desc *match)
513 {
514 struct list_head *heads[] = {
515 ¬ifier->waiting_list,
516 ¬ifier->done_list,
517 };
518 unsigned int i;
519
520 lockdep_assert_held(&list_lock);
521
522 /* Check that an asd is not being added more than once. */
523 for (i = 0; i < ARRAY_SIZE(heads); i++) {
524 struct v4l2_async_connection *asc;
525
526 list_for_each_entry(asc, heads[i], asc_entry) {
527 if (&asc->match == match)
528 continue;
529 if (v4l2_async_match_equal(&asc->match, match))
530 return true;
531 }
532 }
533
534 /* Check that an asc does not exist in other notifiers. */
535 list_for_each_entry(notifier, ¬ifier_list, notifier_entry)
536 if (v4l2_async_nf_has_async_match_entry(notifier, match))
537 return true;
538
539 return false;
540 }
541
v4l2_async_nf_match_valid(struct v4l2_async_notifier * notifier,struct v4l2_async_match_desc * match)542 static int v4l2_async_nf_match_valid(struct v4l2_async_notifier *notifier,
543 struct v4l2_async_match_desc *match)
544 {
545 struct device *dev = notifier_dev(notifier);
546
547 switch (match->type) {
548 case V4L2_ASYNC_MATCH_TYPE_I2C:
549 case V4L2_ASYNC_MATCH_TYPE_FWNODE:
550 if (v4l2_async_nf_has_async_match(notifier, match)) {
551 dev_dbg(dev, "v4l2-async: match descriptor already listed in a notifier\n");
552 return -EEXIST;
553 }
554 break;
555 default:
556 dev_err(dev, "v4l2-async: Invalid match type %u on %p\n",
557 match->type, match);
558 return -EINVAL;
559 }
560
561 return 0;
562 }
563
v4l2_async_nf_init(struct v4l2_async_notifier * notifier,struct v4l2_device * v4l2_dev)564 void v4l2_async_nf_init(struct v4l2_async_notifier *notifier,
565 struct v4l2_device *v4l2_dev)
566 {
567 INIT_LIST_HEAD(¬ifier->waiting_list);
568 INIT_LIST_HEAD(¬ifier->done_list);
569 INIT_LIST_HEAD(¬ifier->notifier_entry);
570 notifier->v4l2_dev = v4l2_dev;
571 }
572 EXPORT_SYMBOL(v4l2_async_nf_init);
573
v4l2_async_subdev_nf_init(struct v4l2_async_notifier * notifier,struct v4l2_subdev * sd)574 void v4l2_async_subdev_nf_init(struct v4l2_async_notifier *notifier,
575 struct v4l2_subdev *sd)
576 {
577 INIT_LIST_HEAD(¬ifier->waiting_list);
578 INIT_LIST_HEAD(¬ifier->done_list);
579 INIT_LIST_HEAD(¬ifier->notifier_entry);
580 notifier->sd = sd;
581 }
582 EXPORT_SYMBOL_GPL(v4l2_async_subdev_nf_init);
583
__v4l2_async_nf_register(struct v4l2_async_notifier * notifier)584 static int __v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
585 {
586 struct v4l2_async_connection *asc;
587 int ret;
588
589 mutex_lock(&list_lock);
590
591 list_for_each_entry(asc, ¬ifier->waiting_list, asc_entry) {
592 ret = v4l2_async_nf_match_valid(notifier, &asc->match);
593 if (ret)
594 goto err_unlock;
595 }
596
597 ret = v4l2_async_nf_try_all_subdevs(notifier);
598 if (ret < 0)
599 goto err_unbind;
600
601 ret = v4l2_async_nf_try_complete(notifier);
602 if (ret < 0)
603 goto err_unbind;
604
605 /* Keep also completed notifiers on the list */
606 list_add(¬ifier->notifier_entry, ¬ifier_list);
607
608 mutex_unlock(&list_lock);
609
610 return 0;
611
612 err_unbind:
613 /*
614 * On failure, unbind all sub-devices registered through this notifier.
615 */
616 v4l2_async_nf_unbind_all_subdevs(notifier);
617
618 err_unlock:
619 mutex_unlock(&list_lock);
620
621 return ret;
622 }
623
v4l2_async_nf_register(struct v4l2_async_notifier * notifier)624 int v4l2_async_nf_register(struct v4l2_async_notifier *notifier)
625 {
626 if (WARN_ON(!notifier->v4l2_dev == !notifier->sd))
627 return -EINVAL;
628
629 return __v4l2_async_nf_register(notifier);
630 }
631 EXPORT_SYMBOL(v4l2_async_nf_register);
632
633 static void
__v4l2_async_nf_unregister(struct v4l2_async_notifier * notifier)634 __v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
635 {
636 if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
637 return;
638
639 v4l2_async_nf_unbind_all_subdevs(notifier);
640
641 list_del_init(¬ifier->notifier_entry);
642 }
643
v4l2_async_nf_unregister(struct v4l2_async_notifier * notifier)644 void v4l2_async_nf_unregister(struct v4l2_async_notifier *notifier)
645 {
646 mutex_lock(&list_lock);
647
648 __v4l2_async_nf_unregister(notifier);
649
650 mutex_unlock(&list_lock);
651 }
652 EXPORT_SYMBOL(v4l2_async_nf_unregister);
653
__v4l2_async_nf_cleanup(struct v4l2_async_notifier * notifier)654 static void __v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
655 {
656 struct v4l2_async_connection *asc, *tmp;
657
658 if (!notifier || !notifier->waiting_list.next)
659 return;
660
661 WARN_ON(!list_empty(¬ifier->done_list));
662
663 list_for_each_entry_safe(asc, tmp, ¬ifier->waiting_list, asc_entry) {
664 list_del(&asc->asc_entry);
665 v4l2_async_nf_call_destroy(notifier, asc);
666
667 if (asc->match.type == V4L2_ASYNC_MATCH_TYPE_FWNODE)
668 fwnode_handle_put(asc->match.fwnode);
669
670 kfree(asc);
671 }
672
673 notifier->sd = NULL;
674 notifier->v4l2_dev = NULL;
675 }
676
v4l2_async_nf_cleanup(struct v4l2_async_notifier * notifier)677 void v4l2_async_nf_cleanup(struct v4l2_async_notifier *notifier)
678 {
679 mutex_lock(&list_lock);
680
681 __v4l2_async_nf_cleanup(notifier);
682
683 mutex_unlock(&list_lock);
684 }
685 EXPORT_SYMBOL_GPL(v4l2_async_nf_cleanup);
686
__v4l2_async_nf_add_connection(struct v4l2_async_notifier * notifier,struct v4l2_async_connection * asc)687 static void __v4l2_async_nf_add_connection(struct v4l2_async_notifier *notifier,
688 struct v4l2_async_connection *asc)
689 {
690 mutex_lock(&list_lock);
691
692 list_add_tail(&asc->asc_entry, ¬ifier->waiting_list);
693
694 mutex_unlock(&list_lock);
695 }
696
697 struct v4l2_async_connection *
__v4l2_async_nf_add_fwnode(struct v4l2_async_notifier * notifier,struct fwnode_handle * fwnode,unsigned int asc_struct_size)698 __v4l2_async_nf_add_fwnode(struct v4l2_async_notifier *notifier,
699 struct fwnode_handle *fwnode,
700 unsigned int asc_struct_size)
701 {
702 struct v4l2_async_connection *asc;
703
704 asc = kzalloc(asc_struct_size, GFP_KERNEL);
705 if (!asc)
706 return ERR_PTR(-ENOMEM);
707
708 asc->notifier = notifier;
709 asc->match.type = V4L2_ASYNC_MATCH_TYPE_FWNODE;
710 asc->match.fwnode = fwnode_handle_get(fwnode);
711
712 __v4l2_async_nf_add_connection(notifier, asc);
713
714 return asc;
715 }
716 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode);
717
718 struct v4l2_async_connection *
__v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier * notif,struct fwnode_handle * endpoint,unsigned int asc_struct_size)719 __v4l2_async_nf_add_fwnode_remote(struct v4l2_async_notifier *notif,
720 struct fwnode_handle *endpoint,
721 unsigned int asc_struct_size)
722 {
723 struct v4l2_async_connection *asc;
724 struct fwnode_handle *remote;
725
726 remote = fwnode_graph_get_remote_endpoint(endpoint);
727 if (!remote)
728 return ERR_PTR(-ENOTCONN);
729
730 asc = __v4l2_async_nf_add_fwnode(notif, remote, asc_struct_size);
731 /*
732 * Calling __v4l2_async_nf_add_fwnode grabs a refcount,
733 * so drop the one we got in fwnode_graph_get_remote_port_parent.
734 */
735 fwnode_handle_put(remote);
736 return asc;
737 }
738 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_fwnode_remote);
739
740 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)741 __v4l2_async_nf_add_i2c(struct v4l2_async_notifier *notifier, int adapter_id,
742 unsigned short address, unsigned int asc_struct_size)
743 {
744 struct v4l2_async_connection *asc;
745
746 asc = kzalloc(asc_struct_size, GFP_KERNEL);
747 if (!asc)
748 return ERR_PTR(-ENOMEM);
749
750 asc->notifier = notifier;
751 asc->match.type = V4L2_ASYNC_MATCH_TYPE_I2C;
752 asc->match.i2c.adapter_id = adapter_id;
753 asc->match.i2c.address = address;
754
755 __v4l2_async_nf_add_connection(notifier, asc);
756
757 return asc;
758 }
759 EXPORT_SYMBOL_GPL(__v4l2_async_nf_add_i2c);
760
v4l2_async_subdev_endpoint_add(struct v4l2_subdev * sd,struct fwnode_handle * fwnode)761 int v4l2_async_subdev_endpoint_add(struct v4l2_subdev *sd,
762 struct fwnode_handle *fwnode)
763 {
764 struct v4l2_async_subdev_endpoint *ase;
765
766 ase = kmalloc(sizeof(*ase), GFP_KERNEL);
767 if (!ase)
768 return -ENOMEM;
769
770 ase->endpoint = fwnode;
771 list_add(&ase->async_subdev_endpoint_entry,
772 &sd->async_subdev_endpoint_list);
773
774 return 0;
775 }
776 EXPORT_SYMBOL_GPL(v4l2_async_subdev_endpoint_add);
777
778 struct v4l2_async_connection *
v4l2_async_connection_unique(struct v4l2_subdev * sd)779 v4l2_async_connection_unique(struct v4l2_subdev *sd)
780 {
781 if (!list_is_singular(&sd->asc_list))
782 return NULL;
783
784 return list_first_entry(&sd->asc_list,
785 struct v4l2_async_connection, asc_subdev_entry);
786 }
787 EXPORT_SYMBOL_GPL(v4l2_async_connection_unique);
788
v4l2_async_register_subdev(struct v4l2_subdev * sd)789 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
790 {
791 struct v4l2_async_notifier *subdev_notifier;
792 struct v4l2_async_notifier *notifier;
793 struct v4l2_async_connection *asc;
794 int ret;
795
796 INIT_LIST_HEAD(&sd->asc_list);
797
798 /*
799 * No reference taken. The reference is held by the device (struct
800 * v4l2_subdev.dev), and async sub-device does not exist independently
801 * of the device at any point of time.
802 *
803 * The async sub-device shall always be registered for its device node,
804 * not the endpoint node.
805 */
806 if (!sd->fwnode && sd->dev) {
807 sd->fwnode = dev_fwnode(sd->dev);
808 } else if (fwnode_graph_is_endpoint(sd->fwnode)) {
809 dev_warn(sd->dev, "sub-device fwnode is an endpoint!\n");
810 return -EINVAL;
811 }
812
813 mutex_lock(&list_lock);
814
815 list_for_each_entry(notifier, ¬ifier_list, notifier_entry) {
816 struct v4l2_device *v4l2_dev =
817 v4l2_async_nf_find_v4l2_dev(notifier);
818
819 if (!v4l2_dev)
820 continue;
821
822 while ((asc = v4l2_async_find_match(notifier, sd))) {
823 ret = v4l2_async_match_notify(notifier, v4l2_dev, sd,
824 asc);
825 if (ret)
826 goto err_unbind;
827
828 ret = v4l2_async_nf_try_complete(notifier);
829 if (ret)
830 goto err_unbind;
831 }
832 }
833
834 /* None matched, wait for hot-plugging */
835 list_add(&sd->async_list, &subdev_list);
836
837 mutex_unlock(&list_lock);
838
839 return 0;
840
841 err_unbind:
842 /*
843 * Complete failed. Unbind the sub-devices bound through registering
844 * this async sub-device.
845 */
846 subdev_notifier = v4l2_async_find_subdev_notifier(sd);
847 if (subdev_notifier)
848 v4l2_async_nf_unbind_all_subdevs(subdev_notifier);
849
850 if (asc)
851 v4l2_async_unbind_subdev_one(notifier, asc);
852
853 mutex_unlock(&list_lock);
854
855 return ret;
856 }
857 EXPORT_SYMBOL(v4l2_async_register_subdev);
858
v4l2_async_unregister_subdev(struct v4l2_subdev * sd)859 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
860 {
861 struct v4l2_async_connection *asc, *asc_tmp;
862
863 if (!sd->async_list.next)
864 return;
865
866 v4l2_subdev_put_privacy_led(sd);
867
868 mutex_lock(&list_lock);
869
870 __v4l2_async_nf_unregister(sd->subdev_notifier);
871 __v4l2_async_nf_cleanup(sd->subdev_notifier);
872 kfree(sd->subdev_notifier);
873 sd->subdev_notifier = NULL;
874
875 if (sd->asc_list.next) {
876 list_for_each_entry_safe(asc, asc_tmp, &sd->asc_list,
877 asc_subdev_entry) {
878 list_move(&asc->asc_entry,
879 &asc->notifier->waiting_list);
880
881 v4l2_async_unbind_subdev_one(asc->notifier, asc);
882 }
883 }
884
885 list_del(&sd->async_list);
886 sd->async_list.next = NULL;
887
888 mutex_unlock(&list_lock);
889 }
890 EXPORT_SYMBOL(v4l2_async_unregister_subdev);
891
print_waiting_match(struct seq_file * s,struct v4l2_async_match_desc * match)892 static void print_waiting_match(struct seq_file *s,
893 struct v4l2_async_match_desc *match)
894 {
895 switch (match->type) {
896 case V4L2_ASYNC_MATCH_TYPE_I2C:
897 seq_printf(s, " [i2c] dev=%d-%04x\n", match->i2c.adapter_id,
898 match->i2c.address);
899 break;
900 case V4L2_ASYNC_MATCH_TYPE_FWNODE: {
901 struct fwnode_handle *devnode, *fwnode = match->fwnode;
902
903 devnode = fwnode_graph_is_endpoint(fwnode) ?
904 fwnode_graph_get_port_parent(fwnode) :
905 fwnode_handle_get(fwnode);
906
907 seq_printf(s, " [fwnode] dev=%s, node=%pfw\n",
908 devnode->dev ? dev_name(devnode->dev) : "nil",
909 fwnode);
910
911 fwnode_handle_put(devnode);
912 break;
913 }
914 }
915 }
916
917 static const char *
v4l2_async_nf_name(struct v4l2_async_notifier * notifier)918 v4l2_async_nf_name(struct v4l2_async_notifier *notifier)
919 {
920 if (notifier->v4l2_dev)
921 return notifier->v4l2_dev->name;
922 else if (notifier->sd)
923 return notifier->sd->name;
924 else
925 return "nil";
926 }
927
pending_subdevs_show(struct seq_file * s,void * data)928 static int pending_subdevs_show(struct seq_file *s, void *data)
929 {
930 struct v4l2_async_notifier *notif;
931 struct v4l2_async_connection *asc;
932
933 mutex_lock(&list_lock);
934
935 list_for_each_entry(notif, ¬ifier_list, notifier_entry) {
936 seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
937 list_for_each_entry(asc, ¬if->waiting_list, asc_entry)
938 print_waiting_match(s, &asc->match);
939 }
940
941 mutex_unlock(&list_lock);
942
943 return 0;
944 }
945 DEFINE_SHOW_ATTRIBUTE(pending_subdevs);
946
947 static struct dentry *v4l2_async_debugfs_dir;
948
v4l2_async_init(void)949 static int __init v4l2_async_init(void)
950 {
951 v4l2_async_debugfs_dir = debugfs_create_dir("v4l2-async", NULL);
952 debugfs_create_file("pending_async_subdevices", 0444,
953 v4l2_async_debugfs_dir, NULL,
954 &pending_subdevs_fops);
955
956 return 0;
957 }
958
v4l2_async_exit(void)959 static void __exit v4l2_async_exit(void)
960 {
961 debugfs_remove_recursive(v4l2_async_debugfs_dir);
962 }
963
964 subsys_initcall(v4l2_async_init);
965 module_exit(v4l2_async_exit);
966
967 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
968 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
969 MODULE_AUTHOR("Ezequiel Garcia <ezequiel@collabora.com>");
970 MODULE_LICENSE("GPL");
971