If we pass a software node to a newly created device using struct
platform_device_info, it will not be removed when the device is
released. This may happen when a module creating the device is removed
or on failure in platform_device_add().
When we try to reuse that software node in a subsequent call to
platform_device_register_full(), it will fail with -EBUSY.
Provide a wrapper around the existing platform_device_release() that
additonally calls device_remove_software_node() and use it to replace
the former if we end up adding a software node.
While at it: check all three possible situations in which two software
nodes for a single platform device can be created/assigned in
platform_device_register_full() and bail-out early.
Fixes: 0fc434bc2c45 ("driver core: platform: allow attaching software nodes
when creating devices")
Signed-off-by: Bartosz Golaszewski <[email protected]>
---
drivers/base/platform.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index
75b4698d0e582e67adafa78c312d75c72fd654cf..a19dd22deef2f3edf7cddcf824d02b4e09091852
100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -606,6 +606,12 @@ static void platform_device_release(struct device *dev)
kfree(pa);
}
+static void platform_device_release_full(struct device *dev)
+{
+ device_remove_software_node(dev);
+ platform_device_release(dev);
+}
+
/**
* platform_device_alloc - create a platform device
* @name: base name of the device we're adding
@@ -848,7 +854,13 @@ struct platform_device
*platform_device_register_full(const struct platform_devi
int ret;
struct platform_device *pdev;
- if (pdevinfo->swnode && pdevinfo->properties)
+ /*
+ * Only one software node per device is allowed. Make sure we don't
+ * accept or create two.
+ */
+ if ((pdevinfo->swnode && pdevinfo->properties) ||
+ (pdevinfo->swnode && is_software_node(pdevinfo->fwnode)) ||
+ (pdevinfo->properties && is_software_node(pdevinfo->fwnode)))
return ERR_PTR(-EINVAL);
pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
@@ -878,6 +890,8 @@ struct platform_device *platform_device_register_full(const
struct platform_devi
ret = device_add_software_node(&pdev->dev, pdevinfo->swnode);
if (ret)
goto err;
+
+ pdev->dev.release = platform_device_release_full;
} else if (pdevinfo->properties) {
ret = device_create_managed_software_node(&pdev->dev,
pdevinfo->properties,
NULL);
--
2.47.3