• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &notifier->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, &notifier_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(&notifier->waiting_list))
262 		return false;
263 
264 	list_for_each_entry(asc, &notifier->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(&notifier->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, &notifier->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, &notifier->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, &notifier->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, &notifier->waiting_list, asc_entry)
496 		if (v4l2_async_match_equal(&asc->match, match))
497 			return true;
498 
499 	list_for_each_entry(asc, &notifier->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 		&notifier->waiting_list,
516 		&notifier->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, &notifier_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(&notifier->waiting_list);
568 	INIT_LIST_HEAD(&notifier->done_list);
569 	INIT_LIST_HEAD(&notifier->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(&notifier->waiting_list);
578 	INIT_LIST_HEAD(&notifier->done_list);
579 	INIT_LIST_HEAD(&notifier->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, &notifier->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(&notifier->notifier_entry, &notifier_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(&notifier->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(&notifier->done_list));
662 
663 	list_for_each_entry_safe(asc, tmp, &notifier->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, &notifier->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, &notifier_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, &notifier_list, notifier_entry) {
936 		seq_printf(s, "%s:\n", v4l2_async_nf_name(notif));
937 		list_for_each_entry(asc, &notif->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