* [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic
@ 2026-10-26 10:09 Uwe Kleine-König
2026-10-26 10:09 ` [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu Uwe Kleine-König
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Uwe Kleine-König @ 2026-10-26 10:09 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: Wolfram Sang, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-remoteproc, imx, linux-arm-kernel,
linux-kernel
Hello,
I'm currently working on remoteproc for ADI's ADSP SoC family (SC598 +
SC846 and others). On at least SC846 the memory of the remote processor
isn't directly accessible by the main cpu. (The memory is mapped into
the cpu's memory space, but cannot be accessed directly from non-secure
EL2.)
Instead of creating another near-copy of rproc_elf_load_segments() that
just differs by the memory access functions, generalize this function
and make the driver that already has such a copy benefit from it.
This is only compile tested.
Uwe Kleine-König (2):
remoteproc: elf_loader: Create new callback for copying segments to
remote cpu
remoteproc: imx_dsp_rproc: Implement .memcpy_tova()
drivers/remoteproc/imx_dsp_rproc.c | 120 ++++++---------------
drivers/remoteproc/remoteproc_elf_loader.c | 63 ++++++-----
include/linux/remoteproc.h | 3 +
3 files changed, 69 insertions(+), 117 deletions(-)
base-commit: bd1ecbb61afefc6a8b876ccbc31e9228b44e9eab
--
2.47.3
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu
2026-10-26 10:09 [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Uwe Kleine-König
@ 2026-10-26 10:09 ` Uwe Kleine-König
2026-10-27 2:58 ` Peng Fan
2026-10-26 10:09 ` [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova() Uwe Kleine-König
2026-10-27 15:55 ` [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Mathieu Poirier
2 siblings, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2026-10-26 10:09 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: Wolfram Sang, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-remoteproc, imx, linux-arm-kernel,
linux-kernel
Some devices have special needs about how an Elf segment is copied to
the remote cpu's memory space where the default implementation using
memcpy_toio/memcpy and memset_io/memset isn't suitable. An affected
mainline driver is imx-dsp-rproc which includes a near-copy of
rproc_elf_load_segments() just to handle the IRAM only allowing 32 bit
accesses. On (not-yet-mainline) ADI SC846 the respective memory isn't
directly accessible at all and DMA must be used to copy the data.
The new callback can be used to implement just the driver specific
memcpy + memset to increase code reuse.
The patch only appears big because of indentation changes.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/remoteproc/remoteproc_elf_loader.c | 63 ++++++++++++----------
include/linux/remoteproc.h | 3 ++
2 files changed, 39 insertions(+), 27 deletions(-)
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index da3cddbe7d4c..0698bba2db89 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -227,35 +227,44 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
break;
}
- /* grab the kernel address for this device address */
- ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem);
- if (!ptr) {
- dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
- memsz);
- ret = -EINVAL;
- break;
- }
+ if (rproc->ops->memcpy_tova) {
+ ret = rproc->ops->memcpy_tova(rproc, da, elf_data + offset, filesz, memsz);
+ if (ret) {
+ dev_err(dev, "Failed to copy segment %d to device addres 0x%llx: %pe\n",
+ i, da, ERR_PTR(ret));
+ break;
+ }
+ } else {
+ /* grab the kernel address for this device address */
+ ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem);
+ if (!ptr) {
+ dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
+ memsz);
+ ret = -EINVAL;
+ break;
+ }
- /* put the segment where the remote processor expects it */
- if (filesz) {
- if (is_iomem)
- memcpy_toio((void __iomem *)ptr, elf_data + offset, filesz);
- else
- memcpy(ptr, elf_data + offset, filesz);
- }
+ /* put the segment where the remote processor expects it */
+ if (filesz) {
+ if (is_iomem)
+ memcpy_toio((void __iomem *)ptr, elf_data + offset, filesz);
+ else
+ memcpy(ptr, elf_data + offset, filesz);
+ }
- /*
- * Zero out remaining memory for this segment.
- *
- * This isn't strictly required since dma_alloc_coherent already
- * did this for us. albeit harmless, we may consider removing
- * this.
- */
- if (memsz > filesz) {
- if (is_iomem)
- memset_io((void __iomem *)(ptr + filesz), 0, memsz - filesz);
- else
- memset(ptr + filesz, 0, memsz - filesz);
+ /*
+ * Zero out remaining memory for this segment.
+ *
+ * This isn't strictly required since dma_alloc_coherent already
+ * did this for us. albeit harmless, we may consider removing
+ * this.
+ */
+ if (memsz > filesz) {
+ if (is_iomem)
+ memset_io((void __iomem *)(ptr + filesz), 0, memsz - filesz);
+ else
+ memset(ptr + filesz, 0, memsz - filesz);
+ }
}
}
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 00019b1895e6..ffa22c2f04af 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -75,6 +75,7 @@ enum rsc_handling_status {
* @detach: detach from a device, leaving it powered up
* @kick: kick a virtqueue (virtqueue id given as a parameter)
* @da_to_va: optional platform hook to perform address translations
+ * @memcpy_tova:optional platform hook to copy data into remote memory range
* @parse_fw: parse firmware to extract information (e.g. resource table)
* @handle_rsc: optional platform hook to handle vendor resources. Should return
* RSC_HANDLED if resource was handled, RSC_IGNORED if not handled
@@ -99,6 +100,8 @@ struct rproc_ops {
int (*detach)(struct rproc *rproc);
void (*kick)(struct rproc *rproc, int vqid);
void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
+ int (*memcpy_tova)(struct rproc *rproc, u64 da, const void *src, size_t filesz, size_t memsz);
+
int (*parse_fw)(struct rproc *rproc, const struct firmware *fw);
int (*handle_rsc)(struct rproc *rproc, u32 rsc_type, void *rsc,
int offset, int avail);
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova()
2026-10-26 10:09 [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Uwe Kleine-König
2026-10-26 10:09 ` [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu Uwe Kleine-König
@ 2026-10-26 10:09 ` Uwe Kleine-König
2026-10-27 2:58 ` Peng Fan
2026-10-27 15:55 ` [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Mathieu Poirier
2 siblings, 1 reply; 6+ messages in thread
From: Uwe Kleine-König @ 2026-10-26 10:09 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier
Cc: Wolfram Sang, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, linux-remoteproc, imx, linux-arm-kernel,
linux-kernel
This callback allows to use the core's rproc_elf_load_segments()
function instead of reimplementing it for very minor changes.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
---
drivers/remoteproc/imx_dsp_rproc.c | 120 ++++++++---------------------
1 file changed, 30 insertions(+), 90 deletions(-)
diff --git a/drivers/remoteproc/imx_dsp_rproc.c b/drivers/remoteproc/imx_dsp_rproc.c
index 96d619daf3f5..324c10f18507 100644
--- a/drivers/remoteproc/imx_dsp_rproc.c
+++ b/drivers/remoteproc/imx_dsp_rproc.c
@@ -864,97 +864,41 @@ static int imx_dsp_rproc_memset(void *addr, u8 value, size_t size)
return 0;
}
-/*
- * imx_dsp_rproc_elf_load_segments() - load firmware segments to memory
- * @rproc: remote processor which will be booted using these fw segments
- * @fw: the ELF firmware image
- *
- * This function loads the firmware segments to memory, where the remote
- * processor expects them.
- *
- * Return: 0 on success and an appropriate error code otherwise
- */
-static int imx_dsp_rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
+static int imx_dsp_rproc_memcpy_tova(struct rproc *rproc, u64 da, const void *src,
+ size_t filesz, size_t memsz)
{
struct device *dev = &rproc->dev;
- const void *ehdr, *phdr;
- int i, ret = 0;
- u16 phnum;
- const u8 *elf_data = fw->data;
- u8 class = fw_elf_get_class(fw);
- u32 elf_phdr_get_size = elf_size_of_phdr(class);
+ void *ptr;
+ int ret;
- ehdr = elf_data;
- phnum = elf_hdr_get_e_phnum(class, ehdr);
- phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr);
+ /* grab the kernel address for this device address */
+ ptr = rproc_da_to_va(rproc, da, memsz, NULL);
+ if (!ptr) {
+ dev_err(dev, "bad phdr da 0x%llx mem 0x%zx\n", da, memsz);
+ return -EINVAL;
+ }
- /* go through the available ELF segments */
- for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) {
- u64 da = elf_phdr_get_p_paddr(class, phdr);
- u64 memsz = elf_phdr_get_p_memsz(class, phdr);
- u64 filesz = elf_phdr_get_p_filesz(class, phdr);
- u64 offset = elf_phdr_get_p_offset(class, phdr);
- u32 type = elf_phdr_get_p_type(class, phdr);
- void *ptr;
-
- if (type != PT_LOAD || !memsz)
- continue;
-
- dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
- type, da, memsz, filesz);
-
- if (filesz > memsz) {
- dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
- filesz, memsz);
- ret = -EINVAL;
- break;
- }
-
- if (offset + filesz > fw->size) {
- dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
- offset + filesz, fw->size);
- ret = -EINVAL;
- break;
- }
-
- if (!rproc_u64_fit_in_size_t(memsz)) {
- dev_err(dev, "size (%llx) does not fit in size_t type\n",
- memsz);
- ret = -EOVERFLOW;
- break;
- }
-
- /* grab the kernel address for this device address */
- ptr = rproc_da_to_va(rproc, da, memsz, NULL);
- if (!ptr) {
- dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
- memsz);
- ret = -EINVAL;
- break;
- }
-
- /* put the segment where the remote processor expects it */
- if (filesz) {
- ret = imx_dsp_rproc_memcpy(ptr, elf_data + offset, filesz);
- if (ret) {
- dev_err(dev, "memory copy failed for da 0x%llx memsz 0x%llx\n",
- da, memsz);
- break;
- }
- }
-
- /* zero out remaining memory for this segment */
- if (memsz > filesz) {
- ret = imx_dsp_rproc_memset(ptr + filesz, 0, memsz - filesz);
- if (ret) {
- dev_err(dev, "memset failed for da 0x%llx memsz 0x%llx\n",
- da, memsz);
- break;
- }
+ /* put the segment where the remote processor expects it */
+ if (filesz) {
+ ret = imx_dsp_rproc_memcpy(ptr, src, filesz);
+ if (ret) {
+ dev_err(dev, "memory copy failed for da 0x%llx memsz 0x%zx\n",
+ da, memsz);
+ return ret;
}
}
- return ret;
+ /* zero out remaining memory for this segment */
+ if (memsz > filesz) {
+ ret = imx_dsp_rproc_memset(ptr + filesz, 0, memsz - filesz);
+ if (ret) {
+ dev_err(dev, "memset failed for da 0x%llx memsz 0x%zx\n",
+ da, memsz);
+ return ret;
+ }
+ }
+
+ return 0;
}
static int imx_dsp_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
@@ -969,7 +913,6 @@ static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw)
struct imx_dsp_rproc *priv = rproc->priv;
const struct imx_dsp_rproc_dcfg *dsp_dcfg = priv->dsp_dcfg;
struct rproc_mem_entry *carveout;
- int ret;
/* Reset DSP if needed */
if (dsp_dcfg->reset)
@@ -985,11 +928,7 @@ static int imx_dsp_rproc_load(struct rproc *rproc, const struct firmware *fw)
}
}
- ret = imx_dsp_rproc_elf_load_segments(rproc, fw);
- if (ret)
- return ret;
-
- return 0;
+ return rproc_elf_load_segments(rproc, fw);
}
static const struct rproc_ops imx_dsp_rproc_ops = {
@@ -998,6 +937,7 @@ static const struct rproc_ops imx_dsp_rproc_ops = {
.start = imx_dsp_rproc_start,
.stop = imx_dsp_rproc_stop,
.kick = imx_dsp_rproc_kick,
+ .memcpy_tova = imx_dsp_rproc_memcpy_tova,
.load = imx_dsp_rproc_load,
.parse_fw = imx_dsp_rproc_parse_fw,
.handle_rsc = imx_dsp_rproc_handle_rsc,
--
2.47.3
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu
2026-10-26 10:09 ` [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu Uwe Kleine-König
@ 2026-10-27 2:58 ` Peng Fan
0 siblings, 0 replies; 6+ messages in thread
From: Peng Fan @ 2026-10-27 2:58 UTC (permalink / raw)
To: Uwe Kleine-K??nig
Cc: Bjorn Andersson, Mathieu Poirier, Wolfram Sang, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
linux-remoteproc, imx, linux-arm-kernel, linux-kernel
On Mon, Oct 26, 2026 at 11:09:30AM +0100, Uwe Kleine-K??nig wrote:
>Some devices have special needs about how an Elf segment is copied to
>the remote cpu's memory space where the default implementation using
>memcpy_toio/memcpy and memset_io/memset isn't suitable. An affected
>mainline driver is imx-dsp-rproc which includes a near-copy of
>rproc_elf_load_segments() just to handle the IRAM only allowing 32 bit
>accesses. On (not-yet-mainline) ADI SC846 the respective memory isn't
>directly accessible at all and DMA must be used to copy the data.
>
>The new callback can be used to implement just the driver specific
>memcpy + memset to increase code reuse.
>
>The patch only appears big because of indentation changes.
>
>Signed-off-by: Uwe Kleine-K??nig <u.kleine-koenig@baylibre.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova()
2026-10-26 10:09 ` [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova() Uwe Kleine-König
@ 2026-10-27 2:58 ` Peng Fan
0 siblings, 0 replies; 6+ messages in thread
From: Peng Fan @ 2026-10-27 2:58 UTC (permalink / raw)
To: Uwe Kleine-K??nig
Cc: Bjorn Andersson, Mathieu Poirier, Wolfram Sang, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
linux-remoteproc, imx, linux-arm-kernel, linux-kernel
On Mon, Oct 26, 2026 at 11:09:31AM +0100, Uwe Kleine-K??nig wrote:
>This callback allows to use the core's rproc_elf_load_segments()
>function instead of reimplementing it for very minor changes.
>
>Signed-off-by: Uwe Kleine-K??nig <u.kleine-koenig@baylibre.com>
Reviewed-by: Peng Fan <peng.fan@nxp.com>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic
2026-10-26 10:09 [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Uwe Kleine-König
2026-10-26 10:09 ` [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu Uwe Kleine-König
2026-10-26 10:09 ` [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova() Uwe Kleine-König
@ 2026-10-27 15:55 ` Mathieu Poirier
2 siblings, 0 replies; 6+ messages in thread
From: Mathieu Poirier @ 2026-10-27 15:55 UTC (permalink / raw)
To: Uwe Kleine-König
Cc: Bjorn Andersson, Wolfram Sang, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, linux-remoteproc, imx,
linux-arm-kernel, linux-kernel
On Mon, Oct 26, 2026 at 11:09:29AM +0100, Uwe Kleine-König wrote:
> Hello,
>
> I'm currently working on remoteproc for ADI's ADSP SoC family (SC598 +
> SC846 and others). On at least SC846 the memory of the remote processor
> isn't directly accessible by the main cpu. (The memory is mapped into
> the cpu's memory space, but cannot be accessed directly from non-secure
> EL2.)
>
> Instead of creating another near-copy of rproc_elf_load_segments() that
> just differs by the memory access functions, generalize this function
> and make the driver that already has such a copy benefit from it.
>
> This is only compile tested.
>
> Uwe Kleine-König (2):
> remoteproc: elf_loader: Create new callback for copying segments to
> remote cpu
> remoteproc: imx_dsp_rproc: Implement .memcpy_tova()
>
> drivers/remoteproc/imx_dsp_rproc.c | 120 ++++++---------------
> drivers/remoteproc/remoteproc_elf_loader.c | 63 ++++++-----
> include/linux/remoteproc.h | 3 +
> 3 files changed, 69 insertions(+), 117 deletions(-)
>
$ ./scripts/checkpatch.pl *.patch
----------------------------------------------------------------------------
_PATCH_1-2_remoteproc_elf_loader_Create_new_callback_for_copying_segme.patch
----------------------------------------------------------------------------
WARNING: 'addres' may be misspelled - perhaps 'address'?
#56: FILE: drivers/remoteproc/remoteproc_elf_loader.c:233:
+ dev_err(dev, "Failed to copy segment %d to device addres 0x%llx: %pe\n",
^^^^^^
WARNING: line length of 101 exceeds 100 columns
#106: FILE: drivers/remoteproc/remoteproc_elf_loader.c:264:
+ memset_io((void __iomem *)(ptr + filesz), 0, memsz - filesz);
WARNING: line length of 102 exceeds 100 columns
#129: FILE: include/linux/remoteproc.h:103:
+ int (*memcpy_tova)(struct rproc *rproc, u64 da, const void *src, size_t filesz, size_t memsz);
total: 0 errors, 3 warnings, 86 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
_PATCH_1-2_remoteproc_elf_loader_Create_new_callback_for_copying_segme.patch has style problems, please review.
-----------------------------------------------------------------
_PATCH_2-2_remoteproc_imx_dsp_rproc_Implement_.memcpy_tova_.patch
-----------------------------------------------------------------
total: 0 errors, 0 warnings, 151 lines checked
_PATCH_2-2_remoteproc_imx_dsp_rproc_Implement_.memcpy_tova_.patch has no obvious style problems and is ready for submission.
>
> base-commit: bd1ecbb61afefc6a8b876ccbc31e9228b44e9eab
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-27 15:55 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26 10:09 [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Uwe Kleine-König
2026-10-26 10:09 ` [PATCH 1/2] remoteproc: elf_loader: Create new callback for copying segments to remote cpu Uwe Kleine-König
2026-10-27 2:58 ` Peng Fan
2026-10-26 10:09 ` [PATCH 2/2] remoteproc: imx_dsp_rproc: Implement .memcpy_tova() Uwe Kleine-König
2026-10-27 2:58 ` Peng Fan
2026-10-27 15:55 ` [PATCH 0/2] remoteproc: elf_loader: Make rproc_elf_load_segments() more generic Mathieu Poirier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox