1 // SPDX-License-Identifier: GPL-2.0
3 * Software nodes for the firmware node framework.
5 * Copyright (C) 2018, Intel Corporation
6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
9 #include <linux/device.h>
10 #include <linux/kernel.h>
11 #include <linux/property.h>
12 #include <linux/slab.h>
14 struct software_node
{
17 struct fwnode_handle fwnode
;
21 struct list_head entry
;
22 struct list_head children
;
23 struct software_node
*parent
;
26 const struct property_entry
*properties
;
29 static DEFINE_IDA(swnode_root_ids
);
30 static struct kset
*swnode_kset
;
32 #define kobj_to_swnode(_kobj_) container_of(_kobj_, struct software_node, kobj)
34 static const struct fwnode_operations software_node_ops
;
36 bool is_software_node(const struct fwnode_handle
*fwnode
)
38 return !IS_ERR_OR_NULL(fwnode
) && fwnode
->ops
== &software_node_ops
;
41 #define to_software_node(__fwnode) \
43 typeof(__fwnode) __to_software_node_fwnode = __fwnode; \
45 is_software_node(__to_software_node_fwnode) ? \
46 container_of(__to_software_node_fwnode, \
47 struct software_node, fwnode) : \
51 /* -------------------------------------------------------------------------- */
52 /* property_entry processing */
54 static const struct property_entry
*
55 property_entry_get(const struct property_entry
*prop
, const char *name
)
60 for (; prop
->name
; prop
++)
61 if (!strcmp(name
, prop
->name
))
68 property_set_pointer(struct property_entry
*prop
, const void *pointer
)
73 prop
->pointer
.u8_data
= pointer
;
75 prop
->value
.u8_data
= *((u8
*)pointer
);
79 prop
->pointer
.u16_data
= pointer
;
81 prop
->value
.u16_data
= *((u16
*)pointer
);
85 prop
->pointer
.u32_data
= pointer
;
87 prop
->value
.u32_data
= *((u32
*)pointer
);
91 prop
->pointer
.u64_data
= pointer
;
93 prop
->value
.u64_data
= *((u64
*)pointer
);
97 prop
->pointer
.str
= pointer
;
99 prop
->value
.str
= pointer
;
106 static const void *property_get_pointer(const struct property_entry
*prop
)
108 switch (prop
->type
) {
111 return prop
->pointer
.u8_data
;
112 return &prop
->value
.u8_data
;
115 return prop
->pointer
.u16_data
;
116 return &prop
->value
.u16_data
;
119 return prop
->pointer
.u32_data
;
120 return &prop
->value
.u32_data
;
123 return prop
->pointer
.u64_data
;
124 return &prop
->value
.u64_data
;
125 case DEV_PROP_STRING
:
127 return prop
->pointer
.str
;
128 return &prop
->value
.str
;
134 static const void *property_entry_find(const struct property_entry
*props
,
135 const char *propname
, size_t length
)
137 const struct property_entry
*prop
;
140 prop
= property_entry_get(props
, propname
);
142 return ERR_PTR(-EINVAL
);
143 pointer
= property_get_pointer(prop
);
145 return ERR_PTR(-ENODATA
);
146 if (length
> prop
->length
)
147 return ERR_PTR(-EOVERFLOW
);
151 static int property_entry_read_u8_array(const struct property_entry
*props
,
152 const char *propname
,
153 u8
*values
, size_t nval
)
156 size_t length
= nval
* sizeof(*values
);
158 pointer
= property_entry_find(props
, propname
, length
);
160 return PTR_ERR(pointer
);
162 memcpy(values
, pointer
, length
);
166 static int property_entry_read_u16_array(const struct property_entry
*props
,
167 const char *propname
,
168 u16
*values
, size_t nval
)
171 size_t length
= nval
* sizeof(*values
);
173 pointer
= property_entry_find(props
, propname
, length
);
175 return PTR_ERR(pointer
);
177 memcpy(values
, pointer
, length
);
181 static int property_entry_read_u32_array(const struct property_entry
*props
,
182 const char *propname
,
183 u32
*values
, size_t nval
)
186 size_t length
= nval
* sizeof(*values
);
188 pointer
= property_entry_find(props
, propname
, length
);
190 return PTR_ERR(pointer
);
192 memcpy(values
, pointer
, length
);
196 static int property_entry_read_u64_array(const struct property_entry
*props
,
197 const char *propname
,
198 u64
*values
, size_t nval
)
201 size_t length
= nval
* sizeof(*values
);
203 pointer
= property_entry_find(props
, propname
, length
);
205 return PTR_ERR(pointer
);
207 memcpy(values
, pointer
, length
);
212 property_entry_count_elems_of_size(const struct property_entry
*props
,
213 const char *propname
, size_t length
)
215 const struct property_entry
*prop
;
217 prop
= property_entry_get(props
, propname
);
221 return prop
->length
/ length
;
224 static int property_entry_read_int_array(const struct property_entry
*props
,
226 unsigned int elem_size
, void *val
,
230 return property_entry_count_elems_of_size(props
, name
,
234 return property_entry_read_u8_array(props
, name
, val
, nval
);
236 return property_entry_read_u16_array(props
, name
, val
, nval
);
238 return property_entry_read_u32_array(props
, name
, val
, nval
);
240 return property_entry_read_u64_array(props
, name
, val
, nval
);
246 static int property_entry_read_string_array(const struct property_entry
*props
,
247 const char *propname
,
248 const char **strings
, size_t nval
)
250 const struct property_entry
*prop
;
252 size_t array_len
, length
;
254 /* Find out the array length. */
255 prop
= property_entry_get(props
, propname
);
260 /* Find the length of an array. */
261 array_len
= property_entry_count_elems_of_size(props
, propname
,
262 sizeof(const char *));
264 /* The array length for a non-array string property is 1. */
267 /* Return how many there are if strings is NULL. */
271 array_len
= min(nval
, array_len
);
272 length
= array_len
* sizeof(*strings
);
274 pointer
= property_entry_find(props
, propname
, length
);
276 return PTR_ERR(pointer
);
278 memcpy(strings
, pointer
, length
);
283 static void property_entry_free_data(const struct property_entry
*p
)
285 const void *pointer
= property_get_pointer(p
);
289 if (p
->type
== DEV_PROP_STRING
&& p
->pointer
.str
) {
290 nval
= p
->length
/ sizeof(const char *);
291 for (i
= 0; i
< nval
; i
++)
292 kfree(p
->pointer
.str
[i
]);
295 } else if (p
->type
== DEV_PROP_STRING
) {
301 static int property_copy_string_array(struct property_entry
*dst
,
302 const struct property_entry
*src
)
305 size_t nval
= src
->length
/ sizeof(*d
);
308 d
= kcalloc(nval
, sizeof(*d
), GFP_KERNEL
);
312 for (i
= 0; i
< nval
; i
++) {
313 d
[i
] = kstrdup(src
->pointer
.str
[i
], GFP_KERNEL
);
314 if (!d
[i
] && src
->pointer
.str
[i
]) {
322 dst
->pointer
.str
= d
;
326 static int property_entry_copy_data(struct property_entry
*dst
,
327 const struct property_entry
*src
)
329 const void *pointer
= property_get_pointer(src
);
337 if (src
->type
== DEV_PROP_STRING
) {
338 error
= property_copy_string_array(dst
, src
);
341 new = dst
->pointer
.str
;
343 new = kmemdup(pointer
, src
->length
, GFP_KERNEL
);
347 } else if (src
->type
== DEV_PROP_STRING
) {
348 new = kstrdup(src
->value
.str
, GFP_KERNEL
);
349 if (!new && src
->value
.str
)
355 dst
->length
= src
->length
;
356 dst
->is_array
= src
->is_array
;
357 dst
->type
= src
->type
;
359 property_set_pointer(dst
, new);
361 dst
->name
= kstrdup(src
->name
, GFP_KERNEL
);
368 property_entry_free_data(dst
);
373 * property_entries_dup - duplicate array of properties
374 * @properties: array of properties to copy
376 * This function creates a deep copy of the given NULL-terminated array
377 * of property entries.
379 struct property_entry
*
380 property_entries_dup(const struct property_entry
*properties
)
382 struct property_entry
*p
;
386 while (properties
[n
].name
)
389 p
= kcalloc(n
+ 1, sizeof(*p
), GFP_KERNEL
);
391 return ERR_PTR(-ENOMEM
);
393 for (i
= 0; i
< n
; i
++) {
394 ret
= property_entry_copy_data(&p
[i
], &properties
[i
]);
397 property_entry_free_data(&p
[i
]);
405 EXPORT_SYMBOL_GPL(property_entries_dup
);
408 * property_entries_free - free previously allocated array of properties
409 * @properties: array of properties to destroy
411 * This function frees given NULL-terminated array of property entries,
412 * along with their data.
414 void property_entries_free(const struct property_entry
*properties
)
416 const struct property_entry
*p
;
421 for (p
= properties
; p
->name
; p
++)
422 property_entry_free_data(p
);
426 EXPORT_SYMBOL_GPL(property_entries_free
);
428 /* -------------------------------------------------------------------------- */
429 /* fwnode operations */
431 static struct fwnode_handle
*software_node_get(struct fwnode_handle
*fwnode
)
433 struct software_node
*swnode
= to_software_node(fwnode
);
435 kobject_get(&swnode
->kobj
);
437 return &swnode
->fwnode
;
440 static void software_node_put(struct fwnode_handle
*fwnode
)
442 struct software_node
*swnode
= to_software_node(fwnode
);
444 kobject_put(&swnode
->kobj
);
447 static bool software_node_property_present(const struct fwnode_handle
*fwnode
,
448 const char *propname
)
450 return !!property_entry_get(to_software_node(fwnode
)->properties
,
454 static int software_node_read_int_array(const struct fwnode_handle
*fwnode
,
455 const char *propname
,
456 unsigned int elem_size
, void *val
,
459 struct software_node
*swnode
= to_software_node(fwnode
);
461 return property_entry_read_int_array(swnode
->properties
, propname
,
462 elem_size
, val
, nval
);
465 static int software_node_read_string_array(const struct fwnode_handle
*fwnode
,
466 const char *propname
,
467 const char **val
, size_t nval
)
469 struct software_node
*swnode
= to_software_node(fwnode
);
471 return property_entry_read_string_array(swnode
->properties
, propname
,
475 struct fwnode_handle
*
476 software_node_get_parent(const struct fwnode_handle
*fwnode
)
478 struct software_node
*swnode
= to_software_node(fwnode
);
480 return swnode
? (swnode
->parent
? &swnode
->parent
->fwnode
: NULL
) :
484 struct fwnode_handle
*
485 software_node_get_next_child(const struct fwnode_handle
*fwnode
,
486 struct fwnode_handle
*child
)
488 struct software_node
*p
= to_software_node(fwnode
);
489 struct software_node
*c
= to_software_node(child
);
491 if (!p
|| list_empty(&p
->children
) ||
492 (c
&& list_is_last(&c
->entry
, &p
->children
)))
496 c
= list_next_entry(c
, entry
);
498 c
= list_first_entry(&p
->children
, struct software_node
, entry
);
502 static struct fwnode_handle
*
503 software_node_get_named_child_node(const struct fwnode_handle
*fwnode
,
504 const char *childname
)
506 struct software_node
*swnode
= to_software_node(fwnode
);
507 const struct property_entry
*prop
;
508 struct software_node
*child
;
510 if (!swnode
|| list_empty(&swnode
->children
))
513 list_for_each_entry(child
, &swnode
->children
, entry
) {
514 prop
= property_entry_get(child
->properties
, "name");
517 if (!strcmp(childname
, prop
->value
.str
)) {
518 kobject_get(&child
->kobj
);
519 return &child
->fwnode
;
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_parent
= software_node_get_parent
,
532 .get_next_child_node
= software_node_get_next_child
,
533 .get_named_child_node
= software_node_get_named_child_node
,
536 /* -------------------------------------------------------------------------- */
539 software_node_register_properties(struct software_node
*swnode
,
540 const struct property_entry
*properties
)
542 struct property_entry
*props
;
544 props
= property_entries_dup(properties
);
546 return PTR_ERR(props
);
548 swnode
->properties
= props
;
553 static void software_node_release(struct kobject
*kobj
)
555 struct software_node
*swnode
= kobj_to_swnode(kobj
);
557 if (swnode
->parent
) {
558 ida_simple_remove(&swnode
->parent
->child_ids
, swnode
->id
);
559 list_del(&swnode
->entry
);
561 ida_simple_remove(&swnode_root_ids
, swnode
->id
);
564 ida_destroy(&swnode
->child_ids
);
565 property_entries_free(swnode
->properties
);
569 static struct kobj_type software_node_type
= {
570 .release
= software_node_release
,
571 .sysfs_ops
= &kobj_sysfs_ops
,
574 struct fwnode_handle
*
575 fwnode_create_software_node(const struct property_entry
*properties
,
576 const struct fwnode_handle
*parent
)
578 struct software_node
*p
= NULL
;
579 struct software_node
*swnode
;
584 return ERR_CAST(parent
);
585 if (!is_software_node(parent
))
586 return ERR_PTR(-EINVAL
);
587 p
= to_software_node(parent
);
590 swnode
= kzalloc(sizeof(*swnode
), GFP_KERNEL
);
592 return ERR_PTR(-ENOMEM
);
594 ret
= ida_simple_get(p
? &p
->child_ids
: &swnode_root_ids
, 0, 0,
602 swnode
->kobj
.kset
= swnode_kset
;
603 swnode
->fwnode
.ops
= &software_node_ops
;
605 ida_init(&swnode
->child_ids
);
606 INIT_LIST_HEAD(&swnode
->entry
);
607 INIT_LIST_HEAD(&swnode
->children
);
611 list_add_tail(&swnode
->entry
, &p
->children
);
613 ret
= kobject_init_and_add(&swnode
->kobj
, &software_node_type
,
614 p
? &p
->kobj
: NULL
, "node%d", swnode
->id
);
616 kobject_put(&swnode
->kobj
);
620 ret
= software_node_register_properties(swnode
, properties
);
622 kobject_put(&swnode
->kobj
);
626 kobject_uevent(&swnode
->kobj
, KOBJ_ADD
);
627 return &swnode
->fwnode
;
629 EXPORT_SYMBOL_GPL(fwnode_create_software_node
);
631 void fwnode_remove_software_node(struct fwnode_handle
*fwnode
)
633 struct software_node
*swnode
= to_software_node(fwnode
);
638 kobject_put(&swnode
->kobj
);
640 EXPORT_SYMBOL_GPL(fwnode_remove_software_node
);
642 int software_node_notify(struct device
*dev
, unsigned long action
)
644 struct fwnode_handle
*fwnode
= dev_fwnode(dev
);
645 struct software_node
*swnode
;
651 if (!is_software_node(fwnode
))
652 fwnode
= fwnode
->secondary
;
653 if (!is_software_node(fwnode
))
656 swnode
= to_software_node(fwnode
);
660 ret
= sysfs_create_link(&dev
->kobj
, &swnode
->kobj
,
665 ret
= sysfs_create_link(&swnode
->kobj
, &dev
->kobj
,
668 sysfs_remove_link(&dev
->kobj
, "software_node");
671 kobject_get(&swnode
->kobj
);
674 sysfs_remove_link(&swnode
->kobj
, dev_name(dev
));
675 sysfs_remove_link(&dev
->kobj
, "software_node");
676 kobject_put(&swnode
->kobj
);
685 static int __init
software_node_init(void)
687 swnode_kset
= kset_create_and_add("software_nodes", NULL
, kernel_kobj
);
692 postcore_initcall(software_node_init
);
694 static void __exit
software_node_exit(void)
696 ida_destroy(&swnode_root_ids
);
697 kset_unregister(swnode_kset
);
699 __exitcall(software_node_exit
);