Lines Matching +full:child +full:- +full:nodes
1 // SPDX-License-Identifier: GPL-2.0
3 * Software nodes for the firmware node framework.
41 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &software_node_ops; in is_software_node()
62 fwnode = fwnode->secondary; in dev_to_swnode()
76 spin_lock(&swnode_kset->list_lock); in software_node_to_swnode()
78 list_for_each_entry(k, &swnode_kset->list, entry) { in software_node_to_swnode()
80 if (swnode->node == node) in software_node_to_swnode()
85 spin_unlock(&swnode_kset->list_lock); in software_node_to_swnode()
94 return swnode ? swnode->node : NULL; in to_software_node()
102 return swnode ? &swnode->fwnode : NULL; in software_node_fwnode()
106 /* -------------------------------------------------------------------------- */
115 for (; prop->name; prop++) in property_entry_get()
116 if (!strcmp(name, prop->name)) in property_entry_get()
124 if (!prop->length) in property_get_pointer()
127 return prop->is_inline ? &prop->value : prop->pointer; in property_get_pointer()
138 return ERR_PTR(-EINVAL); in property_entry_find()
141 return ERR_PTR(-ENODATA); in property_entry_find()
142 if (length > prop->length) in property_entry_find()
143 return ERR_PTR(-EOVERFLOW); in property_entry_find()
155 return -EINVAL; in property_entry_count_elems_of_size()
157 return prop->length / length; in property_entry_count_elems_of_size()
173 return -ENXIO; in property_entry_read_int_array()
220 if (p->type == DEV_PROP_STRING) { in property_entry_free_data()
222 nval = p->length / sizeof(*src_str); in property_entry_free_data()
227 if (!p->is_inline) in property_entry_free_data()
228 kfree(p->pointer); in property_entry_free_data()
230 kfree(p->name); in property_entry_free_data()
242 while (--i >= 0) in property_copy_string_array()
262 if (!src->is_inline && !src->length) in property_entry_copy_data()
263 return -ENODATA; in property_entry_copy_data()
269 if (src->type == DEV_PROP_REF && src->is_inline) in property_entry_copy_data()
270 return -EINVAL; in property_entry_copy_data()
272 if (src->length <= sizeof(dst->value)) { in property_entry_copy_data()
273 dst_ptr = &dst->value; in property_entry_copy_data()
274 dst->is_inline = true; in property_entry_copy_data()
276 dst_ptr = kmalloc(src->length, GFP_KERNEL); in property_entry_copy_data()
278 return -ENOMEM; in property_entry_copy_data()
279 dst->pointer = dst_ptr; in property_entry_copy_data()
282 if (src->type == DEV_PROP_STRING) { in property_entry_copy_data()
283 nval = src->length / sizeof(const char *); in property_entry_copy_data()
285 if (!dst->is_inline) in property_entry_copy_data()
286 kfree(dst->pointer); in property_entry_copy_data()
287 return -ENOMEM; in property_entry_copy_data()
290 memcpy(dst_ptr, pointer, src->length); in property_entry_copy_data()
293 dst->length = src->length; in property_entry_copy_data()
294 dst->type = src->type; in property_entry_copy_data()
295 dst->name = kstrdup(src->name, GFP_KERNEL); in property_entry_copy_data()
296 if (!dst->name) { in property_entry_copy_data()
298 return -ENOMEM; in property_entry_copy_data()
305 * property_entries_dup - duplicate array of properties
308 * This function creates a deep copy of the given NULL-terminated array
326 return ERR_PTR(-ENOMEM); in property_entries_dup()
331 while (--i >= 0) in property_entries_dup()
343 * property_entries_free - free previously allocated array of properties
346 * This function frees given NULL-terminated array of property entries,
356 for (p = properties; p->name; p++) in property_entries_free()
363 /* -------------------------------------------------------------------------- */
370 kobject_get(&swnode->kobj); in software_node_get()
372 return &swnode->fwnode; in software_node_get()
379 kobject_put(&swnode->kobj); in software_node_put()
387 return !!property_entry_get(swnode->node->properties, propname); in software_node_property_present()
397 return property_entry_read_int_array(swnode->node->properties, propname, in software_node_read_int_array()
407 return property_entry_read_string_array(swnode->node->properties, in software_node_read_string_array()
419 return kobject_name(&swnode->kobj); in software_node_get_name()
448 if (!swnode || !swnode->parent) in software_node_get_parent()
451 return fwnode_handle_get(&swnode->parent->fwnode); in software_node_get_parent()
456 struct fwnode_handle *child) in software_node_get_next_child() argument
459 struct swnode *c = to_swnode(child); in software_node_get_next_child()
461 if (!p || list_empty(&p->children) || in software_node_get_next_child()
462 (c && list_is_last(&c->entry, &p->children))) { in software_node_get_next_child()
463 fwnode_handle_put(child); in software_node_get_next_child()
470 c = list_first_entry(&p->children, struct swnode, entry); in software_node_get_next_child()
472 fwnode_handle_put(child); in software_node_get_next_child()
473 return fwnode_handle_get(&c->fwnode); in software_node_get_next_child()
481 struct swnode *child; in software_node_get_named_child_node() local
483 if (!swnode || list_empty(&swnode->children)) in software_node_get_named_child_node()
486 list_for_each_entry(child, &swnode->children, entry) { in software_node_get_named_child_node()
487 if (!strcmp(childname, kobject_name(&child->kobj))) { in software_node_get_named_child_node()
488 kobject_get(&child->kobj); in software_node_get_named_child_node()
489 return &child->fwnode; in software_node_get_named_child_node()
511 return -ENOENT; in software_node_get_reference_args()
513 prop = property_entry_get(swnode->node->properties, propname); in software_node_get_reference_args()
515 return -ENOENT; in software_node_get_reference_args()
517 if (prop->type != DEV_PROP_REF) in software_node_get_reference_args()
518 return -EINVAL; in software_node_get_reference_args()
524 if (prop->is_inline) in software_node_get_reference_args()
525 return -EINVAL; in software_node_get_reference_args()
527 if (index * sizeof(*ref) >= prop->length) in software_node_get_reference_args()
528 return -ENOENT; in software_node_get_reference_args()
530 ref_array = prop->pointer; in software_node_get_reference_args()
533 refnode = software_node_fwnode(ref->node); in software_node_get_reference_args()
535 return -ENOENT; in software_node_get_reference_args()
538 error = property_entry_read_int_array(swnode->node->properties, in software_node_get_reference_args()
548 return -EINVAL; in software_node_get_reference_args()
550 args->fwnode = software_node_get(refnode); in software_node_get_reference_args()
551 args->nargs = nargs; in software_node_get_reference_args()
554 args->args[i] = ref->args[i]; in software_node_get_reference_args()
570 if (!strncmp(to_swnode(port)->node->name, "port@", in swnode_graph_find_next_port()
596 parent = software_node_get(&swnode->fwnode); in software_node_graph_get_next_endpoint()
624 prop = property_entry_get(swnode->node->properties, "remote-endpoint"); in software_node_graph_get_remote_endpoint()
625 if (!prop || prop->type != DEV_PROP_REF || prop->is_inline) in software_node_graph_get_remote_endpoint()
628 ref = prop->pointer; in software_node_graph_get_remote_endpoint()
638 swnode = swnode->parent; in software_node_graph_get_port_parent()
639 if (swnode && !strcmp(swnode->node->name, "ports")) in software_node_graph_get_port_parent()
640 swnode = swnode->parent; in software_node_graph_get_port_parent()
642 return swnode ? software_node_get(&swnode->fwnode) : NULL; in software_node_graph_get_port_parent()
650 const char *parent_name = swnode->parent->node->name; in software_node_graph_parse_endpoint()
655 return -EINVAL; in software_node_graph_parse_endpoint()
658 ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port); in software_node_graph_parse_endpoint()
662 endpoint->id = swnode->id; in software_node_graph_parse_endpoint()
663 endpoint->local_fwnode = fwnode; in software_node_graph_parse_endpoint()
686 /* -------------------------------------------------------------------------- */
689 * software_node_find_by_name - Find software node by name
693 * The function will find a node that is child of @parent and that is named
707 spin_lock(&swnode_kset->list_lock); in software_node_find_by_name()
709 list_for_each_entry(k, &swnode_kset->list, entry) { in software_node_find_by_name()
711 if (parent == swnode->node->parent && swnode->node->name && in software_node_find_by_name()
712 !strcmp(name, swnode->node->name)) { in software_node_find_by_name()
713 kobject_get(&swnode->kobj); in software_node_find_by_name()
719 spin_unlock(&swnode_kset->list_lock); in software_node_find_by_name()
721 return swnode ? swnode->node : NULL; in software_node_find_by_name()
737 return ERR_PTR(-ENOMEM); in software_node_alloc()
740 node->properties = props; in software_node_alloc()
747 property_entries_free(node->properties); in software_node_free()
755 if (swnode->parent) { in software_node_release()
756 ida_simple_remove(&swnode->parent->child_ids, swnode->id); in software_node_release()
757 list_del(&swnode->entry); in software_node_release()
759 ida_simple_remove(&swnode_root_ids, swnode->id); in software_node_release()
762 if (swnode->allocated) in software_node_release()
763 software_node_free(swnode->node); in software_node_release()
765 ida_destroy(&swnode->child_ids); in software_node_release()
783 return ERR_PTR(-ENOMEM); in swnode_register()
785 ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids, in swnode_register()
792 swnode->id = ret; in swnode_register()
793 swnode->node = node; in swnode_register()
794 swnode->parent = parent; in swnode_register()
795 swnode->kobj.kset = swnode_kset; in swnode_register()
796 fwnode_init(&swnode->fwnode, &software_node_ops); in swnode_register()
798 ida_init(&swnode->child_ids); in swnode_register()
799 INIT_LIST_HEAD(&swnode->entry); in swnode_register()
800 INIT_LIST_HEAD(&swnode->children); in swnode_register()
802 if (node->name) in swnode_register()
803 ret = kobject_init_and_add(&swnode->kobj, &software_node_type, in swnode_register()
804 parent ? &parent->kobj : NULL, in swnode_register()
805 "%s", node->name); in swnode_register()
807 ret = kobject_init_and_add(&swnode->kobj, &software_node_type, in swnode_register()
808 parent ? &parent->kobj : NULL, in swnode_register()
809 "node%d", swnode->id); in swnode_register()
811 kobject_put(&swnode->kobj); in swnode_register()
819 swnode->allocated = allocated; in swnode_register()
822 list_add_tail(&swnode->entry, &parent->children); in swnode_register()
824 kobject_uevent(&swnode->kobj, KOBJ_ADD); in swnode_register()
825 return &swnode->fwnode; in swnode_register()
829 * software_node_register_nodes - Register an array of software nodes
830 * @nodes: Zero terminated array of software nodes to be registered
832 * Register multiple software nodes at once. If any node in the array
836 * child.
838 int software_node_register_nodes(const struct software_node *nodes) in software_node_register_nodes() argument
843 for (i = 0; nodes[i].name; i++) { in software_node_register_nodes()
844 const struct software_node *parent = nodes[i].parent; in software_node_register_nodes()
847 ret = -EINVAL; in software_node_register_nodes()
851 ret = software_node_register(&nodes[i]); in software_node_register_nodes()
859 software_node_unregister_nodes(nodes); in software_node_register_nodes()
865 * software_node_unregister_nodes - Unregister an array of software nodes
866 * @nodes: Zero terminated array of software nodes to be unregistered
868 * Unregister multiple software nodes at once. If parent pointers are set up
869 * in any of the software nodes then the array **must** be ordered such that
874 * remove the nodes individually, in the correct order (child before
877 void software_node_unregister_nodes(const struct software_node *nodes) in software_node_unregister_nodes() argument
881 while (nodes[i].name) in software_node_unregister_nodes()
884 while (i--) in software_node_unregister_nodes()
885 software_node_unregister(&nodes[i]); in software_node_unregister_nodes()
890 * software_node_register_node_group - Register a group of software nodes
893 * Register multiple software nodes at once. If any node in the array
897 * child.
920 * software_node_unregister_node_group - Unregister a group of software nodes
923 * Unregister multiple software nodes at once. If parent pointers are set up
924 * in any of the software nodes then the array **must** be ordered such that
929 * remove the nodes individually, in the correct order (child before
943 while (i--) in software_node_unregister_node_group()
949 * software_node_register - Register static software node
954 struct swnode *parent = software_node_to_swnode(node->parent); in software_node_register()
957 return -EEXIST; in software_node_register()
959 if (node->parent && !parent) in software_node_register()
960 return -EINVAL; in software_node_register()
967 * software_node_unregister - Unregister static software node
976 fwnode_remove_software_node(&swnode->fwnode); in software_node_unregister()
993 return ERR_PTR(-EINVAL); in fwnode_create_software_node()
999 node->parent = p ? p->node : NULL; in fwnode_create_software_node()
1016 kobject_put(&swnode->kobj); in fwnode_remove_software_node()
1021 * device_add_software_node - Assign software node to a device
1036 return -EBUSY; in device_add_software_node()
1040 kobject_get(&swnode->kobj); in device_add_software_node()
1049 set_secondary_fwnode(dev, &swnode->fwnode); in device_add_software_node()
1065 * device_remove_software_node - Remove device's software node
1082 kobject_put(&swnode->kobj); in device_remove_software_node()
1087 * device_create_managed_software_node - Create a software node for a device
1094 * Software nodes created with this function should not be reused or shared
1110 return -EINVAL; in device_create_managed_software_node()
1116 to_swnode(fwnode)->managed = true; in device_create_managed_software_node()
1135 ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); in software_node_notify()
1139 ret = sysfs_create_link(&swnode->kobj, &dev->kobj, dev_name(dev)); in software_node_notify()
1141 sysfs_remove_link(&dev->kobj, "software_node"); in software_node_notify()
1145 kobject_get(&swnode->kobj); in software_node_notify()
1156 sysfs_remove_link(&swnode->kobj, dev_name(dev)); in software_node_notify_remove()
1157 sysfs_remove_link(&dev->kobj, "software_node"); in software_node_notify_remove()
1158 kobject_put(&swnode->kobj); in software_node_notify_remove()
1160 if (swnode->managed) { in software_node_notify_remove()
1162 kobject_put(&swnode->kobj); in software_node_notify_remove()
1170 return -ENOMEM; in software_node_init()