component: track components via array rather than list
[cascardo/linux.git] / drivers / base / component.c
1 /*
2  * Componentized device handling.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  * This is work in progress.  We gather up the component devices into a list,
9  * and bind them when instructed.  At the moment, we're specific to the DRM
10  * subsystem, and only handles one master device, but this doesn't have to be
11  * the case.
12  */
13 #include <linux/component.h>
14 #include <linux/device.h>
15 #include <linux/kref.h>
16 #include <linux/list.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/slab.h>
20
21 struct component;
22
23 struct component_match {
24         size_t alloc;
25         size_t num;
26         struct {
27                 void *data;
28                 int (*fn)(struct device *, void *);
29                 struct component *component;
30                 bool duplicate;
31         } compare[0];
32 };
33
34 struct master {
35         struct list_head node;
36         bool bound;
37
38         const struct component_master_ops *ops;
39         struct device *dev;
40         struct component_match *match;
41 };
42
43 struct component {
44         struct list_head node;
45         struct master *master;
46         bool bound;
47
48         const struct component_ops *ops;
49         struct device *dev;
50 };
51
52 static DEFINE_MUTEX(component_mutex);
53 static LIST_HEAD(component_list);
54 static LIST_HEAD(masters);
55
56 static struct master *__master_find(struct device *dev,
57         const struct component_master_ops *ops)
58 {
59         struct master *m;
60
61         list_for_each_entry(m, &masters, node)
62                 if (m->dev == dev && (!ops || m->ops == ops))
63                         return m;
64
65         return NULL;
66 }
67
68 static struct component *find_component(struct master *master,
69         int (*compare)(struct device *, void *), void *compare_data)
70 {
71         struct component *c;
72
73         list_for_each_entry(c, &component_list, node) {
74                 if (c->master && c->master != master)
75                         continue;
76
77                 if (compare(c->dev, compare_data))
78                         return c;
79         }
80
81         return NULL;
82 }
83
84 static int find_components(struct master *master)
85 {
86         struct component_match *match = master->match;
87         size_t i;
88         int ret = 0;
89
90         /*
91          * Scan the array of match functions and attach
92          * any components which are found to this master.
93          */
94         for (i = 0; i < match->num; i++) {
95                 struct component *c;
96
97                 dev_dbg(master->dev, "Looking for component %zu\n", i);
98
99                 if (match->compare[i].component)
100                         continue;
101
102                 c = find_component(master, match->compare[i].fn,
103                                    match->compare[i].data);
104                 if (!c) {
105                         ret = -ENXIO;
106                         break;
107                 }
108
109                 dev_dbg(master->dev, "found component %s, duplicate %u\n", dev_name(c->dev), !!c->master);
110
111                 /* Attach this component to the master */
112                 match->compare[i].duplicate = !!c->master;
113                 match->compare[i].component = c;
114                 c->master = master;
115         }
116         return ret;
117 }
118
119 /* Detach component from associated master */
120 static void remove_component(struct master *master, struct component *c)
121 {
122         size_t i;
123
124         /* Detach the component from this master. */
125         for (i = 0; i < master->match->num; i++)
126                 if (master->match->compare[i].component == c)
127                         master->match->compare[i].component = NULL;
128 }
129
130 /*
131  * Try to bring up a master.  If component is NULL, we're interested in
132  * this master, otherwise it's a component which must be present to try
133  * and bring up the master.
134  *
135  * Returns 1 for successful bringup, 0 if not ready, or -ve errno.
136  */
137 static int try_to_bring_up_master(struct master *master,
138         struct component *component)
139 {
140         int ret;
141
142         dev_dbg(master->dev, "trying to bring up master\n");
143
144         if (find_components(master)) {
145                 dev_dbg(master->dev, "master has incomplete components\n");
146                 return 0;
147         }
148
149         if (component && component->master != master) {
150                 dev_dbg(master->dev, "master is not for this component (%s)\n",
151                         dev_name(component->dev));
152                 return 0;
153         }
154
155         if (!devres_open_group(master->dev, NULL, GFP_KERNEL))
156                 return -ENOMEM;
157
158         /* Found all components */
159         ret = master->ops->bind(master->dev);
160         if (ret < 0) {
161                 devres_release_group(master->dev, NULL);
162                 dev_info(master->dev, "master bind failed: %d\n", ret);
163                 return ret;
164         }
165
166         master->bound = true;
167         return 1;
168 }
169
170 static int try_to_bring_up_masters(struct component *component)
171 {
172         struct master *m;
173         int ret = 0;
174
175         list_for_each_entry(m, &masters, node) {
176                 if (!m->bound) {
177                         ret = try_to_bring_up_master(m, component);
178                         if (ret != 0)
179                                 break;
180                 }
181         }
182
183         return ret;
184 }
185
186 static void take_down_master(struct master *master)
187 {
188         if (master->bound) {
189                 master->ops->unbind(master->dev);
190                 devres_release_group(master->dev, NULL);
191                 master->bound = false;
192         }
193 }
194
195 static size_t component_match_size(size_t num)
196 {
197         return offsetof(struct component_match, compare[num]);
198 }
199
200 static struct component_match *component_match_realloc(struct device *dev,
201         struct component_match *match, size_t num)
202 {
203         struct component_match *new;
204
205         if (match && match->alloc == num)
206                 return match;
207
208         new = devm_kmalloc(dev, component_match_size(num), GFP_KERNEL);
209         if (!new)
210                 return ERR_PTR(-ENOMEM);
211
212         if (match) {
213                 memcpy(new, match, component_match_size(min(match->num, num)));
214                 devm_kfree(dev, match);
215         } else {
216                 new->num = 0;
217         }
218
219         new->alloc = num;
220
221         return new;
222 }
223
224 /*
225  * Add a component to be matched.
226  *
227  * The match array is first created or extended if necessary.
228  */
229 void component_match_add(struct device *dev, struct component_match **matchptr,
230         int (*compare)(struct device *, void *), void *compare_data)
231 {
232         struct component_match *match = *matchptr;
233
234         if (IS_ERR(match))
235                 return;
236
237         if (!match || match->num == match->alloc) {
238                 size_t new_size = match ? match->alloc + 16 : 15;
239
240                 match = component_match_realloc(dev, match, new_size);
241
242                 *matchptr = match;
243
244                 if (IS_ERR(match))
245                         return;
246         }
247
248         match->compare[match->num].fn = compare;
249         match->compare[match->num].data = compare_data;
250         match->compare[match->num].component = NULL;
251         match->num++;
252 }
253 EXPORT_SYMBOL(component_match_add);
254
255 int component_master_add_with_match(struct device *dev,
256         const struct component_master_ops *ops,
257         struct component_match *match)
258 {
259         struct master *master;
260         int ret;
261
262         /* Reallocate the match array for its true size */
263         match = component_match_realloc(dev, match, match->num);
264         if (IS_ERR(match))
265                 return PTR_ERR(match);
266
267         master = kzalloc(sizeof(*master), GFP_KERNEL);
268         if (!master)
269                 return -ENOMEM;
270
271         master->dev = dev;
272         master->ops = ops;
273         master->match = match;
274
275         /* Add to the list of available masters. */
276         mutex_lock(&component_mutex);
277         list_add(&master->node, &masters);
278
279         ret = try_to_bring_up_master(master, NULL);
280
281         if (ret < 0) {
282                 /* Delete off the list if we weren't successful */
283                 list_del(&master->node);
284                 kfree(master);
285         }
286         mutex_unlock(&component_mutex);
287
288         return ret < 0 ? ret : 0;
289 }
290 EXPORT_SYMBOL_GPL(component_master_add_with_match);
291
292 void component_master_del(struct device *dev,
293         const struct component_master_ops *ops)
294 {
295         struct master *master;
296         int i;
297
298         mutex_lock(&component_mutex);
299         master = __master_find(dev, ops);
300         if (master) {
301                 struct component_match *match = master->match;
302
303                 take_down_master(master);
304
305                 list_del(&master->node);
306
307                 if (match) {
308                         for (i = 0; i < match->num; i++) {
309                                 struct component *c = match->compare[i].component;
310                                 if (c)
311                                         c->master = NULL;
312                         }
313                 }
314                 kfree(master);
315         }
316         mutex_unlock(&component_mutex);
317 }
318 EXPORT_SYMBOL_GPL(component_master_del);
319
320 static void component_unbind(struct component *component,
321         struct master *master, void *data)
322 {
323         WARN_ON(!component->bound);
324
325         component->ops->unbind(component->dev, master->dev, data);
326         component->bound = false;
327
328         /* Release all resources claimed in the binding of this component */
329         devres_release_group(component->dev, component);
330 }
331
332 void component_unbind_all(struct device *master_dev, void *data)
333 {
334         struct master *master;
335         struct component *c;
336         size_t i;
337
338         WARN_ON(!mutex_is_locked(&component_mutex));
339
340         master = __master_find(master_dev, NULL);
341         if (!master)
342                 return;
343
344         /* Unbind components in reverse order */
345         for (i = master->match->num; i--; )
346                 if (!master->match->compare[i].duplicate) {
347                         c = master->match->compare[i].component;
348                         component_unbind(c, master, data);
349                 }
350 }
351 EXPORT_SYMBOL_GPL(component_unbind_all);
352
353 static int component_bind(struct component *component, struct master *master,
354         void *data)
355 {
356         int ret;
357
358         /*
359          * Each component initialises inside its own devres group.
360          * This allows us to roll-back a failed component without
361          * affecting anything else.
362          */
363         if (!devres_open_group(master->dev, NULL, GFP_KERNEL))
364                 return -ENOMEM;
365
366         /*
367          * Also open a group for the device itself: this allows us
368          * to release the resources claimed against the sub-device
369          * at the appropriate moment.
370          */
371         if (!devres_open_group(component->dev, component, GFP_KERNEL)) {
372                 devres_release_group(master->dev, NULL);
373                 return -ENOMEM;
374         }
375
376         dev_dbg(master->dev, "binding %s (ops %ps)\n",
377                 dev_name(component->dev), component->ops);
378
379         ret = component->ops->bind(component->dev, master->dev, data);
380         if (!ret) {
381                 component->bound = true;
382
383                 /*
384                  * Close the component device's group so that resources
385                  * allocated in the binding are encapsulated for removal
386                  * at unbind.  Remove the group on the DRM device as we
387                  * can clean those resources up independently.
388                  */
389                 devres_close_group(component->dev, NULL);
390                 devres_remove_group(master->dev, NULL);
391
392                 dev_info(master->dev, "bound %s (ops %ps)\n",
393                          dev_name(component->dev), component->ops);
394         } else {
395                 devres_release_group(component->dev, NULL);
396                 devres_release_group(master->dev, NULL);
397
398                 dev_err(master->dev, "failed to bind %s (ops %ps): %d\n",
399                         dev_name(component->dev), component->ops, ret);
400         }
401
402         return ret;
403 }
404
405 int component_bind_all(struct device *master_dev, void *data)
406 {
407         struct master *master;
408         struct component *c;
409         size_t i;
410         int ret = 0;
411
412         WARN_ON(!mutex_is_locked(&component_mutex));
413
414         master = __master_find(master_dev, NULL);
415         if (!master)
416                 return -EINVAL;
417
418         /* Bind components in match order */
419         for (i = 0; i < master->match->num; i++)
420                 if (!master->match->compare[i].duplicate) {
421                         c = master->match->compare[i].component;
422                         ret = component_bind(c, master, data);
423                         if (ret)
424                                 break;
425                 }
426
427         if (ret != 0) {
428                 for (; i--; )
429                         if (!master->match->compare[i].duplicate) {
430                                 c = master->match->compare[i].component;
431                                 component_unbind(c, master, data);
432                         }
433         }
434
435         return ret;
436 }
437 EXPORT_SYMBOL_GPL(component_bind_all);
438
439 int component_add(struct device *dev, const struct component_ops *ops)
440 {
441         struct component *component;
442         int ret;
443
444         component = kzalloc(sizeof(*component), GFP_KERNEL);
445         if (!component)
446                 return -ENOMEM;
447
448         component->ops = ops;
449         component->dev = dev;
450
451         dev_dbg(dev, "adding component (ops %ps)\n", ops);
452
453         mutex_lock(&component_mutex);
454         list_add_tail(&component->node, &component_list);
455
456         ret = try_to_bring_up_masters(component);
457         if (ret < 0) {
458                 list_del(&component->node);
459
460                 kfree(component);
461         }
462         mutex_unlock(&component_mutex);
463
464         return ret < 0 ? ret : 0;
465 }
466 EXPORT_SYMBOL_GPL(component_add);
467
468 void component_del(struct device *dev, const struct component_ops *ops)
469 {
470         struct component *c, *component = NULL;
471
472         mutex_lock(&component_mutex);
473         list_for_each_entry(c, &component_list, node)
474                 if (c->dev == dev && c->ops == ops) {
475                         list_del(&c->node);
476                         component = c;
477                         break;
478                 }
479
480         if (component && component->master) {
481                 take_down_master(component->master);
482                 remove_component(component->master, component);
483         }
484
485         mutex_unlock(&component_mutex);
486
487         WARN_ON(!component);
488         kfree(component);
489 }
490 EXPORT_SYMBOL_GPL(component_del);
491
492 MODULE_LICENSE("GPL v2");