Commit 50030d63 authored by Bartosz Golaszewski's avatar Bartosz Golaszewski Committed by Danilo Krummrich
Browse files

driver core: platform: remove software node on release()



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
additionally 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: 0fc434bc ("driver core: platform: allow attaching software nodes when creating devices")
Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260513-swnode-remove-on-dev-unreg-v6-1-f9c58939df27@oss.qualcomm.com


Signed-off-by: default avatarDanilo Krummrich <dakr@kernel.org>
parent 254f4963
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -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);