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; 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(struct fwnode_handle *fwnode) 75 { 76 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 void 107 property_set_pointer(struct property_entry *prop, const void *pointer) 108 { 109 switch (prop->type) { 110 case DEV_PROP_U8: 111 if (prop->is_array) 112 prop->pointer.u8_data = pointer; 113 else 114 prop->value.u8_data = *((u8 *)pointer); 115 break; 116 case DEV_PROP_U16: 117 if (prop->is_array) 118 prop->pointer.u16_data = pointer; 119 else 120 prop->value.u16_data = *((u16 *)pointer); 121 break; 122 case DEV_PROP_U32: 123 if (prop->is_array) 124 prop->pointer.u32_data = pointer; 125 else 126 prop->value.u32_data = *((u32 *)pointer); 127 break; 128 case DEV_PROP_U64: 129 if (prop->is_array) 130 prop->pointer.u64_data = pointer; 131 else 132 prop->value.u64_data = *((u64 *)pointer); 133 break; 134 case DEV_PROP_STRING: 135 if (prop->is_array) 136 prop->pointer.str = pointer; 137 else 138 prop->value.str = pointer; 139 break; 140 default: 141 break; 142 } 143 } 144 145 static const void *property_get_pointer(const struct property_entry *prop) 146 { 147 switch (prop->type) { 148 case DEV_PROP_U8: 149 if (prop->is_array) 150 return prop->pointer.u8_data; 151 return &prop->value.u8_data; 152 case DEV_PROP_U16: 153 if (prop->is_array) 154 return prop->pointer.u16_data; 155 return &prop->value.u16_data; 156 case DEV_PROP_U32: 157 if (prop->is_array) 158 return prop->pointer.u32_data; 159 return &prop->value.u32_data; 160 case DEV_PROP_U64: 161 if (prop->is_array) 162 return prop->pointer.u64_data; 163 return &prop->value.u64_data; 164 case DEV_PROP_STRING: 165 if (prop->is_array) 166 return prop->pointer.str; 167 return &prop->value.str; 168 default: 169 return NULL; 170 } 171 } 172 173 static const void *property_entry_find(const struct property_entry *props, 174 const char *propname, size_t length) 175 { 176 const struct property_entry *prop; 177 const void *pointer; 178 179 prop = property_entry_get(props, propname); 180 if (!prop) 181 return ERR_PTR(-EINVAL); 182 pointer = property_get_pointer(prop); 183 if (!pointer) 184 return ERR_PTR(-ENODATA); 185 if (length > prop->length) 186 return ERR_PTR(-EOVERFLOW); 187 return pointer; 188 } 189 190 static int property_entry_read_u8_array(const struct property_entry *props, 191 const char *propname, 192 u8 *values, size_t nval) 193 { 194 const void *pointer; 195 size_t length = nval * sizeof(*values); 196 197 pointer = property_entry_find(props, propname, length); 198 if (IS_ERR(pointer)) 199 return PTR_ERR(pointer); 200 201 memcpy(values, pointer, length); 202 return 0; 203 } 204 205 static int property_entry_read_u16_array(const struct property_entry *props, 206 const char *propname, 207 u16 *values, size_t nval) 208 { 209 const void *pointer; 210 size_t length = nval * sizeof(*values); 211 212 pointer = property_entry_find(props, propname, length); 213 if (IS_ERR(pointer)) 214 return PTR_ERR(pointer); 215 216 memcpy(values, pointer, length); 217 return 0; 218 } 219 220 static int property_entry_read_u32_array(const struct property_entry *props, 221 const char *propname, 222 u32 *values, size_t nval) 223 { 224 const void *pointer; 225 size_t length = nval * sizeof(*values); 226 227 pointer = property_entry_find(props, propname, length); 228 if (IS_ERR(pointer)) 229 return PTR_ERR(pointer); 230 231 memcpy(values, pointer, length); 232 return 0; 233 } 234 235 static int property_entry_read_u64_array(const struct property_entry *props, 236 const char *propname, 237 u64 *values, size_t nval) 238 { 239 const void *pointer; 240 size_t length = nval * sizeof(*values); 241 242 pointer = property_entry_find(props, propname, length); 243 if (IS_ERR(pointer)) 244 return PTR_ERR(pointer); 245 246 memcpy(values, pointer, length); 247 return 0; 248 } 249 250 static int 251 property_entry_count_elems_of_size(const struct property_entry *props, 252 const char *propname, size_t length) 253 { 254 const struct property_entry *prop; 255 256 prop = property_entry_get(props, propname); 257 if (!prop) 258 return -EINVAL; 259 260 return prop->length / length; 261 } 262 263 static int property_entry_read_int_array(const struct property_entry *props, 264 const char *name, 265 unsigned int elem_size, void *val, 266 size_t nval) 267 { 268 if (!val) 269 return property_entry_count_elems_of_size(props, name, 270 elem_size); 271 switch (elem_size) { 272 case sizeof(u8): 273 return property_entry_read_u8_array(props, name, val, nval); 274 case sizeof(u16): 275 return property_entry_read_u16_array(props, name, val, nval); 276 case sizeof(u32): 277 return property_entry_read_u32_array(props, name, val, nval); 278 case sizeof(u64): 279 return property_entry_read_u64_array(props, name, val, nval); 280 } 281 282 return -ENXIO; 283 } 284 285 static int property_entry_read_string_array(const struct property_entry *props, 286 const char *propname, 287 const char **strings, size_t nval) 288 { 289 const struct property_entry *prop; 290 const void *pointer; 291 size_t array_len, length; 292 293 /* Find out the array length. */ 294 prop = property_entry_get(props, propname); 295 if (!prop) 296 return -EINVAL; 297 298 if (prop->is_array) 299 /* Find the length of an array. */ 300 array_len = property_entry_count_elems_of_size(props, propname, 301 sizeof(const char *)); 302 else 303 /* The array length for a non-array string property is 1. */ 304 array_len = 1; 305 306 /* Return how many there are if strings is NULL. */ 307 if (!strings) 308 return array_len; 309 310 array_len = min(nval, array_len); 311 length = array_len * sizeof(*strings); 312 313 pointer = property_entry_find(props, propname, length); 314 if (IS_ERR(pointer)) 315 return PTR_ERR(pointer); 316 317 memcpy(strings, pointer, length); 318 319 return array_len; 320 } 321 322 static void property_entry_free_data(const struct property_entry *p) 323 { 324 const void *pointer = property_get_pointer(p); 325 size_t i, nval; 326 327 if (p->is_array) { 328 if (p->type == DEV_PROP_STRING && p->pointer.str) { 329 nval = p->length / sizeof(const char *); 330 for (i = 0; i < nval; i++) 331 kfree(p->pointer.str[i]); 332 } 333 kfree(pointer); 334 } else if (p->type == DEV_PROP_STRING) { 335 kfree(p->value.str); 336 } 337 kfree(p->name); 338 } 339 340 static int property_copy_string_array(struct property_entry *dst, 341 const struct property_entry *src) 342 { 343 const char **d; 344 size_t nval = src->length / sizeof(*d); 345 int i; 346 347 d = kcalloc(nval, sizeof(*d), GFP_KERNEL); 348 if (!d) 349 return -ENOMEM; 350 351 for (i = 0; i < nval; i++) { 352 d[i] = kstrdup(src->pointer.str[i], GFP_KERNEL); 353 if (!d[i] && src->pointer.str[i]) { 354 while (--i >= 0) 355 kfree(d[i]); 356 kfree(d); 357 return -ENOMEM; 358 } 359 } 360 361 dst->pointer.str = d; 362 return 0; 363 } 364 365 static int property_entry_copy_data(struct property_entry *dst, 366 const struct property_entry *src) 367 { 368 const void *pointer = property_get_pointer(src); 369 const void *new; 370 int error; 371 372 if (src->is_array) { 373 if (!src->length) 374 return -ENODATA; 375 376 if (src->type == DEV_PROP_STRING) { 377 error = property_copy_string_array(dst, src); 378 if (error) 379 return error; 380 new = dst->pointer.str; 381 } else { 382 new = kmemdup(pointer, src->length, GFP_KERNEL); 383 if (!new) 384 return -ENOMEM; 385 } 386 } else if (src->type == DEV_PROP_STRING) { 387 new = kstrdup(src->value.str, GFP_KERNEL); 388 if (!new && src->value.str) 389 return -ENOMEM; 390 } else { 391 new = pointer; 392 } 393 394 dst->length = src->length; 395 dst->is_array = src->is_array; 396 dst->type = src->type; 397 398 property_set_pointer(dst, new); 399 400 dst->name = kstrdup(src->name, GFP_KERNEL); 401 if (!dst->name) 402 goto out_free_data; 403 404 return 0; 405 406 out_free_data: 407 property_entry_free_data(dst); 408 return -ENOMEM; 409 } 410 411 /** 412 * property_entries_dup - duplicate array of properties 413 * @properties: array of properties to copy 414 * 415 * This function creates a deep copy of the given NULL-terminated array 416 * of property entries. 417 */ 418 struct property_entry * 419 property_entries_dup(const struct property_entry *properties) 420 { 421 struct property_entry *p; 422 int i, n = 0; 423 int ret; 424 425 if (!properties) 426 return NULL; 427 428 while (properties[n].name) 429 n++; 430 431 p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL); 432 if (!p) 433 return ERR_PTR(-ENOMEM); 434 435 for (i = 0; i < n; i++) { 436 ret = property_entry_copy_data(&p[i], &properties[i]); 437 if (ret) { 438 while (--i >= 0) 439 property_entry_free_data(&p[i]); 440 kfree(p); 441 return ERR_PTR(ret); 442 } 443 } 444 445 return p; 446 } 447 EXPORT_SYMBOL_GPL(property_entries_dup); 448 449 /** 450 * property_entries_free - free previously allocated array of properties 451 * @properties: array of properties to destroy 452 * 453 * This function frees given NULL-terminated array of property entries, 454 * along with their data. 455 */ 456 void property_entries_free(const struct property_entry *properties) 457 { 458 const struct property_entry *p; 459 460 if (!properties) 461 return; 462 463 for (p = properties; p->name; p++) 464 property_entry_free_data(p); 465 466 kfree(properties); 467 } 468 EXPORT_SYMBOL_GPL(property_entries_free); 469 470 /* -------------------------------------------------------------------------- */ 471 /* fwnode operations */ 472 473 static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode) 474 { 475 struct swnode *swnode = to_swnode(fwnode); 476 477 kobject_get(&swnode->kobj); 478 479 return &swnode->fwnode; 480 } 481 482 static void software_node_put(struct fwnode_handle *fwnode) 483 { 484 struct swnode *swnode = to_swnode(fwnode); 485 486 kobject_put(&swnode->kobj); 487 } 488 489 static bool software_node_property_present(const struct fwnode_handle *fwnode, 490 const char *propname) 491 { 492 struct swnode *swnode = to_swnode(fwnode); 493 494 return !!property_entry_get(swnode->node->properties, propname); 495 } 496 497 static int software_node_read_int_array(const struct fwnode_handle *fwnode, 498 const char *propname, 499 unsigned int elem_size, void *val, 500 size_t nval) 501 { 502 struct swnode *swnode = to_swnode(fwnode); 503 504 return property_entry_read_int_array(swnode->node->properties, propname, 505 elem_size, val, nval); 506 } 507 508 static int software_node_read_string_array(const struct fwnode_handle *fwnode, 509 const char *propname, 510 const char **val, size_t nval) 511 { 512 struct swnode *swnode = to_swnode(fwnode); 513 514 return property_entry_read_string_array(swnode->node->properties, 515 propname, val, nval); 516 } 517 518 static struct fwnode_handle * 519 software_node_get_parent(const struct fwnode_handle *fwnode) 520 { 521 struct swnode *swnode = to_swnode(fwnode); 522 523 return swnode ? (swnode->parent ? &swnode->parent->fwnode : NULL) : NULL; 524 } 525 526 static struct fwnode_handle * 527 software_node_get_next_child(const struct fwnode_handle *fwnode, 528 struct fwnode_handle *child) 529 { 530 struct swnode *p = to_swnode(fwnode); 531 struct swnode *c = to_swnode(child); 532 533 if (!p || list_empty(&p->children) || 534 (c && list_is_last(&c->entry, &p->children))) 535 return NULL; 536 537 if (c) 538 c = list_next_entry(c, entry); 539 else 540 c = list_first_entry(&p->children, struct swnode, entry); 541 return &c->fwnode; 542 } 543 544 static struct fwnode_handle * 545 software_node_get_named_child_node(const struct fwnode_handle *fwnode, 546 const char *childname) 547 { 548 struct swnode *swnode = to_swnode(fwnode); 549 struct swnode *child; 550 551 if (!swnode || list_empty(&swnode->children)) 552 return NULL; 553 554 list_for_each_entry(child, &swnode->children, entry) { 555 if (!strcmp(childname, kobject_name(&child->kobj))) { 556 kobject_get(&child->kobj); 557 return &child->fwnode; 558 } 559 } 560 return NULL; 561 } 562 563 static int 564 software_node_get_reference_args(const struct fwnode_handle *fwnode, 565 const char *propname, const char *nargs_prop, 566 unsigned int nargs, unsigned int index, 567 struct fwnode_reference_args *args) 568 { 569 struct swnode *swnode = to_swnode(fwnode); 570 const struct software_node_reference *ref; 571 const struct property_entry *prop; 572 struct fwnode_handle *refnode; 573 int i; 574 575 if (!swnode || !swnode->node->references) 576 return -ENOENT; 577 578 for (ref = swnode->node->references; ref->name; ref++) 579 if (!strcmp(ref->name, propname)) 580 break; 581 582 if (!ref->name || index > (ref->nrefs - 1)) 583 return -ENOENT; 584 585 refnode = software_node_fwnode(ref->refs[index].node); 586 if (!refnode) 587 return -ENOENT; 588 589 if (nargs_prop) { 590 prop = property_entry_get(swnode->node->properties, nargs_prop); 591 if (!prop) 592 return -EINVAL; 593 594 nargs = prop->value.u32_data; 595 } 596 597 if (nargs > NR_FWNODE_REFERENCE_ARGS) 598 return -EINVAL; 599 600 args->fwnode = software_node_get(refnode); 601 args->nargs = nargs; 602 603 for (i = 0; i < nargs; i++) 604 args->args[i] = ref->refs[index].args[i]; 605 606 return 0; 607 } 608 609 static const struct fwnode_operations software_node_ops = { 610 .get = software_node_get, 611 .put = software_node_put, 612 .property_present = software_node_property_present, 613 .property_read_int_array = software_node_read_int_array, 614 .property_read_string_array = software_node_read_string_array, 615 .get_parent = software_node_get_parent, 616 .get_next_child_node = software_node_get_next_child, 617 .get_named_child_node = software_node_get_named_child_node, 618 .get_reference_args = software_node_get_reference_args 619 }; 620 621 /* -------------------------------------------------------------------------- */ 622 623 static int 624 software_node_register_properties(struct software_node *node, 625 const struct property_entry *properties) 626 { 627 struct property_entry *props; 628 629 props = property_entries_dup(properties); 630 if (IS_ERR(props)) 631 return PTR_ERR(props); 632 633 node->properties = props; 634 635 return 0; 636 } 637 638 static void software_node_release(struct kobject *kobj) 639 { 640 struct swnode *swnode = kobj_to_swnode(kobj); 641 642 if (swnode->allocated) { 643 property_entries_free(swnode->node->properties); 644 kfree(swnode->node); 645 } 646 ida_destroy(&swnode->child_ids); 647 kfree(swnode); 648 } 649 650 static struct kobj_type software_node_type = { 651 .release = software_node_release, 652 .sysfs_ops = &kobj_sysfs_ops, 653 }; 654 655 static struct fwnode_handle * 656 swnode_register(const struct software_node *node, struct swnode *parent, 657 unsigned int allocated) 658 { 659 struct swnode *swnode; 660 int ret; 661 662 swnode = kzalloc(sizeof(*swnode), GFP_KERNEL); 663 if (!swnode) { 664 ret = -ENOMEM; 665 goto out_err; 666 } 667 668 ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids, 669 0, 0, GFP_KERNEL); 670 if (ret < 0) { 671 kfree(swnode); 672 goto out_err; 673 } 674 675 swnode->id = ret; 676 swnode->node = node; 677 swnode->parent = parent; 678 swnode->allocated = allocated; 679 swnode->kobj.kset = swnode_kset; 680 swnode->fwnode.ops = &software_node_ops; 681 682 ida_init(&swnode->child_ids); 683 INIT_LIST_HEAD(&swnode->entry); 684 INIT_LIST_HEAD(&swnode->children); 685 686 if (node->name) 687 ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 688 parent ? &parent->kobj : NULL, 689 "%s", node->name); 690 else 691 ret = kobject_init_and_add(&swnode->kobj, &software_node_type, 692 parent ? &parent->kobj : NULL, 693 "node%d", swnode->id); 694 if (ret) { 695 kobject_put(&swnode->kobj); 696 return ERR_PTR(ret); 697 } 698 699 if (parent) 700 list_add_tail(&swnode->entry, &parent->children); 701 702 kobject_uevent(&swnode->kobj, KOBJ_ADD); 703 return &swnode->fwnode; 704 705 out_err: 706 if (allocated) 707 property_entries_free(node->properties); 708 return ERR_PTR(ret); 709 } 710 711 /** 712 * software_node_register_nodes - Register an array of software nodes 713 * @nodes: Zero terminated array of software nodes to be registered 714 * 715 * Register multiple software nodes at once. 716 */ 717 int software_node_register_nodes(const struct software_node *nodes) 718 { 719 int ret; 720 int i; 721 722 for (i = 0; nodes[i].name; i++) { 723 ret = software_node_register(&nodes[i]); 724 if (ret) { 725 software_node_unregister_nodes(nodes); 726 return ret; 727 } 728 } 729 730 return 0; 731 } 732 EXPORT_SYMBOL_GPL(software_node_register_nodes); 733 734 /** 735 * software_node_unregister_nodes - Unregister an array of software nodes 736 * @nodes: Zero terminated array of software nodes to be unregistered 737 * 738 * Unregister multiple software nodes at once. 739 */ 740 void software_node_unregister_nodes(const struct software_node *nodes) 741 { 742 struct swnode *swnode; 743 int i; 744 745 for (i = 0; nodes[i].name; i++) { 746 swnode = software_node_to_swnode(&nodes[i]); 747 if (swnode) 748 fwnode_remove_software_node(&swnode->fwnode); 749 } 750 } 751 EXPORT_SYMBOL_GPL(software_node_unregister_nodes); 752 753 /** 754 * software_node_register - Register static software node 755 * @node: The software node to be registered 756 */ 757 int software_node_register(const struct software_node *node) 758 { 759 struct swnode *parent = software_node_to_swnode(node->parent); 760 761 if (software_node_to_swnode(node)) 762 return -EEXIST; 763 764 return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0)); 765 } 766 EXPORT_SYMBOL_GPL(software_node_register); 767 768 struct fwnode_handle * 769 fwnode_create_software_node(const struct property_entry *properties, 770 const struct fwnode_handle *parent) 771 { 772 struct software_node *node; 773 struct swnode *p = NULL; 774 int ret; 775 776 if (parent) { 777 if (IS_ERR(parent)) 778 return ERR_CAST(parent); 779 if (!is_software_node(parent)) 780 return ERR_PTR(-EINVAL); 781 p = to_swnode(parent); 782 } 783 784 node = kzalloc(sizeof(*node), GFP_KERNEL); 785 if (!node) 786 return ERR_PTR(-ENOMEM); 787 788 ret = software_node_register_properties(node, properties); 789 if (ret) { 790 kfree(node); 791 return ERR_PTR(ret); 792 } 793 794 node->parent = p ? p->node : NULL; 795 796 return swnode_register(node, p, 1); 797 } 798 EXPORT_SYMBOL_GPL(fwnode_create_software_node); 799 800 void fwnode_remove_software_node(struct fwnode_handle *fwnode) 801 { 802 struct swnode *swnode = to_swnode(fwnode); 803 804 if (!swnode) 805 return; 806 807 if (swnode->parent) { 808 ida_simple_remove(&swnode->parent->child_ids, swnode->id); 809 list_del(&swnode->entry); 810 } else { 811 ida_simple_remove(&swnode_root_ids, swnode->id); 812 } 813 814 kobject_put(&swnode->kobj); 815 } 816 EXPORT_SYMBOL_GPL(fwnode_remove_software_node); 817 818 int software_node_notify(struct device *dev, unsigned long action) 819 { 820 struct fwnode_handle *fwnode = dev_fwnode(dev); 821 struct swnode *swnode; 822 int ret; 823 824 if (!fwnode) 825 return 0; 826 827 if (!is_software_node(fwnode)) 828 fwnode = fwnode->secondary; 829 if (!is_software_node(fwnode)) 830 return 0; 831 832 swnode = to_swnode(fwnode); 833 834 switch (action) { 835 case KOBJ_ADD: 836 ret = sysfs_create_link(&dev->kobj, &swnode->kobj, 837 "software_node"); 838 if (ret) 839 break; 840 841 ret = sysfs_create_link(&swnode->kobj, &dev->kobj, 842 dev_name(dev)); 843 if (ret) { 844 sysfs_remove_link(&dev->kobj, "software_node"); 845 break; 846 } 847 kobject_get(&swnode->kobj); 848 break; 849 case KOBJ_REMOVE: 850 sysfs_remove_link(&swnode->kobj, dev_name(dev)); 851 sysfs_remove_link(&dev->kobj, "software_node"); 852 kobject_put(&swnode->kobj); 853 break; 854 default: 855 break; 856 } 857 858 return 0; 859 } 860 861 static int __init software_node_init(void) 862 { 863 swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj); 864 if (!swnode_kset) 865 return -ENOMEM; 866 return 0; 867 } 868 postcore_initcall(software_node_init); 869 870 static void __exit software_node_exit(void) 871 { 872 ida_destroy(&swnode_root_ids); 873 kset_unregister(swnode_kset); 874 } 875 __exitcall(software_node_exit); 876