[PATCH v3 09/15] firmware: arm_scmi: Refactor iterators internal allocation

Cristian Marussi
2026-04-28T20:17:01Z

Use cleanup handlers to manage iterator data structures.

No functional change.

Reviewed-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
---
v2 --> v3
- collected Reviewed tags
---
drivers/firmware/arm_scmi/driver.c | 35 +++++++++++++++---------------
1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index f167194f7cf6..66cb64c8ed3d 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/bitmap.h>
+#include <linux/cleanup.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/export.h>
@@ -1789,39 +1790,41 @@ static void *scmi_iterator_init(const struct scmi_protocol_handle *ph,
size_t tx_size, void *priv)
{
int ret;
- struct scmi_iterator *i;

- i = devm_kzalloc(ph->dev, sizeof(*i), GFP_KERNEL);
+ struct scmi_iterator *i __free(kfree) = kzalloc(sizeof(*i), GFP_KERNEL);
if (!i)
return ERR_PTR(-ENOMEM);

+ if (!ops || !ph)
+ return ERR_PTR(-EINVAL);
+
i->ph = ph;
i->ops = ops;
i->priv = priv;

ret = ph->xops->xfer_get_init(ph, msg_id, tx_size, 0, &i->t);
- if (ret) {
- devm_kfree(ph->dev, i);
+ if (ret)
return ERR_PTR(ret);
- }

i->state.max_resources = max_resources;
i->msg = i->t->tx.buf;
i->resp = i->t->rx.buf;

- return i;
+ return no_free_ptr(i);
}

static int scmi_iterator_run(void *iter)
{
- int ret = -EINVAL;
+ int ret;
struct scmi_iterator_ops *iops;
const struct scmi_protocol_handle *ph;
struct scmi_iterator_state *st;
- struct scmi_iterator *i = iter;

- if (!i || !i->ops || !i->ph)
- return ret;
+ if (!iter)
+ return -EINVAL;
+
+ /* Take ownership of the iterator */
+ struct scmi_iterator *i __free(kfree) = iter;

iops = i->ops;
ph = i->ph;
@@ -1846,12 +1849,12 @@ static int scmi_iterator_run(void *iter)
break;
}

- for (st->loop_idx = 0; st->loop_idx < st->num_returned;
- st->loop_idx++) {
+ for (st->loop_idx = 0; !ret && st->loop_idx < st->num_returned;
+ st->loop_idx++)
ret = iops->process_response(ph, i->resp, st, i->priv);
- if (ret)
- goto out;
- }
+
+ if (ret)
+ break;

st->desc_index += st->num_returned;
ph->xops->reset_rx_to_maxsz(ph, i->t);
@@ -1861,10 +1864,8 @@ static int scmi_iterator_run(void *iter)
*/
} while (st->num_returned && st->num_remaining);

-out:
/* Finalize and destroy iterator */
ph->xops->xfer_put(ph, i->t);
- devm_kfree(ph->dev, i);

return ret;
}
--
2.53.0