diff mbox series

[V5,2/8] remoteproc: add is_iomem to da_to_va

Message ID 20201229033019.25899-3-peng.fan@nxp.com (mailing list archive)
State Superseded
Headers show
Series remoteproc: imx_rproc: support iMX8MQ/M | expand

Commit Message

Peng Fan Dec. 29, 2020, 3:30 a.m. UTC
From: Peng Fan <peng.fan@nxp.com>

Introduce an extra parameter is_iomem to da_to_va, then the caller
could take the memory as normal memory or io mapped memory.

Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/remoteproc/imx_rproc.c             |  2 +-
 drivers/remoteproc/ingenic_rproc.c         |  2 +-
 drivers/remoteproc/keystone_remoteproc.c   |  2 +-
 drivers/remoteproc/mtk_scp.c               |  6 +++---
 drivers/remoteproc/omap_remoteproc.c       |  2 +-
 drivers/remoteproc/pru_rproc.c             |  2 +-
 drivers/remoteproc/qcom_q6v5_adsp.c        |  2 +-
 drivers/remoteproc/qcom_q6v5_pas.c         |  2 +-
 drivers/remoteproc/qcom_q6v5_wcss.c        |  2 +-
 drivers/remoteproc/qcom_wcnss.c            |  2 +-
 drivers/remoteproc/remoteproc_core.c       |  7 +++++--
 drivers/remoteproc/remoteproc_coredump.c   |  8 ++++++--
 drivers/remoteproc/remoteproc_debugfs.c    |  2 +-
 drivers/remoteproc/remoteproc_elf_loader.c | 21 +++++++++++++++------
 drivers/remoteproc/remoteproc_internal.h   |  2 +-
 drivers/remoteproc/st_slim_rproc.c         |  2 +-
 drivers/remoteproc/ti_k3_dsp_remoteproc.c  |  2 +-
 drivers/remoteproc/ti_k3_r5_remoteproc.c   |  2 +-
 drivers/remoteproc/wkup_m3_rproc.c         |  2 +-
 include/linux/remoteproc.h                 |  2 +-
 20 files changed, 45 insertions(+), 29 deletions(-)

Comments

