[PATCH v17 01/12] power: reset: reboot-mode: Remove devres based allocations

Shivendra Pratap
2025-11-09T14:38:30Z

Devres APIs are intended for use in drivers, and they should be
avoided in shared subsystem code which is being used by multiple
drivers. Avoid using devres based allocations in the reboot-mode
subsystem and manually free the resources.

Replace devm_kzalloc with kzalloc and handle memory cleanup
explicitly.

Fixes: 4fcd504edbf7 ("power: reset: add reboot mode driver")
Signed-off-by: Shivendra Pratap <shivendra.pratap@oss.qualcomm.com>
---
drivers/power/reset/reboot-mode.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/power/reset/reboot-mode.c b/drivers/power/reset/reboot-mode.c
index fba53f638da04655e756b5f8b7d2d666d1379535..ac4223794083f36960b2bd37a601b7e1f1872de5 100644
--- a/drivers/power/reset/reboot-mode.c
+++ b/drivers/power/reset/reboot-mode.c
@@ -3,6 +3,8 @@
* Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
*/

+#define pr_fmt(fmt) "reboot-mode: " fmt
+
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -71,6 +73,7 @@ static int reboot_mode_notify(struct notifier_block *this,
int reboot_mode_register(struct reboot_mode_driver *reboot)
{
struct mode_info *info;
+ struct mode_info *next;
struct property *prop;
struct device_node *np = reboot->dev->of_node;
size_t len = strlen(PREFIX);
@@ -82,29 +85,27 @@ int reboot_mode_register(struct reboot_mode_driver *reboot)
if (strncmp(prop->name, PREFIX, len))
continue;

- info = devm_kzalloc(reboot->dev, sizeof(*info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
ret = -ENOMEM;
goto error;
}

if (of_property_read_u32(np, prop->name, &info->magic)) {
- dev_err(reboot->dev, "reboot mode %s without magic number\n",
- info->mode);
- devm_kfree(reboot->dev, info);
+ pr_err("reboot mode %s without magic number\n", info->mode);
+ kfree(info);
continue;
}

info->mode = kstrdup_const(prop->name + len, GFP_KERNEL);
if (!info->mode) {
ret = -ENOMEM;
- goto error;
+ goto err_info;
} else if (info->mode[0] == '\0') {
kfree_const(info->mode);
ret = -EINVAL;
- dev_err(reboot->dev, "invalid mode name(%s): too short!\n",
- prop->name);
- goto error;
+ pr_err("invalid mode name(%s): too short!\n", prop->name);
+ goto err_info;
}

list_add_tail(&info->list, &reboot->head);
@@ -115,9 +116,14 @@ int reboot_mode_register(struct reboot_mode_driver *reboot)

return 0;

+err_info:
+ kfree(info);
error:
- list_for_each_entry(info, &reboot->head, list)
+ list_for_each_entry_safe(info, next, &reboot->head, list) {
+ list_del(&info->list);
kfree_const(info->mode);
+ kfree(info);
+ }

return ret;
}
@@ -130,11 +136,15 @@ EXPORT_SYMBOL_GPL(reboot_mode_register);
int reboot_mode_unregister(struct reboot_mode_driver *reboot)
{
struct mode_info *info;
+ struct mode_info *next;

unregister_reboot_notifier(&reboot->reboot_notifier);

- list_for_each_entry(info, &reboot->head, list)
+ list_for_each_entry_safe(info, next, &reboot->head, list) {
+ list_del(&info->list);
kfree_const(info->mode);
+ kfree(info);
+ }

return 0;
}

--
2.34.1