diff options
Diffstat (limited to 'drivers/base/swnode.c')
| -rw-r--r-- | drivers/base/swnode.c | 258 | 
1 files changed, 88 insertions, 170 deletions
diff --git a/drivers/base/swnode.c b/drivers/base/swnode.c index a1f3f0994f9f..d8d0dc0ca5ac 100644 --- a/drivers/base/swnode.c +++ b/drivers/base/swnode.c @@ -71,9 +71,9 @@ software_node_to_swnode(const struct software_node *node)  	return swnode;  } -const struct software_node *to_software_node(struct fwnode_handle *fwnode) +const struct software_node *to_software_node(const struct fwnode_handle *fwnode)  { -	struct swnode *swnode = to_swnode(fwnode); +	const struct swnode *swnode = to_swnode(fwnode);  	return swnode ? swnode->node : NULL;  } @@ -103,71 +103,15 @@ property_entry_get(const struct property_entry *prop, const char *name)  	return NULL;  } -static void -property_set_pointer(struct property_entry *prop, const void *pointer) -{ -	switch (prop->type) { -	case DEV_PROP_U8: -		if (prop->is_array) -			prop->pointer.u8_data = pointer; -		else -			prop->value.u8_data = *((u8 *)pointer); -		break; -	case DEV_PROP_U16: -		if (prop->is_array) -			prop->pointer.u16_data = pointer; -		else -			prop->value.u16_data = *((u16 *)pointer); -		break; -	case DEV_PROP_U32: -		if (prop->is_array) -			prop->pointer.u32_data = pointer; -		else -			prop->value.u32_data = *((u32 *)pointer); -		break; -	case DEV_PROP_U64: -		if (prop->is_array) -			prop->pointer.u64_data = pointer; -		else -			prop->value.u64_data = *((u64 *)pointer); -		break; -	case DEV_PROP_STRING: -		if (prop->is_array) -			prop->pointer.str = pointer; -		else -			prop->value.str = pointer; -		break; -	default: -		break; -	} -} -  static const void *property_get_pointer(const struct property_entry *prop)  { -	switch (prop->type) { -	case DEV_PROP_U8: -		if (prop->is_array) -			return prop->pointer.u8_data; -		return &prop->value.u8_data; -	case DEV_PROP_U16: -		if (prop->is_array) -			return prop->pointer.u16_data; -		return &prop->value.u16_data; -	case DEV_PROP_U32: -		if (prop->is_array) -			return prop->pointer.u32_data; -		return &prop->value.u32_data; -	case DEV_PROP_U64: -		if (prop->is_array) -			return prop->pointer.u64_data; -		return &prop->value.u64_data; -	case DEV_PROP_STRING: -		if (prop->is_array) -			return prop->pointer.str; -		return &prop->value.str; -	default: +	if (!prop->length)  		return NULL; -	} + +	if (prop->is_array) +		return prop->pointer; + +	return &prop->value;  }  static const void *property_entry_find(const struct property_entry *props, @@ -187,66 +131,6 @@ static const void *property_entry_find(const struct property_entry *props,  	return pointer;  } -static int property_entry_read_u8_array(const struct property_entry *props, -					const char *propname, -					u8 *values, size_t nval) -{ -	const void *pointer; -	size_t length = nval * sizeof(*values); - -	pointer = property_entry_find(props, propname, length); -	if (IS_ERR(pointer)) -		return PTR_ERR(pointer); - -	memcpy(values, pointer, length); -	return 0; -} - -static int property_entry_read_u16_array(const struct property_entry *props, -					 const char *propname, -					 u16 *values, size_t nval) -{ -	const void *pointer; -	size_t length = nval * sizeof(*values); - -	pointer = property_entry_find(props, propname, length); -	if (IS_ERR(pointer)) -		return PTR_ERR(pointer); - -	memcpy(values, pointer, length); -	return 0; -} - -static int property_entry_read_u32_array(const struct property_entry *props, -					 const char *propname, -					 u32 *values, size_t nval) -{ -	const void *pointer; -	size_t length = nval * sizeof(*values); - -	pointer = property_entry_find(props, propname, length); -	if (IS_ERR(pointer)) -		return PTR_ERR(pointer); - -	memcpy(values, pointer, length); -	return 0; -} - -static int property_entry_read_u64_array(const struct property_entry *props, -					 const char *propname, -					 u64 *values, size_t nval) -{ -	const void *pointer; -	size_t length = nval * sizeof(*values); - -	pointer = property_entry_find(props, propname, length); -	if (IS_ERR(pointer)) -		return PTR_ERR(pointer); - -	memcpy(values, pointer, length); -	return 0; -} -  static int  property_entry_count_elems_of_size(const struct property_entry *props,  				   const char *propname, size_t length) @@ -265,49 +149,45 @@ static int property_entry_read_int_array(const struct property_entry *props,  					 unsigned int elem_size, void *val,  					 size_t nval)  { +	const void *pointer; +	size_t length; +  	if (!val)  		return property_entry_count_elems_of_size(props, name,  							  elem_size); -	switch (elem_size) { -	case sizeof(u8): -		return property_entry_read_u8_array(props, name, val, nval); -	case sizeof(u16): -		return property_entry_read_u16_array(props, name, val, nval); -	case sizeof(u32): -		return property_entry_read_u32_array(props, name, val, nval); -	case sizeof(u64): -		return property_entry_read_u64_array(props, name, val, nval); -	} -	return -ENXIO; +	if (!is_power_of_2(elem_size) || elem_size > sizeof(u64)) +		return -ENXIO; + +	length = nval * elem_size; + +	pointer = property_entry_find(props, name, length); +	if (IS_ERR(pointer)) +		return PTR_ERR(pointer); + +	memcpy(val, pointer, length); +	return 0;  }  static int property_entry_read_string_array(const struct property_entry *props,  					    const char *propname,  					    const char **strings, size_t nval)  { -	const struct property_entry *prop;  	const void *pointer; -	size_t array_len, length; +	size_t length; +	int array_len;  	/* Find out the array length. */ -	prop = property_entry_get(props, propname); -	if (!prop) -		return -EINVAL; - -	if (prop->is_array) -		/* Find the length of an array. */ -		array_len = property_entry_count_elems_of_size(props, propname, -							  sizeof(const char *)); -	else -		/* The array length for a non-array string property is 1. */ -		array_len = 1; +	array_len = property_entry_count_elems_of_size(props, propname, +						       sizeof(const char *)); +	if (array_len < 0) +		return array_len;  	/* Return how many there are if strings is NULL. */  	if (!strings)  		return array_len; -	array_len = min(nval, array_len); +	array_len = min_t(size_t, nval, array_len);  	length = array_len * sizeof(*strings);  	pointer = property_entry_find(props, propname, length); @@ -322,13 +202,15 @@ static int property_entry_read_string_array(const struct property_entry *props,  static void property_entry_free_data(const struct property_entry *p)  {  	const void *pointer = property_get_pointer(p); +	const char * const *src_str;  	size_t i, nval;  	if (p->is_array) { -		if (p->type == DEV_PROP_STRING && p->pointer.str) { +		if (p->type == DEV_PROP_STRING && p->pointer) { +			src_str = p->pointer;  			nval = p->length / sizeof(const char *);  			for (i = 0; i < nval; i++) -				kfree(p->pointer.str[i]); +				kfree(src_str[i]);  		}  		kfree(pointer);  	} else if (p->type == DEV_PROP_STRING) { @@ -337,29 +219,29 @@ static void property_entry_free_data(const struct property_entry *p)  	kfree(p->name);  } -static int property_copy_string_array(struct property_entry *dst, -				      const struct property_entry *src) +static const char * const * +property_copy_string_array(const struct property_entry *src)  {  	const char **d; +	const char * const *src_str = src->pointer;  	size_t nval = src->length / sizeof(*d);  	int i;  	d = kcalloc(nval, sizeof(*d), GFP_KERNEL);  	if (!d) -		return -ENOMEM; +		return NULL;  	for (i = 0; i < nval; i++) { -		d[i] = kstrdup(src->pointer.str[i], GFP_KERNEL); -		if (!d[i] && src->pointer.str[i]) { +		d[i] = kstrdup(src_str[i], GFP_KERNEL); +		if (!d[i] && src_str[i]) {  			while (--i >= 0)  				kfree(d[i]);  			kfree(d); -			return -ENOMEM; +			return NULL;  		}  	} -	dst->pointer.str = d; -	return 0; +	return d;  }  static int property_entry_copy_data(struct property_entry *dst, @@ -367,36 +249,35 @@ static int property_entry_copy_data(struct property_entry *dst,  {  	const void *pointer = property_get_pointer(src);  	const void *new; -	int error;  	if (src->is_array) {  		if (!src->length)  			return -ENODATA;  		if (src->type == DEV_PROP_STRING) { -			error = property_copy_string_array(dst, src); -			if (error) -				return error; -			new = dst->pointer.str; +			new = property_copy_string_array(src); +			if (!new) +				return -ENOMEM;  		} else {  			new = kmemdup(pointer, src->length, GFP_KERNEL);  			if (!new)  				return -ENOMEM;  		} + +		dst->is_array = true; +		dst->pointer = new;  	} else if (src->type == DEV_PROP_STRING) {  		new = kstrdup(src->value.str, GFP_KERNEL);  		if (!new && src->value.str)  			return -ENOMEM; + +		dst->value.str = new;  	} else { -		new = pointer; +		dst->value = src->value;  	}  	dst->length = src->length; -	dst->is_array = src->is_array;  	dst->type = src->type; - -	property_set_pointer(dst, new); -  	dst->name = kstrdup(src->name, GFP_KERNEL);  	if (!dst->name)  		goto out_free_data; @@ -515,12 +396,47 @@ static int software_node_read_string_array(const struct fwnode_handle *fwnode,  						propname, val, nval);  } +static const char * +software_node_get_name(const struct fwnode_handle *fwnode) +{ +	const struct swnode *swnode = to_swnode(fwnode); + +	if (!swnode) +		return "(null)"; + +	return kobject_name(&swnode->kobj); +} + +static const char * +software_node_get_name_prefix(const struct fwnode_handle *fwnode) +{ +	struct fwnode_handle *parent; +	const char *prefix; + +	parent = fwnode_get_parent(fwnode); +	if (!parent) +		return ""; + +	/* Figure out the prefix from the parents. */ +	while (is_software_node(parent)) +		parent = fwnode_get_next_parent(parent); + +	prefix = fwnode_get_name_prefix(parent); +	fwnode_handle_put(parent); + +	/* Guess something if prefix was NULL. */ +	return prefix ?: "/"; +} +  static struct fwnode_handle *  software_node_get_parent(const struct fwnode_handle *fwnode)  {  	struct swnode *swnode = to_swnode(fwnode); -	return swnode ? (swnode->parent ? &swnode->parent->fwnode : NULL) : NULL; +	if (!swnode || !swnode->parent) +		return NULL; + +	return fwnode_handle_get(&swnode->parent->fwnode);  }  static struct fwnode_handle * @@ -612,6 +528,8 @@ static const struct fwnode_operations software_node_ops = {  	.property_present = software_node_property_present,  	.property_read_int_array = software_node_read_int_array,  	.property_read_string_array = software_node_read_string_array, +	.get_name = software_node_get_name, +	.get_name_prefix = software_node_get_name_prefix,  	.get_parent = software_node_get_parent,  	.get_next_child_node = software_node_get_next_child,  	.get_named_child_node = software_node_get_named_child_node,  |