kernel test robot Dec. 30, 2020, 3:14 p.m. UTC | #1
Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.11-rc1 next-20201223]
[cannot apply to soc/for-next xlnx/master remoteproc/for-next rpmsg/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/peng-fan-nxp-com/remoteproc-imx_rproc-support-iMX8MQ-M/20201229-110725
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git dea8dcf2a9fa8cc540136a6cd885c3beece16ec3
config: powerpc64-randconfig-s032-20201230 (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # apt-get install sparse
        # sparse version: v0.6.3-184-g1b896707-dirty
        # https://github.com/0day-ci/linux/commit/f2054bc05d3b183ef0b0ff0b4c802ba53680a5af
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review peng-fan-nxp-com/remoteproc-imx_rproc-support-iMX8MQ-M/20201229-110725
        git checkout f2054bc05d3b183ef0b0ff0b4c802ba53680a5af
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=powerpc64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const volatile [noderef] __iomem *s @@     got unsigned char const [usertype] * @@
   drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse:     expected void const volatile [noderef] __iomem *s
   drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse:     got unsigned char const [usertype] *
>> drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void volatile [noderef] __iomem *a @@     got void * @@
   drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse:     expected void volatile [noderef] __iomem *a
   drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse:     got void *
--
>> drivers/remoteproc/remoteproc_coredump.c:169:53: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const volatile [noderef] __iomem *s @@     got void *[assigned] ptr @@
   drivers/remoteproc/remoteproc_coredump.c:169:53: sparse:     expected void const volatile [noderef] __iomem *s
   drivers/remoteproc/remoteproc_coredump.c:169:53: sparse:     got void *[assigned] ptr

vim +219 drivers/remoteproc/remoteproc_elf_loader.c

   131	
   132	/**
   133	 * rproc_elf_load_segments() - load firmware segments to memory
   134	 * @rproc: remote processor which will be booted using these fw segments
   135	 * @fw: the ELF firmware image
   136	 *
   137	 * This function loads the firmware segments to memory, where the remote
   138	 * processor expects them.
   139	 *
   140	 * Some remote processors will expect their code and data to be placed
   141	 * in specific device addresses, and can't have them dynamically assigned.
   142	 *
   143	 * We currently support only those kind of remote processors, and expect
   144	 * the program header's paddr member to contain those addresses. We then go
   145	 * through the physically contiguous "carveout" memory regions which we
   146	 * allocated (and mapped) earlier on behalf of the remote processor,
   147	 * and "translate" device address to kernel addresses, so we can copy the
   148	 * segments where they are expected.
   149	 *
   150	 * Currently we only support remote processors that required carveout
   151	 * allocations and got them mapped onto their iommus. Some processors
   152	 * might be different: they might not have iommus, and would prefer to
   153	 * directly allocate memory for every segment/resource. This is not yet
   154	 * supported, though.
   155	 */
   156	int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
   157	{
   158		struct device *dev = &rproc->dev;
   159		const void *ehdr, *phdr;
   160		int i, ret = 0;
   161		u16 phnum;
   162		const u8 *elf_data = fw->data;
   163		u8 class = fw_elf_get_class(fw);
   164		u32 elf_phdr_get_size = elf_size_of_phdr(class);
   165	
   166		ehdr = elf_data;
   167		phnum = elf_hdr_get_e_phnum(class, ehdr);
   168		phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr);
   169	
   170		/* go through the available ELF segments */
   171		for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) {
   172			u64 da = elf_phdr_get_p_paddr(class, phdr);
   173			u64 memsz = elf_phdr_get_p_memsz(class, phdr);
   174			u64 filesz = elf_phdr_get_p_filesz(class, phdr);
   175			u64 offset = elf_phdr_get_p_offset(class, phdr);
   176			u32 type = elf_phdr_get_p_type(class, phdr);
   177			void *ptr;
   178			bool is_iomem;
   179	
   180			if (type != PT_LOAD)
   181				continue;
   182	
   183			dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
   184				type, da, memsz, filesz);
   185	
   186			if (filesz > memsz) {
   187				dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
   188					filesz, memsz);
   189				ret = -EINVAL;
   190				break;
   191			}
   192	
   193			if (offset + filesz > fw->size) {
   194				dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
   195					offset + filesz, fw->size);
   196				ret = -EINVAL;
   197				break;
   198			}
   199	
   200			if (!rproc_u64_fit_in_size_t(memsz)) {
   201				dev_err(dev, "size (%llx) does not fit in size_t type\n",
   202					memsz);
   203				ret = -EOVERFLOW;
   204				break;
   205			}
   206	
   207			/* grab the kernel address for this device address */
   208			ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem);
   209			if (!ptr) {
   210				dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
   211					memsz);
   212				ret = -EINVAL;
   213				break;
   214			}
   215	
   216			/* put the segment where the remote processor expects it */
   217			if (filesz) {
   218				if (is_iomem)
 > 219					memcpy_fromio(ptr, elf_data + offset, filesz);
   220				else
   221					memcpy(ptr, elf_data + offset, filesz);
   222			}
   223	
   224			/*
   225			 * Zero out remaining memory for this segment.
   226			 *
   227			 * This isn't strictly required since dma_alloc_coherent already
   228			 * did this for us. albeit harmless, we may consider removing
   229			 * this.
   230			 */
   231			if (memsz > filesz) {
   232				if (is_iomem)
 > 233					memset_io(ptr + filesz, 0, memsz - filesz);
   234				else
   235					memset(ptr + filesz, 0, memsz - filesz);
   236			}
   237		}
   238	
   239		return ret;
   240	}
   241	EXPORT_SYMBOL(rproc_elf_load_segments);
   242	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Dec. 30, 2020, 3:20 p.m. UTC | #2
Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.11-rc1 next-20201223]
[cannot apply to soc/for-next xlnx/master remoteproc/for-next rpmsg/for-next]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/peng-fan-nxp-com/remoteproc-imx_rproc-support-iMX8MQ-M/20201229-110725
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git dea8dcf2a9fa8cc540136a6cd885c3beece16ec3
config: i386-randconfig-s001-20201230 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-184-g1b896707-dirty
        # https://github.com/0day-ci/linux/commit/f2054bc05d3b183ef0b0ff0b4c802ba53680a5af
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review peng-fan-nxp-com/remoteproc-imx_rproc-support-iMX8MQ-M/20201229-110725
        git checkout f2054bc05d3b183ef0b0ff0b4c802ba53680a5af
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


"sparse warnings: (new ones prefixed by >>)"
>> drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const volatile [noderef] __iomem * @@     got unsigned char const [usertype] * @@
   drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse:     expected void const volatile [noderef] __iomem *
   drivers/remoteproc/remoteproc_elf_loader.c:219:61: sparse:     got unsigned char const [usertype] *
>> drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse: sparse: incorrect type in argument 1 (different address spaces) @@     expected void volatile [noderef] __iomem * @@     got void * @@
   drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse:     expected void volatile [noderef] __iomem *
   drivers/remoteproc/remoteproc_elf_loader.c:233:47: sparse:     got void *
--
>> drivers/remoteproc/remoteproc_coredump.c:169:53: sparse: sparse: incorrect type in argument 2 (different address spaces) @@     expected void const volatile [noderef] __iomem * @@     got void *[assigned] ptr @@
   drivers/remoteproc/remoteproc_coredump.c:169:53: sparse:     expected void const volatile [noderef] __iomem *
   drivers/remoteproc/remoteproc_coredump.c:169:53: sparse:     got void *[assigned] ptr

