Skip to content

Commit a84a1e2

Browse files
dbalutamathieupoirier
authored andcommitted
remoteproc: imx_dsp_rproc: Fix multiple start/stop operations
After commit 67a7bc7 ("remoteproc: Use of reserved_mem_region_* functions for "memory-region"") following commands with imx-dsp-rproc started to fail: $ echo zephyr.elf > /sys/class/remoteproc/remoteproc0/firmware $ echo start > /sys/class/remoteproc/remoteproc0/state $ echo stop > /sys/class/remoteproc/remoteproc0/state $ echo start > /sys/class/remoteproc/remoteproc0/state #! This fails -sh: echo: write error: Device or resource busy This happens because aforementioned commit replaced devm_ioremap_wc with devm_ioremap_resource_wc which will "reserve" the memory region with the first start and then will fail at the second start if the memory region is already reserved. Even partially reverting the faulty commit won't fix the underlying issue because we map the address in prepare() but we never unmap it at unprepare(), so we will keep leaking memory regions. So, lets use alloc() and release() callbacks for memory carveout handling. This will nicely map() the memory region at prepare() time and unmap() it at unprepare(). Fixes: 67a7bc7 ("remoteproc: Use of_reserved_mem_region_* functions for "memory-region"") Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com> Link: https://lore.kernel.org/r/20251210154906.99210-1-daniel.baluta@nxp.com Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
1 parent 93f51b9 commit a84a1e2

1 file changed

Lines changed: 33 additions & 17 deletions

File tree

drivers/remoteproc/imx_dsp_rproc.c

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,32 @@ static void imx_dsp_rproc_free_mbox(struct imx_dsp_rproc *priv)
644644
mbox_free_channel(priv->rxdb_ch);
645645
}
646646

647+
static int imx_dsp_rproc_mem_alloc(struct rproc *rproc,
648+
struct rproc_mem_entry *mem)
649+
{
650+
struct device *dev = rproc->dev.parent;
651+
void *va;
652+
653+
va = ioremap_wc(mem->dma, mem->len);
654+
if (!va) {
655+
dev_err(dev, "Unable to map memory region: %pa+%zx\n",
656+
&mem->dma, mem->len);
657+
return -ENOMEM;
658+
}
659+
660+
mem->va = va;
661+
662+
return 0;
663+
}
664+
665+
static int imx_dsp_rproc_mem_release(struct rproc *rproc,
666+
struct rproc_mem_entry *mem)
667+
{
668+
iounmap(mem->va);
669+
670+
return 0;
671+
}
672+
647673
/**
648674
* imx_dsp_rproc_add_carveout() - request mailbox channels
649675
* @priv: private data pointer
@@ -659,7 +685,6 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
659685
struct device *dev = rproc->dev.parent;
660686
struct device_node *np = dev->of_node;
661687
struct rproc_mem_entry *mem;
662-
void __iomem *cpu_addr;
663688
int a, i = 0;
664689
u64 da;
665690

@@ -673,15 +698,10 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
673698
if (imx_dsp_rproc_sys_to_da(priv, att->sa, att->size, &da))
674699
return -EINVAL;
675700

676-
cpu_addr = devm_ioremap_wc(dev, att->sa, att->size);
677-
if (!cpu_addr) {
678-
dev_err(dev, "failed to map memory %p\n", &att->sa);
679-
return -ENOMEM;
680-
}
681-
682701
/* Register memory region */
683-
mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)att->sa,
684-
att->size, da, NULL, NULL, "dsp_mem");
702+
mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)att->sa,
703+
att->size, da, imx_dsp_rproc_mem_alloc,
704+
imx_dsp_rproc_mem_release, "dsp_mem");
685705

686706
if (mem)
687707
rproc_coredump_add_segment(rproc, da, att->size);
@@ -709,15 +729,11 @@ static int imx_dsp_rproc_add_carveout(struct imx_dsp_rproc *priv)
709729
if (imx_dsp_rproc_sys_to_da(priv, res.start, resource_size(&res), &da))
710730
return -EINVAL;
711731

712-
cpu_addr = devm_ioremap_resource_wc(dev, &res);
713-
if (IS_ERR(cpu_addr)) {
714-
dev_err(dev, "failed to map memory %pR\n", &res);
715-
return PTR_ERR(cpu_addr);
716-
}
717-
718732
/* Register memory region */
719-
mem = rproc_mem_entry_init(dev, (void __force *)cpu_addr, (dma_addr_t)res.start,
720-
resource_size(&res), da, NULL, NULL,
733+
mem = rproc_mem_entry_init(dev, NULL, (dma_addr_t)res.start,
734+
resource_size(&res), da,
735+
imx_dsp_rproc_mem_alloc,
736+
imx_dsp_rproc_mem_release,
721737
"%.*s", strchrnul(res.name, '@') - res.name, res.name);
722738
if (!mem)
723739
return -ENOMEM;

0 commit comments

Comments
 (0)