software node: implement reference properties

It is possible to store references to software nodes in the same fashion as
other static properties, so that users do not need to define separate
structures:

static const struct software_node gpio_bank_b_node = {
	.name = "B",
};

static const struct property_entry simone_key_enter_props[] = {
	PROPERTY_ENTRY_U32("linux,code", KEY_ENTER),
	PROPERTY_ENTRY_STRING("label", "enter"),
	PROPERTY_ENTRY_REF("gpios", &gpio_bank_b_node, 123, GPIO_ACTIVE_LOW),
	{ }
};

Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Dmitry Torokhov
2019-11-07 20:22:22 -08:00
committed by Rafael J. Wysocki
parent 996b0830f9
commit e64b674bc9
2 changed files with 82 additions and 24 deletions

View File

@@ -246,6 +246,13 @@ static int property_entry_copy_data(struct property_entry *dst,
if (!src->is_inline && !src->length)
return -ENODATA;
/*
* Reference properties are never stored inline as
* they are too big.
*/
if (src->type == DEV_PROP_REF && src->is_inline)
return -EINVAL;
if (src->length <= sizeof(dst->value)) {
dst_ptr = &dst->value;
dst->is_inline = true;
@@ -473,23 +480,49 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
{
struct swnode *swnode = to_swnode(fwnode);
const struct software_node_reference *ref;
const struct software_node_ref_args *ref_array;
const struct software_node_ref_args *ref_args;
const struct property_entry *prop;
struct fwnode_handle *refnode;
u32 nargs_prop_val;
int error;
int i;
if (!swnode || !swnode->node->references)
if (!swnode)
return -ENOENT;
for (ref = swnode->node->references; ref->name; ref++)
if (!strcmp(ref->name, propname))
break;
prop = property_entry_get(swnode->node->properties, propname);
if (prop) {
if (prop->type != DEV_PROP_REF)
return -EINVAL;
if (!ref->name || index > (ref->nrefs - 1))
return -ENOENT;
/*
* We expect that references are never stored inline, even
* single ones, as they are too big.
*/
if (prop->is_inline)
return -EINVAL;
refnode = software_node_fwnode(ref->refs[index].node);
if (index * sizeof(*ref_args) >= prop->length)
return -ENOENT;
ref_array = prop->pointer;
ref_args = &ref_array[index];
} else {
if (!swnode->node->references)
return -ENOENT;
for (ref = swnode->node->references; ref->name; ref++)
if (!strcmp(ref->name, propname))
break;
if (!ref->name || index > (ref->nrefs - 1))
return -ENOENT;
ref_args = &ref->refs[index];
}
refnode = software_node_fwnode(ref_args->node);
if (!refnode)
return -ENOENT;
@@ -510,7 +543,7 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
args->nargs = nargs;
for (i = 0; i < nargs; i++)
args->args[i] = ref->refs[index].args[i];
args->args[i] = ref_args->args[i];
return 0;
}