vim +219 drivers/remoteproc/remoteproc_elf_loader.c

   131	
   132	/**
   133	 * rproc_elf_load_segments() - load firmware segments to memory
   134	 * @rproc: remote processor which will be booted using these fw segments
   135	 * @fw: the ELF firmware image
   136	 *
   137	 * This function loads the firmware segments to memory, where the remote
   138	 * processor expects them.
   139	 *
   140	 * Some remote processors will expect their code and data to be placed
   141	 * in specific device addresses, and can't have them dynamically assigned.
   142	 *
   143	 * We currently support only those kind of remote processors, and expect
   144	 * the program header's paddr member to contain those addresses. We then go
   145	 * through the physically contiguous "carveout" memory regions which we
   146	 * allocated (and mapped) earlier on behalf of the remote processor,
   147	 * and "translate" device address to kernel addresses, so we can copy the
   148	 * segments where they are expected.
   149	 *
   150	 * Currently we only support remote processors that required carveout
   151	 * allocations and got them mapped onto their iommus. Some processors
   152	 * might be different: they might not have iommus, and would prefer to
   153	 * directly allocate memory for every segment/resource. This is not yet
   154	 * supported, though.
   155	 */
   156	int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
   157	{
   158		struct device *dev = &rproc->dev;
   159		const void *ehdr, *phdr;
   160		int i, ret = 0;
   161		u16 phnum;
   162		const u8 *elf_data = fw->data;
   163		u8 class = fw_elf_get_class(fw);
   164		u32 elf_phdr_get_size = elf_size_of_phdr(class);
   165	
   166		ehdr = elf_data;
   167		phnum = elf_hdr_get_e_phnum(class, ehdr);
   168		phdr = elf_data + elf_hdr_get_e_phoff(class, ehdr);
   169	
   170		/* go through the available ELF segments */
   171		for (i = 0; i < phnum; i++, phdr += elf_phdr_get_size) {
   172			u64 da = elf_phdr_get_p_paddr(class, phdr);
   173			u64 memsz = elf_phdr_get_p_memsz(class, phdr);
   174			u64 filesz = elf_phdr_get_p_filesz(class, phdr);
   175			u64 offset = elf_phdr_get_p_offset(class, phdr);
   176			u32 type = elf_phdr_get_p_type(class, phdr);
   177			void *ptr;
   178			bool is_iomem;
   179	
   180			if (type != PT_LOAD)
   181				continue;
   182	
   183			dev_dbg(dev, "phdr: type %d da 0x%llx memsz 0x%llx filesz 0x%llx\n",
   184				type, da, memsz, filesz);
   185	
   186			if (filesz > memsz) {
   187				dev_err(dev, "bad phdr filesz 0x%llx memsz 0x%llx\n",
   188					filesz, memsz);
   189				ret = -EINVAL;
   190				break;
   191			}
   192	
   193			if (offset + filesz > fw->size) {
   194				dev_err(dev, "truncated fw: need 0x%llx avail 0x%zx\n",
   195					offset + filesz, fw->size);
   196				ret = -EINVAL;
   197				break;
   198			}
   199	
   200			if (!rproc_u64_fit_in_size_t(memsz)) {
   201				dev_err(dev, "size (%llx) does not fit in size_t type\n",
   202					memsz);
   203				ret = -EOVERFLOW;
   204				break;
   205			}
   206	
   207			/* grab the kernel address for this device address */
   208			ptr = rproc_da_to_va(rproc, da, memsz, &is_iomem);
   209			if (!ptr) {
   210				dev_err(dev, "bad phdr da 0x%llx mem 0x%llx\n", da,
   211					memsz);
   212				ret = -EINVAL;
   213				break;
   214			}
   215	
   216			/* put the segment where the remote processor expects it */
   217			if (filesz) {
   218				if (is_iomem)
 > 219					memcpy_fromio(ptr, elf_data + offset, filesz);
   220				else
   221					memcpy(ptr, elf_data + offset, filesz);
   222			}
   223	
   224			/*
   225			 * Zero out remaining memory for this segment.
   226			 *
   227			 * This isn't strictly required since dma_alloc_coherent already
   228			 * did this for us. albeit harmless, we may consider removing
   229			 * this.
   230			 */
   231			if (memsz > filesz) {
   232				if (is_iomem)
 > 233					memset_io(ptr + filesz, 0, memsz - filesz);
   234				else
   235					memset(ptr + filesz, 0, memsz - filesz);
   236			}
   237		}
   238	
   239		return ret;
   240	}
   241	EXPORT_SYMBOL(rproc_elf_load_segments);
   242	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Mathieu Poirier Jan. 11, 2021, 8:25 p.m. UTC | #3
On Tue, Dec 29, 2020 at 11:30:13AM +0800, peng.fan@nxp.com wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> Introduce an extra parameter is_iomem to da_to_va, then the caller
> could take the memory as normal memory or io mapped memory.
> 
> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/remoteproc/imx_rproc.c             |  2 +-
>  drivers/remoteproc/ingenic_rproc.c         |  2 +-
>  drivers/remoteproc/keystone_remoteproc.c   |  2 +-
>  drivers/remoteproc/mtk_scp.c               |  6 +++---
>  drivers/remoteproc/omap_remoteproc.c       |  2 +-
>  drivers/remoteproc/pru_rproc.c             |  2 +-
>  drivers/remoteproc/qcom_q6v5_adsp.c        |  2 +-
>  drivers/remoteproc/qcom_q6v5_pas.c         |  2 +-
>  drivers/remoteproc/qcom_q6v5_wcss.c        |  2 +-
>  drivers/remoteproc/qcom_wcnss.c            |  2 +-
>  drivers/remoteproc/remoteproc_core.c       |  7 +++++--
>  drivers/remoteproc/remoteproc_coredump.c   |  8 ++++++--
>  drivers/remoteproc/remoteproc_debugfs.c    |  2 +-
>  drivers/remoteproc/remoteproc_elf_loader.c | 21 +++++++++++++++------
>  drivers/remoteproc/remoteproc_internal.h   |  2 +-
>  drivers/remoteproc/st_slim_rproc.c         |  2 +-
>  drivers/remoteproc/ti_k3_dsp_remoteproc.c  |  2 +-
>  drivers/remoteproc/ti_k3_r5_remoteproc.c   |  2 +-
>  drivers/remoteproc/wkup_m3_rproc.c         |  2 +-
>  include/linux/remoteproc.h                 |  2 +-
>  20 files changed, 45 insertions(+), 29 deletions(-)

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

