]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/base/swnode.c
Merge branch 'next.autofs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux.git] / drivers / base / swnode.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Software nodes for the firmware node framework.
4  *
5  * Copyright (C) 2018, Intel Corporation
6  * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
7  */
8
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/property.h>
12 #include <linux/slab.h>
13
14 struct swnode {
15         int id;
16         struct kobject kobj;
17         struct fwnode_handle fwnode;
18         const struct software_node *node;
19
20         /* hierarchy */
21         struct ida child_ids;
22         struct list_head entry;
23         struct list_head children;
24         struct swnode *parent;
25
26         unsigned int allocated:1;
27 };
28
29 static DEFINE_IDA(swnode_root_ids);
30 static struct kset *swnode_kset;
31
32 #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct swnode, kobj)
33
34 static const struct fwnode_operations software_node_ops;
35
36 bool is_software_node(const struct fwnode_handle *fwnode)
37 {
38         return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops;
39 }
40 EXPORT_SYMBOL_GPL(is_software_node);
41
42 #define to_swnode(__fwnode)                                             \
43         ({                                                              \
44                 typeof(__fwnode) __to_swnode_fwnode = __fwnode;         \
45                                                                         \
46                 is_software_node(__to_swnode_fwnode) ?                  \
47                         container_of(__to_swnode_fwnode,                \
48                                      struct swnode, fwnode) : NULL;     \
49         })
50
51 static struct swnode *
52 software_node_to_swnode(const struct software_node *node)
53 {
54         struct swnode *swnode = NULL;
55         struct kobject *k;
56
57         if (!node)
58                 return NULL;
59
60         spin_lock(&swnode_kset->list_lock);
61
62         list_for_each_entry(k, &swnode_kset->list, entry) {
63                 swnode = kobj_to_swnode(k);
64                 if (swnode->node == node)
65                         break;
66                 swnode = NULL;
67         }
68
69         spin_unlock(&swnode_kset->list_lock);
70
71         return swnode;
72 }
73
74 const struct software_node *to_software_node(const struct fwnode_handle *fwnode)
75 {
76         const struct swnode *swnode = to_swnode(fwnode);
77
78         return swnode ? swnode->node : NULL;
79 }
80 EXPORT_SYMBOL_GPL(to_software_node);
81
82 struct fwnode_handle *software_node_fwnode(const struct software_node *node)
83 {
84         struct swnode *swnode = software_node_to_swnode(node);
85
86         return swnode ? &swnode->fwnode : NULL;
87 }
88 EXPORT_SYMBOL_GPL(software_node_fwnode);
89
90 /* -------------------------------------------------------------------------- */
91 /* property_entry processing */
92
93 static const struct property_entry *
94 property_entry_get(const struct property_entry *prop, const char *name)
95 {
96         if (!prop)
97                 return NULL;
98
99         for (; prop->name; prop++)
100                 if (!strcmp(name, prop->name))
101                         return prop;
102
103         return NULL;
104 }
105
106 static const void *property_get_pointer(const struct property_entry *prop)
107 {
108         if (!prop->length)
109                 return NULL;
110
111         if (prop->is_array)
112                 return prop->pointer;
113
114         return &prop->value;
115 }
116
117 static const void *property_entry_find(const struct property_entry *props,
118                                        const char *propname, size_t length)
119 {
120         const struct property_entry *prop;
121         const void *pointer;
122
123         prop = property_entry_get(props, propname);
124         if (!prop)
125                 return ERR_PTR(-EINVAL);
126         pointer = property_get_pointer(prop);
127         if (!pointer)
128                 return ERR_PTR(-ENODATA);
129         if (length > prop->length)
130                 return ERR_PTR(-EOVERFLOW);
131         return pointer;
132 }
133
134 static int
135 property_entry_count_elems_of_size(const struct property_entry *props,
136                                    const char *propname, size_t length)
137 {
138         const struct property_entry *prop;
139
140         prop = property_entry_get(props, propname);
141         if (!prop)
142                 return -EINVAL;
143
144         return prop->length / length;
145 }
146
147 static int property_entry_read_int_array(const struct property_entry *props,
148                                          const char *name,
149                                          unsigned int elem_size, void *val,
150                                          size_t nval)
151 {
152         const void *pointer;
153         size_t length;
154
155         if (!val)
156                 return property_entry_count_elems_of_size(props, name,
157                                                           elem_size);
158
159         if (!is_power_of_2(elem_size) || elem_size > sizeof(u64))
160                 return -ENXIO;
161
162         length = nval * elem_size;
163
164         pointer = property_entry_find(props, name, length);
165         if (IS_ERR(pointer))
166                 return PTR_ERR(pointer);
167
168         memcpy(val, pointer, length);
169         return 0;
170 }
171
172 static int property_entry_read_string_array(const struct property_entry *props,
173                                             const char *propname,
174                                             const char **strings, size_t nval)
175 {
176         const void *pointer;
177         size_t length;
178         int array_len;
179
180         /* Find out the array length. */
181         array_len = property_entry_count_elems_of_size(props, propname,
182                                                        sizeof(const char *));
183         if (array_len < 0)
184                 return array_len;
185
186         /* Return how many there are if strings is NULL. */
187         if (!strings)
188                 return array_len;
189
190         array_len = min_t(size_t, nval, array_len);
191         length = array_len * sizeof(*strings);
192
193         pointer = property_entry_find(props, propname, length);
194         if (IS_ERR(pointer))
195                 return PTR_ERR(pointer);
196
197         memcpy(strings, pointer, length);
198
199         return array_len;
200 }
201
202 static void property_entry_free_data(const struct property_entry *p)
203 {
204         const void *pointer = property_get_pointer(p);
205         const char * const *src_str;
206         size_t i, nval;
207
208         if (p->is_array) {
209                 if (p->type == DEV_PROP_STRING && p->pointer) {
210                         src_str = p->pointer;
211                         nval = p->length / sizeof(const char *);
212                         for (i = 0; i < nval; i++)
213                                 kfree(src_str[i]);
214                 }
215                 kfree(pointer);
216         } else if (p->type == DEV_PROP_STRING) {
217                 kfree(p->value.str);
218         }
219         kfree(p->name);
220 }
221
222 static const char * const *
223 property_copy_string_array(const struct property_entry *src)
224 {
225         const char **d;
226         const char * const *src_str = src->pointer;
227         size_t nval = src->length / sizeof(*d);
228         int i;
229
230         d = kcalloc(nval, sizeof(*d), GFP_KERNEL);
231         if (!d)
232                 return NULL;
233
234         for (i = 0; i < nval; i++) {
235                 d[i] = kstrdup(src_str[i], GFP_KERNEL);
236                 if (!d[i] && src_str[i]) {
237                         while (--i >= 0)
238                                 kfree(d[i]);
239                         kfree(d);
240                         return NULL;
241                 }
242         }
243
244         return d;
245 }
246
247 static int property_entry_copy_data(struct property_entry *dst,
248                                     const struct property_entry *src)
249 {
250         const void *pointer = property_get_pointer(src);
251         const void *new;
252
253         if (src->is_array) {
254                 if (!src->length)
255                         return -ENODATA;
256
257                 if (src->type == DEV_PROP_STRING) {
258                         new = property_copy_string_array(src);
259                         if (!new)
260                                 return -ENOMEM;
261                 } else {
262                         new = kmemdup(pointer, src->length, GFP_KERNEL);
263                         if (!new)
264                                 return -ENOMEM;
265                 }
266
267                 dst->is_array = true;
268                 dst->pointer = new;
269         } else if (src->type == DEV_PROP_STRING) {
270                 new = kstrdup(src->value.str, GFP_KERNEL);
271                 if (!new && src->value.str)
272                         return -ENOMEM;
273
274                 dst->value.str = new;
275         } else {
276                 dst->value = src->value;
277         }
278
279         dst->length = src->length;
280         dst->type = src->type;
281         dst->name = kstrdup(src->name, GFP_KERNEL);
282         if (!dst->name)
283                 goto out_free_data;
284
285         return 0;
286
287 out_free_data:
288         property_entry_free_data(dst);
289         return -ENOMEM;
290 }
291
292 /**
293  * property_entries_dup - duplicate array of properties
294  * @properties: array of properties to copy
295  *
296  * This function creates a deep copy of the given NULL-terminated array
297  * of property entries.
298  */
299 struct property_entry *
300 property_entries_dup(const struct property_entry *properties)
301 {
302         struct property_entry *p;
303         int i, n = 0;
304         int ret;
305
306         if (!properties)
307                 return NULL;
308
309         while (properties[n].name)
310                 n++;
311
312         p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL);
313         if (!p)
314                 return ERR_PTR(-ENOMEM);
315
316         for (i = 0; i < n; i++) {
317                 ret = property_entry_copy_data(&p[i], &properties[i]);
318                 if (ret) {
319                         while (--i >= 0)
320                                 property_entry_free_data(&p[i]);
321                         kfree(p);
322                         return ERR_PTR(ret);
323                 }
324         }
325
326         return p;
327 }
328 EXPORT_SYMBOL_GPL(property_entries_dup);
329
330 /**
331  * property_entries_free - free previously allocated array of properties
332  * @properties: array of properties to destroy
333  *
334  * This function frees given NULL-terminated array of property entries,
335  * along with their data.
336  */
337 void property_entries_free(const struct property_entry *properties)
338 {
339         const struct property_entry *p;
340
341         if (!properties)
342                 return;
343
344         for (p = properties; p->name; p++)
345                 property_entry_free_data(p);
346
347         kfree(properties);
348 }
349 EXPORT_SYMBOL_GPL(property_entries_free);
350
351 /* -------------------------------------------------------------------------- */
352 /* fwnode operations */
353
354 static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
355 {
356         struct swnode *swnode = to_swnode(fwnode);
357
358         kobject_get(&swnode->kobj);
359
360         return &swnode->fwnode;
361 }
362
363 static void software_node_put(struct fwnode_handle *fwnode)
364 {
365         struct swnode *swnode = to_swnode(fwnode);
366
367         kobject_put(&swnode->kobj);
368 }
369
370 static bool software_node_property_present(const struct fwnode_handle *fwnode,
371                                            const char *propname)
372 {
373         struct swnode *swnode = to_swnode(fwnode);
374
375         return !!property_entry_get(swnode->node->properties, propname);
376 }
377
378 static int software_node_read_int_array(const struct fwnode_handle *fwnode,
379                                         const char *propname,
380                                         unsigned int elem_size, void *val,
381                                         size_t nval)
382 {
383         struct swnode *swnode = to_swnode(fwnode);
384
385         return property_entry_read_int_array(swnode->node->properties, propname,
386                                              elem_size, val, nval);
387 }
388
389 static int software_node_read_string_array(const struct fwnode_handle *fwnode,
390                                            const char *propname,
391                                            const char **val, size_t nval)
392 {
393         struct swnode *swnode = to_swnode(fwnode);
394
395         return property_entry_read_string_array(swnode->node->properties,
396                                                 propname, val, nval);
397 }
398
399 static const char *
400 software_node_get_name(const struct fwnode_handle *fwnode)
401 {
402         const struct swnode *swnode = to_swnode(fwnode);
403
404         if (!swnode)
405                 return "(null)";
406
407         return kobject_name(&swnode->kobj);
408 }
409
410 static const char *
411 software_node_get_name_prefix(const struct fwnode_handle *fwnode)
412 {
413         struct fwnode_handle *parent;
414         const char *prefix;
415
416         parent = fwnode_get_parent(fwnode);
417         if (!parent)
418                 return "";
419
420         /* Figure out the prefix from the parents. */
421         while (is_software_node(parent))
422                 parent = fwnode_get_next_parent(parent);
423
424         prefix = fwnode_get_name_prefix(parent);
425         fwnode_handle_put(parent);
426
427         /* Guess something if prefix was NULL. */
428         return prefix ?: "/";
429 }
430
431 static struct fwnode_handle *
432 software_node_get_parent(const struct fwnode_handle *fwnode)
433 {
434         struct swnode *swnode = to_swnode(fwnode);
435
436         if (!swnode || !swnode->parent)
437                 return NULL;
438
439         return fwnode_handle_get(&swnode->parent->fwnode);
440 }
441
442 static struct fwnode_handle *
443 software_node_get_next_child(const struct fwnode_handle *fwnode,
444                              struct fwnode_handle *child)
445 {
446         struct swnode *p = to_swnode(fwnode);
447         struct swnode *c = to_swnode(child);
448
449         if (!p || list_empty(&p->children) ||
450             (c && list_is_last(&c->entry, &p->children)))
451                 return NULL;
452
453         if (c)
454                 c = list_next_entry(c, entry);
455         else
456                 c = list_first_entry(&p->children, struct swnode, entry);
457         return &c->fwnode;
458 }
459
460 static struct fwnode_handle *
461 software_node_get_named_child_node(const struct fwnode_handle *fwnode,
462                                    const char *childname)
463 {
464         struct swnode *swnode = to_swnode(fwnode);
465         struct swnode *child;
466
467         if (!swnode || list_empty(&swnode->children))
468                 return NULL;
469
470         list_for_each_entry(child, &swnode->children, entry) {
471                 if (!strcmp(childname, kobject_name(&child->kobj))) {
472                         kobject_get(&child->kobj);
473                         return &child->fwnode;
474                 }
475         }
476         return NULL;
477 }
478
479 static int
480 software_node_get_reference_args(const struct fwnode_handle *fwnode,
481                                  const char *propname, const char *nargs_prop,
482                                  unsigned int nargs, unsigned int index,
483                                  struct fwnode_reference_args *args)
484 {
485         struct swnode *swnode = to_swnode(fwnode);
486         const struct software_node_reference *ref;
487         const struct property_entry *prop;
488         struct fwnode_handle *refnode;
489         int i;
490
491         if (!swnode || !swnode->node->references)
492                 return -ENOENT;
493
494         for (ref = swnode->node->references; ref->name; ref++)
495                 if (!strcmp(ref->name, propname))
496                         break;
497
498         if (!ref->name || index > (ref->nrefs - 1))
499                 return -ENOENT;
500
501         refnode = software_node_fwnode(ref->refs[index].node);
502         if (!refnode)
503                 return -ENOENT;
504
505         if (nargs_prop) {
506                 prop = property_entry_get(swnode->node->properties, nargs_prop);
507                 if (!prop)
508                         return -EINVAL;
509
510                 nargs = prop->value.u32_data;
511         }
512
513         if (nargs > NR_FWNODE_REFERENCE_ARGS)
514                 return -EINVAL;
515
516         args->fwnode = software_node_get(refnode);
517         args->nargs = nargs;
518
519         for (i = 0; i < nargs; i++)
520                 args->args[i] = ref->refs[index].args[i];
521
522         return 0;
523 }
524
525 static const struct fwnode_operations software_node_ops = {
526         .get = software_node_get,
527         .put = software_node_put,
528         .property_present = software_node_property_present,
529         .property_read_int_array = software_node_read_int_array,
530         .property_read_string_array = software_node_read_string_array,
531         .get_name = software_node_get_name,
532         .get_name_prefix = software_node_get_name_prefix,
533         .get_parent = software_node_get_parent,
534         .get_next_child_node = software_node_get_next_child,
535         .get_named_child_node = software_node_get_named_child_node,
536         .get_reference_args = software_node_get_reference_args
537 };
538
539 /* -------------------------------------------------------------------------- */
540
541 /**
542  * software_node_find_by_name - Find software node by name
543  * @parent: Parent of the software node
544  * @name: Name of the software node
545  *
546  * The function will find a node that is child of @parent and that is named
547  * @name. If no node is found, the function returns NULL.
548  *
549  * NOTE: you will need to drop the reference with fwnode_handle_put() after use.
550  */
551 const struct software_node *
552 software_node_find_by_name(const struct software_node *parent, const char *name)
553 {
554         struct swnode *swnode = NULL;
555         struct kobject *k;
556
557         if (!name)
558                 return NULL;
559
560         spin_lock(&swnode_kset->list_lock);
561
562         list_for_each_entry(k, &swnode_kset->list, entry) {
563                 swnode = kobj_to_swnode(k);
564                 if (parent == swnode->node->parent && swnode->node->name &&
565                     !strcmp(name, swnode->node->name)) {
566                         kobject_get(&swnode->kobj);
567                         break;
568                 }
569                 swnode = NULL;
570         }
571
572         spin_unlock(&swnode_kset->list_lock);
573
574         return swnode ? swnode->node : NULL;
575 }
576 EXPORT_SYMBOL_GPL(software_node_find_by_name);
577
578 static int
579 software_node_register_properties(struct software_node *node,
580                                   const struct property_entry *properties)
581 {
582         struct property_entry *props;
583
584         props = property_entries_dup(properties);
585         if (IS_ERR(props))
586                 return PTR_ERR(props);
587
588         node->properties = props;
589
590         return 0;
591 }
592
593 static void software_node_release(struct kobject *kobj)
594 {
595         struct swnode *swnode = kobj_to_swnode(kobj);
596
597         if (swnode->allocated) {
598                 property_entries_free(swnode->node->properties);
599                 kfree(swnode->node);
600         }
601         ida_destroy(&swnode->child_ids);
602         kfree(swnode);
603 }
604
605 static struct kobj_type software_node_type = {
606         .release = software_node_release,
607         .sysfs_ops = &kobj_sysfs_ops,
608 };
609
610 static struct fwnode_handle *
611 swnode_register(const struct software_node *node, struct swnode *parent,
612                 unsigned int allocated)
613 {
614         struct swnode *swnode;
615         int ret;
616
617         swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
618         if (!swnode) {
619                 ret = -ENOMEM;
620                 goto out_err;
621         }
622
623         ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
624                              0, 0, GFP_KERNEL);
625         if (ret < 0) {
626                 kfree(swnode);
627                 goto out_err;
628         }
629
630         swnode->id = ret;
631         swnode->node = node;
632         swnode->parent = parent;
633         swnode->allocated = allocated;
634         swnode->kobj.kset = swnode_kset;
635         swnode->fwnode.ops = &software_node_ops;
636
637         ida_init(&swnode->child_ids);
638         INIT_LIST_HEAD(&swnode->entry);
639         INIT_LIST_HEAD(&swnode->children);
640
641         if (node->name)
642                 ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
643                                            parent ? &parent->kobj : NULL,
644                                            "%s", node->name);
645         else
646                 ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
647                                            parent ? &parent->kobj : NULL,
648                                            "node%d", swnode->id);
649         if (ret) {
650                 kobject_put(&swnode->kobj);
651                 return ERR_PTR(ret);
652         }
653
654         if (parent)
655                 list_add_tail(&swnode->entry, &parent->children);
656
657         kobject_uevent(&swnode->kobj, KOBJ_ADD);
658         return &swnode->fwnode;
659
660 out_err:
661         if (allocated)
662                 property_entries_free(node->properties);
663         return ERR_PTR(ret);
664 }
665
666 /**
667  * software_node_register_nodes - Register an array of software nodes
668  * @nodes: Zero terminated array of software nodes to be registered
669  *
670  * Register multiple software nodes at once.
671  */
672 int software_node_register_nodes(const struct software_node *nodes)
673 {
674         int ret;
675         int i;
676
677         for (i = 0; nodes[i].name; i++) {
678                 ret = software_node_register(&nodes[i]);
679                 if (ret) {
680                         software_node_unregister_nodes(nodes);
681                         return ret;
682                 }
683         }
684
685         return 0;
686 }
687 EXPORT_SYMBOL_GPL(software_node_register_nodes);
688
689 /**
690  * software_node_unregister_nodes - Unregister an array of software nodes
691  * @nodes: Zero terminated array of software nodes to be unregistered
692  *
693  * Unregister multiple software nodes at once.
694  */
695 void software_node_unregister_nodes(const struct software_node *nodes)
696 {
697         struct swnode *swnode;
698         int i;
699
700         for (i = 0; nodes[i].name; i++) {
701                 swnode = software_node_to_swnode(&nodes[i]);
702                 if (swnode)
703                         fwnode_remove_software_node(&swnode->fwnode);
704         }
705 }
706 EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
707
708 /**
709  * software_node_register - Register static software node
710  * @node: The software node to be registered
711  */
712 int software_node_register(const struct software_node *node)
713 {
714         struct swnode *parent = software_node_to_swnode(node->parent);
715
716         if (software_node_to_swnode(node))
717                 return -EEXIST;
718
719         return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0));
720 }
721 EXPORT_SYMBOL_GPL(software_node_register);
722
723 struct fwnode_handle *
724 fwnode_create_software_node(const struct property_entry *properties,
725                             const struct fwnode_handle *parent)
726 {
727         struct software_node *node;
728         struct swnode *p = NULL;
729         int ret;
730
731         if (parent) {
732                 if (IS_ERR(parent))
733                         return ERR_CAST(parent);
734                 if (!is_software_node(parent))
735                         return ERR_PTR(-EINVAL);
736                 p = to_swnode(parent);
737         }
738
739         node = kzalloc(sizeof(*node), GFP_KERNEL);
740         if (!node)
741                 return ERR_PTR(-ENOMEM);
742
743         ret = software_node_register_properties(node, properties);
744         if (ret) {
745                 kfree(node);
746                 return ERR_PTR(ret);
747         }
748
749         node->parent = p ? p->node : NULL;
750
751         return swnode_register(node, p, 1);
752 }
753 EXPORT_SYMBOL_GPL(fwnode_create_software_node);
754
755 void fwnode_remove_software_node(struct fwnode_handle *fwnode)
756 {
757         struct swnode *swnode = to_swnode(fwnode);
758
759         if (!swnode)
760                 return;
761
762         if (swnode->parent) {
763                 ida_simple_remove(&swnode->parent->child_ids, swnode->id);
764                 list_del(&swnode->entry);
765         } else {
766                 ida_simple_remove(&swnode_root_ids, swnode->id);
767         }
768
769         kobject_put(&swnode->kobj);
770 }
771 EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
772
773 int software_node_notify(struct device *dev, unsigned long action)
774 {
775         struct fwnode_handle *fwnode = dev_fwnode(dev);
776         struct swnode *swnode;
777         int ret;
778
779         if (!fwnode)
780                 return 0;
781
782         if (!is_software_node(fwnode))
783                 fwnode = fwnode->secondary;
784         if (!is_software_node(fwnode))
785                 return 0;
786
787         swnode = to_swnode(fwnode);
788
789         switch (action) {
790         case KOBJ_ADD:
791                 ret = sysfs_create_link(&dev->kobj, &swnode->kobj,
792                                         "software_node");
793                 if (ret)
794                         break;
795
796                 ret = sysfs_create_link(&swnode->kobj, &dev->kobj,
797                                         dev_name(dev));
798                 if (ret) {
799                         sysfs_remove_link(&dev->kobj, "software_node");
800                         break;
801                 }
802                 kobject_get(&swnode->kobj);
803                 break;
804         case KOBJ_REMOVE:
805                 sysfs_remove_link(&swnode->kobj, dev_name(dev));
806                 sysfs_remove_link(&dev->kobj, "software_node");
807                 kobject_put(&swnode->kobj);
808                 break;
809         default:
810                 break;
811         }
812
813         return 0;
814 }
815
816 static int __init software_node_init(void)
817 {
818         swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj);
819         if (!swnode_kset)
820                 return -ENOMEM;
821         return 0;
822 }
823 postcore_initcall(software_node_init);
824
825 static void __exit software_node_exit(void)
826 {
827         ida_destroy(&swnode_root_ids);
828         kset_unregister(swnode_kset);
829 }
830 __exitcall(software_node_exit);