Line data Source code
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 : unsigned int managed:1;
28 : };
29 :
30 : static DEFINE_IDA(swnode_root_ids);
31 : static struct kset *swnode_kset;
32 :
33 : #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct swnode, kobj)
34 :
35 : static const struct fwnode_operations software_node_ops;
36 :
37 0 : bool is_software_node(const struct fwnode_handle *fwnode)
38 : {
39 0 : return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops;
40 : }
41 : EXPORT_SYMBOL_GPL(is_software_node);
42 :
43 : #define to_swnode(__fwnode) \
44 : ({ \
45 : typeof(__fwnode) __to_swnode_fwnode = __fwnode; \
46 : \
47 : is_software_node(__to_swnode_fwnode) ? \
48 : container_of(__to_swnode_fwnode, \
49 : struct swnode, fwnode) : NULL; \
50 : })
51 :
52 175 : static inline struct swnode *dev_to_swnode(struct device *dev)
53 : {
54 175 : struct fwnode_handle *fwnode = dev_fwnode(dev);
55 :
56 175 : if (!fwnode)
57 : return NULL;
58 :
59 0 : if (!is_software_node(fwnode))
60 0 : fwnode = fwnode->secondary;
61 :
62 0 : return to_swnode(fwnode);
63 : }
64 :
65 : static struct swnode *
66 0 : software_node_to_swnode(const struct software_node *node)
67 : {
68 0 : struct swnode *swnode = NULL;
69 0 : struct kobject *k;
70 :
71 0 : if (!node)
72 : return NULL;
73 :
74 0 : spin_lock(&swnode_kset->list_lock);
75 :
76 0 : list_for_each_entry(k, &swnode_kset->list, entry) {
77 0 : swnode = kobj_to_swnode(k);
78 0 : if (swnode->node == node)
79 : break;
80 0 : swnode = NULL;
81 : }
82 :
83 0 : spin_unlock(&swnode_kset->list_lock);
84 :
85 0 : return swnode;
86 : }
87 :
88 0 : const struct software_node *to_software_node(const struct fwnode_handle *fwnode)
89 : {
90 0 : const struct swnode *swnode = to_swnode(fwnode);
91 :
92 0 : return swnode ? swnode->node : NULL;
93 : }
94 : EXPORT_SYMBOL_GPL(to_software_node);
95 :
96 0 : struct fwnode_handle *software_node_fwnode(const struct software_node *node)
97 : {
98 0 : struct swnode *swnode = software_node_to_swnode(node);
99 :
100 0 : return swnode ? &swnode->fwnode : NULL;
101 : }
102 : EXPORT_SYMBOL_GPL(software_node_fwnode);
103 :
104 : /* -------------------------------------------------------------------------- */
105 : /* property_entry processing */
106 :
107 : static const struct property_entry *
108 0 : property_entry_get(const struct property_entry *prop, const char *name)
109 : {
110 0 : if (!prop)
111 : return NULL;
112 :
113 0 : for (; prop->name; prop++)
114 0 : if (!strcmp(name, prop->name))
115 0 : return prop;
116 :
117 : return NULL;
118 : }
119 :
120 0 : static const void *property_get_pointer(const struct property_entry *prop)
121 : {
122 0 : if (!prop->length)
123 : return NULL;
124 :
125 0 : return prop->is_inline ? &prop->value : prop->pointer;
126 : }
127 :
128 0 : static const void *property_entry_find(const struct property_entry *props,
129 : const char *propname, size_t length)
130 : {
131 0 : const struct property_entry *prop;
132 0 : const void *pointer;
133 :
134 0 : prop = property_entry_get(props, propname);
135 0 : if (!prop)
136 0 : return ERR_PTR(-EINVAL);
137 0 : pointer = property_get_pointer(prop);
138 0 : if (!pointer)
139 0 : return ERR_PTR(-ENODATA);
140 0 : if (length > prop->length)
141 0 : return ERR_PTR(-EOVERFLOW);
142 : return pointer;
143 : }
144 :
145 : static int
146 0 : property_entry_count_elems_of_size(const struct property_entry *props,
147 : const char *propname, size_t length)
148 : {
149 0 : const struct property_entry *prop;
150 :
151 0 : prop = property_entry_get(props, propname);
152 0 : if (!prop)
153 : return -EINVAL;
154 :
155 0 : return prop->length / length;
156 : }
157 :
158 0 : static int property_entry_read_int_array(const struct property_entry *props,
159 : const char *name,
160 : unsigned int elem_size, void *val,
161 : size_t nval)
162 : {
163 0 : const void *pointer;
164 0 : size_t length;
165 :
166 0 : if (!val)
167 0 : return property_entry_count_elems_of_size(props, name,
168 : elem_size);
169 :
170 0 : if (!is_power_of_2(elem_size) || elem_size > sizeof(u64))
171 : return -ENXIO;
172 :
173 0 : length = nval * elem_size;
174 :
175 0 : pointer = property_entry_find(props, name, length);
176 0 : if (IS_ERR(pointer))
177 0 : return PTR_ERR(pointer);
178 :
179 0 : memcpy(val, pointer, length);
180 0 : return 0;
181 : }
182 :
183 0 : static int property_entry_read_string_array(const struct property_entry *props,
184 : const char *propname,
185 : const char **strings, size_t nval)
186 : {
187 0 : const void *pointer;
188 0 : size_t length;
189 0 : int array_len;
190 :
191 : /* Find out the array length. */
192 0 : array_len = property_entry_count_elems_of_size(props, propname,
193 : sizeof(const char *));
194 0 : if (array_len < 0)
195 0 : return array_len;
196 :
197 : /* Return how many there are if strings is NULL. */
198 0 : if (!strings)
199 : return array_len;
200 :
201 0 : array_len = min_t(size_t, nval, array_len);
202 0 : length = array_len * sizeof(*strings);
203 :
204 0 : pointer = property_entry_find(props, propname, length);
205 0 : if (IS_ERR(pointer))
206 0 : return PTR_ERR(pointer);
207 :
208 0 : memcpy(strings, pointer, length);
209 :
210 0 : return array_len;
211 : }
212 :
213 0 : static void property_entry_free_data(const struct property_entry *p)
214 : {
215 0 : const char * const *src_str;
216 0 : size_t i, nval;
217 :
218 0 : if (p->type == DEV_PROP_STRING) {
219 0 : src_str = property_get_pointer(p);
220 0 : nval = p->length / sizeof(*src_str);
221 0 : for (i = 0; i < nval; i++)
222 0 : kfree(src_str[i]);
223 : }
224 :
225 0 : if (!p->is_inline)
226 0 : kfree(p->pointer);
227 :
228 0 : kfree(p->name);
229 0 : }
230 :
231 0 : static bool property_copy_string_array(const char **dst_ptr,
232 : const char * const *src_ptr,
233 : size_t nval)
234 : {
235 0 : int i;
236 :
237 0 : for (i = 0; i < nval; i++) {
238 0 : dst_ptr[i] = kstrdup(src_ptr[i], GFP_KERNEL);
239 0 : if (!dst_ptr[i] && src_ptr[i]) {
240 0 : while (--i >= 0)
241 0 : kfree(dst_ptr[i]);
242 : return false;
243 : }
244 : }
245 :
246 : return true;
247 : }
248 :
249 0 : static int property_entry_copy_data(struct property_entry *dst,
250 : const struct property_entry *src)
251 : {
252 0 : const void *pointer = property_get_pointer(src);
253 0 : void *dst_ptr;
254 0 : size_t nval;
255 :
256 : /*
257 : * Properties with no data should not be marked as stored
258 : * out of line.
259 : */
260 0 : if (!src->is_inline && !src->length)
261 : return -ENODATA;
262 :
263 : /*
264 : * Reference properties are never stored inline as
265 : * they are too big.
266 : */
267 0 : if (src->type == DEV_PROP_REF && src->is_inline)
268 : return -EINVAL;
269 :
270 0 : if (src->length <= sizeof(dst->value)) {
271 0 : dst_ptr = &dst->value;
272 0 : dst->is_inline = true;
273 : } else {
274 0 : dst_ptr = kmalloc(src->length, GFP_KERNEL);
275 0 : if (!dst_ptr)
276 : return -ENOMEM;
277 0 : dst->pointer = dst_ptr;
278 : }
279 :
280 0 : if (src->type == DEV_PROP_STRING) {
281 0 : nval = src->length / sizeof(const char *);
282 0 : if (!property_copy_string_array(dst_ptr, pointer, nval)) {
283 0 : if (!dst->is_inline)
284 0 : kfree(dst->pointer);
285 0 : return -ENOMEM;
286 : }
287 : } else {
288 0 : memcpy(dst_ptr, pointer, src->length);
289 : }
290 :
291 0 : dst->length = src->length;
292 0 : dst->type = src->type;
293 0 : dst->name = kstrdup(src->name, GFP_KERNEL);
294 0 : if (!dst->name) {
295 0 : property_entry_free_data(dst);
296 0 : return -ENOMEM;
297 : }
298 :
299 : return 0;
300 : }
301 :
302 : /**
303 : * property_entries_dup - duplicate array of properties
304 : * @properties: array of properties to copy
305 : *
306 : * This function creates a deep copy of the given NULL-terminated array
307 : * of property entries.
308 : */
309 : struct property_entry *
310 0 : property_entries_dup(const struct property_entry *properties)
311 : {
312 0 : struct property_entry *p;
313 0 : int i, n = 0;
314 0 : int ret;
315 :
316 0 : if (!properties)
317 : return NULL;
318 :
319 0 : while (properties[n].name)
320 0 : n++;
321 :
322 0 : p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL);
323 0 : if (!p)
324 0 : return ERR_PTR(-ENOMEM);
325 :
326 0 : for (i = 0; i < n; i++) {
327 0 : ret = property_entry_copy_data(&p[i], &properties[i]);
328 0 : if (ret) {
329 0 : while (--i >= 0)
330 0 : property_entry_free_data(&p[i]);
331 0 : kfree(p);
332 0 : return ERR_PTR(ret);
333 : }
334 : }
335 :
336 : return p;
337 : }
338 : EXPORT_SYMBOL_GPL(property_entries_dup);
339 :
340 : /**
341 : * property_entries_free - free previously allocated array of properties
342 : * @properties: array of properties to destroy
343 : *
344 : * This function frees given NULL-terminated array of property entries,
345 : * along with their data.
346 : */
347 0 : void property_entries_free(const struct property_entry *properties)
348 : {
349 0 : const struct property_entry *p;
350 :
351 0 : if (!properties)
352 : return;
353 :
354 0 : for (p = properties; p->name; p++)
355 0 : property_entry_free_data(p);
356 :
357 0 : kfree(properties);
358 : }
359 : EXPORT_SYMBOL_GPL(property_entries_free);
360 :
361 : /* -------------------------------------------------------------------------- */
362 : /* fwnode operations */
363 :
364 0 : static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
365 : {
366 0 : struct swnode *swnode = to_swnode(fwnode);
367 :
368 0 : kobject_get(&swnode->kobj);
369 :
370 0 : return &swnode->fwnode;
371 : }
372 :
373 0 : static void software_node_put(struct fwnode_handle *fwnode)
374 : {
375 0 : struct swnode *swnode = to_swnode(fwnode);
376 :
377 0 : kobject_put(&swnode->kobj);
378 0 : }
379 :
380 0 : static bool software_node_property_present(const struct fwnode_handle *fwnode,
381 : const char *propname)
382 : {
383 0 : struct swnode *swnode = to_swnode(fwnode);
384 :
385 0 : return !!property_entry_get(swnode->node->properties, propname);
386 : }
387 :
388 0 : static int software_node_read_int_array(const struct fwnode_handle *fwnode,
389 : const char *propname,
390 : unsigned int elem_size, void *val,
391 : size_t nval)
392 : {
393 0 : struct swnode *swnode = to_swnode(fwnode);
394 :
395 0 : return property_entry_read_int_array(swnode->node->properties, propname,
396 : elem_size, val, nval);
397 : }
398 :
399 0 : static int software_node_read_string_array(const struct fwnode_handle *fwnode,
400 : const char *propname,
401 : const char **val, size_t nval)
402 : {
403 0 : struct swnode *swnode = to_swnode(fwnode);
404 :
405 0 : return property_entry_read_string_array(swnode->node->properties,
406 : propname, val, nval);
407 : }
408 :
409 : static const char *
410 0 : software_node_get_name(const struct fwnode_handle *fwnode)
411 : {
412 0 : const struct swnode *swnode = to_swnode(fwnode);
413 :
414 0 : if (!swnode)
415 : return "(null)";
416 :
417 0 : return kobject_name(&swnode->kobj);
418 : }
419 :
420 : static const char *
421 0 : software_node_get_name_prefix(const struct fwnode_handle *fwnode)
422 : {
423 0 : struct fwnode_handle *parent;
424 0 : const char *prefix;
425 :
426 0 : parent = fwnode_get_parent(fwnode);
427 0 : if (!parent)
428 : return "";
429 :
430 : /* Figure out the prefix from the parents. */
431 0 : while (is_software_node(parent))
432 0 : parent = fwnode_get_next_parent(parent);
433 :
434 0 : prefix = fwnode_get_name_prefix(parent);
435 0 : fwnode_handle_put(parent);
436 :
437 : /* Guess something if prefix was NULL. */
438 0 : return prefix ?: "/";
439 : }
440 :
441 : static struct fwnode_handle *
442 0 : software_node_get_parent(const struct fwnode_handle *fwnode)
443 : {
444 0 : struct swnode *swnode = to_swnode(fwnode);
445 :
446 0 : if (!swnode || !swnode->parent)
447 : return NULL;
448 :
449 0 : return fwnode_handle_get(&swnode->parent->fwnode);
450 : }
451 :
452 : static struct fwnode_handle *
453 0 : software_node_get_next_child(const struct fwnode_handle *fwnode,
454 : struct fwnode_handle *child)
455 : {
456 0 : struct swnode *p = to_swnode(fwnode);
457 0 : struct swnode *c = to_swnode(child);
458 :
459 0 : if (!p || list_empty(&p->children) ||
460 0 : (c && list_is_last(&c->entry, &p->children))) {
461 0 : fwnode_handle_put(child);
462 0 : return NULL;
463 : }
464 :
465 0 : if (c)
466 0 : c = list_next_entry(c, entry);
467 : else
468 0 : c = list_first_entry(&p->children, struct swnode, entry);
469 :
470 0 : fwnode_handle_put(child);
471 0 : return fwnode_handle_get(&c->fwnode);
472 : }
473 :
474 : static struct fwnode_handle *
475 0 : software_node_get_named_child_node(const struct fwnode_handle *fwnode,
476 : const char *childname)
477 : {
478 0 : struct swnode *swnode = to_swnode(fwnode);
479 0 : struct swnode *child;
480 :
481 0 : if (!swnode || list_empty(&swnode->children))
482 : return NULL;
483 :
484 0 : list_for_each_entry(child, &swnode->children, entry) {
485 0 : if (!strcmp(childname, kobject_name(&child->kobj))) {
486 0 : kobject_get(&child->kobj);
487 0 : return &child->fwnode;
488 : }
489 : }
490 : return NULL;
491 : }
492 :
493 : static int
494 0 : software_node_get_reference_args(const struct fwnode_handle *fwnode,
495 : const char *propname, const char *nargs_prop,
496 : unsigned int nargs, unsigned int index,
497 : struct fwnode_reference_args *args)
498 : {
499 0 : struct swnode *swnode = to_swnode(fwnode);
500 0 : const struct software_node_ref_args *ref_array;
501 0 : const struct software_node_ref_args *ref;
502 0 : const struct property_entry *prop;
503 0 : struct fwnode_handle *refnode;
504 0 : u32 nargs_prop_val;
505 0 : int error;
506 0 : int i;
507 :
508 0 : if (!swnode)
509 : return -ENOENT;
510 :
511 0 : prop = property_entry_get(swnode->node->properties, propname);
512 0 : if (!prop)
513 : return -ENOENT;
514 :
515 0 : if (prop->type != DEV_PROP_REF)
516 : return -EINVAL;
517 :
518 : /*
519 : * We expect that references are never stored inline, even
520 : * single ones, as they are too big.
521 : */
522 0 : if (prop->is_inline)
523 : return -EINVAL;
524 :
525 0 : if (index * sizeof(*ref) >= prop->length)
526 : return -ENOENT;
527 :
528 0 : ref_array = prop->pointer;
529 0 : ref = &ref_array[index];
530 :
531 0 : refnode = software_node_fwnode(ref->node);
532 0 : if (!refnode)
533 : return -ENOENT;
534 :
535 0 : if (nargs_prop) {
536 0 : error = property_entry_read_int_array(swnode->node->properties,
537 : nargs_prop, sizeof(u32),
538 : &nargs_prop_val, 1);
539 0 : if (error)
540 : return error;
541 :
542 0 : nargs = nargs_prop_val;
543 : }
544 :
545 0 : if (nargs > NR_FWNODE_REFERENCE_ARGS)
546 : return -EINVAL;
547 :
548 0 : args->fwnode = software_node_get(refnode);
549 0 : args->nargs = nargs;
550 :
551 0 : for (i = 0; i < nargs; i++)
552 0 : args->args[i] = ref->args[i];
553 :
554 : return 0;
555 : }
556 :
557 : static struct fwnode_handle *
558 0 : swnode_graph_find_next_port(const struct fwnode_handle *parent,
559 : struct fwnode_handle *port)
560 : {
561 0 : struct fwnode_handle *old = port;
562 :
563 0 : while ((port = software_node_get_next_child(parent, old))) {
564 : /*
565 : * fwnode ports have naming style "port@", so we search for any
566 : * children that follow that convention.
567 : */
568 0 : if (!strncmp(to_swnode(port)->node->name, "port@",
569 : strlen("port@")))
570 0 : return port;
571 : old = port;
572 : }
573 :
574 : return NULL;
575 : }
576 :
577 : static struct fwnode_handle *
578 0 : software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
579 : struct fwnode_handle *endpoint)
580 : {
581 0 : struct swnode *swnode = to_swnode(fwnode);
582 0 : struct fwnode_handle *parent;
583 0 : struct fwnode_handle *port;
584 :
585 0 : if (!swnode)
586 : return NULL;
587 :
588 0 : if (endpoint) {
589 0 : port = software_node_get_parent(endpoint);
590 0 : parent = software_node_get_parent(port);
591 : } else {
592 0 : parent = software_node_get_named_child_node(fwnode, "ports");
593 0 : if (!parent)
594 0 : parent = software_node_get(&swnode->fwnode);
595 :
596 0 : port = swnode_graph_find_next_port(parent, NULL);
597 : }
598 :
599 0 : for (; port; port = swnode_graph_find_next_port(parent, port)) {
600 0 : endpoint = software_node_get_next_child(port, endpoint);
601 0 : if (endpoint) {
602 0 : fwnode_handle_put(port);
603 0 : break;
604 : }
605 : }
606 :
607 0 : fwnode_handle_put(parent);
608 :
609 0 : return endpoint;
610 : }
611 :
612 : static struct fwnode_handle *
613 0 : software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
614 : {
615 0 : struct swnode *swnode = to_swnode(fwnode);
616 0 : const struct software_node_ref_args *ref;
617 0 : const struct property_entry *prop;
618 :
619 0 : if (!swnode)
620 : return NULL;
621 :
622 0 : prop = property_entry_get(swnode->node->properties, "remote-endpoint");
623 0 : if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
624 : return NULL;
625 :
626 0 : ref = prop->pointer;
627 :
628 0 : return software_node_get(software_node_fwnode(ref[0].node));
629 : }
630 :
631 : static struct fwnode_handle *
632 0 : software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
633 : {
634 0 : struct swnode *swnode = to_swnode(fwnode);
635 :
636 0 : swnode = swnode->parent;
637 0 : if (swnode && !strcmp(swnode->node->name, "ports"))
638 0 : swnode = swnode->parent;
639 :
640 0 : return swnode ? software_node_get(&swnode->fwnode) : NULL;
641 : }
642 :
643 : static int
644 0 : software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
645 : struct fwnode_endpoint *endpoint)
646 : {
647 0 : struct swnode *swnode = to_swnode(fwnode);
648 0 : const char *parent_name = swnode->parent->node->name;
649 0 : int ret;
650 :
651 0 : if (strlen("port@") >= strlen(parent_name) ||
652 0 : strncmp(parent_name, "port@", strlen("port@")))
653 : return -EINVAL;
654 :
655 : /* Ports have naming style "port@n", we need to select the n */
656 0 : ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port);
657 0 : if (ret)
658 : return ret;
659 :
660 0 : endpoint->id = swnode->id;
661 0 : endpoint->local_fwnode = fwnode;
662 :
663 0 : return 0;
664 : }
665 :
666 : static const struct fwnode_operations software_node_ops = {
667 : .get = software_node_get,
668 : .put = software_node_put,
669 : .property_present = software_node_property_present,
670 : .property_read_int_array = software_node_read_int_array,
671 : .property_read_string_array = software_node_read_string_array,
672 : .get_name = software_node_get_name,
673 : .get_name_prefix = software_node_get_name_prefix,
674 : .get_parent = software_node_get_parent,
675 : .get_next_child_node = software_node_get_next_child,
676 : .get_named_child_node = software_node_get_named_child_node,
677 : .get_reference_args = software_node_get_reference_args,
678 : .graph_get_next_endpoint = software_node_graph_get_next_endpoint,
679 : .graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
680 : .graph_get_port_parent = software_node_graph_get_port_parent,
681 : .graph_parse_endpoint = software_node_graph_parse_endpoint,
682 : };
683 :
684 : /* -------------------------------------------------------------------------- */
685 :
686 : /**
687 : * software_node_find_by_name - Find software node by name
688 : * @parent: Parent of the software node
689 : * @name: Name of the software node
690 : *
691 : * The function will find a node that is child of @parent and that is named
692 : * @name. If no node is found, the function returns NULL.
693 : *
694 : * NOTE: you will need to drop the reference with fwnode_handle_put() after use.
695 : */
696 : const struct software_node *
697 0 : software_node_find_by_name(const struct software_node *parent, const char *name)
698 : {
699 0 : struct swnode *swnode = NULL;
700 0 : struct kobject *k;
701 :
702 0 : if (!name)
703 : return NULL;
704 :
705 0 : spin_lock(&swnode_kset->list_lock);
706 :
707 0 : list_for_each_entry(k, &swnode_kset->list, entry) {
708 0 : swnode = kobj_to_swnode(k);
709 0 : if (parent == swnode->node->parent && swnode->node->name &&
710 0 : !strcmp(name, swnode->node->name)) {
711 0 : kobject_get(&swnode->kobj);
712 0 : break;
713 : }
714 0 : swnode = NULL;
715 : }
716 :
717 0 : spin_unlock(&swnode_kset->list_lock);
718 :
719 0 : return swnode ? swnode->node : NULL;
720 : }
721 : EXPORT_SYMBOL_GPL(software_node_find_by_name);
722 :
723 : static int
724 0 : software_node_register_properties(struct software_node *node,
725 : const struct property_entry *properties)
726 : {
727 0 : struct property_entry *props;
728 :
729 0 : props = property_entries_dup(properties);
730 0 : if (IS_ERR(props))
731 0 : return PTR_ERR(props);
732 :
733 0 : node->properties = props;
734 :
735 0 : return 0;
736 : }
737 :
738 0 : static void software_node_release(struct kobject *kobj)
739 : {
740 0 : struct swnode *swnode = kobj_to_swnode(kobj);
741 :
742 0 : if (swnode->parent) {
743 0 : ida_simple_remove(&swnode->parent->child_ids, swnode->id);
744 0 : list_del(&swnode->entry);
745 : } else {
746 0 : ida_simple_remove(&swnode_root_ids, swnode->id);
747 : }
748 :
749 0 : if (swnode->allocated) {
750 0 : property_entries_free(swnode->node->properties);
751 0 : kfree(swnode->node);
752 : }
753 0 : ida_destroy(&swnode->child_ids);
754 0 : kfree(swnode);
755 0 : }
756 :
757 : static struct kobj_type software_node_type = {
758 : .release = software_node_release,
759 : .sysfs_ops = &kobj_sysfs_ops,
760 : };
761 :
762 : static struct fwnode_handle *
763 0 : swnode_register(const struct software_node *node, struct swnode *parent,
764 : unsigned int allocated)
765 : {
766 0 : struct swnode *swnode;
767 0 : int ret;
768 :
769 0 : swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
770 0 : if (!swnode) {
771 0 : ret = -ENOMEM;
772 0 : goto out_err;
773 : }
774 :
775 0 : ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
776 : 0, 0, GFP_KERNEL);
777 0 : if (ret < 0) {
778 0 : kfree(swnode);
779 0 : goto out_err;
780 : }
781 :
782 0 : swnode->id = ret;
783 0 : swnode->node = node;
784 0 : swnode->parent = parent;
785 0 : swnode->allocated = allocated;
786 0 : swnode->kobj.kset = swnode_kset;
787 0 : fwnode_init(&swnode->fwnode, &software_node_ops);
788 :
789 0 : ida_init(&swnode->child_ids);
790 0 : INIT_LIST_HEAD(&swnode->entry);
791 0 : INIT_LIST_HEAD(&swnode->children);
792 :
793 0 : if (node->name)
794 0 : ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
795 : parent ? &parent->kobj : NULL,
796 : "%s", node->name);
797 : else
798 0 : ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
799 : parent ? &parent->kobj : NULL,
800 : "node%d", swnode->id);
801 0 : if (ret) {
802 0 : kobject_put(&swnode->kobj);
803 0 : return ERR_PTR(ret);
804 : }
805 :
806 0 : if (parent)
807 0 : list_add_tail(&swnode->entry, &parent->children);
808 :
809 0 : kobject_uevent(&swnode->kobj, KOBJ_ADD);
810 0 : return &swnode->fwnode;
811 :
812 0 : out_err:
813 0 : if (allocated)
814 0 : property_entries_free(node->properties);
815 0 : return ERR_PTR(ret);
816 : }
817 :
818 : /**
819 : * software_node_register_nodes - Register an array of software nodes
820 : * @nodes: Zero terminated array of software nodes to be registered
821 : *
822 : * Register multiple software nodes at once. If any node in the array
823 : * has its .parent pointer set (which can only be to another software_node),
824 : * then its parent **must** have been registered before it is; either outside
825 : * of this function or by ordering the array such that parent comes before
826 : * child.
827 : */
828 0 : int software_node_register_nodes(const struct software_node *nodes)
829 : {
830 0 : int ret;
831 0 : int i;
832 :
833 0 : for (i = 0; nodes[i].name; i++) {
834 0 : const struct software_node *parent = nodes[i].parent;
835 :
836 0 : if (parent && !software_node_to_swnode(parent)) {
837 0 : ret = -EINVAL;
838 0 : goto err_unregister_nodes;
839 : }
840 :
841 0 : ret = software_node_register(&nodes[i]);
842 0 : if (ret)
843 0 : goto err_unregister_nodes;
844 : }
845 :
846 : return 0;
847 :
848 0 : err_unregister_nodes:
849 0 : software_node_unregister_nodes(nodes);
850 0 : return ret;
851 : }
852 : EXPORT_SYMBOL_GPL(software_node_register_nodes);
853 :
854 : /**
855 : * software_node_unregister_nodes - Unregister an array of software nodes
856 : * @nodes: Zero terminated array of software nodes to be unregistered
857 : *
858 : * Unregister multiple software nodes at once. If parent pointers are set up
859 : * in any of the software nodes then the array **must** be ordered such that
860 : * parents come before their children.
861 : *
862 : * NOTE: If you are uncertain whether the array is ordered such that
863 : * parents will be unregistered before their children, it is wiser to
864 : * remove the nodes individually, in the correct order (child before
865 : * parent).
866 : */
867 0 : void software_node_unregister_nodes(const struct software_node *nodes)
868 : {
869 0 : unsigned int i = 0;
870 :
871 0 : while (nodes[i].name)
872 0 : i++;
873 :
874 0 : while (i--)
875 0 : software_node_unregister(&nodes[i]);
876 0 : }
877 : EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
878 :
879 : /**
880 : * software_node_register_node_group - Register a group of software nodes
881 : * @node_group: NULL terminated array of software node pointers to be registered
882 : *
883 : * Register multiple software nodes at once.
884 : */
885 0 : int software_node_register_node_group(const struct software_node **node_group)
886 : {
887 0 : unsigned int i;
888 0 : int ret;
889 :
890 0 : if (!node_group)
891 : return 0;
892 :
893 0 : for (i = 0; node_group[i]; i++) {
894 0 : ret = software_node_register(node_group[i]);
895 0 : if (ret) {
896 0 : software_node_unregister_node_group(node_group);
897 0 : return ret;
898 : }
899 : }
900 :
901 : return 0;
902 : }
903 : EXPORT_SYMBOL_GPL(software_node_register_node_group);
904 :
905 : /**
906 : * software_node_unregister_node_group - Unregister a group of software nodes
907 : * @node_group: NULL terminated array of software node pointers to be unregistered
908 : *
909 : * Unregister multiple software nodes at once. The array will be unwound in
910 : * reverse order (i.e. last entry first) and thus if any members of the array are
911 : * children of another member then the children must appear later in the list such
912 : * that they are unregistered first.
913 : */
914 0 : void software_node_unregister_node_group(
915 : const struct software_node **node_group)
916 : {
917 0 : unsigned int i = 0;
918 :
919 0 : if (!node_group)
920 : return;
921 :
922 0 : while (node_group[i])
923 0 : i++;
924 :
925 0 : while (i--)
926 0 : software_node_unregister(node_group[i]);
927 : }
928 : EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
929 :
930 : /**
931 : * software_node_register - Register static software node
932 : * @node: The software node to be registered
933 : */
934 0 : int software_node_register(const struct software_node *node)
935 : {
936 0 : struct swnode *parent = software_node_to_swnode(node->parent);
937 :
938 0 : if (software_node_to_swnode(node))
939 : return -EEXIST;
940 :
941 0 : if (node->parent && !parent)
942 : return -EINVAL;
943 :
944 0 : return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0));
945 : }
946 : EXPORT_SYMBOL_GPL(software_node_register);
947 :
948 : /**
949 : * software_node_unregister - Unregister static software node
950 : * @node: The software node to be unregistered
951 : */
952 0 : void software_node_unregister(const struct software_node *node)
953 : {
954 0 : struct swnode *swnode;
955 :
956 0 : swnode = software_node_to_swnode(node);
957 0 : if (swnode)
958 0 : fwnode_remove_software_node(&swnode->fwnode);
959 0 : }
960 : EXPORT_SYMBOL_GPL(software_node_unregister);
961 :
962 : struct fwnode_handle *
963 0 : fwnode_create_software_node(const struct property_entry *properties,
964 : const struct fwnode_handle *parent)
965 : {
966 0 : struct software_node *node;
967 0 : struct swnode *p = NULL;
968 0 : int ret;
969 :
970 0 : if (parent) {
971 0 : if (IS_ERR(parent))
972 0 : return ERR_CAST(parent);
973 0 : if (!is_software_node(parent))
974 0 : return ERR_PTR(-EINVAL);
975 0 : p = to_swnode(parent);
976 : }
977 :
978 0 : node = kzalloc(sizeof(*node), GFP_KERNEL);
979 0 : if (!node)
980 0 : return ERR_PTR(-ENOMEM);
981 :
982 0 : ret = software_node_register_properties(node, properties);
983 0 : if (ret) {
984 0 : kfree(node);
985 0 : return ERR_PTR(ret);
986 : }
987 :
988 0 : node->parent = p ? p->node : NULL;
989 :
990 0 : return swnode_register(node, p, 1);
991 : }
992 : EXPORT_SYMBOL_GPL(fwnode_create_software_node);
993 :
994 0 : void fwnode_remove_software_node(struct fwnode_handle *fwnode)
995 : {
996 0 : struct swnode *swnode = to_swnode(fwnode);
997 :
998 0 : if (!swnode)
999 : return;
1000 :
1001 0 : kobject_put(&swnode->kobj);
1002 : }
1003 : EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
1004 :
1005 : /**
1006 : * device_add_software_node - Assign software node to a device
1007 : * @dev: The device the software node is meant for.
1008 : * @node: The software node.
1009 : *
1010 : * This function will make @node the secondary firmware node pointer of @dev. If
1011 : * @dev has no primary node, then @node will become the primary node. The
1012 : * function will register @node automatically if it wasn't already registered.
1013 : */
1014 0 : int device_add_software_node(struct device *dev, const struct software_node *node)
1015 : {
1016 0 : struct swnode *swnode;
1017 0 : int ret;
1018 :
1019 : /* Only one software node per device. */
1020 0 : if (dev_to_swnode(dev))
1021 : return -EBUSY;
1022 :
1023 0 : swnode = software_node_to_swnode(node);
1024 0 : if (swnode) {
1025 0 : kobject_get(&swnode->kobj);
1026 : } else {
1027 0 : ret = software_node_register(node);
1028 0 : if (ret)
1029 : return ret;
1030 :
1031 0 : swnode = software_node_to_swnode(node);
1032 : }
1033 :
1034 0 : set_secondary_fwnode(dev, &swnode->fwnode);
1035 :
1036 0 : return 0;
1037 : }
1038 : EXPORT_SYMBOL_GPL(device_add_software_node);
1039 :
1040 : /**
1041 : * device_remove_software_node - Remove device's software node
1042 : * @dev: The device with the software node.
1043 : *
1044 : * This function will unregister the software node of @dev.
1045 : */
1046 0 : void device_remove_software_node(struct device *dev)
1047 : {
1048 0 : struct swnode *swnode;
1049 :
1050 0 : swnode = dev_to_swnode(dev);
1051 0 : if (!swnode)
1052 : return;
1053 :
1054 0 : software_node_notify(dev, KOBJ_REMOVE);
1055 0 : set_secondary_fwnode(dev, NULL);
1056 0 : kobject_put(&swnode->kobj);
1057 : }
1058 : EXPORT_SYMBOL_GPL(device_remove_software_node);
1059 :
1060 : /**
1061 : * device_create_managed_software_node - Create a software node for a device
1062 : * @dev: The device the software node is assigned to.
1063 : * @properties: Device properties for the software node.
1064 : * @parent: Parent of the software node.
1065 : *
1066 : * Creates a software node as a managed resource for @dev, which means the
1067 : * lifetime of the newly created software node is tied to the lifetime of @dev.
1068 : * Software nodes created with this function should not be reused or shared
1069 : * because of that. The function takes a deep copy of @properties for the
1070 : * software node.
1071 : *
1072 : * Since the new software node is assigned directly to @dev, and since it should
1073 : * not be shared, it is not returned to the caller. The function returns 0 on
1074 : * success, and errno in case of an error.
1075 : */
1076 0 : int device_create_managed_software_node(struct device *dev,
1077 : const struct property_entry *properties,
1078 : const struct software_node *parent)
1079 : {
1080 0 : struct fwnode_handle *p = software_node_fwnode(parent);
1081 0 : struct fwnode_handle *fwnode;
1082 :
1083 0 : if (parent && !p)
1084 : return -EINVAL;
1085 :
1086 0 : fwnode = fwnode_create_software_node(properties, p);
1087 0 : if (IS_ERR(fwnode))
1088 0 : return PTR_ERR(fwnode);
1089 :
1090 0 : to_swnode(fwnode)->managed = true;
1091 0 : set_secondary_fwnode(dev, fwnode);
1092 :
1093 0 : return 0;
1094 : }
1095 : EXPORT_SYMBOL_GPL(device_create_managed_software_node);
1096 :
1097 175 : int software_node_notify(struct device *dev, unsigned long action)
1098 : {
1099 175 : struct swnode *swnode;
1100 175 : int ret;
1101 :
1102 175 : swnode = dev_to_swnode(dev);
1103 175 : if (!swnode)
1104 : return 0;
1105 :
1106 0 : switch (action) {
1107 0 : case KOBJ_ADD:
1108 0 : ret = sysfs_create_link(&dev->kobj, &swnode->kobj,
1109 : "software_node");
1110 0 : if (ret)
1111 : break;
1112 :
1113 0 : ret = sysfs_create_link(&swnode->kobj, &dev->kobj,
1114 : dev_name(dev));
1115 0 : if (ret) {
1116 0 : sysfs_remove_link(&dev->kobj, "software_node");
1117 0 : break;
1118 : }
1119 0 : kobject_get(&swnode->kobj);
1120 0 : break;
1121 : case KOBJ_REMOVE:
1122 0 : sysfs_remove_link(&swnode->kobj, dev_name(dev));
1123 0 : sysfs_remove_link(&dev->kobj, "software_node");
1124 0 : kobject_put(&swnode->kobj);
1125 :
1126 0 : if (swnode->managed) {
1127 0 : set_secondary_fwnode(dev, NULL);
1128 0 : kobject_put(&swnode->kobj);
1129 : }
1130 : break;
1131 : default:
1132 : break;
1133 : }
1134 :
1135 0 : return 0;
1136 : }
1137 :
1138 1 : static int __init software_node_init(void)
1139 : {
1140 1 : swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj);
1141 1 : if (!swnode_kset)
1142 0 : return -ENOMEM;
1143 : return 0;
1144 : }
1145 : postcore_initcall(software_node_init);
1146 :
1147 0 : static void __exit software_node_exit(void)
1148 : {
1149 0 : ida_destroy(&swnode_root_ids);
1150 0 : kset_unregister(swnode_kset);
1151 0 : }
1152 : __exitcall(software_node_exit);
|