remoteproc: use rsc_table_for_each_entry() in rproc_handle_resources()

Replace the open-coded resource table iteration loop in
rproc_handle_resources() with the rsc_table_for_each_entry() helper.

The remoteproc-specific dispatch logic (vendor resource handling via
rproc_handle_rsc(), RSC_LAST bounds check, handler table lookup) is
moved into a local callback rproc_handle_rsc_entry(), keeping the
iteration mechanics in one canonical place.

The callback receives the payload offset within the table so that
handlers which write back into the resource table (e.g.
rproc_handle_carveout() recording a dynamically allocated address via
rsc_offset) continue to work correctly.

No functional change.

Signed-off-by: Mukesh Ojha <mukesh.ojha@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260506050107.1985033-3-mukesh.ojha@oss.qualcomm.com
This commit is contained in:
Mukesh Ojha 2026-05-06 10:31:04 +05:30 committed by Mathieu Poirier
parent 0590420c2f
commit 49abb5d6e1
2 changed files with 94 additions and 46 deletions

View File

@ -1011,60 +1011,55 @@ static rproc_handle_resource_t rproc_loading_handlers[RSC_LAST] = {
[RSC_VDEV] = rproc_handle_vdev,
};
struct rproc_rsc_cb_data {
struct rproc *rproc;
rproc_handle_resource_t *handlers;
};
static int rproc_handle_rsc_entry(u32 type, void *rsc, int offset,
int avail, void *data)
{
struct rproc_rsc_cb_data *d = data;
struct rproc *rproc = d->rproc;
struct device *dev = &rproc->dev;
rproc_handle_resource_t handler;
int ret;
dev_dbg(dev, "rsc: type %d\n", type);
if (type >= RSC_VENDOR_START && type <= RSC_VENDOR_END) {
ret = rproc_handle_rsc(rproc, type, rsc, offset, avail);
if (ret == RSC_HANDLED)
return 0;
if (ret < 0)
return ret;
dev_warn(dev, "unsupported vendor resource %d\n", type);
return 0;
}
if (type >= RSC_LAST) {
dev_warn(dev, "unsupported resource %d\n", type);
return 0;
}
handler = d->handlers[type];
if (!handler)
return 0;
return handler(rproc, rsc, offset, avail);
}
/* handle firmware resource entries before booting the remote processor */
static int rproc_handle_resources(struct rproc *rproc,
rproc_handle_resource_t handlers[RSC_LAST])
{
struct device *dev = &rproc->dev;
rproc_handle_resource_t handler;
int ret = 0, i;
struct rproc_rsc_cb_data d = { .rproc = rproc, .handlers = handlers };
if (!rproc->table_ptr)
return 0;
for (i = 0; i < rproc->table_ptr->num; i++) {
int offset = rproc->table_ptr->offset[i];
struct fw_rsc_hdr *hdr = (void *)rproc->table_ptr + offset;
int avail = rproc->table_sz - offset - sizeof(*hdr);
void *rsc = (void *)hdr + sizeof(*hdr);
/* make sure table isn't truncated */
if (avail < 0) {
dev_err(dev, "rsc table is truncated\n");
return -EINVAL;
}
dev_dbg(dev, "rsc: type %d\n", hdr->type);
if (hdr->type >= RSC_VENDOR_START &&
hdr->type <= RSC_VENDOR_END) {
ret = rproc_handle_rsc(rproc, hdr->type, rsc,
offset + sizeof(*hdr), avail);
if (ret == RSC_HANDLED)
continue;
else if (ret < 0)
break;
dev_warn(dev, "unsupported vendor resource %d\n",
hdr->type);
continue;
}
if (hdr->type >= RSC_LAST) {
dev_warn(dev, "unsupported resource %d\n", hdr->type);
continue;
}
handler = handlers[hdr->type];
if (!handler)
continue;
ret = handler(rproc, rsc, offset + sizeof(*hdr), avail);
if (ret)
break;
}
return ret;
return rsc_table_for_each_entry(rproc->table_ptr, rproc->table_sz,
&rproc->dev, rproc_handle_rsc_entry, &d);
}
static int rproc_prepare_subdevices(struct rproc *rproc)

View File

@ -303,4 +303,57 @@ struct fw_rsc_vdev {
struct fw_rsc_vdev_vring vring[];
} __packed;
/**
* rsc_table_for_each_entry() - iterate over all entries in a resource table
* @table: pointer to the resource table
* @table_sz: total size of the table buffer in bytes
* @dev: device used for error logging
* @cb: callback invoked for each entry:
* @type - value from enum fw_resource_type
* @rsc - pointer to the entry payload (past struct fw_rsc_hdr)
* @offset - byte offset of the payload within the table; callers
* that write back into the table (e.g. to record a
* dynamically allocated address) use this to locate the
* entry for later update
* @avail - bytes available in the payload
* @data - caller-supplied private pointer
* Return 0 to continue iteration, non-zero to stop.
* @data: private pointer forwarded to @cb on every call
*
* Iterates over every resource entry in @table, performing the standard
* truncation check, and invokes @cb for each one. Iteration stops on the
* first non-zero return from @cb or on a malformed table.
*
* Returns 0 after a complete iteration, -EINVAL if the table is truncated,
* or the first non-zero value returned by @cb.
*/
static inline int rsc_table_for_each_entry(struct resource_table *table,
size_t table_sz,
struct device *dev,
int (*cb)(u32 type, void *rsc,
int offset, int avail,
void *data),
void *data) {
int i, ret;
for (i = 0; i < table->num; i++) {
int offset = table->offset[i];
struct fw_rsc_hdr *hdr = (void *)table + offset;
int avail = table_sz - offset - sizeof(*hdr);
int rsc_offset = offset + sizeof(*hdr);
void *rsc = (void *)hdr + sizeof(*hdr);
if (avail < 0) {
dev_err(dev, "rsc table is truncated\n");
return -EINVAL;
}
ret = cb(hdr->type, rsc, rsc_offset, avail, data);
if (ret)
return ret;
}
return 0;
}
#endif /* RSC_TABLE_H */