[PATCH v7 1/5] remoteproc: core: Introduce rproc_pa_to_va helper
Mathieu Poirier
mathieu.poirier at linaro.org
Thu Jun 20 14:28:58 PDT 2024
On Tue, Jun 11, 2024 at 09:39:00AM +0200, Arnaud Pouliquen wrote:
> When a resource table is loaded by an external entity such as U-boot or
> OP-TEE, we do not necessary get the device address(da) but the physical
s/necessary/necessarily
> address(pa).
> This helper performs similar translation than the rproc_da_to_va()
> but based on a physical address.
>
> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen at foss.st.com>
> ---
> drivers/remoteproc/remoteproc_core.c | 74 +++++++++++++++++++++++++++-
> include/linux/remoteproc.h | 3 ++
> 2 files changed, 75 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index f276956f2c5c..3fdec0336fd6 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -230,6 +230,77 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
> }
> EXPORT_SYMBOL(rproc_da_to_va);
>
> +/**
> + * rproc_pa_to_va() - lookup the kernel virtual address for a physical address of a remoteproc
> + * memory
> + *
> + * @rproc: handle of a remote processor
> + * @pa: remoteproc physical address
> + * @len: length of the memory region @pa is pointing to
> + * @is_iomem: optional pointer filled in to indicate if @da is iomapped memory
> + *
> + * Some remote processors will ask us to allocate them physically contiguous
> + * memory regions (which we call "carveouts"), and map them to specific
> + * device addresses (which are hardcoded in the firmware). They may also have
> + * dedicated memory regions internal to the processors, and use them either
> + * exclusively or alongside carveouts.
> + *
> + * They may then ask us to copy objects into specific addresses (e.g.
> + * code/data sections) or expose us certain symbols in other device address
> + * (e.g. their trace buffer).
> + *
> + * This function is a helper function with which we can go over the allocated
> + * carveouts and translate specific physical addresses to kernel virtual addresses
> + * so we can access the referenced memory. This function also allows to perform
> + * translations on the internal remoteproc memory regions through a platform
> + * implementation specific pa_to_va ops, if present.
> + *
> + * Note: phys_to_virt(iommu_iova_to_phys(rproc->domain, da)) will work too,
> + * but only on kernel direct mapped RAM memory. Instead, we're just using
> + * here the output of the DMA API for the carveouts, which should be more
> + * correct.
No point in copying all this. Just say that it does the same thing as
rproc_da_to_va(), but with the PA address.
> + *
> + * Return: a valid kernel address on success or NULL on failure
> + */
> +void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem)
> +{
> + struct rproc_mem_entry *carveout;
> + void *ptr = NULL;
> +
> + if (rproc->ops->da_to_va) {
This is really wrong.
> + ptr = rproc->ops->pa_to_va(rproc, pa, len);
> + if (ptr)
> + goto out;
> + }
There is no current customer for ops::pa_to_va() so please remove.
Thanks,
Mathieu
> +
> + list_for_each_entry(carveout, &rproc->carveouts, node) {
> + int offset = pa - carveout->dma;
> +
> + /* Verify that carveout is allocated */
> + if (!carveout->va)
> + continue;
> +
> + /* try next carveout if da is too small */
> + if (offset < 0)
> + continue;
> +
> + /* try next carveout if da is too large */
> + if (offset + len > carveout->len)
> + continue;
> +
> + ptr = carveout->va + offset;
> +
> + if (is_iomem)
> + *is_iomem = carveout->is_iomem;
> +
> + break;
> + }
> +
> +out:
> + return ptr;
> +}
> +EXPORT_SYMBOL(rproc_pa_to_va);
> +
> /**
> * rproc_find_carveout_by_name() - lookup the carveout region by a name
> * @rproc: handle of a remote processor
> @@ -724,8 +795,7 @@ static int rproc_alloc_carveout(struct rproc *rproc,
> * firmware was compiled with.
> *
> * In this case, we must use the IOMMU API directly and map
> - * the memory to the device address as expected by the remote
> - * processor.
> + * the memory to the device address as etable
> *
> * Obviously such remote processor devices should not be configured
> * to use the iommu-based DMA API: we expect 'dma' to contain the
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index b4795698d8c2..28aa62a3b505 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -367,6 +367,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
> + * @pa_to_va: optional platform hook to perform address translations
> * @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
> @@ -391,6 +392,7 @@ 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);
> + void * (*pa_to_va)(struct rproc *rproc, phys_addr_t da, size_t len);
> 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);
> @@ -690,6 +692,7 @@ int rproc_detach(struct rproc *rproc);
> int rproc_set_firmware(struct rproc *rproc, const char *fw_name);
> void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
> void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
> +void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem);
>
> /* from remoteproc_coredump.c */
> void rproc_coredump_cleanup(struct rproc *rproc);
> --
> 2.25.1
>
More information about the linux-arm-kernel
mailing list