> 
> diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
> index 8957ed271d20..6603e00bb6f4 100644
> --- a/drivers/remoteproc/imx_rproc.c
> +++ b/drivers/remoteproc/imx_rproc.c
> @@ -208,7 +208,7 @@ static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
>  	return -ENOENT;
>  }
>  
> -static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct imx_rproc *priv = rproc->priv;
>  	void *va = NULL;
> diff --git a/drivers/remoteproc/ingenic_rproc.c b/drivers/remoteproc/ingenic_rproc.c
> index 26e19e6143b7..bb5049295576 100644
> --- a/drivers/remoteproc/ingenic_rproc.c
> +++ b/drivers/remoteproc/ingenic_rproc.c
> @@ -116,7 +116,7 @@ static void ingenic_rproc_kick(struct rproc *rproc, int vqid)
>  	writel(vqid, vpu->aux_base + REG_CORE_MSG);
>  }
>  
> -static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct vpu *vpu = rproc->priv;
>  	void __iomem *va = NULL;
> diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
> index cd266163a65f..54781f553f4e 100644
> --- a/drivers/remoteproc/keystone_remoteproc.c
> +++ b/drivers/remoteproc/keystone_remoteproc.c
> @@ -246,7 +246,7 @@ static void keystone_rproc_kick(struct rproc *rproc, int vqid)
>   * can be used either by the remoteproc core for loading (when using kernel
>   * remoteproc loader), or by any rpmsg bus drivers.
>   */
> -static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct keystone_rproc *ksproc = rproc->priv;
>  	void __iomem *va = NULL;
> diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
> index e0c235690361..535175f013e4 100644
> --- a/drivers/remoteproc/mtk_scp.c
> +++ b/drivers/remoteproc/mtk_scp.c
> @@ -270,7 +270,7 @@ static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		}
>  
>  		/* grab the kernel address for this device address */
> -		ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz);
> +		ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz, NULL);
>  		if (!ptr) {
>  			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
>  			ret = -EINVAL;
> @@ -458,7 +458,7 @@ static int scp_start(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
>  	int offset;
> @@ -587,7 +587,7 @@ void *scp_mapping_dm_addr(struct mtk_scp *scp, u32 mem_addr)
>  {
>  	void *ptr;
>  
> -	ptr = scp_da_to_va(scp->rproc, mem_addr, 0);
> +	ptr = scp_da_to_va(scp->rproc, mem_addr, 0, NULL);
>  	if (!ptr)
>  		return ERR_PTR(-EINVAL);
>  
> diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
> index d94b7391bf9d..43531caa1959 100644
> --- a/drivers/remoteproc/omap_remoteproc.c
> +++ b/drivers/remoteproc/omap_remoteproc.c
> @@ -728,7 +728,7 @@ static int omap_rproc_stop(struct rproc *rproc)
>   * Return: translated virtual address in kernel memory space on success,
>   *         or NULL on failure.
>   */
> -static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct omap_rproc *oproc = rproc->priv;
>  	int i;
> diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
> index 2667919d76b3..2dcaa274e266 100644
> --- a/drivers/remoteproc/pru_rproc.c
> +++ b/drivers/remoteproc/pru_rproc.c
> @@ -465,7 +465,7 @@ static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
>   * core for any PRU client drivers. The PRU Instruction RAM access is restricted
>   * only to the PRU loader code.
>   */
> -static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct pru_rproc *pru = rproc->priv;
>  
> diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
> index e02450225e4a..8b0d8bbacd2e 100644
> --- a/drivers/remoteproc/qcom_q6v5_adsp.c
> +++ b/drivers/remoteproc/qcom_q6v5_adsp.c
> @@ -281,7 +281,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
> index ee586226e438..333a1e389fcd 100644
> --- a/drivers/remoteproc/qcom_q6v5_pas.c
> +++ b/drivers/remoteproc/qcom_q6v5_pas.c
> @@ -242,7 +242,7 @@ static int adsp_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
> index 78ebe1168b33..704cd63c9af4 100644
> --- a/drivers/remoteproc/qcom_q6v5_wcss.c
> +++ b/drivers/remoteproc/qcom_q6v5_wcss.c
> @@ -410,7 +410,7 @@ static int q6v5_wcss_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct q6v5_wcss *wcss = rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
> index f95854255c70..1bf60dc84f69 100644
> --- a/drivers/remoteproc/qcom_wcnss.c
> +++ b/drivers/remoteproc/qcom_wcnss.c
> @@ -320,7 +320,7 @@ static int wcnss_stop(struct rproc *rproc)
>  	return ret;
>  }
>  
> -static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
>  	int offset;
> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index 2394eef383e3..9bec422ccce3 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -189,13 +189,13 @@ EXPORT_SYMBOL(rproc_va_to_pa);
>   * here the output of the DMA API for the carveouts, which should be more
>   * correct.
>   */
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct rproc_mem_entry *carveout;
>  	void *ptr = NULL;
>  
>  	if (rproc->ops->da_to_va) {
> -		ptr = rproc->ops->da_to_va(rproc, da, len);
> +		ptr = rproc->ops->da_to_va(rproc, da, len, is_iomem);
>  		if (ptr)
>  			goto out;
>  	}
> @@ -217,6 +217,9 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
>  
>  		ptr = carveout->va + offset;
>  
> +		if (is_iomem)
> +			*is_iomem = carveout->is_iomem;
> +
>  		break;
>  	}
>  
> diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c
> index 81ec154a6a5e..aee657cc08c6 100644
> --- a/drivers/remoteproc/remoteproc_coredump.c
> +++ b/drivers/remoteproc/remoteproc_coredump.c
> @@ -153,18 +153,22 @@ static void rproc_copy_segment(struct rproc *rproc, void *dest,
>  			       size_t offset, size_t size)
>  {
>  	void *ptr;
> +	bool is_iomem;
>  
>  	if (segment->dump) {
>  		segment->dump(rproc, segment, dest, offset, size);
>  	} else {
> -		ptr = rproc_da_to_va(rproc, segment->da + offset, size);
> +		ptr = rproc_da_to_va(rproc, segment->da + offset, size, &is_iomem);
>  		if (!ptr) {
>  			dev_err(&rproc->dev,
>  				"invalid copy request for segment %pad with offset %zu and size %zu)\n",
>  				&segment->da, offset, size);
>  			memset(dest, 0xff, size);
>  		} else {
> -			memcpy(dest, ptr, size);
> +			if (is_iomem)
> +				memcpy_fromio(dest, ptr, size);
> +			else
> +				memcpy(dest, ptr, size);
>  		}
>  	}
>  }
> diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
> index 7e5845376e9f..b5a1e3b697d9 100644
> --- a/drivers/remoteproc/remoteproc_debugfs.c
> +++ b/drivers/remoteproc/remoteproc_debugfs.c
> @@ -132,7 +132,7 @@ static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf,
>  	char buf[100];
>  	int len;
>  
> -	va = rproc_da_to_va(data->rproc, trace->da, trace->len);
> +	va = rproc_da_to_va(data->rproc, trace->da, trace->len, NULL);
>  
>  	if (!va) {
>  		len = scnprintf(buf, sizeof(buf), "Trace %s not available\n",
> diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
> index df68d87752e4..c02d4fec93a9 100644
> --- a/drivers/remoteproc/remoteproc_elf_loader.c
> +++ b/drivers/remoteproc/remoteproc_elf_loader.c
> @@ -175,6 +175,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		u64 offset = elf_phdr_get_p_offset(class, phdr);
>  		u32 type = elf_phdr_get_p_type(class, phdr);
>  		void *ptr;
> +		bool is_iomem;
>  
>  		if (type != PT_LOAD)
>  			continue;
> @@ -204,7 +205,7 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		}
>  
>  		/* grab the kernel address for this device address */
> -		ptr = rproc_da_to_va(rproc, da, memsz);
> +		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);
> @@ -213,8 +214,12 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		}
>  
>  		/* put the segment where the remote processor expects it */
> -		if (filesz)
> -			memcpy(ptr, elf_data + offset, filesz);
> +		if (filesz) {
> +			if (is_iomem)
> +				memcpy_fromio(ptr, elf_data + offset, filesz);
> +			else
> +				memcpy(ptr, elf_data + offset, filesz);
> +		}
>  
>  		/*
>  		 * Zero out remaining memory for this segment.
> @@ -223,8 +228,12 @@ int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
>  		 * did this for us. albeit harmless, we may consider removing
>  		 * this.
>  		 */
> -		if (memsz > filesz)
> -			memset(ptr + filesz, 0, memsz - filesz);
> +		if (memsz > filesz) {
> +			if (is_iomem)
> +				memset_io(ptr + filesz, 0, memsz - filesz);
> +			else
> +				memset(ptr + filesz, 0, memsz - filesz);
> +		}
>  	}
>  
>  	return ret;
> @@ -377,6 +386,6 @@ struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
>  		return NULL;
>  	}
>  
> -	return rproc_da_to_va(rproc, sh_addr, sh_size);
> +	return rproc_da_to_va(rproc, sh_addr, sh_size, NULL);
>  }
>  EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
> diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
> index c34002888d2c..9ea37aa687d2 100644
> --- a/drivers/remoteproc/remoteproc_internal.h
> +++ b/drivers/remoteproc/remoteproc_internal.h
> @@ -84,7 +84,7 @@ static inline void  rproc_char_device_remove(struct rproc *rproc)
>  void rproc_free_vring(struct rproc_vring *rvring);
>  int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
>  
> -void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len);
> +void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
>  phys_addr_t rproc_va_to_pa(void *cpu_addr);
>  int rproc_trigger_recovery(struct rproc *rproc);
>  
> diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
> index 09bcb4d8b9e0..22096adc1ad3 100644
> --- a/drivers/remoteproc/st_slim_rproc.c
> +++ b/drivers/remoteproc/st_slim_rproc.c
> @@ -174,7 +174,7 @@ static int slim_rproc_stop(struct rproc *rproc)
>  	return 0;
>  }
>  
> -static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct st_slim_rproc *slim_rproc = rproc->priv;
>  	void *va = NULL;
> diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> index 863c0214e0a8..fd4eb67a6681 100644
> --- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> +++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
> @@ -354,7 +354,7 @@ static int k3_dsp_rproc_stop(struct rproc *rproc)
>   * can be used either by the remoteproc core for loading (when using kernel
>   * remoteproc loader), or by any rpmsg bus drivers.
>   */
> -static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct k3_dsp_rproc *kproc = rproc->priv;
>  	void __iomem *va = NULL;
> diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
> index 62b5a4c29456..5cf8d030a1f0 100644
> --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c
> +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c
> @@ -590,7 +590,7 @@ static int k3_r5_rproc_stop(struct rproc *rproc)
>   * present in a DSP or IPU device). The translated addresses can be used
>   * either by the remoteproc core for loading, or by any rpmsg bus drivers.
>   */
> -static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct k3_r5_rproc *kproc = rproc->priv;
>  	struct k3_r5_core *core = kproc->core;
> diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
> index 92d387dfc03b..484f7605823e 100644
> --- a/drivers/remoteproc/wkup_m3_rproc.c
> +++ b/drivers/remoteproc/wkup_m3_rproc.c
> @@ -89,7 +89,7 @@ static int wkup_m3_rproc_stop(struct rproc *rproc)
>  	return error;
>  }
>  
> -static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
> +static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
>  {
>  	struct wkup_m3_rproc *wkupm3 = rproc->priv;
>  	void *va = NULL;
> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
> index a5f6d2d9cde2..1b7d56c7a453 100644
> --- a/include/linux/remoteproc.h
> +++ b/include/linux/remoteproc.h
> @@ -386,7 +386,7 @@ struct rproc_ops {
>  	int (*stop)(struct rproc *rproc);
>  	int (*attach)(struct rproc *rproc);
>  	void (*kick)(struct rproc *rproc, int vqid);
> -	void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len);
> +	void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
>  	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.28.0
>
diff mbox series

Patch

diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c
index 8957ed271d20..6603e00bb6f4 100644
--- a/drivers/remoteproc/imx_rproc.c
+++ b/drivers/remoteproc/imx_rproc.c
@@ -208,7 +208,7 @@  static int imx_rproc_da_to_sys(struct imx_rproc *priv, u64 da,
 	return -ENOENT;
 }
 
-static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *imx_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct imx_rproc *priv = rproc->priv;
 	void *va = NULL;
diff --git a/drivers/remoteproc/ingenic_rproc.c b/drivers/remoteproc/ingenic_rproc.c
index 26e19e6143b7..bb5049295576 100644
--- a/drivers/remoteproc/ingenic_rproc.c
+++ b/drivers/remoteproc/ingenic_rproc.c
@@ -116,7 +116,7 @@  static void ingenic_rproc_kick(struct rproc *rproc, int vqid)
 	writel(vqid, vpu->aux_base + REG_CORE_MSG);
 }
 
