xref: /openbmc/linux/drivers/base/swnode.c (revision 7ec6b431)
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);
831