Commit 3f6b6536 authored by Andy Shevchenko's avatar Andy Shevchenko Committed by Greg Kroah-Hartman

software node: Free resources explicitly when swnode_register() fails

Currently we have a slightly twisted logic in swnode_register().
It frees resources that it doesn't allocate on error path and
in once case it relies on the ->release() implementation.

Untwist the logic by freeing resources explicitly when swnode_register()
fails. Currently it happens only in fwnode_create_software_node().
Tested-by: default avatarDaniel Scally <djrscally@gmail.com>
Reviewed-by: default avatarDaniel Scally <djrscally@gmail.com>
Reviewed-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20210329151207.36619-1-andriy.shevchenko@linux.intel.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c8a9c285
...@@ -767,22 +767,19 @@ swnode_register(const struct software_node *node, struct swnode *parent, ...@@ -767,22 +767,19 @@ swnode_register(const struct software_node *node, struct swnode *parent,
int ret; int ret;
swnode = kzalloc(sizeof(*swnode), GFP_KERNEL); swnode = kzalloc(sizeof(*swnode), GFP_KERNEL);
if (!swnode) { if (!swnode)
ret = -ENOMEM; return ERR_PTR(-ENOMEM);
goto out_err;
}
ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids, ret = ida_simple_get(parent ? &parent->child_ids : &swnode_root_ids,
0, 0, GFP_KERNEL); 0, 0, GFP_KERNEL);
if (ret < 0) { if (ret < 0) {
kfree(swnode); kfree(swnode);
goto out_err; return ERR_PTR(ret);
} }
swnode->id = ret; swnode->id = ret;
swnode->node = node; swnode->node = node;
swnode->parent = parent; swnode->parent = parent;
swnode->allocated = allocated;
swnode->kobj.kset = swnode_kset; swnode->kobj.kset = swnode_kset;
fwnode_init(&swnode->fwnode, &software_node_ops); fwnode_init(&swnode->fwnode, &software_node_ops);
...@@ -803,16 +800,17 @@ swnode_register(const struct software_node *node, struct swnode *parent, ...@@ -803,16 +800,17 @@ swnode_register(const struct software_node *node, struct swnode *parent,
return ERR_PTR(ret); return ERR_PTR(ret);
} }
/*
* Assign the flag only in the successful case, so
* the above kobject_put() won't mess up with properties.
*/
swnode->allocated = allocated;
if (parent) if (parent)
list_add_tail(&swnode->entry, &parent->children); list_add_tail(&swnode->entry, &parent->children);
kobject_uevent(&swnode->kobj, KOBJ_ADD); kobject_uevent(&swnode->kobj, KOBJ_ADD);
return &swnode->fwnode; return &swnode->fwnode;
out_err:
if (allocated)
property_entries_free(node->properties);
return ERR_PTR(ret);
} }
/** /**
...@@ -971,6 +969,7 @@ struct fwnode_handle * ...@@ -971,6 +969,7 @@ struct fwnode_handle *
fwnode_create_software_node(const struct property_entry *properties, fwnode_create_software_node(const struct property_entry *properties,
const struct fwnode_handle *parent) const struct fwnode_handle *parent)
{ {
struct fwnode_handle *fwnode;
struct software_node *node; struct software_node *node;
struct swnode *p = NULL; struct swnode *p = NULL;
int ret; int ret;
...@@ -995,7 +994,13 @@ fwnode_create_software_node(const struct property_entry *properties, ...@@ -995,7 +994,13 @@ fwnode_create_software_node(const struct property_entry *properties,
node->parent = p ? p->node : NULL; node->parent = p ? p->node : NULL;
return swnode_register(node, p, 1); fwnode = swnode_register(node, p, 1);
if (IS_ERR(fwnode)) {
property_entries_free(node->properties);
kfree(node);
}
return fwnode;
} }
EXPORT_SYMBOL_GPL(fwnode_create_software_node); EXPORT_SYMBOL_GPL(fwnode_create_software_node);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment