1 /*
2  * V4L2 asynchronous subdevice registration API
3  *
4  * Copyright (C) 2012-2013, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5  *
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.
9  */
10 
11 #include <linux/device.h>
12 #include <linux/err.h>
13 #include <linux/i2c.h>
14 #include <linux/list.h>
15 #include <linux/mm.h>
16 #include <linux/module.h>
17 #include <linux/mutex.h>
18 #include <linux/of.h>
19 #include <linux/platform_device.h>
20 #include <linux/slab.h>
21 #include <linux/types.h>
22 
23 #include <media/v4l2-async.h>
24 #include <media/v4l2-device.h>
25 #include <media/v4l2-subdev.h>
26 
27 static bool match_i2c(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
28 {
29 #if IS_ENABLED(CONFIG_I2C)
30 	struct i2c_client *client = i2c_verify_client(sd->dev);
31 	return client &&
32 		asd->match.i2c.adapter_id == client->adapter->nr &&
33 		asd->match.i2c.address == client->addr;
34 #else
35 	return false;
36 #endif
37 }
38 
39 static bool match_devname(struct v4l2_subdev *sd,
40 			  struct v4l2_async_subdev *asd)
41 {
42 	return !strcmp(asd->match.device_name.name, dev_name(sd->dev));
43 }
44 
45 static bool match_fwnode(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
46 {
47 	if (!is_of_node(sd->fwnode) || !is_of_node(asd->match.fwnode.fwnode))
48 		return sd->fwnode == asd->match.fwnode.fwnode;
49 
50 	return !of_node_cmp(of_node_full_name(to_of_node(sd->fwnode)),
51 			    of_node_full_name(
52 				    to_of_node(asd->match.fwnode.fwnode)));
53 }
54 
55 static bool match_custom(struct v4l2_subdev *sd, struct v4l2_async_subdev *asd)
56 {
57 	if (!asd->match.custom.match)
58 		/* Match always */
59 		return true;
60 
61 	return asd->match.custom.match(sd->dev, asd);
62 }
63 
64 static LIST_HEAD(subdev_list);
65 static LIST_HEAD(notifier_list);
66 static DEFINE_MUTEX(list_lock);
67 
68 static struct v4l2_async_subdev *v4l2_async_belongs(struct v4l2_async_notifier *notifier,
69 						    struct v4l2_subdev *sd)
70 {
71 	bool (*match)(struct v4l2_subdev *, struct v4l2_async_subdev *);
72 	struct v4l2_async_subdev *asd;
73 
74 	list_for_each_entry(asd, &notifier->waiting, list) {
75 		/* bus_type has been verified valid before */
76 		switch (asd->match_type) {
77 		case V4L2_ASYNC_MATCH_CUSTOM:
78 			match = match_custom;
79 			break;
80 		case V4L2_ASYNC_MATCH_DEVNAME:
81 			match = match_devname;
82 			break;
83 		case V4L2_ASYNC_MATCH_I2C:
84 			match = match_i2c;
85 			break;
86 		case V4L2_ASYNC_MATCH_FWNODE:
87 			match = match_fwnode;
88 			break;
89 		default:
90 			/* Cannot happen, unless someone breaks us */
91 			WARN_ON(true);
92 			return NULL;
93 		}
94 
95 		/* match cannot be NULL here */
96 		if (match(sd, asd))
97 			return asd;
98 	}
99 
100 	return NULL;
101 }
102 
103 static int v4l2_async_test_notify(struct v4l2_async_notifier *notifier,
104 				  struct v4l2_subdev *sd,
105 				  struct v4l2_async_subdev *asd)
106 {
107 	int ret;
108 
109 	if (notifier->bound) {
110 		ret = notifier->bound(notifier, sd, asd);
111 		if (ret < 0)
112 			return ret;
113 	}
114 
115 	ret = v4l2_device_register_subdev(notifier->v4l2_dev, sd);
116 	if (ret < 0) {
117 		if (notifier->unbind)
118 			notifier->unbind(notifier, sd, asd);
119 		return ret;
120 	}
121 
122 	/* Remove from the waiting list */
123 	list_del(&asd->list);
124 	sd->asd = asd;
125 	sd->notifier = notifier;
126 
127 	/* Move from the global subdevice list to notifier's done */
128 	list_move(&sd->async_list, &notifier->done);
129 
130 	if (list_empty(&notifier->waiting) && notifier->complete)
131 		return notifier->complete(notifier);
132 
133 	return 0;
134 }
135 
136 static void v4l2_async_cleanup(struct v4l2_subdev *sd)
137 {
138 	v4l2_device_unregister_subdev(sd);
139 	/* Subdevice driver will reprobe and put the subdev back onto the list */
140 	list_del_init(&sd->async_list);
141 	sd->asd = NULL;
142 	sd->dev = NULL;
143 }
144 
145 int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
146 				 struct v4l2_async_notifier *notifier)
147 {
148 	struct v4l2_subdev *sd, *tmp;
149 	struct v4l2_async_subdev *asd;
150 	int i;
151 
152 	if (!v4l2_dev || !notifier->num_subdevs ||
153 	    notifier->num_subdevs > V4L2_MAX_SUBDEVS)
154 		return -EINVAL;
155 
156 	notifier->v4l2_dev = v4l2_dev;
157 	INIT_LIST_HEAD(&notifier->waiting);
158 	INIT_LIST_HEAD(&notifier->done);
159 
160 	for (i = 0; i < notifier->num_subdevs; i++) {
161 		asd = notifier->subdevs[i];
162 
163 		switch (asd->match_type) {
164 		case V4L2_ASYNC_MATCH_CUSTOM:
165 		case V4L2_ASYNC_MATCH_DEVNAME:
166 		case V4L2_ASYNC_MATCH_I2C:
167 		case V4L2_ASYNC_MATCH_FWNODE:
168 			break;
169 		default:
170 			dev_err(notifier->v4l2_dev ? notifier->v4l2_dev->dev : NULL,
171 				"Invalid match type %u on %p\n",
172 				asd->match_type, asd);
173 			return -EINVAL;
174 		}
175 		list_add_tail(&asd->list, &notifier->waiting);
176 	}
177 
178 	mutex_lock(&list_lock);
179 
180 	list_for_each_entry_safe(sd, tmp, &subdev_list, async_list) {
181 		int ret;
182 
183 		asd = v4l2_async_belongs(notifier, sd);
184 		if (!asd)
185 			continue;
186 
187 		ret = v4l2_async_test_notify(notifier, sd, asd);
188 		if (ret < 0) {
189 			mutex_unlock(&list_lock);
190 			return ret;
191 		}
192 	}
193 
194 	/* Keep also completed notifiers on the list */
195 	list_add(&notifier->list, &notifier_list);
196 
197 	mutex_unlock(&list_lock);
198 
199 	return 0;
200 }
201 EXPORT_SYMBOL(v4l2_async_notifier_register);
202 
203 void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
204 {
205 	struct v4l2_subdev *sd, *tmp;
206 	unsigned int notif_n_subdev = notifier->num_subdevs;
207 	unsigned int n_subdev = min(notif_n_subdev, V4L2_MAX_SUBDEVS);
208 	struct device **dev;
209 	int i = 0;
210 
211 	if (!notifier->v4l2_dev)
212 		return;
213 
214 	dev = kvmalloc_array(n_subdev, sizeof(*dev), GFP_KERNEL);
215 	if (!dev) {
216 		dev_err(notifier->v4l2_dev->dev,
217 			"Failed to allocate device cache!\n");
218 	}
219 
220 	mutex_lock(&list_lock);
221 
222 	list_del(&notifier->list);
223 
224 	list_for_each_entry_safe(sd, tmp, &notifier->done, async_list) {
225 		struct device *d;
226 
227 		d = get_device(sd->dev);
228 
229 		v4l2_async_cleanup(sd);
230 
231 		/* If we handled USB devices, we'd have to lock the parent too */
232 		device_release_driver(d);
233 
234 		if (notifier->unbind)
235 			notifier->unbind(notifier, sd, sd->asd);
236 
237 		/*
238 		 * Store device at the device cache, in order to call
239 		 * put_device() on the final step
240 		 */
241 		if (dev)
242 			dev[i++] = d;
243 		else
244 			put_device(d);
245 	}
246 
247 	mutex_unlock(&list_lock);
248 
249 	/*
250 	 * Call device_attach() to reprobe devices
251 	 *
252 	 * NOTE: If dev allocation fails, i is 0, and the whole loop won't be
253 	 * executed.
254 	 */
255 	while (i--) {
256 		struct device *d = dev[i];
257 
258 		if (d && device_attach(d) < 0) {
259 			const char *name = "(none)";
260 			int lock = device_trylock(d);
261 
262 			if (lock && d->driver)
263 				name = d->driver->name;
264 			dev_err(d, "Failed to re-probe to %s\n", name);
265 			if (lock)
266 				device_unlock(d);
267 		}
268 		put_device(d);
269 	}
270 	kvfree(dev);
271 
272 	notifier->v4l2_dev = NULL;
273 
274 	/*
275 	 * Don't care about the waiting list, it is initialised and populated
276 	 * upon notifier registration.
277 	 */
278 }
279 EXPORT_SYMBOL(v4l2_async_notifier_unregister);
280 
281 int v4l2_async_register_subdev(struct v4l2_subdev *sd)
282 {
283 	struct v4l2_async_notifier *notifier;
284 
285 	/*
286 	 * No reference taken. The reference is held by the device
287 	 * (struct v4l2_subdev.dev), and async sub-device does not
288 	 * exist independently of the device at any point of time.
289 	 */
290 	if (!sd->fwnode && sd->dev)
291 		sd->fwnode = dev_fwnode(sd->dev);
292 
293 	mutex_lock(&list_lock);
294 
295 	INIT_LIST_HEAD(&sd->async_list);
296 
297 	list_for_each_entry(notifier, &notifier_list, list) {
298 		struct v4l2_async_subdev *asd = v4l2_async_belongs(notifier, sd);
299 		if (asd) {
300 			int ret = v4l2_async_test_notify(notifier, sd, asd);
301 			mutex_unlock(&list_lock);
302 			return ret;
303 		}
304 	}
305 
306 	/* None matched, wait for hot-plugging */
307 	list_add(&sd->async_list, &subdev_list);
308 
309 	mutex_unlock(&list_lock);
310 
311 	return 0;
312 }
313 EXPORT_SYMBOL(v4l2_async_register_subdev);
314 
315 void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
316 {
317 	struct v4l2_async_notifier *notifier = sd->notifier;
318 
319 	if (!sd->asd) {
320 		if (!list_empty(&sd->async_list))
321 			v4l2_async_cleanup(sd);
322 		return;
323 	}
324 
325 	mutex_lock(&list_lock);
326 
327 	list_add(&sd->asd->list, &notifier->waiting);
328 
329 	v4l2_async_cleanup(sd);
330 
331 	if (notifier->unbind)
332 		notifier->unbind(notifier, sd, sd->asd);
333 
334 	mutex_unlock(&list_lock);
335 }
336 EXPORT_SYMBOL(v4l2_async_unregister_subdev);
337