-static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *ingenic_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct vpu *vpu = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/keystone_remoteproc.c b/drivers/remoteproc/keystone_remoteproc.c
index cd266163a65f..54781f553f4e 100644
--- a/drivers/remoteproc/keystone_remoteproc.c
+++ b/drivers/remoteproc/keystone_remoteproc.c
@@ -246,7 +246,7 @@  static void keystone_rproc_kick(struct rproc *rproc, int vqid)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *keystone_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct keystone_rproc *ksproc = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index e0c235690361..535175f013e4 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -270,7 +270,7 @@  static int scp_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		}
 
 		/* grab the kernel address for this device address */
-		ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz);
+		ptr = (void __iomem *)rproc_da_to_va(rproc, da, memsz, NULL);
 		if (!ptr) {
 			dev_err(dev, "bad phdr da 0x%x mem 0x%x\n", da, memsz);
 			ret = -EINVAL;
@@ -458,7 +458,7 @@  static int scp_start(struct rproc *rproc)
 	return ret;
 }
 
-static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *scp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct mtk_scp *scp = (struct mtk_scp *)rproc->priv;
 	int offset;
@@ -587,7 +587,7 @@  void *scp_mapping_dm_addr(struct mtk_scp *scp, u32 mem_addr)
 {
 	void *ptr;
 
-	ptr = scp_da_to_va(scp->rproc, mem_addr, 0);
+	ptr = scp_da_to_va(scp->rproc, mem_addr, 0, NULL);
 	if (!ptr)
 		return ERR_PTR(-EINVAL);
 
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index d94b7391bf9d..43531caa1959 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -728,7 +728,7 @@  static int omap_rproc_stop(struct rproc *rproc)
  * Return: translated virtual address in kernel memory space on success,
  *         or NULL on failure.
  */
-static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *omap_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct omap_rproc *oproc = rproc->priv;
 	int i;
diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
index 2667919d76b3..2dcaa274e266 100644
--- a/drivers/remoteproc/pru_rproc.c
+++ b/drivers/remoteproc/pru_rproc.c
@@ -465,7 +465,7 @@  static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
  * core for any PRU client drivers. The PRU Instruction RAM access is restricted
  * only to the PRU loader code.
  */
-static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct pru_rproc *pru = rproc->priv;
 
diff --git a/drivers/remoteproc/qcom_q6v5_adsp.c b/drivers/remoteproc/qcom_q6v5_adsp.c
index e02450225e4a..8b0d8bbacd2e 100644
--- a/drivers/remoteproc/qcom_q6v5_adsp.c
+++ b/drivers/remoteproc/qcom_q6v5_adsp.c
@@ -281,7 +281,7 @@  static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_pas.c b/drivers/remoteproc/qcom_q6v5_pas.c
index ee586226e438..333a1e389fcd 100644
--- a/drivers/remoteproc/qcom_q6v5_pas.c
+++ b/drivers/remoteproc/qcom_q6v5_pas.c
@@ -242,7 +242,7 @@  static int adsp_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *adsp_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct qcom_adsp *adsp = (struct qcom_adsp *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_q6v5_wcss.c b/drivers/remoteproc/qcom_q6v5_wcss.c
index 78ebe1168b33..704cd63c9af4 100644
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -410,7 +410,7 @@  static int q6v5_wcss_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *q6v5_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct q6v5_wcss *wcss = rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/qcom_wcnss.c b/drivers/remoteproc/qcom_wcnss.c
index f95854255c70..1bf60dc84f69 100644
--- a/drivers/remoteproc/qcom_wcnss.c
+++ b/drivers/remoteproc/qcom_wcnss.c
@@ -320,7 +320,7 @@  static int wcnss_stop(struct rproc *rproc)
 	return ret;
 }
 
-static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *wcnss_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct qcom_wcnss *wcnss = (struct qcom_wcnss *)rproc->priv;
 	int offset;
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 2394eef383e3..9bec422ccce3 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -189,13 +189,13 @@  EXPORT_SYMBOL(rproc_va_to_pa);
  * here the output of the DMA API for the carveouts, which should be more
  * correct.
  */
-void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct rproc_mem_entry *carveout;
 	void *ptr = NULL;
 
 	if (rproc->ops->da_to_va) {
-		ptr = rproc->ops->da_to_va(rproc, da, len);
+		ptr = rproc->ops->da_to_va(rproc, da, len, is_iomem);
 		if (ptr)
 			goto out;
 	}
@@ -217,6 +217,9 @@  void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
 
 		ptr = carveout->va + offset;
 
+		if (is_iomem)
+			*is_iomem = carveout->is_iomem;
+
 		break;
 	}
 
