The software node added to the platform device in platform_device_register_full() is currently not removed on device release. In order to fix this, we need to first convert all drivers that use platform_device_alloc() and then assign a software node as the primary firmware node to using device_add_software_node() for correct reference counting.
To that end: provide platform_device_add_software_node() in line with other existing helpers like platform_device_add_data(). Signed-off-by: Bartosz Golaszewski <[email protected]> --- drivers/base/platform.c | 25 ++++++++++++++++++++++++- include/linux/platform_device.h | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 18f33bec36726490255bc7ca3c4ab07d9b7606b0..f617e02b171f6e59a3c40504a71f8915a41e8514 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -613,6 +613,10 @@ static void platform_device_release(struct device *dev) * * Create a platform device object which can have other objects attached * to it, and which will have attached objects freed when it is released. + * + * Note: devices allocated with this function must not have the following + * members assigned manually: swnode, resources and dev->platform_data. + * Please use the provided helper interfaces. */ struct platform_device *platform_device_alloc(const char *name, int id) { @@ -687,6 +691,25 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, } EXPORT_SYMBOL_GPL(platform_device_add_data); +/** + * platform_device_add_software_node - add a software node to a platform device + * @pdev: platform device allocated with platform_device_alloc() + * @swnode: software node to assign to this device, does not need to be registered + * + * If this device is already associated with a primary firmware node, add the + * software node as the secondary firmware node. Otherwise, make it the primary + * firmware node. Register the software node if needed. + * + * Returns: + * 0 on success, negative error number on failure. + */ +int platform_device_add_software_node(struct platform_device *pdev, + const struct software_node *swnode) +{ + return device_add_software_node(&pdev->dev, swnode); +} +EXPORT_SYMBOL_GPL(platform_device_add_software_node); + /** * platform_device_add - add a platform device to device hierarchy * @pdev: platform device we're adding @@ -881,7 +904,7 @@ struct platform_device *platform_device_register_full(const struct platform_devi goto err; if (pdevinfo->swnode) { - ret = device_add_software_node(&pdev->dev, pdevinfo->swnode); + ret = platform_device_add_software_node(pdev, pdevinfo->swnode); if (ret) goto err; } else if (pdevinfo->properties) { diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 975400a472e30e2f98cc8f13bc36a63129bd4fcf..bd421506e98fc293c97121693e4bd18b703e41fa 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -19,6 +19,7 @@ struct irq_affinity; struct mfd_cell; struct property_entry; struct platform_device_id; +struct software_node; struct platform_device { const char *name; @@ -262,6 +263,8 @@ extern int platform_device_add_resources(struct platform_device *pdev, unsigned int num); extern int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size); +int platform_device_add_software_node(struct platform_device *pdev, + const struct software_node *swnode); extern int platform_device_add(struct platform_device *pdev); extern void platform_device_del(struct platform_device *pdev); extern void platform_device_put(struct platform_device *pdev); -- 2.47.3

