0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/kernel.h>
0011 #include <linux/property.h>
0012 #include <linux/slab.h>
0013
0014 #include "base.h"
0015
0016 struct swnode {
0017 struct kobject kobj;
0018 struct fwnode_handle fwnode;
0019 const struct software_node *node;
0020 int id;
0021
0022
0023 struct ida child_ids;
0024 struct list_head entry;
0025 struct list_head children;
0026 struct swnode *parent;
0027
0028 unsigned int allocated:1;
0029 unsigned int managed:1;
0030 };
0031
0032 static DEFINE_IDA(swnode_root_ids);
0033 static struct kset *swnode_kset;
0034
0035 #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct swnode, kobj)
0036
0037 static const struct fwnode_operations software_node_ops;
0038
0039 bool is_software_node(const struct fwnode_handle *fwnode)
0040 {
0041 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops;
0042 }
0043 EXPORT_SYMBOL_GPL(is_software_node);
0044
0045 #define to_swnode(__fwnode) \
0046 ({ \
0047 typeof(__fwnode) __to_swnode_fwnode = __fwnode; \
0048 \
0049 is_software_node(__to_swnode_fwnode) ? \
0050 container_of(__to_swnode_fwnode, \
0051 struct swnode, fwnode) : NULL; \
0052 })
0053
0054 static inline struct swnode *dev_to_swnode(struct device *dev)
0055 {
0056 struct fwnode_handle *fwnode = dev_fwnode(dev);
0057
0058 if (!fwnode)
0059 return NULL;
0060
0061 if (!is_software_node(fwnode))
0062 fwnode = fwnode->secondary;
0063
0064 return to_swnode(fwnode);
0065 }
0066
0067 static struct swnode *
0068 software_node_to_swnode(const struct software_node *node)
0069 {
0070 struct swnode *swnode = NULL;
0071 struct kobject *k;
0072
0073 if (!node)
0074 return NULL;
0075
0076 spin_lock(&swnode_kset->list_lock);
0077
0078 list_for_each_entry(k, &swnode_kset->list, entry) {
0079 swnode = kobj_to_swnode(k);
0080 if (swnode->node == node)
0081 break;
0082 swnode = NULL;
0083 }
0084
0085 spin_unlock(&swnode_kset->list_lock);
0086
0087 return swnode;
0088 }
0089
0090 const struct software_node *to_software_node(const struct fwnode_handle *fwnode)
0091 {
0092 const struct swnode *swnode = to_swnode(fwnode);
0093
0094 return swnode ? swnode->node : NULL;
0095 }
0096 EXPORT_SYMBOL_GPL(to_software_node);
0097
0098 struct fwnode_handle *software_node_fwnode(const struct software_node *node)
0099 {
0100 struct swnode *swnode = software_node_to_swnode(node);
0101
0102 return swnode ? &swnode->fwnode : NULL;
0103 }
0104 EXPORT_SYMBOL_GPL(software_node_fwnode);
0105
0106
0107
0108
0109 static const struct property_entry *
0110 property_entry_get(const struct property_entry *prop, const char *name)
0111 {
0112 if (!prop)
0113 return NULL;
0114
0115 for (; prop->name; prop++)
0116 if (!strcmp(name, prop->name))
0117 return prop;
0118
0119 return NULL;
0120 }
0121
0122 static const void *property_get_pointer(const struct property_entry *prop)
0123 {
0124 if (!prop->length)
0125 return NULL;
0126
0127 return prop->is_inline ? &prop->value : prop->pointer;
0128 }
0129
0130 static const void *property_entry_find(const struct property_entry *props,
0131 const char *propname, size_t length)
0132 {
0133 const struct property_entry *prop;
0134 const void *pointer;
0135
0136 prop = property_entry_get(props, propname);
0137 if (!prop)
0138 return ERR_PTR(-EINVAL);
0139 pointer = property_get_pointer(prop);
0140 if (!pointer)
0141 return ERR_PTR(-ENODATA);
0142 if (length > prop->length)
0143 return ERR_PTR(-EOVERFLOW);
0144 return pointer;
0145 }
0146
0147 static int
0148 property_entry_count_elems_of_size(const struct property_entry *props,
0149 const char *propname, size_t length)
0150 {
0151 const struct property_entry *prop;
0152
0153 prop = property_entry_get(props, propname);
0154 if (!prop)
0155 return -EINVAL;
0156
0157 return prop->length / length;
0158 }
0159
0160 static int property_entry_read_int_array(const struct property_entry *props,
0161 const char *name,
0162 unsigned int elem_size, void *val,
0163 size_t nval)
0164 {
0165 const void *pointer;
0166 size_t length;
0167
0168 if (!val)
0169 return property_entry_count_elems_of_size(props, name,
0170 elem_size);
0171
0172 if (!is_power_of_2(elem_size) || elem_size > sizeof(u64))
0173 return -ENXIO;
0174
0175 length = nval * elem_size;
0176
0177 pointer = property_entry_find(props, name, length);
0178 if (IS_ERR(pointer))
0179 return PTR_ERR(pointer);
0180
0181 memcpy(val, pointer, length);
0182 return 0;
0183 }
0184
0185 static int property_entry_read_string_array(const struct property_entry *props,
0186 const char *propname,
0187 const char **strings, size_t nval)
0188 {
0189 const void *pointer;
0190 size_t length;
0191 int array_len;
0192
0193
0194 array_len = property_entry_count_elems_of_size(props, propname,
0195 sizeof(const char *));
0196 if (array_len < 0)
0197 return array_len;
0198
0199
0200 if (!strings)
0201 return array_len;
0202
0203 array_len = min_t(size_t, nval, array_len);
0204 length = array_len * sizeof(*strings);
0205
0206 pointer = property_entry_find(props, propname, length);
0207 if (IS_ERR(pointer))
0208 return PTR_ERR(pointer);
0209
0210 memcpy(strings, pointer, length);
0211
0212 return array_len;
0213 }
0214
0215 static void property_entry_free_data(const struct property_entry *p)
0216 {
0217 const char * const *src_str;
0218 size_t i, nval;
0219
0220 if (p->type == DEV_PROP_STRING) {
0221 src_str = property_get_pointer(p);
0222 nval = p->length / sizeof(*src_str);
0223 for (i = 0; i < nval; i++)
0224 kfree(src_str[i]);
0225 }
0226
0227 if (!p->is_inline)
0228 kfree(p->pointer);
0229
0230 kfree(p->name);
0231 }
0232
0233 static bool property_copy_string_array(const char **dst_ptr,
0234 const char * const *src_ptr,
0235 size_t nval)
0236 {
0237 int i;
0238
0239 for (i = 0; i < nval; i++) {
0240 dst_ptr[i] = kstrdup(src_ptr[i], GFP_KERNEL);
0241 if (!dst_ptr[i] && src_ptr[i]) {
0242 while (--i >= 0)
0243 kfree(dst_ptr[i]);
0244 return false;
0245 }
0246 }
0247
0248 return true;
0249 }
0250
0251 static int property_entry_copy_data(struct property_entry *dst,
0252 const struct property_entry *src)
0253 {
0254 const void *pointer = property_get_pointer(src);
0255 void *dst_ptr;
0256 size_t nval;
0257
0258
0259
0260
0261
0262 if (!src->is_inline && !src->length)
0263 return -ENODATA;
0264
0265
0266
0267
0268
0269 if (src->type == DEV_PROP_REF && src->is_inline)
0270 return -EINVAL;
0271
0272 if (src->length <= sizeof(dst->value)) {
0273 dst_ptr = &dst->value;
0274 dst->is_inline = true;
0275 } else {
0276 dst_ptr = kmalloc(src->length, GFP_KERNEL);
0277 if (!dst_ptr)
0278 return -ENOMEM;
0279 dst->pointer = dst_ptr;
0280 }
0281
0282 if (src->type == DEV_PROP_STRING) {
0283 nval = src->length / sizeof(const char *);
0284 if (!property_copy_string_array(dst_ptr, pointer, nval)) {
0285 if (!dst->is_inline)
0286 kfree(dst->pointer);
0287 return -ENOMEM;
0288 }
0289 } else {
0290 memcpy(dst_ptr, pointer, src->length);
0291 }
0292
0293 dst->length = src->length;
0294 dst->type = src->type;
0295 dst->name = kstrdup(src->name, GFP_KERNEL);
0296 if (!dst->name) {
0297 property_entry_free_data(dst);
0298 return -ENOMEM;
0299 }
0300
0301 return 0;
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311 struct property_entry *
0312 property_entries_dup(const struct property_entry *properties)
0313 {
0314 struct property_entry *p;
0315 int i, n = 0;
0316 int ret;
0317
0318 if (!properties)
0319 return NULL;
0320
0321 while (properties[n].name)
0322 n++;
0323
0324 p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL);
0325 if (!p)
0326 return ERR_PTR(-ENOMEM);
0327
0328 for (i = 0; i < n; i++) {
0329 ret = property_entry_copy_data(&p[i], &properties[i]);
0330 if (ret) {
0331 while (--i >= 0)
0332 property_entry_free_data(&p[i]);
0333 kfree(p);
0334 return ERR_PTR(ret);
0335 }
0336 }
0337
0338 return p;
0339 }
0340 EXPORT_SYMBOL_GPL(property_entries_dup);
0341
0342
0343
0344
0345
0346
0347
0348
0349 void property_entries_free(const struct property_entry *properties)
0350 {
0351 const struct property_entry *p;
0352
0353 if (!properties)
0354 return;
0355
0356 for (p = properties; p->name; p++)
0357 property_entry_free_data(p);
0358
0359 kfree(properties);
0360 }
0361 EXPORT_SYMBOL_GPL(property_entries_free);
0362
0363
0364
0365
0366 static struct fwnode_handle *software_node_get(struct fwnode_handle *fwnode)
0367 {
0368 struct swnode *swnode = to_swnode(fwnode);
0369
0370 kobject_get(&swnode->kobj);
0371
0372 return &swnode->fwnode;
0373 }
0374
0375 static void software_node_put(struct fwnode_handle *fwnode)
0376 {
0377 struct swnode *swnode = to_swnode(fwnode);
0378
0379 kobject_put(&swnode->kobj);
0380 }
0381
0382 static bool software_node_property_present(const struct fwnode_handle *fwnode,
0383 const char *propname)
0384 {
0385 struct swnode *swnode = to_swnode(fwnode);
0386
0387 return !!property_entry_get(swnode->node->properties, propname);
0388 }
0389
0390 static int software_node_read_int_array(const struct fwnode_handle *fwnode,
0391 const char *propname,
0392 unsigned int elem_size, void *val,
0393 size_t nval)
0394 {
0395 struct swnode *swnode = to_swnode(fwnode);
0396
0397 return property_entry_read_int_array(swnode->node->properties, propname,
0398 elem_size, val, nval);
0399 }
0400
0401 static int software_node_read_string_array(const struct fwnode_handle *fwnode,
0402 const char *propname,
0403 const char **val, size_t nval)
0404 {
0405 struct swnode *swnode = to_swnode(fwnode);
0406
0407 return property_entry_read_string_array(swnode->node->properties,
0408 propname, val, nval);
0409 }
0410
0411 static const char *
0412 software_node_get_name(const struct fwnode_handle *fwnode)
0413 {
0414 const struct swnode *swnode = to_swnode(fwnode);
0415
0416 return kobject_name(&swnode->kobj);
0417 }
0418
0419 static const char *
0420 software_node_get_name_prefix(const struct fwnode_handle *fwnode)
0421 {
0422 struct fwnode_handle *parent;
0423 const char *prefix;
0424
0425 parent = fwnode_get_parent(fwnode);
0426 if (!parent)
0427 return "";
0428
0429
0430 while (is_software_node(parent))
0431 parent = fwnode_get_next_parent(parent);
0432
0433 prefix = fwnode_get_name_prefix(parent);
0434 fwnode_handle_put(parent);
0435
0436
0437 return prefix ?: "/";
0438 }
0439
0440 static struct fwnode_handle *
0441 software_node_get_parent(const struct fwnode_handle *fwnode)
0442 {
0443 struct swnode *swnode = to_swnode(fwnode);
0444
0445 if (!swnode || !swnode->parent)
0446 return NULL;
0447
0448 return fwnode_handle_get(&swnode->parent->fwnode);
0449 }
0450
0451 static struct fwnode_handle *
0452 software_node_get_next_child(const struct fwnode_handle *fwnode,
0453 struct fwnode_handle *child)
0454 {
0455 struct swnode *p = to_swnode(fwnode);
0456 struct swnode *c = to_swnode(child);
0457
0458 if (!p || list_empty(&p->children) ||
0459 (c && list_is_last(&c->entry, &p->children))) {
0460 fwnode_handle_put(child);
0461 return NULL;
0462 }
0463
0464 if (c)
0465 c = list_next_entry(c, entry);
0466 else
0467 c = list_first_entry(&p->children, struct swnode, entry);
0468
0469 fwnode_handle_put(child);
0470 return fwnode_handle_get(&c->fwnode);
0471 }
0472
0473 static struct fwnode_handle *
0474 software_node_get_named_child_node(const struct fwnode_handle *fwnode,
0475 const char *childname)
0476 {
0477 struct swnode *swnode = to_swnode(fwnode);
0478 struct swnode *child;
0479
0480 if (!swnode || list_empty(&swnode->children))
0481 return NULL;
0482
0483 list_for_each_entry(child, &swnode->children, entry) {
0484 if (!strcmp(childname, kobject_name(&child->kobj))) {
0485 kobject_get(&child->kobj);
0486 return &child->fwnode;
0487 }
0488 }
0489 return NULL;
0490 }
0491
0492 static int
0493 software_node_get_reference_args(const struct fwnode_handle *fwnode,
0494 const char *propname, const char *nargs_prop,
0495 unsigned int nargs, unsigned int index,
0496 struct fwnode_reference_args *args)
0497 {
0498 struct swnode *swnode = to_swnode(fwnode);
0499 const struct software_node_ref_args *ref_array;
0500 const struct software_node_ref_args *ref;
0501 const struct property_entry *prop;
0502 struct fwnode_handle *refnode;
0503 u32 nargs_prop_val;
0504 int error;
0505 int i;
0506
0507 prop = property_entry_get(swnode->node->properties, propname);
0508 if (!prop)
0509 return -ENOENT;
0510
0511 if (prop->type != DEV_PROP_REF)
0512 return -EINVAL;
0513
0514
0515
0516
0517
0518 if (prop->is_inline)
0519 return -EINVAL;
0520
0521 if (index * sizeof(*ref) >= prop->length)
0522 return -ENOENT;
0523
0524 ref_array = prop->pointer;
0525 ref = &ref_array[index];
0526
0527 refnode = software_node_fwnode(ref->node);
0528 if (!refnode)
0529 return -ENOENT;
0530
0531 if (nargs_prop) {
0532 error = property_entry_read_int_array(ref->node->properties,
0533 nargs_prop, sizeof(u32),
0534 &nargs_prop_val, 1);
0535 if (error)
0536 return error;
0537
0538 nargs = nargs_prop_val;
0539 }
0540
0541 if (nargs > NR_FWNODE_REFERENCE_ARGS)
0542 return -EINVAL;
0543
0544 args->fwnode = software_node_get(refnode);
0545 args->nargs = nargs;
0546
0547 for (i = 0; i < nargs; i++)
0548 args->args[i] = ref->args[i];
0549
0550 return 0;
0551 }
0552
0553 static struct fwnode_handle *
0554 swnode_graph_find_next_port(const struct fwnode_handle *parent,
0555 struct fwnode_handle *port)
0556 {
0557 struct fwnode_handle *old = port;
0558
0559 while ((port = software_node_get_next_child(parent, old))) {
0560
0561
0562
0563
0564 if (!strncmp(to_swnode(port)->node->name, "port@",
0565 strlen("port@")))
0566 return port;
0567 old = port;
0568 }
0569
0570 return NULL;
0571 }
0572
0573 static struct fwnode_handle *
0574 software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
0575 struct fwnode_handle *endpoint)
0576 {
0577 struct swnode *swnode = to_swnode(fwnode);
0578 struct fwnode_handle *parent;
0579 struct fwnode_handle *port;
0580
0581 if (!swnode)
0582 return NULL;
0583
0584 if (endpoint) {
0585 port = software_node_get_parent(endpoint);
0586 parent = software_node_get_parent(port);
0587 } else {
0588 parent = software_node_get_named_child_node(fwnode, "ports");
0589 if (!parent)
0590 parent = software_node_get(&swnode->fwnode);
0591
0592 port = swnode_graph_find_next_port(parent, NULL);
0593 }
0594
0595 for (; port; port = swnode_graph_find_next_port(parent, port)) {
0596 endpoint = software_node_get_next_child(port, endpoint);
0597 if (endpoint) {
0598 fwnode_handle_put(port);
0599 break;
0600 }
0601 }
0602
0603 fwnode_handle_put(parent);
0604
0605 return endpoint;
0606 }
0607
0608 static struct fwnode_handle *
0609 software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
0610 {
0611 struct swnode *swnode = to_swnode(fwnode);
0612 const struct software_node_ref_args *ref;
0613 const struct property_entry *prop;
0614
0615 if (!swnode)
0616 return NULL;
0617
0618 prop = property_entry_get(swnode->node->properties, "remote-endpoint");
0619 if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
0620 return NULL;
0621
0622 ref = prop->pointer;
0623
0624 return software_node_get(software_node_fwnode(ref[0].node));
0625 }
0626
0627 static struct fwnode_handle *
0628 software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
0629 {
0630 struct swnode *swnode = to_swnode(fwnode);
0631
0632 swnode = swnode->parent;
0633 if (swnode && !strcmp(swnode->node->name, "ports"))
0634 swnode = swnode->parent;
0635
0636 return swnode ? software_node_get(&swnode->fwnode) : NULL;
0637 }
0638
0639 static int
0640 software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
0641 struct fwnode_endpoint *endpoint)
0642 {
0643 struct swnode *swnode = to_swnode(fwnode);
0644 const char *parent_name = swnode->parent->node->name;
0645 int ret;
0646
0647 if (strlen("port@") >= strlen(parent_name) ||
0648 strncmp(parent_name, "port@", strlen("port@")))
0649 return -EINVAL;
0650
0651
0652 ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port);
0653 if (ret)
0654 return ret;
0655
0656 endpoint->id = swnode->id;
0657 endpoint->local_fwnode = fwnode;
0658
0659 return 0;
0660 }
0661
0662 static const struct fwnode_operations software_node_ops = {
0663 .get = software_node_get,
0664 .put = software_node_put,
0665 .property_present = software_node_property_present,
0666 .property_read_int_array = software_node_read_int_array,
0667 .property_read_string_array = software_node_read_string_array,
0668 .get_name = software_node_get_name,
0669 .get_name_prefix = software_node_get_name_prefix,
0670 .get_parent = software_node_get_parent,
0671 .get_next_child_node = software_node_get_next_child,
0672 .get_named_child_node = software_node_get_named_child_node,
0673 .get_reference_args = software_node_get_reference_args,
0674 .graph_get_next_endpoint = software_node_graph_get_next_endpoint,
0675 .graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
0676 .graph_get_port_parent = software_node_graph_get_port_parent,
0677 .graph_parse_endpoint = software_node_graph_parse_endpoint,
0678 };
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692 const struct software_node *
0693 software_node_find_by_name(const struct software_node *parent, const char *name)
0694 {
0695 struct swnode *swnode = NULL;
0696 struct kobject *k;
0697
0698 if (!name)
0699 return NULL;
0700
0701 spin_lock(&swnode_kset->list_lock);
0702
0703 list_for_each_entry(k, &swnode_kset->list, entry) {
0704 swnode = kobj_to_swnode(k);
0705 if (parent == swnode->node->parent && swnode->node->name &&
0706 !strcmp(name, swnode->node->name)) {
0707 kobject_get(&swnode->kobj);
0708 break;
0709 }
0710 swnode = NULL;
0711 }
0712
0713 spin_unlock(&swnode_kset->list_lock);
0714
0715 return swnode ? swnode->node : NULL;
0716 }
0717 EXPORT_SYMBOL_GPL(software_node_find_by_name);
0718
0719 static struct software_node *software_node_alloc(const struct property_entry *properties)
0720 {
0721 struct property_entry *props;
0722 struct software_node *node;
0723
0724 props = property_entries_dup(properties);
0725 if (IS_ERR(props))
0726 return ERR_CAST(props);
0727
0728 node = kzalloc(sizeof(*node), GFP_KERNEL);
0729 if (!node) {
0730 property_entries_free(props);
0731 return ERR_PTR(-ENOMEM);
0732 }
0733
0734 node->properties = props;
0735
0736 return node;
0737 }
0738
0739 static void software_node_free(const struct software_node *node)
0740 {
0741 property_entries_free(node->properties);
0742 kfree(node);
0743 }
0744
0745 static void software_node_release(struct kobject *kobj)
0746 {
0747 struct swnode *swnode = kobj_to_swnode(kobj);
0748
0749 if (swnode->parent) {
0750 ida_simple_remove(&swnode->parent->child_ids, swnode->id);
0751 list_del(&swnode->entry);
0752 } else {
0753 ida_simple_remove(&swnode_root_ids, swnode->id);
0754 }
0755
0756 if (swnode->allocated)
0757 software_node_free(swnode->node);
0758
0759 ida_destroy(&swnode->child_ids);
0760 kfree(swnode);
0761 }
0762
0763 static struct kobj_type software_node_type = {
0764 .release = software_node_release,
0765 .sysfs_ops = &kobj_sysfs_ops,
0766 };
0767
0768 static struct fwnode_handle *
0769 swnode_register(const struct software_node *node, struct swnode *parent,
0770 unsigned int allocated)
0771 {
0772 struct swnode *swnode;
0773 int ret;
0774
0775 swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
0776 if (!swnode)
0777 return ERR_PTR(-ENOMEM);
0778
0779 ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
0780 0, 0, GFP_KERNEL);
0781 if (ret < 0) {
0782 kfree(swnode);
0783 return ERR_PTR(ret);
0784 }
0785
0786 swnode->id = ret;
0787 swnode->node = node;
0788 swnode->parent = parent;
0789 swnode->kobj.kset = swnode_kset;
0790 fwnode_init(&swnode->fwnode, &software_node_ops);
0791
0792 ida_init(&swnode->child_ids);
0793 INIT_LIST_HEAD(&swnode->entry);
0794 INIT_LIST_HEAD(&swnode->children);
0795
0796 if (node->name)
0797 ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
0798 parent ? &parent->kobj : NULL,
0799 "%s", node->name);
0800 else
0801 ret = kobject_init_and_add(&swnode->kobj, &software_node_type,
0802 parent ? &parent->kobj : NULL,
0803 "node%d", swnode->id);
0804 if (ret) {
0805 kobject_put(&swnode->kobj);
0806 return ERR_PTR(ret);
0807 }
0808
0809
0810
0811
0812
0813 swnode->allocated = allocated;
0814
0815 if (parent)
0816 list_add_tail(&swnode->entry, &parent->children);
0817
0818 kobject_uevent(&swnode->kobj, KOBJ_ADD);
0819 return &swnode->fwnode;
0820 }
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832 int software_node_register_nodes(const struct software_node *nodes)
0833 {
0834 int ret;
0835 int i;
0836
0837 for (i = 0; nodes[i].name; i++) {
0838 const struct software_node *parent = nodes[i].parent;
0839
0840 if (parent && !software_node_to_swnode(parent)) {
0841 ret = -EINVAL;
0842 goto err_unregister_nodes;
0843 }
0844
0845 ret = software_node_register(&nodes[i]);
0846 if (ret)
0847 goto err_unregister_nodes;
0848 }
0849
0850 return 0;
0851
0852 err_unregister_nodes:
0853 software_node_unregister_nodes(nodes);
0854 return ret;
0855 }
0856 EXPORT_SYMBOL_GPL(software_node_register_nodes);
0857
0858
0859
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870
0871 void software_node_unregister_nodes(const struct software_node *nodes)
0872 {
0873 unsigned int i = 0;
0874
0875 while (nodes[i].name)
0876 i++;
0877
0878 while (i--)
0879 software_node_unregister(&nodes[i]);
0880 }
0881 EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
0882
0883
0884
0885
0886
0887
0888
0889
0890
0891
0892
0893 int software_node_register_node_group(const struct software_node **node_group)
0894 {
0895 unsigned int i;
0896 int ret;
0897
0898 if (!node_group)
0899 return 0;
0900
0901 for (i = 0; node_group[i]; i++) {
0902 ret = software_node_register(node_group[i]);
0903 if (ret) {
0904 software_node_unregister_node_group(node_group);
0905 return ret;
0906 }
0907 }
0908
0909 return 0;
0910 }
0911 EXPORT_SYMBOL_GPL(software_node_register_node_group);
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926 void software_node_unregister_node_group(
0927 const struct software_node **node_group)
0928 {
0929 unsigned int i = 0;
0930
0931 if (!node_group)
0932 return;
0933
0934 while (node_group[i])
0935 i++;
0936
0937 while (i--)
0938 software_node_unregister(node_group[i]);
0939 }
0940 EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
0941
0942
0943
0944
0945
0946 int software_node_register(const struct software_node *node)
0947 {
0948 struct swnode *parent = software_node_to_swnode(node->parent);
0949
0950 if (software_node_to_swnode(node))
0951 return -EEXIST;
0952
0953 if (node->parent && !parent)
0954 return -EINVAL;
0955
0956 return PTR_ERR_OR_ZERO(swnode_register(node, parent, 0));
0957 }
0958 EXPORT_SYMBOL_GPL(software_node_register);
0959
0960
0961
0962
0963
0964 void software_node_unregister(const struct software_node *node)
0965 {
0966 struct swnode *swnode;
0967
0968 swnode = software_node_to_swnode(node);
0969 if (swnode)
0970 fwnode_remove_software_node(&swnode->fwnode);
0971 }
0972 EXPORT_SYMBOL_GPL(software_node_unregister);
0973
0974 struct fwnode_handle *
0975 fwnode_create_software_node(const struct property_entry *properties,
0976 const struct fwnode_handle *parent)
0977 {
0978 struct fwnode_handle *fwnode;
0979 struct software_node *node;
0980 struct swnode *p;
0981
0982 if (IS_ERR(parent))
0983 return ERR_CAST(parent);
0984
0985 p = to_swnode(parent);
0986 if (parent && !p)
0987 return ERR_PTR(-EINVAL);
0988
0989 node = software_node_alloc(properties);
0990 if (IS_ERR(node))
0991 return ERR_CAST(node);
0992
0993 node->parent = p ? p->node : NULL;
0994
0995 fwnode = swnode_register(node, p, 1);
0996 if (IS_ERR(fwnode))
0997 software_node_free(node);
0998
0999 return fwnode;
1000 }
1001 EXPORT_SYMBOL_GPL(fwnode_create_software_node);
1002
1003 void fwnode_remove_software_node(struct fwnode_handle *fwnode)
1004 {
1005 struct swnode *swnode = to_swnode(fwnode);
1006
1007 if (!swnode)
1008 return;
1009
1010 kobject_put(&swnode->kobj);
1011 }
1012 EXPORT_SYMBOL_GPL(fwnode_remove_software_node);
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023 int device_add_software_node(struct device *dev, const struct software_node *node)
1024 {
1025 struct swnode *swnode;
1026 int ret;
1027
1028
1029 if (dev_to_swnode(dev))
1030 return -EBUSY;
1031
1032 swnode = software_node_to_swnode(node);
1033 if (swnode) {
1034 kobject_get(&swnode->kobj);
1035 } else {
1036 ret = software_node_register(node);
1037 if (ret)
1038 return ret;
1039
1040 swnode = software_node_to_swnode(node);
1041 }
1042
1043 set_secondary_fwnode(dev, &swnode->fwnode);
1044
1045
1046
1047
1048
1049
1050
1051 if (device_is_registered(dev))
1052 software_node_notify(dev);
1053
1054 return 0;
1055 }
1056 EXPORT_SYMBOL_GPL(device_add_software_node);
1057
1058
1059
1060
1061
1062
1063
1064 void device_remove_software_node(struct device *dev)
1065 {
1066 struct swnode *swnode;
1067
1068 swnode = dev_to_swnode(dev);
1069 if (!swnode)
1070 return;
1071
1072 if (device_is_registered(dev))
1073 software_node_notify_remove(dev);
1074
1075 set_secondary_fwnode(dev, NULL);
1076 kobject_put(&swnode->kobj);
1077 }
1078 EXPORT_SYMBOL_GPL(device_remove_software_node);
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096 int device_create_managed_software_node(struct device *dev,
1097 const struct property_entry *properties,
1098 const struct software_node *parent)
1099 {
1100 struct fwnode_handle *p = software_node_fwnode(parent);
1101 struct fwnode_handle *fwnode;
1102
1103 if (parent && !p)
1104 return -EINVAL;
1105
1106 fwnode = fwnode_create_software_node(properties, p);
1107 if (IS_ERR(fwnode))
1108 return PTR_ERR(fwnode);
1109
1110 to_swnode(fwnode)->managed = true;
1111 set_secondary_fwnode(dev, fwnode);
1112
1113 if (device_is_registered(dev))
1114 software_node_notify(dev);
1115
1116 return 0;
1117 }
1118 EXPORT_SYMBOL_GPL(device_create_managed_software_node);
1119
1120 void software_node_notify(struct device *dev)
1121 {
1122 struct swnode *swnode;
1123 int ret;
1124
1125 swnode = dev_to_swnode(dev);
1126 if (!swnode)
1127 return;
1128
1129 ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node");
1130 if (ret)
1131 return;
1132
1133 ret = sysfs_create_link(&swnode->kobj, &dev->kobj, dev_name(dev));
1134 if (ret) {
1135 sysfs_remove_link(&dev->kobj, "software_node");
1136 return;
1137 }
1138
1139 kobject_get(&swnode->kobj);
1140 }
1141
1142 void software_node_notify_remove(struct device *dev)
1143 {
1144 struct swnode *swnode;
1145
1146 swnode = dev_to_swnode(dev);
1147 if (!swnode)
1148 return;
1149
1150 sysfs_remove_link(&swnode->kobj, dev_name(dev));
1151 sysfs_remove_link(&dev->kobj, "software_node");
1152 kobject_put(&swnode->kobj);
1153
1154 if (swnode->managed) {
1155 set_secondary_fwnode(dev, NULL);
1156 kobject_put(&swnode->kobj);
1157 }
1158 }
1159
1160 static int __init software_node_init(void)
1161 {
1162 swnode_kset = kset_create_and_add("software_nodes", NULL, kernel_kobj);
1163 if (!swnode_kset)
1164 return -ENOMEM;
1165 return 0;
1166 }
1167 postcore_initcall(software_node_init);
1168
1169 static void __exit software_node_exit(void)
1170 {
1171 ida_destroy(&swnode_root_ids);
1172 kset_unregister(swnode_kset);
1173 }
1174 __exitcall(software_node_exit);