diff --git a/drivers/remoteproc/remoteproc_coredump.c b/drivers/remoteproc/remoteproc_coredump.c
index 81ec154a6a5e..aee657cc08c6 100644
--- a/drivers/remoteproc/remoteproc_coredump.c
+++ b/drivers/remoteproc/remoteproc_coredump.c
@@ -153,18 +153,22 @@  static void rproc_copy_segment(struct rproc *rproc, void *dest,
 			       size_t offset, size_t size)
 {
 	void *ptr;
+	bool is_iomem;
 
 	if (segment->dump) {
 		segment->dump(rproc, segment, dest, offset, size);
 	} else {
-		ptr = rproc_da_to_va(rproc, segment->da + offset, size);
+		ptr = rproc_da_to_va(rproc, segment->da + offset, size, &is_iomem);
 		if (!ptr) {
 			dev_err(&rproc->dev,
 				"invalid copy request for segment %pad with offset %zu and size %zu)\n",
 				&segment->da, offset, size);
 			memset(dest, 0xff, size);
 		} else {
-			memcpy(dest, ptr, size);
+			if (is_iomem)
+				memcpy_fromio(dest, ptr, size);
+			else
+				memcpy(dest, ptr, size);
 		}
 	}
 }
diff --git a/drivers/remoteproc/remoteproc_debugfs.c b/drivers/remoteproc/remoteproc_debugfs.c
index 7e5845376e9f..b5a1e3b697d9 100644
--- a/drivers/remoteproc/remoteproc_debugfs.c
+++ b/drivers/remoteproc/remoteproc_debugfs.c
@@ -132,7 +132,7 @@  static ssize_t rproc_trace_read(struct file *filp, char __user *userbuf,
 	char buf[100];
 	int len;
 
-	va = rproc_da_to_va(data->rproc, trace->da, trace->len);
+	va = rproc_da_to_va(data->rproc, trace->da, trace->len, NULL);
 
 	if (!va) {
 		len = scnprintf(buf, sizeof(buf), "Trace %s not available\n",
diff --git a/drivers/remoteproc/remoteproc_elf_loader.c b/drivers/remoteproc/remoteproc_elf_loader.c
index df68d87752e4..c02d4fec93a9 100644
--- a/drivers/remoteproc/remoteproc_elf_loader.c
+++ b/drivers/remoteproc/remoteproc_elf_loader.c
@@ -175,6 +175,7 @@  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		u64 offset = elf_phdr_get_p_offset(class, phdr);
 		u32 type = elf_phdr_get_p_type(class, phdr);
 		void *ptr;
+		bool is_iomem;
 
 		if (type != PT_LOAD)
 			continue;
@@ -204,7 +205,7 @@  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		}
 
 		/* grab the kernel address for this device address */
-		ptr = rproc_da_to_va(rproc, da, memsz);
+		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);
@@ -213,8 +214,12 @@  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		}
 
 		/* put the segment where the remote processor expects it */
