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