-		if (filesz)
-			memcpy(ptr, elf_data + offset, filesz);
+		if (filesz) {
+			if (is_iomem)
+				memcpy_fromio(ptr, elf_data + offset, filesz);
+			else
+				memcpy(ptr, elf_data + offset, filesz);
+		}
 
 		/*
 		 * Zero out remaining memory for this segment.
@@ -223,8 +228,12 @@  int rproc_elf_load_segments(struct rproc *rproc, const struct firmware *fw)
 		 * did this for us. albeit harmless, we may consider removing
 		 * this.
 		 */
-		if (memsz > filesz)
-			memset(ptr + filesz, 0, memsz - filesz);
+		if (memsz > filesz) {
+			if (is_iomem)
+				memset_io(ptr + filesz, 0, memsz - filesz);
+			else
+				memset(ptr + filesz, 0, memsz - filesz);
+		}
 	}
 
 	return ret;
@@ -377,6 +386,6 @@  struct resource_table *rproc_elf_find_loaded_rsc_table(struct rproc *rproc,
 		return NULL;
 	}
 
-	return rproc_da_to_va(rproc, sh_addr, sh_size);
+	return rproc_da_to_va(rproc, sh_addr, sh_size, NULL);
 }
 EXPORT_SYMBOL(rproc_elf_find_loaded_rsc_table);
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index c34002888d2c..9ea37aa687d2 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -84,7 +84,7 @@  static inline void  rproc_char_device_remove(struct rproc *rproc)
 void rproc_free_vring(struct rproc_vring *rvring);
 int rproc_alloc_vring(struct rproc_vdev *rvdev, int i);
 
-void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len);
+void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
 phys_addr_t rproc_va_to_pa(void *cpu_addr);
 int rproc_trigger_recovery(struct rproc *rproc);
 
diff --git a/drivers/remoteproc/st_slim_rproc.c b/drivers/remoteproc/st_slim_rproc.c
index 09bcb4d8b9e0..22096adc1ad3 100644
--- a/drivers/remoteproc/st_slim_rproc.c
+++ b/drivers/remoteproc/st_slim_rproc.c
@@ -174,7 +174,7 @@  static int slim_rproc_stop(struct rproc *rproc)
 	return 0;
 }
 
-static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *slim_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct st_slim_rproc *slim_rproc = rproc->priv;
 	void *va = NULL;
diff --git a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
index 863c0214e0a8..fd4eb67a6681 100644
--- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
@@ -354,7 +354,7 @@  static int k3_dsp_rproc_stop(struct rproc *rproc)
  * can be used either by the remoteproc core for loading (when using kernel
  * remoteproc loader), or by any rpmsg bus drivers.
  */
-static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct k3_dsp_rproc *kproc = rproc->priv;
 	void __iomem *va = NULL;
diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
index 62b5a4c29456..5cf8d030a1f0 100644
--- a/drivers/remoteproc/ti_k3_r5_remoteproc.c
+++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c
@@ -590,7 +590,7 @@  static int k3_r5_rproc_stop(struct rproc *rproc)
  * present in a DSP or IPU device). The translated addresses can be used
  * either by the remoteproc core for loading, or by any rpmsg bus drivers.
  */
-static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *k3_r5_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct k3_r5_rproc *kproc = rproc->priv;
 	struct k3_r5_core *core = kproc->core;
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index 92d387dfc03b..484f7605823e 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -89,7 +89,7 @@  static int wkup_m3_rproc_stop(struct rproc *rproc)
 	return error;
 }
 
-static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len)
+static void *wkup_m3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 {
 	struct wkup_m3_rproc *wkupm3 = rproc->priv;
 	void *va = NULL;
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index a5f6d2d9cde2..1b7d56c7a453 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -386,7 +386,7 @@  struct rproc_ops {
 	int (*stop)(struct rproc *rproc);
 	int (*attach)(struct rproc *rproc);
 	void (*kick)(struct rproc *rproc, int vqid);
-	void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len);
+	void * (*da_to_va)(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
 	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);